Ukieweb

Diary

I write here what I learn

Laravel Migration, Where & Why

Laravel Migration, Where & Why

Laravel Migration বাক্যটির সাথে আমরা যারা লারাভেলে কাজ করি তারা সবাই মোটামুটি পরিচিত। কিন্তু আমরা অনেকেই এর ব্যবহার ঠিক মতো জানিনা বা সঠিক কাজে ব্যবহার করি না। আমি এমন অনেককেই দেখেছি যারা এটিকে শুধু ডাটাবেস স্কিমা ডিজাইনের জন্য ব্যবহার করেন অর্থাৎ ডাটাবেস ও এর টেবিলের স্ট্রাকচার তৈরীর জন্য ব্যবহার করেন। তারা এটা দিয়ে যে ধরনের সুবিধা পান সেটা হলো প্রোজেক্টটিকে যদি অন্য কোথাও নিয়ে যাওয়া হয় তবে ডাটাবেস নিয়ে ভাবতে হয় না, শুধু গিয়ে একটা মাইগ্রেশন কমান্ড চালালেই হয়, ব্যস ডাটাবেস প্রস্তুত। কত্ত মজা তাই না?

কিন্তু আপনার এই কোমল মন অনন্ত জলিলের সেই বুলেটের আঘাতে এখন চূর্নবিচূর্ন হতে যাচ্ছে। আর আপনি যখন আমার সামনে এসে আপনার এই ক্ষতবিক্ষত মন নিয়ে প্রশ্ন করবেন What is migration ফ্রান্স? তখন আমার এই পাষাণ মন আপনাকে একটিই উত্তর দিবে "Migration is a version controling system for database". যদি বুঝতে একটু কষ্ট হয় তবে খুলেই বলি। আপনি এতদিন মাইগ্রেশন যে কারনে ব্যবহার করে এসেছেন সেটা হলো এর অনেকগুলো সুবিধার মধ্যে একটি। কিন্তু এর প্রধান কাজ হলো একটি প্রোজেক্টের শুরু থেকে শেষ পর্যন্ত ডাটাবেসে যতগুলো পরিবর্তন হয়েছে তার একটি log রাখা অর্থাৎ ডাটাবেসের একটি হিস্ট্রি রেখে দেয়া। যাতে করে আপনি অথবা আপনার প্রোজেক্ট ম্যানেজার একটু চোখ বুলালেই বুঝতে পারেন যে ডাটাবেসে কবে কোন পরিবর্তন এসেছে। শুধু তাই নয় প্রয়োজনে যেন তারা পিছনের কোন একটি অবস্থানে ডাটাবেসকে ফিরিয়েও নিয়ে যেতে পারেন। এটি খুবই প্রয়োজনীয় একটি ফিচার কারন একটি প্রোজেক্টে ডাটাবেসের স্ট্রাকচার প্রতিনিয়তই পরিবর্তন হয় আবার অনেক সময়েই ডাটাবেসকে আগে অবস্থানে ফিরিয়ে নিয়ে যেতে হয়, আর এসব সমস্যা সমাধানে Laravel Migration এর জুড়ি নেই। তাহলে চলুন দেখে নেই কিভাবে আমরা Laravel Migration নিয়ে কাজ করবো।

Laravel Migration এর পূর্বে আপনাকে অবশ্যই ডাটাবেস কনফিগার করে নিতে হবে, এ জন্য আপনি আমার Installing and Configuring Laravel 5.1 [Bangla] লেখাটি পড়তে পারেন

মাইগ্রেশন তৈরী

Laravel এর প্রতিটি মাইগ্রেশনই ডাটাবেসের এক একটি চেন্জ লগ, অর্থাৎ আপনি ডাটাবেসে কি পরিবর্তন করছেন তার একটি হিস্ট্রি। তাই মাইগ্রেশনটি এমনভাবে লিখবেন যাতে ফাইলের নাম দেখলেই বোঝা যায় এটি কি কারনে লেখা হয়েছিল। ধরুন আমরা ডাটাবেসে ইউজারদের জন্য একটি টেবিল তৈরী করবো, তাহলে এর জন্য একটি মাইগ্রেশন লেখা দরকার। চলুন প্রথমেই একটি মাইগ্রেশন তৈরী করি। টার্মিনালে গিয়ে লিখিঃ

php artisan make:migration create_users_table

ফলে database/migrations ডিরেক্টরীতে 2016_10_12_000000_create_users_table.php এরকম একটি ফাইল তৈরী হবে। ফাইলের নামটি একটু মনোযোগ দিয়ে খেয়াল করে দেখুন, নামের প্রথম অংশটা হলো মাইগ্রেশন তৈরীর timestamp যা নির্ধারন করে এই মাইগ্রেশন ফাইলটি কখন তৈরী করা হয়েছে আর বাকি অংশটি হলো এই মাইগ্রেশনের জন্য আপনার দেয়া নোট অর্থাৎ আপনি কি পার্পাসের এই মাইগ্রেশনটি লিখছেন সেটি।

