Artisan and Laravel Migrations

For those who struggle with maintaining their database schema, or who have problems applying updates and often revert them, there is a solution. Laravel, the MVC framework which I wrote about previously, offers you migrations.

In short, migrations are files which contain a class definition with both an up() and a down() method. The up() method is run when the migration is executed to apply changes to the database. The down() method is run to revert the changes. If you need to update the database, you just create a new migration and voilà. Not happy with it? Revert it and you’re back on track.

It all seems pretty cool, doesn’t it? But how does it work for Laravel? First you have to configure your database connection, and then you use Artisan, Laravel’s command line interface, to install the migrations table and run, revert, create… migrations.

Open a console and navigate to the root directory of your Laravel install. Run the following command:

php artisan migrate:install

This command causes Artisan to create a special table in your database to keep track of what migrations have already been executed.

To create a new migration, run this command:

php artisan migrate:make create_users_table

This creates the migration file which handles the users table. You can find your migration file inside the application/migrations folder. Artisan adds the date and time of the command’s execution as a prefix to the file, so the file would be named something like “2012_07_25_071925_create_users_table.php”. Be sure to use a descriptive name so that it’s clear what the migration does from just a glance.

Open the file and you’ll see a class with the two methods up() and down().

<?php
class Create_Users_Table
{
    public function up() {
        Schema::create("users", function($table) {
            $table->increments("id");
            $table->string("username", 32);
            $table->string("email", 320);
            $table->string("password", 64);
            $table->timestamps();
        });
    }

    public function down() {
        Schema::drop("users");
    }
}

The up() method runs when the migration is executed and creates the users table which holds five columns. The first is an auto-incrementing ID column, followed by VARCHAR columns for a username, email, and password. The first parameter to string() is the name of the column (e.g. “username”) and the second is the size of the column (e.g. 32 characters long). The final columns are created by the timestamps() method which creates “created_at” and “updated_at” columns.

The down() method is simpler than its predecessor and simply tells the database to drop the users table.

Now this file won’t do anything if it just sits there. To execute all outstanding migrations, run:

php artisan migrate

Currently it is not possible to run a specific migration. You can however run all the migrations in the application folder by the command:

php artisan migrate application

You can do the same for a specific bundle by using the same command but with the bundle’s name.

Now let’s say you realize that you made a design error and you want to roll back the last migration run. Simply type:

php artisan migrate:rollback

It’s not yet possible to automatically roll-back to a point before a specific migration, so you’ll have to run the command repeatedly until you reach that migration. You can however reset all migrations that you’ve ever ran just by running:

php artisan migrate:reset

As it stands now, the database would allow users to register the same username or email address any number of times. We want to restrict that and only allow an address or username to be used once. Of course, we don’t want to roll back the previous migration because we would lose data if we did, so instead we create a new one.

php artisan migrate:make users_add_username_email

The up() method should add a unique index on the fields, like this:

<?php
public function up() {
    Schema::table("users", function($table) {
        $table->unique("username");
        $table->unique("email");
    });
}

In the <code>down()</code> method, you want simply to remove the indexes.

<?php
public function up() {
    $table->drop_unique("username");
    $table->drop_unique("email");
}

That’s it! I hope you find Laravel’s migrations a solution to avoid all the hours of pain you’ve gone through managing your database schema. See you next time!

