FuelPHP: Làm việc hiệu quả với cơ sở dữ liệu thông qua migrations, generate migration và DBUtil

Migrations

  • Migrations giúp quản lý, control database một cách dễ dàng. Bạn có thể sử dụng migration để chỉnh sửa database cả về cấu trúc lẫn dữ liệu. Khi sử dụng migration để thay đổi database sẽ giúp cho các dev trong cùng dự án hay trong quá trình maintain có thể tường minh về database. Khi bạn là một dev phát triển dự án cùng nhiều người khác, bạn có thay đổi database, bạn chỉ cần tạo migration và thông báo với những bên liên quan biết bạn đã thay đổi và thông báo họ chạy lệnh run command line để thay đổi database sao cho đồng bộ. Khi tạo migration, migration sẽ giống như một nhân chứng cho việc thay đổi của bạn.
  • Khi sử dụng migration, trong databse của bạn sẽ có một bảng là bảng "migration" theo dõi các migration đã được chạy vì vậy bạn chỉ cần cập nhật các tệp ứng dụng của mình và gọi Migrate :: current () để tìm ra các migration nào cần được chạy. Phiên bản hiện tại được tìm thấy trong tệp tin core/config/migration.php vì vậy bất kỳ tệp cấu hình nào khác bạn nên sao chép tệp này lên app/config để thực hiện thay đổi.

Configuration

  • Để chạy lệnh migration kết nối với database, ta cần config để app biết đang kết nối đến database nào. Trong FuelPHP chúng ta có thể tìm và cấu hình trong folder /fuel/app/config/.../db.php
  • Các thông số cần config có: hostname, port, database, username, password (mặc định default chính là mysqli, tuy nhiên chúng ta có thể thay đổi tùy theo yêu cầu). Ví dụ:
<?php
return array(
        'default' => array(
                'type' => 'mysqli',
                'connection'  => array(
                        'hostname' => 'localhost',
                        'port' => '3306',
                        'database' => 'demo',
                        'username'   => 'root',
                        'password'   => '000000',
                ),
        ),
);
  • Trong FuelPHP, chúng ta sẽ tạo migration tại folder /fuel/app/migrations/

Lưu ý: Sau khi migrations đã được chạy, file config sẽ được viết lại với thông tin vừa thay đổi. Những số phiên bản này được sử dụng nội bộ và không nên thay đổi.

Creating a Migration

Tạo file trong folder app/migrations. Tiền tố phải là số gia tăng bắt đầu từ 001, không bỏ qua số và không có hai số trùng nhau. Ví dụ tạo migration đầu tiên sẽ giống như app/migrations/001_example.php.

namespace Fuel\Migrations;

class Example
{

    function up()
    {
        \DBUtil::create_table('posts', array(
            'id' => array('type' => 'int', 'constraint' => 5),
            'title' => array('type' => 'varchar', 'constraint' => 100),
            'body' => array('type' => 'text'),
        ), array('id'));
    }

    function down()
    {
       \DBUtil::drop_table('posts');
    }
}

Run a Migration

Migration có thể được thực hiện bằng hai cách:

  1. Migrate class
  2. Oil Refine Command Oil command sử dụng Refine Command để gọi migrate
$ php oil refine migrate
$ php oil refine migrate:current
$ php oil refine migrate:up
$ php oil refine migrate:down
$ php oil refine migrate --version=10

Migration cũng được hỗ trợ cho module và package. Bạn có thể chỉ định trên dòng lệnh lệnh dầu nếu bạn muốn migrate tất cả, hoặc chỉ các module and/or package cụ thể. Nếu làm vậy, ta có thể sử dụng '--default' để cho ta biết ta muốn bao gồm app migrations nào.

$ php oil refine migrate -all
$ php oil refine migrate --modules=module1,module2 --packages=package1
$ php oil refine migrate:up --packages=package1
$ php oil refine migrate:down --modules=module1,module2 --default
$ php oil refine migrate --version=10

Lưu ý: Tác vụ migrate:current là để khớp schema của bạn với phiên bản được liệt kê trong fuel/[app|core]/config/migrate.php như thể bạn vừa nhận được một bản sao của ứng dụng, migration mới nhất không phải là một được coi là ổn định. Sử dụng oil để migrate sẽ sửa đổi migration config number này để lệnh hiện tại sẽ không có liên quan trong nhiều tình huống.

Generating Migrations

