การสร้างและใช้งาน Migration ใน Yii Framework 2

คู่มือการเรียนรู้ Yii Framework 2 (Yii2)

บทเรียนดีๆ สำหรับผู้ที่ต้องการแบ่งปัน บทเรียนของคุณอาจมีค่าสำหรับอีกหลายๆ คน

beta version

การสร้างและใช้งาน Migration ใน Yii Framework 2

มานพ กองอุ่น yii migration 3,731

Migration คืออะไร

Migration คือการสร้าง versioning ของการทำงานกับฐานข้อมูล เช่น การสร้างตาราง การเพิ่ม field การลบ field เพื่อให้เห็น version ต่างๆ และทราบที่มาที่ไปได้

การ Migration จึงมีความสำคัญกับการพัฒนาระบบที่ทำงานเป็นทีมหลายๆ คน

รูปแบบของ Migration นั้นถูกนำมาใช้ให้เหมือนกับการ Coding ที่ต้องมีการเก็บ Versioning ของ Code เช่น Git โดยจะเห็นว่าประวัติของ Code นั้นมีที่มาที่ไปอย่างไร มีการแก้ไขตรงไหนบ้าง หรือ เพิ่มตรงไหนบ้าง จึงเป็นที่มาของ Migration นั่นเอง

ไฟล์ Migration นั้นจะมี Method หลักๆ อยู่ 2 Method คือ up() และ down() โดยทั้ง 2 Method นี้ทำหน้าที่ตรงกันข้ามกัน เช่น up() คือการสร้างตาราง down() คือการลบตาราง เป็นต้น

เริ่มใช้งาน Migration

ก่อนอื่นเมื่อติดตั้ง Yii Framework 2 เสร็จเรียบร้อยแล้วให้แก้ไขการเชื่อมต่อฐานข้อมูล จากนั้นเปิด CommandPrompt/Terminal แล้วพิมพ์คำสั่งในการสร้างตาราง migration ดังนี้

yii migrate

ก็จะได้ตาราง migration ในฐานข้อมูลเรียบร้อยแล้ว เพื่อเก็บ version ของการเรียกใช้งาน Migration file ต่างๆ

ที่เก็บไฟล์ Migration

ไฟล์ Migration จะถูกเก็บไว้ใน folder console/migrations

ชนิดฟิวด์แบบต่างๆ

ชนิดของฟิวด์แบบต่างๆ ที่ใช้ในการสร้าง

$this->primaryKey() //PRIMARy และ AUTO_INCREMENT
$this->string(255) //VARCHAR(255) 255 คือความยาว
$this->text() //ชนิด TEXT
$this->integer() //จำนวนเต็ม คือ INT
$this->timestamp() //แบบ TIMESTAMP

การสร้างไฟล์ Migration

สำหรับการสร้างไฟล์ migration นั้นเราจะใช้ commandPrompt/Terminal ในการพิมพ์คำสั่งในการสร้าง

การสร้างตาราง

การสร้างตารางจะใช้คำสั่งในการสร้างดังนี้

yii migrate/create create_table_name

ตามธรรมเนียมของ Yii Framework 2 จะให้มีคำว่า create_ชื่อตาราง เช่น

yii migrate/create create_product

ก็จะได้ไฟล์ลักษณะดังนี้

console/migrations/m160221_055928_create_product.php

จากนั้นเราก็สามารถเขียนคำสั่งใน method up() และ down() ได้แล้ว ทดลองเขียนคำสั่งใน method up()

<?php

use yii\db\Migration;

class m160221_055928_create_product extends Migration
{
    public function up()
    {
        $this->createTable('product', [
            'id' => $this->primaryKey(),
            'name' => $this->string(255),
            'description' => $this->text(),
            'photo' => $this->string(255),
            'cost' => $this->integer(),
            'price' => $this->integer(),
            'status' => $this->integer(1),
            'created_at' => $this->timestamp(),
            'updated_at' => $this->timestamp(),
        ]);
    }

    public function down()
    {
        $this->dropTable('product');
    }
}

ทดลองเรียกใช้งานด้วยคำสั่ง

yii migrate

