ThinkPHP 6.0实战:构建完整的博客系统 | PHP框架教程

2025-09-19 0 337

从零开始学习使用ThinkPHP 6.0构建功能完善的博客系统

ThinkPHP 6.0简介

ThinkPHP是一个免费开源的轻量级PHP开发框架,遵循Apache2开源协议发布。ThinkPHP 6.0版本基于PHP 7.1+,优化了核心架构,引入了新特性,提供了更强大的开发体验。

主要特性:

  • 简洁的路由定义和强大的路由功能
  • 完善的ORM支持,支持多种数据库
  • 强大的模板引擎,支持标签库
  • 丰富的扩展机制和类库支持
  • 支持Composer依赖管理
  • PSR规范支持,易于与其他框架集成

环境搭建与项目创建

在开始之前,确保您的系统满足以下要求:

  • PHP >= 7.1.0
  • PDO PHP Extension
  • MBstring PHP Extension
  • Composer工具

安装ThinkPHP 6.0


# 使用Composer创建项目
composer create-project topthink/think tp-blog

# 进入项目目录
cd tp-blog

# 启动内置服务器
php think run
                

配置数据库

修改config/database.php文件,配置数据库连接信息:


return [
    // 默认数据库连接
    'default' => 'mysql',
    
    // 数据库连接信息
    'connections' => [
        'mysql' => [
            // 数据库类型
            'type' => 'mysql',
            // 服务器地址
            'hostname' => '127.0.0.1',
            // 数据库名
            'database' => 'blog',
            // 用户名
            'username' => 'root',
            // 密码
            'password' => 'password',
            // 端口
            'hostport' => '3306',
            // 连接dsn
            'dsn' => '',
            // 数据库连接参数
            'params' => [],
            // 数据库编码默认采用utf8
            'charset' => 'utf8mb4',
            // 数据库表前缀
            'prefix' => 'blog_',
            // 数据库调试模式
            'debug' => true,
        ],
    ],
];
                

项目结构说明

ThinkPHP 6.0采用模块化设计,标准目录结构如下:


tp-blog/
├── app/                    // 应用目录
│   ├── controller/        // 控制器目录
│   ├── model/            // 模型目录
│   ├── view/             // 视图目录
│   └── ...              // 其他目录
├── config/               // 配置目录
├── public/              // WEB部署目录
├── route/               // 路由定义目录
├── runtime/             // 运行时目录
├── vendor/              // 第三方类库目录
└── extend/              // 扩展类库目录
                

多应用模式配置

ThinkPHP 6.0默认采用单应用模式,我们可以启用多应用模式:


# 安装多应用模式扩展
composer require topthink/think-multi-app

# 创建应用目录
cd app
mkdir index blog admin

# 在每个应用目录中创建必要的子目录
mkdir controller model view
                

数据库设计与迁移

我们将创建以下数据表来支持博客系统:

数据表设计

  • 文章表(blog_articles):存储文章内容
  • 分类表(blog_categories):文章分类
  • 标签表(blog_tags):文章标签
  • 文章标签关联表(blog_article_tags):文章和标签的多对多关系
  • 评论表(blog_comments):文章评论
  • 用户表(blog_users):后台管理员

创建数据库迁移文件


# 创建文章表迁移
php think make:migration CreateArticlesTable

# 编辑迁移文件
# database/migrations/20230101000000_create_articles_table.php
                

迁移文件示例


<?php
use thinkmigrationMigrator;
use thinkmigrationdbColumn;

class CreateArticlesTable extends Migrator
{
    public function change()
    {
        $table = $this->table('blog_articles', ['engine' => 'InnoDB', 'comment' => '文章表']);
        $table->addColumn('category_id', 'integer', ['limit' => 10, 'default' => 0, 'comment' => '分类ID'])
            ->addColumn('title', 'string', ['limit' => 255, 'default' => '', 'comment' => '文章标题'])
            ->addColumn('content', 'text', ['comment' => '文章内容'])
            ->addColumn('excerpt', 'string', ['limit' => 500, 'default' => '', 'comment' => '文章摘要'])
            ->addColumn('status', 'integer', ['limit' => 1, 'default' => 0, 'comment' => '状态:0草稿,1发布'])
            ->addColumn('views', 'integer', ['limit' => 10, 'default' => 0, 'comment' => '浏览量'])
            ->addColumn('is_top', 'integer', ['limit' => 1, 'default' => 0, 'comment' => '是否置顶'])
            ->addColumn('created_at', 'timestamp', ['default' => 'CURRENT_TIMESTAMP', 'comment' => '创建时间'])
            ->addColumn('updated_at', 'timestamp', ['null' => true, 'comment' => '更新时间'])
            ->addIndex(['category_id'])
            ->addIndex(['status'])
            ->create();
    }
}
                

执行数据库迁移


# 运行迁移
php think migrate:run
                

博客系统功能实现

下面我们将实现博客系统的核心功能,包括文章管理、分类管理、标签管理和评论功能。

1. 创建文章模型


<?php
namespace appindexmodel;

use thinkModel;
use thinkmodelconcernSoftDelete;

