使用 Laravel 和 Filament 搭建一个内容管理系统(CMS)是一个高效且灵活的选择。Filament 提供了现代化的管理后台界面,使内容管理变得直观和高效。以下是一个详细的步骤指南,帮助您从零开始搭建一个功能强大的 CMS 系统。
目录
- 项目初始化
- 安装 Filament
- 定义数据模型
- 创建 Filament 资源
- 配置权限和角色
- 创建内容管理功能
- 前端集成(可选)
- 额外功能
- 部署
- 参考资源
- 总结
1. 项目初始化
1.1 创建新的 Laravel 项目
如果尚未创建 Laravel 项目,可以使用 Composer 创建一个新项目:
composer create-project laravel/laravel cms-system
进入项目目录:
cd cms-system
1.2 设置数据库连接
在 .env
文件中配置数据库连接:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cms_system
DB_USERNAME=root
DB_PASSWORD=your_password
创建数据库(例如使用 MySQL):
CREATE DATABASE cms_system;
1.3 运行迁移
运行初始迁移以创建必要的表:
php artisan migrate
2. 安装 Filament
2.1 使用 Composer 安装 Filament
composer require filament/filament
2.2 运行 Filament 安装命令
php artisan filament:install
安装过程中,Filament 会提示您创建管理员用户。按照提示完成安装。
2.3 构建前端资源
安装前端依赖并构建资源:
npm install
npm run build
在开发环境中,可以使用:
npm run dev
确保 public/build/manifest.json
文件存在。
3. 定义数据模型
根据您的 CMS 需求,定义需要管理的内容。例如,假设您要管理文章(Posts)、分类(Categories)、标签(Tags)等。
3.1 创建 Eloquent 模型和迁移
以文章(Post)为例:
php artisan make:model Post -m
编辑迁移文件 database/migrations/xxxx_xx_xx_create_posts_table.php
:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->foreignId('category_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
同样,为分类(Category)创建模型和迁移:
php artisan make:model Category -m
编辑迁移文件 database/migrations/xxxx_xx_xx_create_categories_table.php
:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
运行迁移:
php artisan migrate
3.2 定义模型关系
在 App\Models\Post.php
中:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'content', 'category_id'];
public function category()
{
return $this->belongsTo(Category::class);
}
}
在 App\Models\Category.php
中:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = ['name'];
public function posts()
{
return $this->hasMany(Post::class);
}
}
4. 创建 Filament 资源
4.1 创建 Post 资源
使用 Filament 提供的 Artisan 命令生成资源:
php artisan make:filament-resource Post
这将在 app/Filament/Resources/PostResource
目录下生成必要的文件。
4.2 配置 Post 资源
编辑 app/Filament/Resources/PostResource.php
:
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\PostResource\Pages;
use App\Models\Post;
use Filament\Forms;
use Filament\Tables;
use Filament\Resources\Resource;
class PostResource extends Resource
{
protected static ?string $model = Post::class;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?int $navigationSort = 1;
public static function form(Forms\Form $form): Forms\Form
{
return $form
->schema([
Forms\Components\TextInput::make('title')
->required()
->maxLength(255),
Forms\Components\Select::make('category_id')
->relationship('category', 'name')
->required(),
Forms\Components\RichEditor::make('content')
->required(),
]);
}
public static function table(Tables\Table $table): Tables\Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\TextColumn::make('title')->sortable()->searchable(),
Tables\Columns\TextColumn::make('category.name')->label('Category')->sortable()->searchable(),
Tables\Columns\TextColumn::make('created_at')->dateTime(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getPages(): array
{
return [
'index' => Pages\ListPosts::route('/'),
'create' => Pages\CreatePost::route('/create'),
'edit' => Pages\EditPost::route('/{record}/edit'),
];
}
}
4.3 创建 Category 资源
同样地,创建并配置分类资源:
php artisan make:filament-resource Category
编辑 app/Filament/Resources/CategoryResource.php
:
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\CategoryResource\Pages;
use App\Models\Category;
use Filament\Forms;
use Filament\Tables;
use Filament\Resources\Resource;
class CategoryResource extends Resource
{
protected static ?string $model = Category::class;
protected static ?string $navigationIcon = 'heroicon-o-collection';
protected static ?int $navigationSort = 2;
public static function form(Forms\Form $form): Forms\Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
]);
}
public static function table(Tables\Table $table): Tables\Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\TextColumn::make('name')->sortable()->searchable(),
Tables\Columns\TextColumn::make('created_at')->dateTime(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getPages(): array
{
return [
'index' => Pages\ListCategories::route('/'),
'create' => Pages\CreateCategory::route('/create'),
'edit' => Pages\EditCategory::route('/{record}/edit'),
];
}
}
4.4 创建其他资源
根据需要,创建更多的资源,如标签(Tags)、用户(Users)、媒体(Media)等。
5. 配置权限和角色
为了确保只有授权用户可以访问和管理 CMS 内容,建议使用 Spatie Laravel Permission 包来管理角色和权限。
5.1 安装 Spatie Laravel Permission
composer require spatie/laravel-permission
5.2 发布配置和迁移
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
5.3 配置 User 模型
在 App\Models\User.php
中添加 HasRoles
trait:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// 其他代码...
}
5.4 创建角色和权限
使用 Tinker 或编写 Seeder 来创建角色和权限:
php artisan tinker
在 Tinker 中:
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use App\Models\User;
// 创建角色
$adminRole = Role::create(['name' => 'admin']);
$editorRole = Role::create(['name' => 'editor']);
// 创建权限
$managePosts = Permission::create(['name' => 'manage posts']);
$manageCategories = Permission::create(['name' => 'manage categories']);
// 分配权限给角色
$adminRole->givePermissionTo(['manage posts', 'manage categories']);
$editorRole->givePermissionTo(['manage posts']);
// 查找用户并分配角色
$user = User::where('email', 'admin@example.com')->first();
if ($user) {
$user->assignRole('admin');
} else {
$user = User::create([
'name' => 'Admin User',
'email' => 'admin@example.com',
'password' => bcrypt('password'), // 请使用更安全的密码
]);
$user->assignRole('admin');
}
5.5 配置 Filament 中间件
在 config/filament.php
中,确保 Filament 只允许特定角色的用户访问后台:
'auth' => [
'guard' => 'web',
'passwords' => 'users',
'middleware' => [
'web',
'auth',
function ($request, $next) {
if (!$request->user() || !$request->user()->hasRole('admin')) {
abort(403);
}
return $next($request);
},
],
],
6. 创建内容管理功能
根据 CMS 的需求,创建更多的内容管理资源,如页面(Pages)、媒体(Media)、菜单(Menus)等。
示例:创建 Page 资源
php artisan make:model Page -m
php artisan make:filament-resource Page
编辑 database/migrations/xxxx_xx_xx_create_pages_table.php
:
public function up()
{
Schema::create('pages', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug')->unique();
$table->text('content');
$table->timestamps();
});
}
运行迁移:
php artisan migrate
编辑 app/Filament/Resources/PageResource.php
:
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\PageResource\Pages;
use App\Models\Page;
use Filament\Forms;
use Filament\Tables;
use Filament\Resources\Resource;
class PageResource extends Resource
{
protected static ?string $model = Page::class;
protected static ?string $navigationIcon = 'heroicon-o-document';
protected static ?int $navigationSort = 3;
public static function form(Forms\Form $form): Forms\Form
{
return $form
->schema([
Forms\Components\TextInput::make('title')
->required()
->maxLength(255),
Forms\Components\TextInput::make('slug')
->required()
->maxLength(255)
->unique(ignoreRecord: true),
Forms\Components\RichEditor::make('content')
->required(),
]);
}
public static function table(Tables\Table $table): Tables\Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\TextColumn::make('title')->sortable()->searchable(),
Tables\Columns\TextColumn::make('slug')->sortable()->searchable(),
Tables\Columns\TextColumn::make('created_at')->dateTime(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getPages(): array
{
return [
'index' => Pages\ListPages::route('/'),
'create' => Pages\CreatePage::route('/create'),
'edit' => Pages\EditPage::route('/{record}/edit'),
];
}
}
7. 前端集成(可选)
如果需要在前端展示 CMS 内容,可以使用 Blade 模板或构建 API 端点。
7.1 使用 Blade 模板
创建前端视图来展示 CMS 内容。例如,在 resources/views/pages.blade.php
中:
@extends('layouts.app')
@section('content')
<h1>Pages</h1>
@foreach($pages as $page)
<div>
<h2>{{ $page->title }}</h2>
<div>{!! $page->content !!}</div>
</div>
@endforeach
@endsection
在控制器中获取数据:
<?php
namespace App\Http\Controllers;
use App\Models\Page;
class PageController extends Controller
{
public function index()
{
$pages = Page::all();
return view('pages', compact('pages'));
}
public function show($slug)
{
$page = Page::where('slug', $slug)->firstOrFail();
return view('page', compact('page'));
}
}
定义路由:
use App\Http\Controllers\PageController;
Route::get('/pages', [PageController::class, 'index']);
Route::get('/pages/{slug}', [PageController::class, 'show']);
7.2 构建 API
如果前端需要使用 JavaScript 框架(如 Vue.js、React),可以构建 API 端点。
创建 API 资源:
php artisan make:controller Api/PageController --api
编辑 app/Http/Controllers/Api/PageController.php
:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\PageResource;
use App\Models\Page;
use Illuminate\Http\Request;
class PageController extends Controller
{
public function index()
{
return PageResource::collection(Page::all());
}
public function show($slug)
{
$page = Page::where('slug', $slug)->firstOrFail();
return new PageResource($page);
}
}
创建资源类:
php artisan make:resource PageResource
编辑 app/Http/Resources/PageResource.php
:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PageResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'content' => $this->content,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
定义 API 路由:
use App\Http\Controllers\Api\PageController;
Route::prefix('api')->group(function () {
Route::get('/pages', [PageController::class, 'index']);
Route::get('/pages/{slug}', [PageController::class, 'show']);
});
8. 额外功能
8.1 媒体管理
Filament 提供了一个强大的媒体库,可以管理上传的文件。
8.2 用户角色与权限
进一步配置用户角色和权限,以满足 CMS 的访问控制需求。
8.3 搜索和过滤
在 Filament 资源中添加搜索和过滤功能,以便更高效地管理内容。
9. 部署
在开发完成后,将 CMS 系统部署到生产环境。确保前端资源已构建,并且服务器配置正确。
9.1 构建前端资源
npm run build
9.2 运行迁移
php artisan migrate --force
9.3 清理和缓存
php artisan config:cache
php artisan route:cache
php artisan view:cache
9.4 设置文件权限
确保 storage
和 bootstrap/cache
目录具有正确的权限。
chmod -R 755 storage
chmod -R 755 bootstrap/cache
chown -R www-data:www-data storage
chown -R www-data:www-data bootstrap/cache
10. 参考资源
11. 总结
通过以上步骤,您可以使用 Laravel 和 Filament 搭建一个功能强大的 CMS 系统。Filament 提供了一个现代化的后台管理界面,使内容管理变得更加高效和直观。结合 Laravel 的强大功能和扩展生态系统,您可以根据需求进一步定制和扩展 CMS 的功能。
关键步骤回顾:
- 项目初始化:创建 Laravel 项目并配置数据库。
- 安装 Filament:使用 Composer 安装 Filament 并运行安装命令。
- 定义数据模型:创建 Eloquent 模型和迁移,定义模型关系。
- 创建 Filament 资源:生成并配置 Filament 资源以管理内容。
- 配置权限和角色:使用 Spatie Laravel Permission 管理用户角色和权限。
- 创建内容管理功能:根据需求创建更多的内容管理资源。
- 前端集成:使用 Blade 模板或构建 API 端点展示内容。
- 额外功能:实现媒体管理、搜索过滤等高级功能。
- 部署:构建前端资源,运行迁移,设置文件权限并部署到生产环境。
如果在搭建过程中遇到任何问题或需要进一步的帮助,请随时提问,我将乐意为您提供更多的指导和支持!
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:JefskyWong ——程序猿甜品店
链接:https://www.jefsky.com/blog/346
来源:https://www.jefsky.com/