Quản trị database với Migration, Seeder, Eloquent

A.   Migration

Trong Laravel, migration giúp bạn quản lý, lưu trữ cấu trúc database, nó cũng giúp bạn sửa database dễ dàng.

Mỗi migration được lưu trong 1 file, các file migrations lưu trong folder App\database\migrations

1.      Tạo migrations

Đễ tại một migration, dùng công cụ artisan như sau:

Tạo migrations để create 1 table :

php artisan make:migration TenMigrate --create=TableName

Tạo migrations để sửa 1 bảng.

php artisan make:migration TenMigrate --table=TableName

Ví dụ:  Tạo 1 migration có tên là taobangsp, migration này có tác dụng tạo 1 table tên sanpham

php artisan make:migration taobang_sp --create=sanpham

Kết quả: bạn sẽ có file App\database\migrations\xxx_taobang_sp.php

Cấu trúc file mirgration:

– Mở file xxx_taobang_sp.php vừa tạo, bạn sẽ thấy thế này:

up() {
        Schema::create('sanpham', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }
    public function down() {
        Schema::dropIfExists('sanpham');
    }
}

Còn file xxx_chinhbanguser.php cũng tương tự thế này

Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class Chinhbanguser extends Migration{
    public function up()  {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
    public function down()  {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
}

Trong file migration, bạn thấy có sẵn 2 hàm up down.  Hàm up để thực thi migration. Hàm down có tác dụng thực thi rollback (trở về trước đó).

Ví dụ :  để tạo bảng sanpham với các cột:  id (khóa chính tự động tăng), tensp (kiểu varchar), gia ( kiểu int), urlhinh (kiểu varchar) thì sửa trong hàm up để được như sau:

Schema::create('sanpham', function (Blueprint $table) {
   $table->increments('id');
   $table->string('tensp',30)->unique();
   $table->float('gia',8,2);
   $table->string('urlhinh',100);
});

2.      Thực thi (chạy) 1 migration

php artisan migrate --path=database/migrations/tênfileMigration.php

Sau khi thực thi xong bạn xem trong database sẽ thấy table sanpham như sau

3.      Các lệnh thực thi migration

php artisan migrate Chạy tất cả file  migration
php artisan migrate –path=database/migrations/my_migration.phpChạy 1 file migration chỉ định
php artisan migrate:resetReset migration , tức chạy hàm down trong file migration
php artisan migrate:refeshChạy lại migration. Lệnh này = tổng 2 lệnh reset và chạy migration.
php artisan migrate:statusXem trạng thái của các file migration đã chạy
php artisan migrate:installTạo table migrations trong database của bạn để ghi nhận trạng thái chạy các file migration

4.      Các lệnh trong migration

LệnhChức năng
$table->bigIncrements('id');Tạo cột id khóa chính tự động tăng kiểu bigint
$table->bigInteger('votes');Tạo cột votes với kiểu bigint
$table->binary('data');Tạo cột data với kiểu blob
$table->boolean('confirmed');Tạo cột confirmed với kiểu boolean
$table->char('name', 4);Tạo cột name với kiểu char tối đa 4 kí tự
$table->date('created_at');Tạo cột created_atvới kiểu date
$table->dateTime('created_at');Tạo cột created_atvới kiểu dateTime
$table->dateTimeTz('created_at'); Tạo cột name với kiểu DATETIME (with timezone)
$table->decimal('amount', 5, 2); Tạo cột name với kiểu DECIMAL
$table->double('column', 15, 8);Tạo cột name với kiểu DOUBLE
$table->enum('choices', ['foo', 'bar']);ENUM equivalent for the database.
$table->float('amount', 8, 2);FLOAT equivalent for the database, 8 digits in total and 2 after the decimal point.
$table->increments('id');Incrementing ID (primary key) using a “UNSIGNED INTEGER” equivalent.
$table->integer('votes');INTEGER equivalent for the database.
$table->json('options');JSON equivalent for the database.
$table->jsonb('options');JSONB equivalent for the database.
$table->longText('description');LONGTEXT equivalent for the database.
$table->macAddress('device');MAC address equivalent for the database.
$table->mediumIncrements('id');Incrementing ID (primary key) using a “UNSIGNED MEDIUM INTEGER” equivalent.
$table->mediumInteger('numbers');MEDIUMINT equivalent for the database.
$table->mediumText('description');MEDIUMTEXT equivalent for the database.
$table->morphs('taggable');Adds unsigned INTEGER taggable_id and STRING taggable_type.
$table->nullableTimestamps();Same as timestamps().
$table->rememberToken();Adds remember_token as VARCHAR(100) NULL.
$table->smallIncrements('id');Incrementing ID (primary key) using a “UNSIGNED SMALL INTEGER” equivalent.
$table->smallInteger('votes');SMALLINT equivalent for the database.
$table->softDeletes();Adds nullable deleted_at column for soft deletes.
$table->string('email');VARCHAR equivalent column.
$table->string('name', 100);VARCHAR equivalent with a length.
$table->text('description');TEXT equivalent for the database.
$table->time('sunrise');TIME equivalent for the database.
$table->tinyInteger('numbers');TINYINT equivalent for the database.
$table->timestamp('added_on');TIMESTAMP equivalent for the database.
$table->timestampTz('added_on');TIMESTAMP (with timezone) equivalent for the database.
$table->timestamps();Adds nullable created_at and updated_at columns.
$table->timestampsTz();Adds nullable created_at and updated_at (with timezone) columns.
$table->uuid('id');UUID equivalent for the database.
$table->renameColumn(‘from’, ‘to’);Đổi tên cột
$table->dropColumn(‘TênColumn’);Xóa cột
$table->string(‘name’, 50)->change();Chỉnh thuộc tính của cột
Schema::rename($from, $to);Đổi tên table
Schema::drop(‘users’);
Schema::dropIfExists(‘users’);
Xóa table/xóa table nếu tồn tại
Schema::hasTable(‘users’)Kiểm tra 1 table có tồn tại không. Cho true nếu table users tồn tại
$table->charset = ‘utf8’;Chỉ định charset cho table
$table->engine = ‘InnoDB’;Chỉ định kiểu lưu trữ cho table
$table->collation = ‘utf8_unicode_ci’;Chỉ định collation cho table
$table->foreign(‘user_id’)
->references(‘id’)->on(‘users’);
Tạo khóa ngoại

B.    Seeder

Khi tạo xong database, bạn phải tạo một số lượng dữ liệu để hiển thị lên website, thay vì nhập tay thủ công tốn thời gian và công sức thì Laravel hỗ trợ công cụ Seeder để nhanh chóng tạo dữ liệu.

Các file seed được đặt trong fodler /database/seeds. Trong folder này, Laravel đã tạo sẵn 1 file có tên DatabaseSeeder.php để bạn sử dụng (nếu muốn)

Tạo file seeder

Để tạo 1 file seeder có tên chenspham, bạn dùng lệnh như sau:

php artisan make:seeder chenspham

Kết quả bạn sẽ có file database/seeds/chenspham.php như sau:

use Illuminate\Database\Seeder;
class chenspham extends Seeder {
    public function run()     {
        //
    }
}

Thực thi file seeder

php artisan db:seed  => Thực thi file DatabaseSeeder.php

php artisan db:seed –class=chenspham =>  thực thi file seeder chỉ định

Chèn dữ liệu vào table bằng Seeder

Cách 1: Viết lệnh chèn trong hàm run của file DataTableSeeder.php

DB::table('sanpham')->insert([
    ['tensp' => 'Sam sung A9','gia'=>150000,'urlhinh'=>''],
    ['tensp' => 'HTC M10','gia'=>140000,'urlhinh'=>''],
    ['tensp' => 'Galaxy ','gia'=>50000,'urlhinh'=>''],
]);

Cách 2: Viết lệnh chèn trong 1 class và sử dụng hàm hàm call() trong function run()

use Illuminate\Database\Seeder;
class chenspham extends Seeder {
    public function run()    {
       $this->call('taosp');
    }
}
class taosp extends Seeder{
    public function run(){
         DB::table('sanpham')->insert([
            ['tensp' => 'Oppo F11','gia'=>720000,'urlhinh'=>''],
            ['tensp' => 'Iphone xs Max','gia'=>290000,'urlhinh'=>''],
            ['tensp' => 'Nokia 8.1','gia'=>8900,'urlhinh'=>''],
         ]); 
    }
}

Tạo hàng loại dữ liệu (viết trong hàm run )

for($i=0;$i<100; $i++ ){
  DB::table('sanpham')->insert([
       ['tensp' => 'Oppo XA ' . $i,'gia'=>mt_rand(700000, 1000000),'urlhinh'=>''],
       ['tensp' => 'Iphone xs Max ' . $i,'gia'=>mt_rand(500000, 800000),'urlhinh'=>''],
       ['tensp' => 'Nokia Pro ' . $i, 'gia'=>mt_rand(250000, 500000),'urlhinh'=>''],
   ]);   
 }//for

Chèn dữ liệu ngẫu nhiên

use Illuminate\Support\Str;
class taouser extends Seeder{
    public function run(){
         for($i=0;$i<10; $i++ ){
         DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(5).'@gmail.com',
            'password' => bcrypt('hehe'),
        ]);
         }//for
    }
}