Image via Fotolia

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Chiristian

    Hmm.. why not just refer to the original guide?
    http://guides.rubyonrails.org/migrations.html

    • Alexander Cogneau

      Because this is not a RoR guide but a Laravel guide

  • Rich Lovelock

    Probably worth mentioning that you can get bundles such as Bob or the very nice https://github.com/JeffreyWay/Laravel-Generator/ to help with code generation, including migrations to make life even easier

  • Andy

    Thanks for the article. I always find it useful to read up on ways of working in PHP that tackle the kind of issues that crop up during more enterprise-level projects.
    I found it much easier to follow than the ‘original guide’ linked above, (not least because your examples were in PHP rather than ruby). Having said that, I’m sure the guide contains much more information and would serve well as a point of reference.

    • þyrs

      If you’re working in PHP, this doesn’t offer much over Doctrine. And why are you porting Rails to PHP? Perhaps you should have named your framework Sisyphus.

      • http://philsturgeon.co.uk Phil Sturgeon

        The advantage of using framework migrations, is that you don’t have to install Doctrine. You might like Doctrine, and you might use it all the time. Good for you.

        If you don’t like Doctrine, and you don’t want to install it all the time – it’s it nice that frameworks have an option to run migrations themselves, without relying on an ORM to do it for you?
        Laravel is not the only framework to do this, its a common tool that a lot of PHP frameworks do and I am very glad that they do.
        Even if it is a copy of Ruby, what is the issue there? If you have are building a PHP application then you can’t just plug random Rails code in for the sake of it. Rails is very nice, but simmer down.
        Trolls…

    • Christian

      That is.. hilarious.. Andy, its not the original guide, just an example of someone taking a less-than “Artisanal” license with an existing framework.
      If you guys are going to crow about a Rails port, albeit with pretentious naming, then why not just use.. Rails?

      • Alexander Cogneau

        Because Rails is Ruby? And Laravel is PHP

        • Christian

          I am going to leave aside the fact that php is a fundamentally flawed language (http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/), and go with the argument of using the “best tool for the job”. Here we have two tools, one clearly modeled after the other, except for one is 7+ years old and has the support of an entire community; the other, is but the latest entry into an unbelievably fking crowded mess of existing frameworks. I would argue that the disparate and fractured nature of this field will eventually be one of the causes of the community’s stagnation – so please people, put aside the ego and stop writing fking frameworks. Do yourself a favor as well, learn a lot of different languages so as to expose yourself to the ideas presented in each – it will make you a far better developer.

          • http://philsturgeon.co.uk Phil Sturgeon

            So just because a developer uses PHP, it means he doesn’t know anything else?
            I respect everyones point of view, but you sound like a very young or inexperienced developer if that is your mindset. Have you worked in corporate environments much? Ever built a distributable application that needs to install on $5 hosting without any problems or technical experience? Every done ANYTHING other than build with Rails?
            People need to use PHP, and you will need to learn to be ok with that.

          • http://www.zizaco.net Zizaco

            @Christian
            Following your logic: you should throw you lovely ruby into the garbage, stop using Rails, go learn scala and play, also all the OS are crap because then are written in C/C++, people should re-write then in some “better” language like “c0mPiLeD” Ruby. Maybe the whole google should witch over to scala too?

            “So just because a developer uses PHP, it means he doesn’t know anything else?”²
            Actually I work with Ruby on Rails (and have worked with BlitzMax, Lua, ASP, PHP and even C++) and I do like and use Laravel.
            http://www.zizaco.net/2012/10/rails-vs-modern-php-frameworks/

            So I tell you “Do yourself a favor as well, learn a lot of different languages so as to expose yourself something other than Rails – it will make you a far better developer.”

            There are developers and there are RoR fan-boys.

      • carl

        shut up Troll!
        ……….nice tutorial!

  • Theodor

    @Christian: good point. @Phil Sturgeon I do not agree with “People need to use PHP, and you will need to learn to be ok with that.” That actually sounds like something coming from a very young or inexperienced developer. But there is nothing bad with copying ideas from other frameworks and porting them to PHP.
    PHP is easy, it has it’s flaws, but in the end it’s the most popular web platform.
    So what it copies Rails ? Rails is a great source of inspiration, but, speaking for myself here, I’d rather use Rails than a PHP copy of it.

  • Steve MacEwan

    Thanks for the write-up Alex. I use PHP/Frameworks and RoR when the need arises and find benefits in both technologies. The article is about Laravel migrations and, while not a complete subset of Zends capabilities, does a good job none-the-less.

  • sanny

    Hi,i have a photo table created with artisan but i want to change “photo” to “photos” ..is there way to change table name with laravel’s artisan … thanks