Thao Tác Với Migrations Và Seeding Trên Laravel

Thao Tác Với Migrations Và Seeding Trên Laravel

Ở phần trước chúng ta đã cùng nhau cấu hình và chạy laravel trên LEMP STACK. Ở phần tiếp theo này chúng ta sẽ cùng nhau thao tác với dữ liệu thông qua migration và seeder nhé.

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 1 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 các phần mềm như PHPMyAdmin, Workbench hoặc Navicat để 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.Với Laravel mọi thứ trở lên đơn giản hơn với các công cụ như Laravel Migrate, Laravel Seeding và các lớp được xây dựng sẵn như Schema, Factory. Cơ sở dữ liệu cũng giống như mã nguồn cần được quản lý phiên bản và Laravel đã đưa ra một cách xử lý hết sức tinh tế cho công việc thật sự khó khăn này.

Các bạn có thể cài các phần mềm PHPMyAdmin, Workbench hoặc Navicat để dễ dàng thao tác, còn trong khuôn khổ bài viết này mình sẽ hướng dẫn các bạn thao tác bằng terminal:

1. Thao tác trên MySql Server

Để đăng nhập vào MySql Server ta dùng lệnh sau:

mysql -u root -p

Sau khi đăng nhập vào MySql Server bạn có thể tạo cơ sở dữ liệu bằng lệnh sau:

create database demo;

ở đây mình tạo 1 database có tên là demo

Sử dụng lệnh sau để thiết lập đầy đủ các quyền cho user root

grant all on demo.* to [email protected];

trong đó all chính là quyền của user root trên database demo, các bạn cũng có thể thiết lập quyền cho user theo danh sách sau đây:

ALL

ALTER

CREATE VIEW

CREATE

DELETE

DROP

GRANT OPTION

INDEX

INSERT

SELECT

SHOW VIEW

TRIGGER

UPDATE

Và liệt kê lại cho chắc chắn:

show databases;

Như vậy là khá đầy đủ, giờ chúng ta mở 1 IDE lên và viết code thôi nào, let'go!

2. Kết nối database

Đầu tiên chúng ta sẽ kết nối project với cơ sở dữ liệu bằng cách mở file .env và sửa như sau

DB_DATABASE=demo

DB_USERNAME=root

DB_PASSWORD=

3. Migration

Bây giờ đến phần chính đấy là Migration.

Migration 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.

Bạn có thể đọc thêm về migrations ở đây nhé.

Chúng ta sử dụng terminal để tạo 1 bảng products mới trong cơ sở dữ liệu bằng câu lệnh sau:

php artisan make:migration create_table_ products_table --create=products

Khi ta nhấn enter thì ngay lập tức trong file sẽ được tạo trong folder database/migration 1 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 bảng products mà bạn chọn ở trên và nội dung của file sẽ như sau:

<?php

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;

class CreateProductsTable extends Migration

{

    /**

     * Run the migrations.

     *

     * @return void

     */

    public function up()

    {

        Schema::create('products', function (Blueprint $table) {

            $table->increments('id');

            $table->timestamps();

        });

    }

    /**

     * Reverse the migrations.

     *

     * @return void

     */

    public function down()

    {

        Schema::dropIfExists('products');

    }

}

Để thêm các trường của bảng products trong CSDL ta sẽ thêm vào function up() trong file migration.

public function up()
{
     Schema::create('products', function (Blueprint $table) {
           $table->increments('id'); // cột id có kiểu là interger và tự động tăng
           $table->string('name',150); // cột name có kiểu là varchar và giới hạn là 150 ký tự
           $table->text('description')->nullable(); // cột description có kiểu là text và có thể để NULL
           $table->integer('price'); // cột price có kiểu là integer
           $table->string('image',255); // cột image có kiểu là varchar và giới hạn là 255 ký tự
           $table->timestamps(); // cột thể hiện timestamps mặc định
     });
}

File migration chứa Migration class với hai phương thức up()down(), phương thức up() sử dụng để thêm các bảng, cột hoặc tạo một index cho cột nào đó trong CSDL. Phương thức down() sử dụng để làm những việc ngược lại với phương thức up().

Như vậy, thông qua các Schema chúng ta không cần thao tác trực tiếp với database.

Khi tạo bảng có thể bảng đó đã tồn tại, chúng ta cần kiểm tra trước khi tạo, tương tự với các cột trong bảng thông qua các phương thức hasTable()hasColumn():

if (!Schema::hasTable('products')) {
        Schema::create('products', function (Blueprint $table) {
           $table->increments('id'); // cột id có kiểu là interger và tự động tăng
           $table->string('name',150); // cột name có kiểu là varchar và giới hạn là 150 ký tự
           $table->text('description')->nullable(); // cột description có kiểu là text và có thể để NULL
           $table->integer('price'); // cột price có kiểu là integer
           $table->string('image',255); // cột image có kiểu là varchar và giới hạn là 255 ký tự
           $table->timestamps(); // cột thể hiện timestamps mặc định
        });
}

if (Schema::hasColumn('products', 'product_info')) {
    //
}