class Article extends Model
{
    use SoftDelete;
    
    // 设置表名
    protected $name = 'blog_articles';
    
    // 设置自动时间戳
    protected $autoWriteTimestamp = 'datetime';
    protected $createTime = 'created_at';
    protected $updateTime = 'updated_at';
    protected $deleteTime = 'deleted_at';
    protected $defaultSoftDelete = null;
    
    // 定义状态常量
    const STATUS_DRAFT = 0; // 草稿
    const STATUS_PUBLISHED = 1; // 已发布
    
    // 分类关联
    public function category()
    {
        return $this->belongsTo(Category::class);
    }
    
    // 标签多对多关联
    public function tags()
    {
        return $this->belongsToMany(Tag::class, 'blog_article_tags');
    }
    
    // 评论一对多关联
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
    
    // 获取器 - 状态文字描述
    public function getStatusTextAttr($value, $data)
    {
        $status = $data['status'] ?? 0;
        $statusMap = [
            self::STATUS_DRAFT => '草稿',
            self::STATUS_PUBLISHED => '已发布'
        ];
        return $statusMap[$status] ?? '未知';
    }
    
    // 获取器 - 格式化创建时间
    public function getCreatedAtTextAttr($value, $data)
    {
        return date('Y-m-d H:i', strtotime($data['created_at']));
    }
    
    // 范围查询 - 已发布文章
    public function scopePublished($query)
    {
        $query->where('status', self::STATUS_PUBLISHED);
    }
    
    // 范围查询 - 置顶文章
    public function scopeTop($query)
    {
        $query->where('is_top', 1);
    }
}
                

2. 创建文章控制器


<?php
namespace appindexcontroller;

use thinkfacadeView;
use appindexmodelArticle as ArticleModel;
use appindexmodelCategory;
use appindexmodelTag;

class Article extends Base
{
    // 文章列表
    public function index()
    {
        $categoryId = input('category_id', 0);
        $tagId = input('tag_id', 0);
        $keyword = input('keyword', '');
        
        // 构建查询条件
        $query = ArticleModel::with(['category', 'tags'])
            ->published()
            ->order('is_top DESC, created_at DESC');
            
        if ($categoryId) {
            $query->where('category_id', $categoryId);
        }
        
        if ($tagId) {
            $query->whereHas('tags', function($query) use ($tagId) {
                $query->where('tag_id', $tagId);
            });
        }
        
        if ($keyword) {
            $query->whereLike('title|content', '%' . $keyword . '%');
        }
        
        $articles = $query->paginate(10);
        
        // 获取分类和标签用于侧边栏
        $categories = Category::withCount('articles')->select();
        $tags = Tag::withCount('articles')->select();
        
        View::assign([
            'articles' => $articles,
            'categories' => $categories,
            'tags' => $tags,
            'category_id' => $categoryId,
            'tag_id' => $tagId,
            'keyword' => $keyword
        ]);
        
        return View::fetch();
    }
    
    // 文章详情
    public function detail($id)
    {
        $article = ArticleModel::with(['category', 'tags', 'comments' => function($query) {
            $query->where('status', 1)->order('created_at DESC');
        }])->published()->findOrFail($id);
        
        // 增加浏览量
        $article->setInc('views');
        
        View::assign('article', $article);
        return View::fetch();
    }
    
    // 搜索文章
    public function search()
    {
        $keyword = input('keyword', '');
        
        if (empty($keyword)) {
            return redirect('index/article/index');
        }
        
        $articles = ArticleModel::with(['category', 'tags'])
            ->published()
            ->whereLike('title|content', '%' . $keyword . '%')
            ->order('created_at DESC')
            ->paginate(10, false, ['query' => ['keyword' => $keyword]]);
            
        View::assign([
            'articles' => $articles,
            'keyword' => $keyword
        ]);
        
        return View::fetch('index');
    }
}
                

3. 配置路由

在route/route.php中定义路由规则:


<?php
use thinkfacadeRoute;

// 文章列表页
Route::get('article', 'index/article/index');
Route::get('article/category/:id', 'index/article/index');

// 文章详情页
Route::get('article/:id', 'index/article/detail')
    ->pattern(['id' => 'd+']);

// 搜索页面
Route::get('search', 'index/article/search');

// 标签页面
Route::get('tag/:id', 'index/article/index')
    ->pattern(['id' => 'd+']);

// 提交评论
Route::post('comment/add', 'index/comment/add');
                

4. 创建视图模板

创建文章列表视图模板view/index/article/index.html:


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>文章列表 - {$site.title}</title>
    <meta name="keywords" content="{$site.keywords}">
    <meta name="description" content="{$site.description}">