จะเห็นว่าในฐานข้อมูลมีตาราง product และมี field ต่างๆ ตามที่เราได้กำหนดขึ้นแล้ว

 

การเพิ่มคอลัมน์ (Column) ในตาราง

ในบางครั้งการออกแบบตารางไปแล้วและได้สร้าง migration ไปแล้ว หากมีการเพิ่ม field ใหม่โดยมีรูปแบบดังนี้

yii migrate/create add_ชื่อฟิวด์_to_ชื่อตาราง --fields="ชื่อฟิวด์:ชนิด","ชื่อฟิวด์:ชนิด"

ตามธรรมเนียมของ Yii Framework 2 จะให้มีคำว่า add_ชื่อฟิวด์_to_ชื่อตาราง เช่น

yii migrate/create add_note_to_product --fields="note:text"

ก็จะได้ไฟล์ลักษณะดังนี้

m160407_083440_add_note_to_product.php

เมื่อเปิดดูไฟล์ก็จะได้คำสั่งในการเพิ่ม field ดังนี้

<?php

use yii\db\Migration;

class m160407_083440_add_note_to_product extends Migration
{
    public function up()
    {
        $this->addColumn('product', 'note', $this->text());
    }

    public function down()
    {
        $this->dropColumn('product', 'note');
    }
}

ทดลองเรียกใช้งานด้วยคำสั่ง

yii migrate

จะเห็นว่าในฐานข้อมูลตาราง product มี field note เกิดขึ้น

การลบคอลัมน์ (Column) ในตาราง

และในบางครั้งเช่นกันเมื่อเราสร้างตารางเรียบร้อยแล้ว หากเราไม่ต้องการฟิวด์นั้นอีกต่อไปเราก็สามารถลบออกได้ด้วยคำสั่งรูปแบบนี้

yii migrate/create drop_ชื่อฟิวด์_from_ชื่อตาราง --fields="ชื่อฟิวด์:ชนิด"

ตามธรรมเนียมของ Yii Framework 2 จะให้มีคำว่า drop_ชื่อฟิวด์_from_ชื่อตาราง เช่น

yii migrate/create drop_note_from_product --fields="note:text"

ก็จะได้ไฟล์ลักษณะดังนี้

m160407_085053_drop_note_from_product.php

เมื่อเปิดดูไฟล์ก็จะได้คำสั่งในการเพิ่ม field ดังนี้

<?php

use yii\db\Migration;

class m160407_085242_drop_note_from_product extends Migration
{
    public function up()
    {
        $this->dropColumn('product', 'note');
    }

    public function down()
    {
        $this->addColumn('product', 'note', $this->text());
    }
}

ทดลองเรียกใช้งานด้วยคำสั่ง

yii migrate

จะเห็นว่าในฐานข้อมูลในตาราง product field note ได้ถูกลบไปแล้ว

การลบตาราง

การสร้างตารางจะใช้คำสั่งในการสร้างดังนี้

yii migrate/create drop_table_name

ตามธรรมเนียมของ Yii Framework 2 จะให้มีคำว่า drop_ชื่อตาราง เช่น

yii migrate/create drop_product

ก็จะได้ไฟล์ลักษณะดังนี้

m160407_082347_drop_product.php

เมื่อเปิดไฟล์ก็จะได้คำสั่งในการลบตารางดังนี้

<?php

use yii\db\Migration;

class m160407_082347_drop_product extends Migration
{
    public function up()
    {
        $this->dropTable('product');
    }

    public function down()
    {
        $this->createTable('product', [
            'id' => $this->primaryKey()
        ]);
    }
}

ทดลองเรียกใช้งานด้วยคำสั่ง

yii migrate

จะเห็นว่าในฐานข้อมูลตาราง product จะถูกลบไปแล้ว

 

การใช้งานแบบ batchInsert() ร่วมกับ Facker

Facker เป็น class สำหรับการ generate ข้อมูลทดสอบ เป็นข้อมูลตัวอย่างช่วยให้การทดสอบการใช้งาน Web Application มีความสมจริงมากยิ่งขึ้น ดูรายละเอียดได้ที่

