[laravel series] 4. Build blog - Thiết kế database, seed dữ liệu mẫu

Tiếp tục laravel resies, bài này mình sẽ bắt đầu build các tính năng của một trang blog, qua đó chúng ta có thể học được cách thiết kế database, áp dụng các tính năng của laravel để build các tính năng liên quan. Thực hành chính là cách học nhanh nhất :). Bài này chúng ta sẽ tập trung vào phần thiết kế database, các bảng dữ liệu, quan hệ giữa các bảng.

Link project ở đây mọi người tham khảo thêm ở đây nhé, trong quá trình viết bài có thể có thiếu xót. phuongdm1987/laravel-tutorial (github.com)


Trong bài [Laravel series] 2. Cài đặt môi trường local chúng ta đã tạo database laravel_tutorial, bây giờ chúng ta sẽ tạo các bảng trong database này.

  • Tạo migrate cho bảng categories
    docker/run artisan make:migration create_categories_table
    • Update function up trong file migrate vừa tạo như bên dưới:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->foreignId('parent_id')->default(0)->index();
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
  • Tạo migrate cho bảng posts
    docker/run artisan make:migration create_posts_table
    • Update function up trong file migrate vừa tạo như bên dưới:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('author_id')->index();
$table->foreignId('category_id')->default(0)->index();
$table->string('title');
$table->string('slug')->unique();
$table->text('summary');
$table->text('content');
$table->enum('status', ['DRAFT', 'PUBLISHED'])->default('DRAFT')->index();
$table->softDeletes();
$table->timestamps();
});
  • Tạo migrate cho bảng comments
    docker/run artisan make:migration create_comments_table
    • Update function up trong file migrate vừa tạo như bên dưới:
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->index();
$table->foreignId('post_id')->index();
$table->foreignId('parent_id')->default(0)->index();
$table->text('content');
$table->timestamps();
});
  • Tạo migrate cho bảng tags
    docker/run artisan make:migration create_tags_table
    • Update function up trong file migrate vừa tạo như bên dưới:
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
});
  • Tạo migrate cho bảng post_tag
    docker/run artisan make:migration create_post_tag_table
    • Update function up trong file migrate vừa tạo như bên dưới:
Schema::create('post_tag', function (Blueprint $table) {
$table->foreignId('post_id');
$table->foreignId('tag_id');
$table->primary(['post_id', 'tag_id']);
});

Chúng ta chạy lệnh docker/run artisan migrate để tạo các bảng phía trên.
Tiếp theo chúng ta sẽ tạo model, factory, và seeder để tạo dữ liệu mẫu cho các đối tượng: category, post, comment, tag
Các câu lệnh tạo model, factory, và seeder

  • docker/run artisan make:model ten_model
  • docker/run artisan make:factory ten_factory
  • docker/run artisan make:seeder ten_seeder

Mình sẽ tạo model và factory với đường dẫn là tên model, trước tiên chúng ta chuyển model User từ /model/User.php thành /model/User/User.php mục đích để sau này chung ta thêm các file liên quan đến model vào cùng một thư mục, để dễ quản lý hơn.
Tương tự chuyển /database/factories/UserFactory thành /database/factories/User/UserFactory

  • Tạo model, factory, seeder cho category
    • docker/run artisan make:model Category/Category
    • docker/run artisan make:factory Category/CategoryFactory
    • docker/run artisan make:seeder CategorySeeder

Ở function definition trong file /database/factories/Category/CategoryFactory chúng ta update như sau:

$name = $this->faker->unique()->name;
$slug = Str::snake($name);

return [
'name' => $name,
'slug' => Str::lower($slug),
];

Ở function run trong file /database/seeders/CategorySeeder chúng ta update như sau:

$data = [
[
'name' => 'News General',
'slug' => 'news-general',
],
[
'name' => 'Technology - Hi Tech',
'slug' => 'technology-hi-tech',
],
[
'name' => 'Health',
'slug' => 'health',
],
[
'name' => 'Fashion',
'slug' => 'fashion',
],
[
'name' => 'Sport',
'slug' => 'sport',
],
[
'name' => 'Culture & Education',
'slug' => 'culture-&-education',
],
[
'name' => 'Automotive & Vehicles',
'slug' => 'automotive-&-vehicles',
],
];

$categories = Category::factory()->createMany($data);

$tags = Tag::factory()->count(10)->create();

$posts = collect();
for ($i = 1; $i <= 10; $i++) {
$post = Post::factory()->create([
'category_id' => $categories->random()->id,
]);

$posts->add($post);
}

foreach ($posts as $post) {
$post->tags()->sync([
'tag_id' => $tags->random()->id,
]);
}

$comments = collect();
for ($i = 1; $i <= 10; $i++) {
$comment = Comment::factory()->create([
'post_id' => $posts->random()->id,
]);

$comments->add($comment);
}

foreach ($comments as $comment) {
Comment::factory([
'parent_id' => $comment->id,
'post_id' => $comment->post_id,
])
->count(2)
->create();
}
  • Tạo model, factory, seeder cho post
    • docker/run artisan make:model Post/Post
    • docker/run artisan make:factory Post/PostFactory

Ở function definition trong file /database/factories/Post/PostFactory chúng ta update như sau:

$title = $this->faker->unique()->name;
$slug = Str::snake($title);
$status = Arr::random([
'DRAFT',
'PUBLISHED',
]);

return [
'author_id' => 1,
'category_id' => random_int(1, 7), // 7 category in CategorySeeder
'title' => $title,
'slug' => Str::lower($slug),
'summary' => $this->faker->paragraph,
'content' => $this->faker->realText(),
'status' => $status,
];
  • Tạo model, factory, seeder cho comment
    • docker/run artisan make:model Comment/Comment
    • docker/run artisan make:factory Comment/CommentFactory

Ở function definition trong file /database/factories/Comment/CommentFactory chúng ta update như sau:

return [
'user_id' => 1,
'post_id' => random_int(1, 10),
'content' => $this->faker->realText(),
];
  • Tạo model, factory, seeder cho tag
    • docker/run artisan make:model Tag/Tag
    • docker/run artisan make:factory Tag/TagFactory

Ở function definition trong file /database/factories/Tag/TagFactory chúng ta update như sau:

$name = $this->faker->unique()->name;
$slug = Str::snake($name);

return [
'name' => $name,
'slug' => Str::lower($slug),
];
  • Update function run trong file /database/seeders/DatabaseSeeder.php
User::factory([
'email' => 'henry@gmail.com',
])->create();

$this->call([
CategorySeeder::class,
]);

Chạy lệnh docker/run artisan db:seed để seed dữ liệu mẫu, lệnh này sẽ gọi đến file /database/seeders/DatabaseSeeder.php để seed data.

Vậy là chúng ta đã hoàn tất quá trình tạo bảng và thêm dữ liệu mẫu. Về các bảng dữ liệu mình tạo các field đơn giản có thể chưa đầy đủ, trong quá trình chúng ta trinh phục project blog này, có thể sẽ có các cập nhật về cấu trúc database để tiến hoá hơn. Các bạn cùng theo dõi trong các phần sau nhé, thanks.

Mọi thắc mắc, góp ý, mọi người cứ mạnh dạn comment ở dưới bài giúp mình. Mình sẽ có gắng phản hồi sớm nhất có thể :).

Nhận xét

Bài đăng phổ biến từ blog này

[Laravel series] 3. Sử dụng Laravel Breeze để xác thực người dùng

[Laravel series] 2. Cài đặt môi trường local

[Laravel series] 5. Build blog - Sử dụng route, controller để hiển thị bài viết