Migration এর নাম অবশ্যই lowercase ও snake_case এ লিখবেন যেন নামে কোনো ব্লাঙ্ক স্পেস না থাকে। এবং নামটি হবে আপনি কি কারনে এই মাইগ্রেশনটি লিখছেন তার একটি নোট তাই অবশ্যই পুরো কারনটি নোট আকারে লিখবেন এতে যদি নাম একটু বড়ও হয় তাও লিখবেন। আমার উপরের মাইগ্রেশন টি দেখলেই বুঝতে পারবেন যে এটি users নামে একটি টেবিল তৈরীর জন্য লেখা হয়েছে।

মাইগ্রেশন/স্কিমা লেখা

মাইগ্রেশন ফাইল তো তৈরী হয়ে গেল এবার আমাদের মাইগ্রেশন লিখতে হবে অর্থাৎ ডাটাবেস স্কিমা লিখবো। এর জন্য আমাদেরকে মাইগ্রেশন ফাইলটি ওপেন করতে হবে। আমরা এমাত্র যে মাইগ্রেশনটি তৈরী করেছি সেটি ওপেন করি যেটা দেখতে এরকমেরঃ

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        
    }
}

দেখুন আপনি যে নামটি দিয়ে মাইগ্রেশন ফাইলটি তৈরী করেছেন ঠিক সে নামটি দিয়ে StudlyCase এ একটা class তৈরী হয়েছে যেটি Migration class কে extend করেছে। এই class এ দুটি মেথড (up, down) ডিফল্টভাবে দেয়া আছে। up মেথডটিতে মূলতে ডাটাবেসে এখন নতুন কি পরিবর্তন আসবে সেটি লেখা হয় আর down মেথডে রিভার্স মাইগ্রেশন লেখা হয় অর্থাৎ এটিকে যদি রোলব্যক করা হয় তবে এই মাইগ্রেশনের পূর্বে যেমন ছিল তেমন অবস্থাতে যেন যায়। তো চলুন আমরা ইউজারের জন্য মাইগ্রেশন লিখিঃ

 public function up()
  {
      Schema::create('users', function(Blueprint $tbl) {
          $tbl->increments('id');
          $tbl->string('name', 50);
          $tbl->string('email', 100)->unique();
          $tbl->string('password', 60);
          $tbl->boolean('status')->default(0);
          $tbl->timestamps();
      });
  }

 
  public function down()
  {
      Schema::dropIfExists('users');
  }

মাইগ্রেশন ব্যাচ কমান্ড রান

এবার আমরা টার্মিনালে নিচের কমান্ডটি চালালে ডাটাবেসে users নামে একটি টেবিল তৈরী হবে যেখানে মাইগ্রেশনে বর্নিত সকল column থাকবে।

php artisan migrate

কমান্ডটি চালানোর ফলে নিচের মতো দুটো টেবিল তৈরী হবে

table lists

কিন্তু প্রশ্ন হলো আমিতো একটি মাইগ্রেশন লিখেছি তাহলে ডাটাবেসে migrations নামে টেবিলটি আসলো কোথা থেকে? হ্যা এটি একটি ভালো পয়েন্ট, এই migrations টেবিলই মূলত আপনার ডাটাবেসের ভার্সন কন্ট্রোল করে থাকে। চলুন migrations টেবিলটি একটু দেখিঃ

enter image description here

দেখুন এখানে মোট ৩টি কলাম রয়েছে id, migration, batch. id এর কাজতো এমনিতেই বোঝা যায় এটি মাইগ্রেশনের সিরিয়াল স্টোর করে, migration কলামে থাকে যে মাইগ্রেশনটি এক্সিকিউট হয়েছে সেটি আর batch কলাম স্টোর করে আপনি কত নম্বর মাইগ্রেশন চালিয়েছেন। অর্থাৎ একবারে migration run করলে এর সাথে অনেকগুলো মাইগ্রেশন একসাথে এক্সিকিউট হতে পারে। যেমনঃ আমরা এখানে শুধু একটি টেবিল তৈরীর জন্য মাইগ্রেশন লিখেছি কিন্তু আমরা যদি এর সাথে আরো ৩টি টেবিলের মাইগ্রেশন তৈরী করে তারপর লিখতে রান করাতাম তাহলে 2016_10_12_000000_create_users_table.php এর মতো আরো ৩টি মাইগ্রেশন একবারে রান হতো ফলে এই এখানে টোটাল ৪টি মাইগ্রেশন রান করতো, আর এই ৪টির batch হতো 1. কারন এ ৪টিই একবারের কমান্ডেই রান করেছে।

নতুন column যুক্ত করা

