Migration và Seeder
Bài đăng này đã không được cập nhật trong 3 năm
Khi bắt đầu bài viết này mình mặc định bạn đã cài đặt và chạy được Laravel rồi nên mình sẽ không hướng dẫn lại quá trình cài đặt. Còn nếu bạn chưa cài đặt thì bạn có thể truy cập vào document trên trang chính thức của Laravel và làm theo hướng dẫn.
Mở đầu
Chắc hẳn khi bắt tay vào code một project công việc đầu tiên bạn cần làm là tạo cho mình cơ sở dữ liệu cùng với một số dữ liệu mẫu để phục vụ cho quá trình phát triển chức năng. Đối với PHP thông thường, bạn phải truy cập vào CSDL thông qua PHPMyAdmin, Workbench (nếu bạn sử dụng MySQl) để tạo CSDL, tạo các bảng và thêm dữ liệu mẫu bằng giao diện hoặc bằng việc gõ lệnh SQL. Tuy nhiên cách làm này có thể nói là khá thủ công và sẽ phát sinh nhiều vấn đề nhất là khi bạn làm việc teamwork với các thành viên khác. Để giải quyết những vấn đề phát sinh đó, Laravel giới thiệu đến người sử dụng hai tính năng là Migration
và Seeder
.
Migration
Migration
theo như trong document chính thức của Laravel giới thiệu nó giống như một hệ thống quản lý phiên bản giống như Git nhưng dành cho cơ sở dữ liệu của bạn. Migration
cho phép bạn định nghĩa các bảng trong CSDL, định nghĩa nội dung các bảng cũng như cập nhật thay đổi các bảng đó hoàn toàn bằng PHP. Đồng thời các thao tác với CSDL này còn có thể sử dụng trên các loại CSDL khác nhau như MySQL, SQL Server, Postgres, ... mà không cần phải chỉnh sửa lại code theo CSDL sử dụng.
1. Các file migration
- Mặc định khi bạn tạo mới project Laravel sẽ có sẵn một thư mục dành cho các file migration là folder
database/migrations
. Toàn bộ các file migration bạn tạo ra trong quá trình làm việc sẽ được lưu trữ ở đây. Các file migration này đơn giản chỉ là các file PHP có nhiệm vụ định nghĩa cấu trúc các bảng cho CSDL của bạn.
- Còn đây là nội dung bên trong 1 file migration
2. Cách tạo một file migration
- Để tạo một file migration, ta sử dụng cú pháp sau trên terminal (command line):
$ php artisan make:migration <file-name> --create=<table-name>
-
Lệnh này sẽ tạo ra một file migration mới có tên dưới dạng
<timestamp>_<file-name>.php
. Bên trong đó sẽ tạo sẵn cho bạn cấu trúc để định nghĩa nội dung một bảng có tên giống với<table-name>
mà bạn chọn ở trên. -
Từ đó bạn có thể dễ dàng định nghĩa các cột trong bảng của mình như sau: Tạm thời bạn chưa cần quan tầm đến hàm up bọc bên ngoài đó
-
Như các bạn đã thấy, chúng ta có thể dễ dàng định nghĩa các cột trong bảng của mình thông qua cú pháp mà Laravel cung cấp. Bạn chỉ cần định nghĩa kiểu dữ liệu thông qua các hàm mà Laravel cung cấp đi kèm đó là tên cột cùng một số chọn lựa khác như cột đó có giá trị defaul là gì, có thể để null không,...
-
Ngoài ra bạn cũng có thể định nghĩa quan hệ giữa các bảng với nhau:
-
Đoạn code trên đơn giản định nghĩa một khóa ngoại có tên là
users_id
liên kết với cộtid
trong bảngusers
và cột đó có dạnginterger
-
Ngoài việc tạo mới bản, ta cũng có thể tạo file migration mới nhằm chỉnh sửa lại bảng bằng cú pháp tương tự như khi tạo mới file migration để tạo bảng
$ php artisan make:migration <file-name> --table=<table-name>
- Sẽ tạo cho ta file migration mới có nhiệm vụ để cập nhật nội dung cho bảng đã được tạo trước đó
Để chạy được hàm change() bạn cần cài thêm package tên là doctrine/dbal
- Nếu bạn để ý kĩ, khi tạo mới bảng thì sẽ thực hiện hàm có tên
Schema::create
còn khi cập nhật bảng sẽ dùng hàmSchema::table
. Để xem được hết các hafmg mà Laravel cung cấp cho bạn khi cập nhật chỉnh sửa hay xóa cột trong bảng bạn có thế tìm kiếm ở đây. - Bằng việc sử dụng migration, khi bạn tạo mới hay chỉnh sửa CSDL thì thay vì bạn phải sửa thủ công trong CSDL sau đó lại báo lại với các thành viên khác và hướng dẫn họ sửa theo bạn thì bạn chỉ cân đưa họ file migration có chứa chỉnh sửa mà bạn viết để các thành viên chạy lên và các thay đổi hoàn toàn được đồng bộ giữa mọi người.
3. Chạy file migration
- Sau khi đã định nghĩa xong cấu trúc cũng như quan hệ giữa các bảng với nhau trong CSDL, bạn gõ lệnh:
$ php artisan migrate
và đây là kết quả chúng ta thu được sau khi chạy lệnh Các file migration sẽ lần lượt được chạy theo thứ tự bạn tạo cho đến hết nếu không có lỗi gì.
- Để tiến hành biến những bảng trong file migration bạn đã tạo thành các bảng trong CSDL mà bạn kết nối tới. Lưu ý để chạy lệnh này bạn cần chỉnh sửa phần khai báo CSDL trong file
.env
và đảm bảo các bảng có sử dụng quan hệ khóa ngoại được tạo sau các bảng cha của nó. Đây là kết quả khi chúng ta mở CSDL bằng Workbench lên xem: Ngoài các các bảng mà chúng ta tạo từ file migration, có thể thấy xuất hiện thêm một bảng tên làmigrations
, đây chính là bảng dùng để quản lý các phiên bản cho CSDL của bạn cho mỗi lần chạy lệnh, nó bao gồm 1 cột id, 1 cột chứa tên file và cuối cùng là cộtbatch
chứa lần chạy lệnhmigrate
mà file đó được thực hiện
Như ví dụ trên 4 hàng đầu tiên thể hiện file migration được chạy ở lần thứ nhất, dòng thứ 5 là thể hiện file migration được tạo và chạy sau 4 file đó nên nó có batch
là 2. Các file tiếp theo được thêm vào khi chạy lệnh sẽ lần lượt là 3, 4, ...
- Như trong hình ở trên mình cung cấp về nội dung file migration sẽ có hai hàm là
function up()
vàfunction down()
. Vớifunction down()
sẽ là các lệnh dùng để đảo ngược những định nghĩa hay chỉnh sửa trongfunction up()
. Đối với thao tác tạo mới bảng thì mặc địnhfunction down()
của các bạn sẽ là xóa bảng đó đi, còn trong trường hợp bạn chỉnh sửa bảng thì bạn cần tự thêm code vàofunction down()
này để nó chạy ngược lại vớifunction up()
. - Sở dĩ bạn cần định nghĩa
function down()
là vì ngoài lệnhphp artisan migrate
, Laravel còn cung cấp cho chúng ta các lệnh khác là:
$ php artisan migrate:rollback
Với lệnh này, toàn bộ file có batch
mới nhất trong bảng migration
sẽ được thực hiện function down
của nó hay chính xác hơn là đảo ngược lại thay đổi mà nó tạo ra cho CSDL. Nếu bạn không định nghĩa nội dung cho function down
thì mặc dù trong bảng migration đã rollback file migration đó nhưng thực chất nó vẫn tồn tại trong CSDL hay nói cách khác lệnh rollback là vô dụng. Ngoài việc rollback từng batch
một, bạn có thể tiến hành rollback nhiều batch
cùng lúc bằng lệnh:
$ php artisan migrate:rollback --step=n
Với n là số lượng batch
bạn muộn rollback. Ví dụ bạn đang có các batch
cho các lần migrate khác nhau là 1, 2, 3, 4, 5. Khi chạy lệnh trên với n = 2 thì trong migration sẽ chỉ còn lại batch
1, 2, 3. Cuối cùng, nếu bạn muốn rollback toàn bộ thì sẽ dùng lệnh sau:
$ php artisan migrate:reset
Lệnh trên sẽ rollback toàn bộ CSDL của bạn hay đúng hơn là chạy toàn bộ function down()
trong các file migration của bạn. Cuối cùng chúng ta có lệnh:
$ php artisan migrate:refresh
Lệnh này nhằm rollback toàn bộ CSDL đồng thời chạy lại luôn toàn bộ các file migrate của bạn.
Seeder
Sau khi đã đã có CSDL, việc tiếp theo bạn có thể cần làm đó là thêm một số dữ liệu mẫu trước khi bắt đầu thực hiện việc code các tính năng. Như đã nói trên việc các bạn thêm dữ liệu mẫu thủ công tốn rất nhiều công sức và nếu làm viêc team bạn lại mất công export thành file .sql và đưa cho thành viên khác của team nếu không mỗi thành viên lại phải tự tạo dữ liệu thì lại càng mất thời gian. Để giải quyết vấn đề này, Seedẻr cung cấp cho bạn các phương thức đơn giản để tạo ra dữ liệu mẫu bạn cần cho việc phát triển các tính năng.
1. Các file seeder
- Trong một project Laravel các file seeder được lưu trong thư mục
database/seeds
, Nghĩ là khi bạn tạo mới một file seeder thì nó sẽ được lưu hết vào đây. Các file seeder này có nhiệm vụ thêm dữ liệu mẫu vào trong CSDL của bạn sau khi tạo.
- Ban đầu thư mục này sẽ chưa một file tên là
DatabaseSeeder.php
, đây chính là file gốc được chạy khi ta thực hiện lệnh thêm dữ liệu (sẽ được nói ở dưới). Các file seeder nói chung chỉ có duy nhất một function làrun()
, hàm này sẽ dùng để thêm dữ liệu vào CSDL. Nội dung fileDatabaseSeeder.php
:
- Ở trên chính là dữ liệu mẫu mà chúng ta muốn thêm được vào CSDL, tuy nhiên nó vẫn khác là thủ công vì ta vẫn phải gõ tay dữ liệu và thông thường ta sẽ không thêm trực tiếp dữ liệu cho bảng trực tiếp trong file
DatabaseSeeder.php
như thế này mà thay vào đó ta sẽ tạo các file seeder cho từng bảng rồi gọi nó trong fileDatabaseSeeder.php
, cụ thể khi áp dụng cách này file của chúng ta sẽ như sau:
Lưu ý dữ liệu thêm vào CSDL cần được sắp xếp theo đúng thứ tự phù hợp như nếu sử dụng khóa ngoại thì bảng cha cần được chạy trước
Lúc này ta sẽ sử dụng hàm call để gọi đến các class Seeder khác dùng cho từng bảng trong CSDL, nội dung các class Seeder này cũng giống như nội dung class DatabaseSeeder.php
ở ảnh trước kia. Ví dụ class UserTableSeeder:
Để thêm đồng thời nhiều giữ liệu, ta có thể sử dụng truyền vào nhiều mảng cho hàm insert, tuy nhiên nếu bạn muốn dữ liệu độc đáo hơn và có nhiều lựa chọn hơn cho các dạng email, ngày sinh, tên, đoạn văn thì bạn nên dùng 1 package có sẵn trong Laravel tên là Faker.
2. Tạo các file seeder
- Để tạo các file seeder cho các bảng, ta dùng lệnh:
$ php artisan make:seeder <seeder-class-name>
Sau khi thực hiện lệnh trên sẽ tạo cho ta 1 file và 1 class trong file đó giống với tên mà ta đã đặt ở trên. Bên trong class này cũng có một function run()
rỗng đợi để được chúng ta định nghĩa, giả sử ta tạo dữ liệu mẫu cho bảng users
cùng với 3 cột là name, email, password và muốn tạo 10 bản ghi thì file seeder của chúng ta lúc này sẽ như sau:
Ở đây ta đang dùng Faker để tạo dữ liệu mẫu theo từng cột. Tuy nhiên nhìn vào cách làm trên, bạn sẽ thấy nếu muốn tạo dữ liệu nhiều hơn chả nhẽ ta sẽ đi copy đủ số lượng record ta muốn như 100, 1000. Để giải quyết vấn đề này, ta có thể sử dụng khái niệm tên là ModelFactory
. Trong folder database
ta sẽ thấy còn có một folder nữa là factories
, bên trong folder này có 1 file tên là ModelFactory.php
dùng để định nghĩa cấu trúc của dữ liệu mẫu mà ta muốn thêm vào CSDL theo từng bảng:
Lưu ý để dùng được model factory thì trước đó ta cần tạo các Model cho các bảng trong CSDL
Sau khi định nghĩa cấu trúc của một record nằm trong bảng users
ứng với model User
thì lúc này trong file UserTableSeeder.php
ta có thể sửa lại thành như sau:
Như bạn thấy, do chúng ta đã định nghĩa cấu trúc của 1 record cho model User
bằng fatory nên ta chỉ đơn giản dùng cú pháp như trên đi kèm với số lượng bản ghi muốn tạo là xong. Ngắn gọn và hiệu quả hơn nhiều so với việc copy đủ số lượng record trong hàm insert .
3. Chạy filder seeder
- Để tiến hành chạy file seeder và thêm dữ liệu vào CSDL ta thực hiện lệnh sau:
$ php artisan db:seed
Lệnh trên sẽ tiến hành chạy nội dung file DatabaseSeeder.php
theo hàm run được khai báo trong đó. Trong trường hợp bạn muốn chạy một file Seeder cụ thể thì ta thực hiện lệnh sau:
$ php artisan db:seed --class=UserTableSeeder
Sẽ chạy duy nhất file UserTableSeeder
Kết bài
Mong rằng qua bài viết này, bạn hiểu được phần nào về cách sử dụng cũng như điểm hay mà 2 tính năng migration
và seeder
trong Laravel. Hẹn gặp lại bạn trong các bài viết sau.
All rights reserved