Thoughts, ideas and notes about PHP web development.

Laravel 4 Gems: Maintenance mode

A short tip to finish up the week.

When making changes to your site such as running migrations to update your database, you might want to make sure that it is not accessible from the outside in order to avoid showing intermediate errors. Laravel 4 adds a very simple, but useful feature for such situations: maintenance mode.

Whenever you want to shut down access from the outside for your site, just run this command from the command line:

php artisan down

Try accessing your site with your browser now. You will see a message stating “Be right back!”. To disable maintenance mode, just run this command:

php artisan up

Of course, you might want to display more information or explain the reasons when your site is in maintenance mode. Open app/start/global.php and find the App::down() handler. You can replace the default string with a custom message. For more advanced pages, you can even render a view:

App::down(function()
{
    return Response::view('maintenance', array(), 503);
});

This will render the view called “maintenance” in your views directory. Since we don’t have any custom data, we pass an empty array as second parameter. The 503 stands for the “Service unavailable” header from the HTTP specification.

Laravel 4 Gems: Model query scopes

Query scopes are a wonderful way to make queries with Eloquent even more readable. They also help you encapsulate your actual database logic inside your model class and avoid repetitive code.

If you have used Yii or Ruby on Rails, you might already know this concept. Well, Laravel 4 now has it, too. (And with a little bit of pride I might add: it was my idea!)

Imagine (my favorite use case) a forum software. A pretty common query for all “closed” (or resolved) topics might then read like this:

Topic::where('closed', '=', 1)->get();

We directly check for the closed field in the database table to have the value 1. This type of query for closed topics might actually happen rather frequently in different places across the forum. Now imagine a situation in the future where you have to change the structure of your database (for whatever reason). For example, you might mark closed topics with the value 0 in the opened column instead: you will have to change every single one of those queries.

You guessed it: query scopes to the rescue! We want our query to look like this:

Topic::closed()->get();

Now, of course Laravel can not know how this scope called closed should be resolved in the query, so we have to tell it. Add this method to your topic model class:

public function scopeClosed($query)
{
    // Note that the second parameter can be omitted
    // if we're checking for equality.
    return $query->where('closed', 1);
}

As you can see, the scope method accepts a query object as parameter. In the method body, we can manipulate that query and then have to return it.

Combining scopes

Where scopes really shine is when you combine them. In a forum with a lot of topics, you probably want to show only the 25 most recent ones quite often.

So, you might decide to create another scope that orders the topics by post date and applies a LIMIT clause to the query:

public function scopeLatest($query)
{
    // We're ordering by post date and apply
    // a LIMIT clause to the query.
    return $query->orderBy('post_date', 'desc')->take(25);
}

To get only the latest closed topics, you can now combine both scopes like this:

Topic::latest()->closed()->get();

Marvel at the readability. Code and text are almost equal.

Less, but official, info can be found in the documentation.

Laravel 4 Gems: Query results caching

It is here! Laravel 4.0 was released yesterday. Obviously, Taylor was very busy in the past days, trying to fix remaining bugs. Still, he even had time to introduce some nice new features every now and then.

A very recent example for such a feature would be query results caching.

With a very simple chained method call, you can make sure that long-running or frequently-run queries are executed only once every hour, with the result being cached in the meantime.

$users = DB::table('users')
           ->orderBy('num_posts', 'desc')
           ->take(5)
           ->remember(60)
           ->get()

What this does behind the scenes: it executes the query once and stores it along with the results using the cache adapter, with an expiration time of 60 minutes. When this code is run again, the cached query statement will be found, and the query won’t be executed, but instead the results will be taken directly from the cache.

Of course, this also works with Eloquent queries. If you have a user model, you can do this instead:

$users = User::orderBy('num_posts', 'desc')
             ->take(5)
             ->remember(60)
             ->get()

Who’s looking sharp now?

Laravel 4: The day is here

Today is the day. In a few hours, Laravel 4.0 will see the light of the day.

What a huge day for the Laravel community and the PHP community at large! Laravel 3 was awesome, but version 4 is so much better. It has the same ease of use, pretty much the same syntax and tons of new features, some of which I will write about in the coming days.

But the best new feature is clearly under the hood, which means it will sadly go largely unnoticed: it is the fact that the framework was implemented completely from scratch, with a largely superior architecture. Not only is the code now much more testable and thoroughly unit-tested, it is decoupled in such a way that you can use the 27 (!) components on their own, thanks to Composer!
This is where Taylor has really outdone himself. It’s a piece of art.

And last but not least, Laravel 4 tries to encourage developers to use best practices like dependency injection. Sometimes, the shortest code isn’t the best one, and the framework puts some tools in your hand that help you write better object-oriented code.

Now it’s time to celebrate. (Happy Birthday, Taylor!) Have fun using this version! Or trying it out if you haven’t yet. It will change the way you do PHP.

Laravel 4 Gems: Route parameter binding

The final release of Laravel 4.0 is right around the corner. In fact, it’s tomorrow that the new version will see the light of the world.

So much has changed and improved in this new version that it is hard to keep track of all the good new things. Thus, I decided to start a little series on some hidden gems of the framework: let us dive into some of the lesser-known features that can really make daily development even more pleasant – if you know they exist!

In your controllers, you might find yourself writing code like this pretty often:

public function view($id)
{
    $model = MyModel::find($id);
    if (is_null($model))
    {
        App::abort(404);
    }
    // Render view etc.
}

Now, this can become quite repetitive and boring. Thankfully Taylor added a new feature in Laravel 4 that allows you to bind the respective model to your parameter during routing. Behold, route parameter binding:

Route::bind('mymodel', function($value, $route) {
    return MyModel::findOrFail($value);
});

This makes sure the closure will be executed every time you name a parameter “mymodel” in your routes. Note the use of the findOrFail() method. This takes care of throwing an exception in case the model can not be found. To actually use this feature, you need to adapt your routes, too:

Route::get('models/{mymodel}', 'MyController@view');

That also means that your controller method will now be passed a Model instance instead of the parameter value:

public function view(MyModel $model)
{
    // Render view etc.
}

And last but not least, for this classic model use-case, the framework offers another shortcut that fetches a model for the given class name by ID:

Route::model('mymodel', 'MyModel');

This does exactly what we did earlier with Route::bind(), except we don’t have to write the code ourselves. Isn’t that great?
For more information, refer to the documentation.

Next Page »