Bạn có thể tạo ra migration mà không cần tạo model. Điều này có thể được sử dụng để đổi tên một bảng, hoặc thêm các trường vào một bảng trong một cách mà dễ triển khai trong các môi trường khác.

$ php oil generate migration rename_table_users_to_accounts
    Building magic migration: rename_table
    Created migration: APPPATH/migrations/002_rename_table_users_to_accounts.php

Magic Migrations

Có một số Magic Migrations tự động tạo một migration dựa trên tiền tố cho tên migration của bạn.

$ php oil generate migration create_users name:text email:string[50] password:string[125]
$ php oil generate migration rename_table_users_to_accounts
$ php oil generate migration add_bio_to_accounts bio:text
$ php oil generate migration delete_bio_from_accounts bio:text
$ php oil generate migration rename_field_name_to_username_in_accounts
$ php oil generate migration drop_accounts

Lưu ý: Cẩn thận khi đặt tên migration của bạn mà bạn không bắt đầu bất kỳ từ khóa nào một cách ngẫu nhiên.

DBUtil Class

DBUtil class cho phép bạn quản lý và thực hiện các hoạt động thường xuyên trên cơ sở dữ liệu của bạn.

  • Managing functions: DBUtil cho phép bạn tạo, đổi tên, thay đổi và xóa các trường cơ sở dữ liệu.

create_database($database, charset = null, $if_not_exists = true, $db = null)

Phương thức create_database tạo một cơ sở dữ liệu. Sẽ ném một Database_Exception nếu nó không thể. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

// Create a database named `my_database`
DBUtil::create_database('my_database');

// Catch the exception
try
{
    DBUtil::create_database('my_database');
}
catch(\Database_Exception $e)
{
    // Creation failed...
}

// You can also set a default charset.
// CREATE DATABASE IF NOT EXISTS `new_database` DEFAULT CHARACTER SET 'utf8'
DBUtil::create_database('new_database', 'utf8');

// CREATE DATABASE IF NOT EXISTS `new_database  DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'
DBUtil::create_database('new_database', 'utf8_unicode_ci');

Nếu không có bộ mã hoá nào được cung cấp thì nó sẽ quay trở lại bảng ký tự mã hóa của group db đang hoạt động.

drop_database($database, $db = null)

Phương thức drop_database xóa một cơ sở dữ liệu. Sẽ ném một Database_Exception nếu nó không thể. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

// Drop a database named `my_database`
DBUtil::drop_database('my_database');

// Catch the exception
try
{
    DBUtil::drop_database('my_database');
}
catch(\Database_Exception $e)
{
    // Drop failed...
}

table_exists($table, $db = null)

Phương thức table_exists kiểm tra một bảng nhất định tồn tại. Trả về true nếu bảng tồn tại, false nếu không. Ví dụ:

// Check if table named 'my_table' exists
if(DBUtil::table_exists('my_table'))
{
    // Table exists
} else
{
    // Table does NOT exist, create it!
}

drop_table($table, $db = null)

Phương thức drop_table xóa một bảng. Sẽ ném một Database_Exception nếu nó không thể. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

// Drop a table named `my_table`
DBUtil::drop_table('my_table');

// Catch the exception
try
{
    DBUtil::drop_table('my_table');
}
catch(\Database_Exception $e)
{
    // Drop failed...
}

rename_table($table, $new_table_name, $db = null)

Phương thức rename_table đổi tên một bảng. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

// Rename `my_table` to `my_new_table`
DBUtil::rename_table('my_table', 'my_new_table');

// Catch the exception
try
{
    DBUtil::rename_table('my_table', 'my_new_table');
}
catch(\Database_Exception $e)
{
    // Rename failed...
}

create_table($table, $fields, $primary_keys = array(), $if_not_exists = true, $engine = false, $charset = null, $foreign_keys = array(), $db = null)

Phương thức create_table tạo một bảng. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

\DBUtil::create_table('users', array(
    'id' => array('constraint' => 11, 'type' => 'int', 'auto_increment' => true),
    'name' => array('type' => 'text'),
    'email' => array('constraint' => 50, 'type' => 'varchar'),
    'title' => array('constraint' => 50, 'type' => 'varchar', 'default' => 'mr.'),
    'created' => array('type' => 'timestamp', 'default' => \DB::expr('CURRENT_TIMESTAMP')),
    'password' => array('constraint' => 125, 'type' => 'varchar'),
), array('id'));