তো আমাদের ইতিমধ্যে users টেবিল তৈরী হয়ে গেছে কিন্তু কাজ চলাকালীন সময়ে আপনার মনে হলো এই টেবিলে role নামে একটি কলাম যুক্ত করার প্রয়োজন। কিন্তু এটি আপনি কিভাবে করবেন? হ্যা ডাটাবেসের প্রতিটি পরিবর্তনই একেকটি মাইগ্রেশন, তাই এ কাজের জন্যও আপনাকে নতুন একটি মাইগ্রেশন লিখতে হবে। তাহলে একটি মাইগ্রেশন তৈরী করে নেই

php artisan make:migration add_role_column_in_users_table

এবার আমরা এর জন্য স্কিমা লিখবো

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddRoleColumnInUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function(Blueprint $tbl) {
            $tbl->string('role', 20);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        if (Schema::hasColumn('users', 'role')) {
            Schema::table('users', function(Blueprint $tbl) {
                $tbl->dropColumn('role');
            });
        }
    }
}

মাইগ্রেশন লেখা শেষ এবার আমরা migrate কমান্ডটি চালাবো

php artisan migrate

ফলে users টেবিলে password কলামের পরে role নামে একটি কলাম যুক্ত হয়েছে এবং মাইগ্রেশন টেবিল এবার দেখতে এরকমের হবে

enter image description here

দেখুন এখানে নতুন আরেকটি মাইগ্রেশন যুক্ত হয়েছে যার batch 2 অর্থাৎ আমরা দ্বিতীয়বারের মতো মাইগ্রেশন চালিয়েছি। মনে রাখবেন batch হলো আপনি কতবার মাইগ্রেট করেছেন সেটি কিন্তু কতটি মাইগ্রেশন লিখেছেন সেটি নয়। কারন একবারে আপনি একাধিক মাইগ্রেশনকেও মাইগ্রেট করতে পারবেন ফলে একই batch এর অধিনে সবগুলো আলাদা আলাদা মাইগ্রেশন হিস্ট্রিতে থেকে যেতো।

Rollback

এটি খুবই গুরুত্বপূর্ন একটি ফিচার। ধরুন কিছুদিন পর সিস্টেম ডিজাইনের জন্য আপনার আর users টেবিলের সেই role কলামটি প্রয়োজন নেই অর্থাৎ আপনাকে এর আগের অবস্থানে ফিরে যেতে হবে। মনে রাখবে আপনি যখনই কাজ করছেন সেটিই ডাটাবাসের লেটেস্ট স্টেট। আপনি যখন রোলব্যক করবেন তখন আপনি ঠিক এর আগের স্টেট বা ভার্সনে ফিরে যাবেন। আর এই ভার্সনটি নির্ধারন হয় migrations টেবিলের batch কলামের মাধ্যমে। এখানে প্রতিটি ব্যাচ নম্বর হলো একেকটি ভার্সন। তাহলে চলুন আমরা বর্তমান ভার্সন থেকে আগের ভার্সনে রোলব্যক করি।

php artisan migrate:rollback

এবার ডাটাবেসে গিয়ে দেখুন আপনার ডাটাবেস আগের ভার্সনে চলে গেছে অর্থাৎ batch 1 এ। যেখানে users টেবিলে role কলামটি নেই। এবার প্রশ্ন আসতে পারে এটি কিভাবে হয়েছে? খেয়াল করলে দেখবেন আমরা প্রতিটি মাইগ্রেশনে একটা রিভার্স মাইগ্রেশন লিখেছি down মেথডে। রোলব্যক এই মেথডটিকেই ব্যবহার করেছে।

আমরা এই ডায়েরীর একেবারে শেষ পর্যায়ে। এই ডায়েরীটি লেখার উদ্দেশ্য মাইগ্রেশন কিভাবে লিখতে হয় সেটি নয় বরং আমার উদ্দেশ্য ছিলো আপনি মাইগ্রেশন কোথায়, কোন ক্ষেত্রে এবং কেন লিখবেন সেটি আর সাথে মাইগ্রেশন কিভাবে কাজ করে সেটিও বোঝানোর চেষ্টা করেছি। আশা করি এবার মাইগ্রেশনের সঠিক প্রয়োগ করবেন।

ধন্যবাদ :)

5 Comments

25/10/2016

Nahid ভাই যদি Middleware নিয়ে একটু লিখতেন , উদাহরন সহ । অনেক ভাল হত

25/10/2016

ইনশা’আল্লাহ লিখবো :)

25/10/2016

laravel 5.3 -তে অনেক একটা সুন্দর ফিচার এনেছে php artisan migrate:rollback --step=? পোস্টে এটাও অ্যাড করে দিলে মনে হয় ভালো হয় .........

26/10/2016

আচ্ছা এড করে দিব, ধন্যবাদ শিপু গুরুত্বপূর্ন একটি তথ্য দেয়ার জন্য :)

26/10/2016

৩ বছর ধরে লারাভেল করতেছেন? ছিঃ ছিঃ ছিঃ :P

To make a comment you have to login