Sau đó để tạo bảng trong CSDL thì chúng ta sẽ dùng câu lệnh thần thánh:

php artisan migrate

Rất đơn giản phải không nào.

Các migration file có thể ảnh hưởng đến cấu trúc database hiện tại, do đó khi chạy lệnh trên có thể nó sẽ thông báo xác nhận chạy hay không, để ép buộc chạy migration mà không hiển thị thông báo sử dụng thêm tùy chọn –force

php artisan migrate --force


Trong quá trình migration có thể bạn muốn quay trở lại cấu trúc CSDL trước lúc thực thi các migration, hoàn toàn có thể được bằng cách sử dụng rollback và reset.
Rollback thì cần cung cấp thêm tùy chọn –step là rollback lại bao nhiêu lần, còn reset sẽ đưa cấu trúc CSDL về thời điểm chưa có bất kỳ một migration nào.

php artisan migrate:rollback --step=3
php artisan migrate:reset

Ngoài ra, Laravel còn cung cấp migrate:refresh, đúng như tên gọi của nó, lệnh ra rollback toàn bộ các migrate và sau đó chạy lại lệnh migrate, tức là tương đương hai lệnh sau chạy lần lượt:

php artisan migrate:reset
php artisan migrate

4. Seeder

Khi tạo bảng xong rồi mà chưa có dữ liệu, thay vì cách nhập tay thủ công thông thường vừa tốn thời gian vừa tốn công mà rất nông dân thì Laravel đã hỗ trợ chúng ta Seeder để nhanh chóng tạo dữ liệu.

Các bạn có thể tìm hiểu seeder thêm ở đây nhé.

À quên mất chúng ta còn phải tạo model Product đã chứ nhỉ:

php artisan make:model Product

Khai báo table cần sử dụng trong Model Product vừa tạo bằng cách thêm:

protected $table='products';

kết quả sẽ như sau:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
          protected $table = 'products';
}

Giờ đây chúng ta muốn có khoảng 100 records trong bảng products. Có nhiều các để thêm 100 records hoặc có thể là 1000 records nay tuy nhiên trong bài viết này mình sẽ sử dụng factory cùng với thư viện faker để tạo dữ liệu mẫu.

Để tạo factory ta dùng lệnh:

php artisan make:factory ProductFactory

Bên trong folder database/factories này có sẽ xuất hiện thêm 1 file tên là ProductFactory.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 bảng product.

<?php

use Faker\Generator as Faker;

$factory->define(\App\Product::class, function (Faker $faker) {

    return [

        'name' => $faker->name, // faker sẽ ramdom cho bạn những cái tên

        'description' => $faker->text, // // faker sẽ ramdom cho bạn những cái đoạn text

        'price' => $faker->numberBetween(100000,2000000), // faker sẽ ramdom number trong khoảng 100000 đến 2000000.

        'image' => $faker->imageUrl($width = 200,$height = 300,'',true,'Faker'), // faker sẽ ramdom cho bạn đường link chưa ảnh,các bạn có thể tùy biến width và height cho ảnh.

        'created_at' => new DateTime(), // ngày giờ hiện tại.

        'updated_at' => new DateTime()

    ];

});

ở đây mình sử dụng faker để tạo dữ liệu mẫu, các bạn có thể tìm hiểu faker sâu hơn ở đây nhé.

kế tiếp để tạo một seed ta dùng lệnh:

php artisan make:seed ProductTableSeeder

Bên trong folder database/seeds này có sẽ xuất hiện thêm 1 file tên là ProductTableSeeder.php

mở fle này lên,trong hàm run ta chỉ cần gọi factory(tên_lớp_model, số_lượng)->create()

<?php

use Illuminate\Database\Seeder;

class ProductTableSeeder extends Seeder
{
  /**
  * Run the database seeds.
  *
  * @return void
  */
  public function run()
  {
         factory(\App\Product::class,100)->create(); // gọi lớp model Product và số lượng 100 records
  }
}

Bây giờ để gọi Seeders thì ta mở file database/seeds/DatabaseSeeder.phpcall các lớp seed khác trong hàm run().

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
         $this->call(ProductTableSeeder::class); // gọi lớp seed ProductTableSeeder
    }
}

Cuối cùng trước khi chạy bạn nên load lại các file sử dụng bằng câu lệnh:

composer dump-autoload

Để chạy tất cả các file được call trong lớp DatabaseSeeder ta sử dụng:

php artisan db:seed

Chỉ định seed một lớp được chỉ định

php artisan db:seed --class=ProductsTableSeeder.

Để xóa tất cả các bảng sau đó chạy lại các bảng và seed:

php artisan migrate:fresh --seed

Tèn tén, vậy là chúng ta đã làm xong cơ sở dữ liệu bằng cách sử dụng Migration, Seed, với thư viện Faker cho phép tạo những dữ liệu mẫu đúng với thực tế hơn.

Phần tiếp theo

Ở phần kế tiếp chúng ta sẽ cùng nhau tìm hiểu và xây dựng RESTful API với Laravel dựa trên table products này luôn nhé. Chúc các bạn thành công!