C.   Sử dụng Eloquent ORM

1. ORM là gì?

ORM (Object Relational Mapping) là một kỹ thuật dùng để chuyển đổi dữ liệu giữa một hệ thống không hướng đối tượng như CSDL sang hệ thống hướng đối tượng như PHP.  Kỹ thuật này giúp tạo ra các đối tượng CSDL ảo có thể được lập trình trong mã nguồn và có nhiều ưu điểm như mã nguồn trở lên rõ ràng và dễ bảo trì, dễ dàng thao tác với dữ liệu…

Eloquent ORM trong Laravel là thư viện giúp bạn thao tác dễ dàng với các table trong database. Mỗi table sẽ có 1 model tương ứng đễ tương tác xử lý dữ liệu. Thông qua model của mỗi table, bạn có thể thêm record vào table, chỉnh sửa record, xóa record rất dễ dàng.

Cấu hỉnh các thông số database cho Eloquent trong file config/database.php

2. Tạo Model

Với Eloquent tromg Laravel, mỗi table có 1 model tương ứng, các thao tác tương tác với table sẽ được thực hiện trên Model. Như select, insert, update… Model có thể được tạo thủ công hoặc tạo thông qua artisan như sau:

php artisan make:model tin

=> sẽ tạo file tin.php trong folder app . File tin.php sẽ có cấu trúc như sau:

