Chào các bạn, trong bài này mình sẽ hướng dẫn các bạn cách tạo dữ liệu mẫu cực nhanh bằng factory trong Laravel.
Thông thường đối với một dự án mới hoàn toàn hoặc khi cần nhiều dữ liệu phải test hệ thống, việc phải thêm một lượng lớn dữ liệu thủ công hoàn toàn hoặc viết hàm chạy vòng lặp để insert vào hệ thống đôi khi khá tốn thời gian và công sức. Ở Laravel, các bạn có thể sử dụng Factory, một lớp hỗ trợ của Model để tạo nhanh dữ liệu dùng cho mục đích nói trên, số lượng dữ liệu tạo ra một lần có thể từ vài trăm, vài nghìn dòng mà chỉ mất công khai báo một lần và một vài lệnh để tạo. Giờ không nói lan man nữa, mình sẽ bắt đầu luôn.
Tạo Factory cho Model
Đầu tiên để có thể sử dụng được factory, model của bạn phải có trait HasFactory, trong ví dụ này mình sẽ dùng model BaiViet
use Illuminate\Database\Eloquent\Factories\HasFactory;
class BaiViet extends Model
{
//bắt buộc phải có để sử dụng Factory
use HasFactory;
Tiếp theo, chúng ta sẽ tạo một class BaiVietFactory để định nghĩa các dữ liệu giả (faker) cho bài viết bằng lệnh
php artisan make:factory BaiVietFactory
Hệ thống sẽ tạo ra một class tương ứng nằm trong thư mục database\factories có tên là BaiVietFactory.
class BaiVietFactory extends Factory
{
public function definition(): array
{
return [
//
];
}
}
Lưu ý: bạn có thể dùng tên model và factory khác nhau (ví dụ BaiViet và PostFactory), hoặc thậm chí là khác namespace khác nhau (ví dụ Admin\BaiViet và Backend\PostFactory) thì sẽ cần phải cấu hình các bước sau
1/ Thêm hàm newFactory cho model
<?php
namespace App\Models\Admin;
use Database\Factories\Backend\PostFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BaiViet extends Model
{
use HasFactory;
public $table = 'blog___bai_viet';
protected static function newFactory()
{
return PostFactory::new();
}
}
2/ Thêm phần $model vào cho PostFactory
<?php
namespace Database\Factories\Backend;
use App\Models\Admin\BaiViet;
use App\Models\Model;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
protected $model = BaiViet::class;
public function definition(): array
{
return [];
}
}
Cấu hình các trường cho Factory để tạo dữ liệu mẫu
Để cấu hình các trường cho factory, chúng ta sẽ dùng dữ liệu tạo từ thư viện faker bằng cú pháp $this->faker, thư viện có rất nhiều kiểu dữ liệu để sử dụng, các bạn có thể tham khảo thêm tại https://fakerphp.org/, trong ví dụ này mình các cột mình dùng chủ yếu là kiểu string nên mình chỉ dùng sentence và text. Riêng id_chuyen_muc là khoá ngoại nên mình sẽ lấy ngẫu nhiên từ model ChuyenMuc
class BaiVietFactory extends Factory
{
public function definition(): array
{
return [
'tieu_de' => $this->faker->sentence(),
'noi_dung' => $this->faker->text(),
'id_chuyen_muc' => ChuyenMuc::inRandomOrder()->value('id')
];
}
}
Tạo dữ liệu mẫu với Laravel Tinker
Để có thể tạo dữ liệu mẫu, chúng ta sẽ sử dụng lệnh factory()->create() thông qua Laravel Tinker. Tinker là một công cụ có nhiều công dụng, từ xem thử các hàm trong Model, chạy các hàm, cho tới tương tác với model, tạo bản ghi hoặc cụ thể hơn là tạo và đổi mật khẩu User luôn (khá nhiều công dụng nên mình sẽ không nói chi tiết quá), tinker được sử dụng bằng cách chạy lệnh sau
php artisan tinker
Tiếp theo chúng ta sẽ tạo 1000 bản ghi (hoặc bạn có thể cho số tuỳ ý) cho BaiViet với lệnh sau
App\Models\BaiViet::factory(1000)->create()
Kết quả sẽ hiển thị ngay trong giao diện của tinker, bạn có thể kiểm tra bằng các lệnh sau tương tự như trong controller hoặc truy cập trực tiếp vào database để kiểm tra dữ liệu trong bảng.
App\Models\BaiViet::all();
hoặc
App\Models\BaiViet::count();
Tạo dữ liệu mẫu thông qua Laravel Seeder
Ngoài cách tạo bằng Laravel Tinker, các bạn có thể dùng Seeder để tạo dữ liệu mẫu khi cần thêm dữ liệu ban đầu vào hệ thống, hoặc kết hợp nhiều hàm lại trong 1 file seeder, để chỉ cần chạy 1 câu lệnh thì sẽ thực thi được tất cả các hàm trong file seeder đó.
Để sử dụng Laravel Seeder, đầu tiên mình sẽ tạo Seeder và đặt tên là BlogSeeder (vì mình sẽ tạo chuyên mục trong file này nữa chứ không chỉ là bài viết) bằng lệnh sau
php artisan make:seeder BlogSeeder
Tiếp theo mình sẽ viết phần tạo sẵn 2 chuyên mục, và gọi factory để tạo 1000 bài viết như sau
class BlogSeeder extends Seeder
{
public function run(): void
{
ChuyenMuc::create([
'ten_chuyen_muc' => 'Tin tuc'
]);
ChuyenMuc::create([
'ten_chuyen_muc' => 'Huong dan'
]);
BaiViet::factory(1000)->create();
}
}
Sau đó chạy file seeder với lệnh
php artisan db:seed --class=BlogSeeder
Lưu ý: nếu không có tuỳ chọn –class, thì hệ thống sẽ chạy toàn bộ seeder đang có, việc này có thể sẽ gặp lỗi khi tạo các bản ghi có trường unique, tương tự với việc chạy 1 seeder 2 lần (ví dụ nếu chuyên mục của mình để ten_chuyen_muc là unique mà chạy db:seed như trên 2 lần thì sẽ bị báo lỗi)
Cách làm này thì mình sẽ giải thích thêm một chút, vì thông thường các lớp Seeder sẽ được sử dụng để tạo dữ liệu ban đầu cho hệ thống, ví dụ như dùng để tạo các user và phân quyền mặc định của một hệ thống.
Nhưng ở một số môi trường hosting, tuỳ thuộc vào cách cấu hình của nhà cung cấp và giới hạn của gói hosting, sẽ có trường hợp các bạn vẫn truy cập vào được SSH để chạy các lệnh artisan nhưng lại không truy cập vào được Laravel Tinker, thì phương án tạo dữ liệu mẫu bằng Seeder sẽ giải quyết luôn được vấn đề đó, vì lệnh seeder sẽ không cần phải truy cập vào Laravel Tinker.
Tổng kết
Qua bài này, mình đã hướng dẫn cho bạn cách để cấu hình và tạo dữ liệu mẫu cực nhanh bằng Factory, cùng với đó là cách sử dụng Laravel Tinker. Mong rằng hướng dẫn này sẽ giúp ích cho các bạn trong quá trình sử dụng Laravel để xây dựng dự án của mình.
Mình có viết một số bài viết về cách sử dụng Slash command trong Slack, nếu muốn đọc thêm các bạn có thể xem tại đây, nếu có gì khó hiểu thì góp ý cho mình.
Mình cũng có làm một video ngắn về tính năng tạo dữ liệu mẫu bằng Factory tương tự nội dung bài viết này, các bạn có thể xem thao tác bằng video để dễ hiểu hơn nha.
Hẹn gặp lại các bạn trong những bài viết tiếp theo.
Nguồn tham khảo:


Để lại một bình luận