Many developers who use Laravel are probably only barely scratching the surface of what the framework has to offer. While the documentation does cover the most common use cases and the obvious features, it doesn’t cover everything.
Don’t get me wrong, the documentation is fine, it’s just that there’s so much you can do, it’s hard to document everything. Because of that, we're going to take a look at some of the hidden gems that lurk within Laravel.
Cascading Views
Available since: v4.0.0
Documented: No
Views are able to cascade much the same as configuration files. Cascading views are extremely useful when developing an extendable theming system. Consider the following directory structure.
/app /views /blog /index.blade.php /themes /default /views /blog /index.blade.php /theme.blade.php
The idea is that when we return View::make('theme::blog.index');
it will first look in the themes/default/views
directory and then, if it can’t find the view, fallback to app/views
.
To do this we use View::addNamespace
to register our own namespace with the two locations.
View::addNamespace('theme', [ base_path().'/themes/default/views', app_path().'/views' ]);
Collections
Available since: v4.0.0
Documented: Partially
Collections are a great way to interact with and manage arrays. Collections have a variety of handy methods and implement a number of useful interfaces such as ArrayableInterface
, IteratorAggregate
, and JsonableInterface
.
Let’s say we’re building a small blogging engine that uses flat files for storage. We want to be able to perform operations such as sorting, filtering, and pagination.
Implementing the blogging engine is beyond the scope of this article, but let’s imagine we have an array, $articles
, and each member of the array is an instance of an Article
class. All we then need to do is get a new instance of Collection
and give it our array of articles.
$articles = new Illuminate\Support\Collection($arrayOfArticles);
Sorting
Using the collection we can sort our articles. Let’s sort our articles and show the most recently updated articles first. For the sake of this article, let’s imagine that when loading the articles from the file system we set the updatedAt
property to the last modified time of the file.
$articles->sortByDesc(function ($article) { return $article->updatedAt; });
The sortBy
and sortByDesc
methods accept a callback, this callback should return a value which can be used for sorting the collection. In our case, we can simply return the articles last modified time and the collection can sort based on that.
Filtering
Similar to sorting, we can also use the collection to filter our articles much like a WHERE
clause in MySQL. Let’s filter our articles based on a search that may have been run.
<?php $searchQuery = 'Laravel rocks!'; $results = $articles->filter(function ($article) use ($searchQuery) { return preg_match(sprintf('/%s/m', $searchQuery), $article->body); });
The filter
method actually returns a new instance of Illuminate\Support\Collection
so we need to assign it to the $results
variable. This new collection will contain only the articles that mentioned “Laravel rocks!” in the body.
Pagination
Using the collection we can paginate our articles so we don’t have too many articles appearing on a single page.
$perPage = 1; $page = Input::get('page', 1); if ($page > ($articles->count() / $perPage)) { $page = 1; } $pageOffset = ($page * $perPage) - $perPage; $results = $articles->slice($pageOffset, $perPage);
Using the slice
method, we extract a portion of the articles in the collection and assign it to the $results
variable.
This example could then be taken even further by creating a new instance of Laravel’s Paginator
class. That way it can generate all the page numbers and links for you.
There’s More!
We could get a random article:
$article = $articles->random();
We can also iterate over our collection of articles as though it were a regular array. This is all thanks to the IteratorAggregate
and ArrayIterator
interfaces.
foreach ($articles as $article) { echo $article->body; }
And we can even transform our articles to a regular array or to its JSON representation.
$array = $articles->toArray(); $json = $articles->toJson();
One of the coolest methods is probably groupBy
, which allows us to group articles by a specific key. Imagine each article had some meta data at the top which was parsed and stripped from the articles body.
Although the parsing of this meta data is beyond the scope of this article, we’ll assume that it’s parsed and is a property on the Article
instance. You could then use groupBy
to group the articles by the category they were posted in.
$results = $articles->groupBy('category');
All articles that share the same category will be grouped. You could then get the articles for a specific category.
foreach ($results->get('tutorial') as $article) { echo $article->body; }
Collections are one of the best hidden gems Laravel has to offer.
Regular Expression Filters
Available since: v4.1.19
Documented: No
Filtering routes in Laravel is a common task that many of us do in all of our projects. A filter allows you to perform tasks such as user authentication or rate limiting, either before or after a route is fired. We create filters using Route::filter
and can apply them to individual routes, a route group, or by using Route::when
and applying to a matched pattern.
Route::filter('restricted', function($route, $request, $group)
{
// Restrict user access based on the value of $group
});
Route::when('admin/*', 'restricted:admin');
In this example, we create a restricted
filter which expects a single parameter, $group
. The $route
and $request
parameters are always given to a before filter.
But what if we wanted more flexibility? Let’s say we wanted to apply the filter to all the admin
routes except for admin/login
. We could use a route group and simply move the route in question outside of the group. Or we could use Route::whenRegex
and write our own regular expression.
Route::whenRegex('/^admin(\/(?!login)\S+)?$/', 'restricted:admin');
This regular expression simply makes sure that it is only applied to routes that start with admin
and are not followed by /login
, but can be followed by anything else. Excellent. We now have our restricted:admin
filter applied to all routes except our admin/login
route.
The Message Bag
Available since: v4.0.0
Documented: Partially
You’ve no doubt been using Illuminate\Support\MessageBag
for a while now without even realizing it. The biggest role MessageBag
plays is containing all of your validation errors when using Laravel’s built in validator.
An$errors
variable is available in each view that will contain either an emptyMessageBag
instance or the instance you flashed to the session withRedirect::to('/')->withErrors($validator);
There’s a good chance that a lot of you may be doing something like this in your forms when displaying an error message beneath a particular input.
{{ Form::text('username', null) }} @if($errors->has('username')) <div class="error">{{ $errors->first('username') }}></div>; @endif
You can actually remove that if
statement entirely and use the second parameter of the first
method to wrap the message in the div
.
{{ Form::text('username', null) }} {{ $errors->first('username', '<div class="error">:message</div>') }}
Much, much, much nicer!
Fluent
Available since: v3.0.0
Documented: Partially
The Fluent
class has been around for a long time and it’s actually used within the framework itself when creating migrations with the schema builder. Between Laravel 3 and Laravel 4 the class itself has barely changed, the only big differences are a few more interfaces.
To use the Fluent
class all you need to do is get an instance and away you go.
$user = new Illuminate\Support\Fluent; $user->name('Jason')->country('Australia')->subscriber();
The instance now has 3 attributes defined, name
with a value of Jason
, country
with a value of Australia
, and subscriber
with a boolean true
value.
Prior to Laravel 4.1 you could only really set and get the attributes from instance. Since Laravel 4.1 you can use the toArray
and toJson
methods to get the array of attributes and its JSON representation respectively.
As of Laravel 4.2, the class also implements the JsonSerializable
interface meaning you can pass the instance directly into json_encode
.
There's Even More!
We've looked at several useful gems of the Laravel framework. But, as you've guessed, there's even more within the framework.
The best way to find out what else Laravel may have on offer is to dig into the source. It's not as scary as you'd think and you'll learn a whole lot about the framework on which you're building.
If you have additional gems that you've found, don't hesitate to share them in the comments!
Comments