namespace App;
use Illuminate\Database\Eloquent\Model;
class tin extends Model {

 }

Nếu model này liên kết với table có tên là tin và khóa chính là idTin thì bạn cần khai báo thêm trong class:

protected $table='tin';
    protected $primaryKey='idTin';
 }

Một số mặc định của Eloquent Model

Mặc định, mỗi model được map với 1 table trong database có tên giống như tên model ở dạng số nhiều trong tiếng Anh (thêm s hoặc ies),  còn được gọi là tiêu chuẩn đặt tên Snake case.

Ví dụ model Product sẽ map với table products , model tin sẽ map với table tins . Nếu bạn muốn bỏ mặc định này để map model sang table khác thì sử dụng thuộc tính $table để khai báo.

namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model{
    protected $table = 'sanpham';
    public $primaryKey = 'idSP';
    public $incrementing = false;
public $timestamps = false
}

Eloquent Model mặc định xem field có tên  id là khóa chính, nếu table của bạn sử dụng field khác làm khóa chính thì khai báo qua thuộc tính $primaryKey. Khóa chính – nếu không phải là dạng số và tăng tự động thì cần thiết lập $incrementing = false.

Eloquent mặc định sẽ ghi nhận thời gian tạo và cập nhật các record trogn table, do đó trong table của bạn phải có các field created_atupdated_at để lưu thời gian tạo record và thời gian cập nhật. Tính năng này giúp bạn quản lý các record trong CSDL rất tốt. Nếu không muốn tính năng này, hãy thiết lập thuộc tính $timestamps = false.

Sử dụng Eloquent Model tương tác với database

Với mỗi model, bạn có 4 hành động:

  • Create: tạo model, tức tạo 1 record trong bảng.
  • Read: truy vấn dữ liệu từ database
  • Update: chỉnh sửa 1 record.
  • Delete: là xóa 1 record dữ liệu.

Gọi Model

Gọi model trong Route thì dùng cú pháp:   App\tenmodel::something;  
Ví dụ:

Route::get('tatcatin/', function(){  
    $kq = App\tin::all();
    print_r($kq);
});

Để gọi model trong controller thì use namespace của model đó trong controller. Ví dụ: gọi model tin trong homecontroller.

use App\tin;
class HomeController extends Controller {
    public function elo(){
         $kq = tin::all();
         print_r($kq);
    }
}

  Routing

Route::get('el', 'homeController@elo');

Lấy ra tất cả dữ liệu trong bảng.

tin::all();

Lấy ra một dòng dữ liệu của table

tin::find(1);

Lấy dữ liệu theo điều kiện.

tin::where('idLT',12)->get();
tin::where('idTin','<',5)->get();
tin::where('TinNoiBat','=',1)->get();
tin::where('TinNoiBat','=',1)->where('lang','en')->get();

Lấy dữ liệu có chọn cột dữ liệu.

tin::select('idTin','TieuDe')->where('SoLanXem','>',500)->get();

Đếm dữ liệu.

tin::all()->count();

Chèn dữ liệu vào bảng

$n = new tin();
$n->TieuDe="Hoàng hôn trên sông Hồng";
$n->tags='hoàng hôn, sông hồng';
$n->Ngay='2019-05-04';
$n->idLT=1;
$n->save();
echo "Đã chèn xong";

Sửa dữ liệu.

$t = tin::find(802);
$t->TieuDe = 'Hoàng hôn trên sông Cửu Long';
$t->save();
echo "Đã cập nhật xong";

hoặc

tin::where('idTin',802)->update(['TieuDe'=>'Hoàng hôn trên sông Tiền']);

Xóa dữ liệu trong table dùng Eloquent – dùng hàm delete

$n = tin::find(802);
$n->delete();
hoặc
tin::where('idTin',783)->delete();

Xóa dữ liệu trong table dùng Eloquent – dùng hàm destroy

tin::destroy(802);
tin::destroy(788,787);
tin::destroy([1,2,3]);
tin::destroy(array(784,785,786));