https://github.com/fzaninotto/Faker

รายละเอียด Facker สำหรับ Yii2 Extension

http://www.yiiframework.com/doc-2.0/ext-faker-index.html

ทำการสร้าง migration ใหม่

yii migrate/create create_category
yii migrate/create create_product
yii migrate/create add_foreign_key_to_product

จากนั้นแก้ไข method up() ดังนี้

ไฟล์ console/migrations/xxxxx_create_category.php

<?php

use yii\db\Migration;
use Faker\Factory;

class m160419_160008_create_category extends Migration
{
    public function up()
    {
        $this->createTable('category', [
            'id' => $this->primaryKey(),
            'name' => $this->string(255),
        ]);
        
        $columns = array('id',
            'name',
        );
        $values = [];
        
        for($i=1; $i<=10; $i++){
            $facker = Factory::create();
        
            $values[] = [
                $i,
                $facker->sentence,
            ];
        }
        
        $this->batchInsert('category', $columns, $values);
    }
    
    

    public function down()
    {
        $this->dropTable('category');
    }
}

ไฟล์ console/migrations/xxxxx_create_product.php

<?php

use yii\db\Migration;
use Faker\Factory;

class m160419_143143_create_product extends Migration
{
    public function up()
    {
        $this->createTable('product', [
            'id' => $this->primaryKey(),
            'name' => $this->string(255),
            'description' => $this->text(),
            'price' => $this->integer(),
            'status' => $this->integer(1),
            'created_at' => $this->integer(),
            'updated_at' => $this->integer(),
        ]);
        
        $columns = array('id',
            'name',
            'description',
            'price',
            'status',
            'created_at',
            'updated_at'
        );
        $values = [];
        
        for($i=1; $i<=50; $i++){
            $facker = Factory::create();
            
            $values[] = [
                $i,
                $facker->sentence,
                $facker->text,
                rand(500,5000),
                rand(0,1),
                time(),
                time(),
            ];
        }
        
        $this->batchInsert('product', $columns, $values);
    }

    public function down()
    {
        $this->dropTable('product');
    }
}

ไฟล์ console/migrations/xxxxx_add_foreign_key_to_product.php

<?php

use yii\db\Migration;

class m160419_163237_add_foreign_key_to_product extends Migration
{
    public function up()
    {
        // creates index for column `category_id`
        $this->createIndex(
            'idx-product-category_id',
            'product',
            'category_id'
            );
        
        // add foreign key for table `category`
        $this->addForeignKey(
            'fk-product-category_id',
            'product',
            'category_id',
            'category',
            'id',
            'CASCADE'
            );
    }

    public function down()
    {
        // drops foreign key for table `category`
        $this->dropForeignKey(
            'fk-product-category_id',
            'product'
            );
        
        // drops index for column `category_id`
        $this->dropIndex(
            'idx-product-category_id',
            'product'
            );
    }
}

ทดลองเรียกใช้งานด้วยคำสั่ง

yii migrate

จะเห็นว่าในฐานข้อมูลมีตาราง product และจะมีข้อมูล 50 record ตาราง category มีข้อมูล 10 record เกิดขึ้น

สรุป

สำหรับการทำ Migration นั้นมีความสำคัญในกรณีที่เราต้องการทำ Version ของการทำงานกับฐานข้อมูล ตั้งแต่การสร้างตาราง การลบตาราง การเพิ่มฟิวด์ การลบฟิวด์ และการปรับแก้ไขส่วนต่างๆ โดยการทำงานเป็นทีมจะช่วยให้เราได้เห็นการเปลี่ยนแปลงของสิ่งต่างๆ ในฐานข้อมูลของ Project เราได้ และ Migration ใน Yii Framework 2 เป็นเครื่องมือที่ยอดเยี่ยมจริงๆ ครับ @Programmer Thailand Team


หากบทเรียนรู้มีความผิดพลาดประการใด หรือมีข้อเสนอแนะกรุณาแจ้ง contact@programmerthailand.com
มานพ กองอุ่น

มานพ กองอุ่น
admin

  • 2 เพื่อน
  • 9 ผู้ติดตาม
  • 758 โพสต์