</head>
<body>
    {include file="common/header" /}
    
    <div class="container">
        <div class="row">
            <div class="col-md-8">
                <div class="page-header">
                    <h1>
                        {if $category_id}
                            {$categories->where('id', $category_id)->value('name')}
                        {elseif $tag_id}
                            标签: {$tags->where('id', $tag_id)->value('name')}
                        {elseif $keyword}
                            搜索: {$keyword}
                        {else}
                            最新文章
                        {/if}
                    </h1>
                </div>
                
                {volist name="articles" id="article"}
                <div class="article-item">
                    {if $article.is_top}
                    <span class="label label-primary">置顶</span>
                    {/if}
                    <h2><a href="{:url('index/article/detail', ['id' => $article.id])}" rel="external nofollow"  rel="external nofollow" >{$article.title}</a></h2>
                    <div class="article-meta">
                        <span><i class="fa fa-calendar"></i> {$article.created_at_text}</span>
                        <span><i class="fa fa-folder"></i> {$article.category.name}</span>
                        <span><i class="fa fa-eye"></i> {$article.views}</span>
                    </div>
                    <div class="article-excerpt">
                        {$article.excerpt|default=$article.content|mb_substr=0,200}
                    </div>
                    <div class="article-footer">
                        <a href="{:url('index/article/detail', ['id' => $article.id])}" rel="external nofollow"  rel="external nofollow"  class="btn btn-primary">阅读更多</a>
                    </div>
                </div>
                {/volist}
                
                <div class="pagination">
                    {$articles|raw}
                </div>
            </div>
            
            <div class="col-md-4">
                {include file="common/sidebar" /}
            </div>
        </div>
    </div>
    
    {include file="common/footer" /}
</body>
</html>
                

5. 后台管理功能

创建后台文章管理控制器:


<?php
namespace appadmincontroller;

use thinkfacadeView;
use appadminmodelArticle as ArticleModel;
use appadminmodelCategory;
use appadminmodelTag;

class Article extends Base
{
    // 文章列表
    public function index()
    {
        $status = input('status', -1);
        $categoryId = input('category_id', 0);
        $keyword = input('keyword', '');
        
        $query = ArticleModel::with(['category', 'tags']);
        
        if ($status != -1) {
            $query->where('status', $status);
        }
        
        if ($categoryId) {
            $query->where('category_id', $categoryId);
        }
        
        if ($keyword) {
            $query->whereLike('title', '%' . $keyword . '%');
        }
        
        $articles = $query->order('is_top DESC, id DESC')->paginate(15);
        
        $categories = Category::select();
        
        View::assign([
            'articles' => $articles,
            'categories' => $categories,
            'status' => $status,
            'category_id' => $categoryId,
            'keyword' => $keyword
        ]);
        
        return View::fetch();
    }
    
    // 添加文章
    public function add()
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            
            $validate = new appadminvalidateArticle;
            if (!$validate->check($data)) {
                $this->error($validate->getError());
            }
            
            $article = ArticleModel::create($data);
            
            // 处理标签
            if (!empty($data['tags'])) {
                $tagIds = Tag::saveTags($data['tags']);
                $article->tags()->attach($tagIds);
            }
            
            $this->success('添加成功', 'index');
        }
        
        $categories = Category::select();
        View::assign('categories', $categories);
        return View::fetch();
    }
    
    // 编辑文章
    public function edit($id)
    {
        $article = ArticleModel::with('tags')->findOrFail($id);
        
        if ($this->request->isPost()) {
            $data = $this->request->post();
            
            $validate = new appadminvalidateArticle;
            if (!$validate->check($data)) {
                $this->error($validate->getError());
            }
            
            $article->save($data);
            
            // 更新标签
            if (!empty($data['tags'])) {
                $tagIds = Tag::saveTags($data['tags']);
                $article->tags()->detach();
                $article->tags()->attach($tagIds);
            }
            
            $this->success('更新成功', 'index');
        }
        
        $categories = Category::select();
        View::assign([
            'article' => $article,
            'categories' => $categories
        ]);
        
        return View::fetch();
    }
    
    // 删除文章
    public function delete($id)
    {
        $article = ArticleModel::findOrFail($id);
        $article->delete();
        
        $this->success('删除成功');
    }
    
    // 设置文章状态
    public function setStatus($id, $status)
    {
        $article = ArticleModel::findOrFail($id);
        $article->status = $status;
        $article->save();
        
        $this->success('操作成功');
    }
}
                

总结

通过本文的教程,我们使用ThinkPHP 6.0构建了一个功能完整的博客系统,涵盖了以下核心内容:

实现的功能:

  • 文章管理(增删改查、状态管理)
  • 分类和标签管理
  • 文章评论系统
  • 文章搜索功能
  • 前后台分离架构
  • 响应式页面设计

使用的ThinkPHP特性:

  • 模型和ORM操作
  • 控制器和请求处理
  • 视图模板和标签库
  • 路由定义和URL生成
  • 验证器和数据验证
  • 中间件和权限控制

这个博客系统可以作为学习ThinkPHP的入门项目,也可以作为实际项目的基础框架进行扩展。ThinkPHP 6.0提供了丰富的功能和灵活的扩展机制,能够满足各种Web开发需求。

希望本文能帮助您更好地理解和使用ThinkPHP框架,在实际开发中发挥其强大的功能。

ThinkPHP 6.0实战:构建完整的博客系统 | PHP框架教程
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 thinkphp ThinkPHP 6.0实战:构建完整的博客系统 | PHP框架教程 https://www.taomawang.com/server/thinkphp/1083.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务