field_exists($table, $columns, $db = null)

Phương thức field_exists kiểm tra xem filed(s) đã cho trong một bảng nhất định có tồn tại hay không. Trả về true nếu field / column tồn tại, false nếu không Ví dụ:

if(DBUtil::field_exists('my_table', array('my_field_or_column')))
{
    // Fields exist
}
else
{
    // Fields are not available on the table
}

add_fields($table, $fields, $db = null)

Phương thức add_fields thêm các trường vào một bảng. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng.

\DBUtil::add_fields('users', array(
    'surname' => array('constraint' => 100, 'type' => 'varchar'),
    'twitter_name' => array('constraint' => 100, 'type' => 'varchar'),
));

drop_fields($table, $fields, $db = null)

Phương thức drop_fields giảm các trường từ một bảng. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

\DBUtil::drop_fields('users', 'surname');

modify_fields($table, $fields, $db = null)

Phương thức modify_fields thay đổi các trường trong một bảng. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

\DBUtil::modify_fields('users2', array(
    'name' => array('constraint' => 100, 'type' => 'varchar', 'charset' => 'utf8_general_ci'),
    'title' => array('constraint' => 50, 'type' => 'varchar', 'default' => 'mrs.'),
));

create_index($table, $index_columns, $index_name, $index = ' ', $db = null)

Phương thức create_index cho phép bạn tạo chỉ mục phụ trên một bảng. Nếu thực thi thành công sẽ trả lại kết quả của hoạt động cơ sở dữ liệu. Ví dụ:

\DBUtil::create_index('table', 'name');
// produces CREATE INDEX name ON table ( `name` )

\DBUtil::create_index('table', array('nameA', 'nameB'), 'name');
// produces CREATE INDEX name ON table ( `nameA`, `nameB` )

\DBUtil::create_index('table', array('nameA' => 'ASC', 'nameB'), 'name', 'fulltext');
// produces CREATE FULLTEXT INDEX name ON table ( `nameA` ASC, `nameB` )

drop_index($table, $index_name, $db = null)

Phương thức drop_index cho phép bạn xóa một chỉ mục phụ từ một bảng. Nếu thực thi thành công sẽ trả lại kết quả của hoạt động cơ sở dữ liệu. Ví du:

\DBUtil::drop_index('table', 'name');
// produces DROP INDEX name ON table

add_foreign_key($table, $foreign_key)

Phương thức add_foreign_key cho phép bạn thêm khóa ngoài vào một bảng sau khi nó được tạo ra. Nếu thực thi thành công sẽ trả lại kết quả của hoạt động cơ sở dữ liệu. Ví du:

\DBUtil::add_foreign_key('users', array(
    'constraint' => 'constraintA',
    'key' => 'keyA',
    'reference' => array(
        'table' => 'table',
        'column' => 'field',
    ),
    'on_update' => 'CASCADE',
    'on_delete' => 'RESTRICT'
));

drop_foreign_key($table, $fk_name)

Phương thức drop_foreign_key cho phép bạn xóa một khoá ngoài từ một bảng. Nếu thực thi thành công sẽ trả lại kết quả của hoạt động cơ sở dữ liệu. Ví dụ:

\DBUtil::drop_foreign_key('table', 'name');
// produces ALTER TABLE `table` DROP FOREIGN KEY name

truncate_table($table, $db = null)

Phương thức truncate_table truncates một bảng. Nếu thực thi thành công sẽ trả lại số hàng bị ảnh hưởng. Ví dụ:

\DBUtil::truncate_table('my_table');```
# Tổng kết và tài liệu tham khảo
* Hi vọng những gì mình chia sẻ ở trên sẽ có ích đối với các bạn khi làm việc với migration fuelPHP. Đây là phần mình tổng hợp được từ DBUtil thuộc phần Core, Generate thuộc phần Oil và Migrations thuộc phần FuelPHP. Docs của fuel rất chi tiết, tuy nhiên trong quá trình làm việc với database thì tự mình thấy cần kiến thức của các phần này, vì vậy nên tổng hợp lại đây cho dễ tìm hiểu. Có thể sẽ có sai sót hay không đúng mong các bạn đừng gạch đá.
* Tài liệu tham khảo
1. https://fuelphp.com/docs/general/migrations.html
2. https://fuelphp.com/docs/packages/oil/generate.html#migrations
3. https://fuelphp.com/docs/classes/database/dbutil.html

All Rights Reserved