Thoughts, ideas and notes about PHP web development.

Laravel 4: Blade helper functions

Laravel’s template engine Blade is already very powerful and fairly extensible. Sometimes you may need special helper functions to simplify your template code. There is currently no “official” way to extend Blade with those. Other template engines, such as Twig, offer such a feature.

You could, of course, use global functions as a workaround. These would, however, be true to their name and clutter the global namespace. If you want to make sure that these functions are only available in the views, you might want to try this approach.

View::share('human_size', function($bytes) {
    $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'];
    for ($i = 0; $bytes > 1024; $i++) {
        $bytes /= 1024;
    }
    return round($bytes, 2).' '.$units[$i];
});

In your Blade views, you can then use this simple function call to convert a number into a human-readable size:

{{ $human_size(123456789) }}

This should return “117.74 MiB”. Note the dollar sign before the function call. This is due to the nature of Blade, which turns everything you pass into View::share() into variables. Since in this case we’re passing a closure, it can just be called like a regular function.

Happy templating!

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.

Next Page »