我的个人博客应用最重要的两个部分是:博客文章和项目,前面已经实现了文章列表和文章详情的展示,现在来实现项目相关的功能,包括项目和里程碑。
数据库表设计
一个项目会有多个里程碑,所以项目和里程碑的关系是一对多的关系,需要设计两个数据表:
projects
表,项目信息表,对应的数据模型Project
。milestones
表,项目的里程碑信息表,对应的数据模型Milestone
。字段设计
接下来需要整理好projects
表和Milestones
表的字段名称和类型。
projects
表:
字段名称 | 描述 | 类型 | 加索引缘由 |
---|---|---|---|
id | 自增 ID | unsigned big int | 主键 |
name | 项目名称 | varchar | 无 |
description | 项目描述 | text | 无 |
cover | 项目封面 | varchar | 无 |
milestones
表:
字段名称 | 描述 | 类型 | 加索引缘由 |
---|---|---|---|
id | 自增 ID | unsigned big int | 主键 |
title | 标题 | varchar | 无 |
content | 里程碑内容 | text | 无 |
project_id | 项目 ID | unsigned big int | 外键 |
创建模型
执行如下命令创建项目的模型、迁移文件和数据工厂:
php artisan make:model Project -mf
执行如下命令创建里程碑的模型、迁移文件和数据工厂:
php artisan make:model Milestone -mf
根据前面整理好的字段修改数据库迁移文件:{timestamp}_create_projects_table.php
.
.
.
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->string('cover');
$table->timestamps();
});
}
.
.
.
{timestamp}_create_milestones_table.php
.
.
.
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->unsignedBigInteger('project_id');
$table->timestamps();
});
}
.
.
.
一对多
在创建里程碑的时候,里程碑必须对应一个项目,而该项目可以拥有多个里程碑,这便是数据模型关联中经常谈到的一对多关系。
Eloquent 模型让关联的管理和处理变得更加简单,可在模型中将 Eloquent 关联定义为函数,如下,我可在里程碑模型中,指明一个里程碑属于一个项目。
app/Models/MileStone.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Milestone extends Model
{
use HasFactory;
public function project(){
return $this->belongsTo(Project::class);
}
}
在项目模型中,指明一个项目拥有多个里程碑。
app/Models/Project.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
use HasFactory;
public function milestones(){
return $this->hasMany(Milestone::class);
}
}
填充数据
前面我们已经创建了项目和里程碑的数据工厂文件,现在分别修改:
database/factories/ProjectFactory.php
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProjectFactory extends Factory
{
public function definition()
{
return [
'name'=>$this->faker->sentence(),
'description'=>$this->faker->text(),
'cover'=>$this->faker->imageUrl()
];
}
}
database/factories/MilestoneFactory.php
<?php
namespace Database\Factories;
use App\Models\Project;
use Illuminate\Database\Eloquent\Factories\Factory;
class MilestoneFactory extends Factory
{
public function definition()
{
$project_ids = Project::pluck('id')->toArray();
return [
'project_id'=>$this->faker->randomElement($project_ids),
'title'=>$this->faker->sentence(),
'content'=>$this->faker->text()
];
}
}
上面的代码中,使用 pluck
方法取出所有项目的 id
字段,使用 toArray
方法转换为一个数组赋值给 $projectIds
变量。 project_id
字段的值使用 randomElement
方法随机从$projectIds
数组取出一个。
创建一个 ProjectsSeeder
文件来对项目假数据进行批量生成:
php artisan make:seeder ProjectsSeeder
生成 20 条假数据:
database/seeders/ProjectsSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Project;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class ProjectSeeder extends Seeder
{
public function run()
{
Project::factory()->count(20)->create();
}
}
创建一个 MileStonesSeeder
文件来对里程碑假数据进行批量生成:
php artisan make:seeder MilestonesSeeder
生成 100 条假数据:
database/seeders/ProjectsSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Milestone;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class MilestonesSeeder extends Seeder
{
public function run()
{
Milestone::factory()->count(100)->create();
}
}
接下来需要在 DatabaseSeeder
类中指定调用项目和里程碑数据填充文件。
database/seeders/DatabaseSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call(ColumnsSeeder::class);
$this->call(ArticlesSeeder::class);
$this->call(ProjectsSeeder::class);
$this->call(MilestonesSeeder::class);
}
}
最后让对数据库进行重置和填充。
php artisan migrate:refresh --seed