News

Laravel: A modern PHP framework

PHP has been crying out for a contemporary framework. Find out why Laravel is taking the community by storm

Laravel

It’s difficult to deny the fact that, in recent years, the web development community has been incredibly hard on the PHP language and its faithful devotees. It’s no wonder why; at the time, a number of poignant PHP-hate articles began circling the web like a virus, and some of its flagship frameworks, such as CodeIgniter, were quickly growing stale. All the while, Ruby on Rails seemed to be leading the pack, in terms of innovation and ease of development. As time moved on, more and more coders found themselves ignoring PHP, as they instead reached for their Ruby toolbelts.

But things change; they always do. Along came a ridiculously smart young former .NET developer, Taylor Otwell, who was on the verge of unleashing a modern, elegant framework called Laravel, into the universe. At first, as is typically the case when yet another framework pokes its head up to say hi, many developers dismissed it as nothing but one more Sinatra clone that would quickly diminish into nothingness. But still, week after week, social network feeds were all of a flutter, praising Laravel’s elegance and readability. Could it be that PHP finally has a truly modern framework?

Are you no longer willing to sit on the sidelines? It’s time to dig in and discover why it is that in such a short timespan, Laravel has amassed such an enormous community of evangelists. Is it true, as they say, that Laravel actually makes PHP fun again? And could it be that PHP, as a framework, is no longer forever doomed to predominantly personal sites and ugly WordPress blogs? Nope; in fact, the PHP community just might find that, thanks to Laravel, Composer, and PHP 5.5, they’re about to experience the next renaissance of the web’s most popular server-side language.

To install the latest development version of Laravel (v4), you’ll need to first install Composer. Then, simply clone the repo, and install the dependencies. Git clone git://github.com/illuminate/app.git myApp and composer install. You’re ready to go!

Eloquent

Most PHP developers begin their journey by nesting countless lines of SQL directly into their frigid, unreadable PHP. Needless to say, excluding the most basic of websites, this quickly leads to an unmaintainable mess.
Remember when you first heard about Ruby on Rails’ ActiveRecord? Well, in the PHP end of the world, Eloquent is its premier implementation.
Need some examples?

001 // Fetch all tasks
 002 $tasks = Task::all();
 003 
 004 // Fetch the task with an id of 1
 005 $task = Task::find(1);
 006 
 007 // Update a task
 008 $task = Task::find(1);
 009 $task->title = ‘Put that cookie down!’;
 010 $task->save();
 011 
 012 // Create a new task
 013 Task::create([
 014     ‘title’ => ‘Write article’
 015 ]);
 016 
 017 // Delete a task
 018 Task::find(1)->delete();

Folks, it’s not possible to write more readable code in PHP! Now it would be one thing if Eloquent only allowed you to perform basic CRUD operations on a table, but that’s certainly not the case.
Consider for a moment table relationships, such as a user and their respective tasks. In Laravel, after setting a quick lookup method for each model, we can easily handle one-to-one relationships – or any kind of association for that matter. Here are a few examples, just to whet your appetite.

001 // Get all tasks by the author with an id  of 1
 002 $tasks = User::find(1)->tasks;
 003 
 004 // Get the author of a task
 005 $author = Task::find(5)->user()->username;
 006 
 007 // Insert a new task by author
 008 $task = new Task([ title: ‘Go to store.’    ]);
 009 User::find(1)->tasks()->insert($task);

It’s not a stretch to consider Eloquent to be the best ActiveRecord implementation in the PHP language.

Composer packages

Beginning with Laravel 4 (currently in Alpha), the entire framework will be modularized and available as individual Composer packages.
Composer is a packaging system for PHP that is similar to PEAR, but better. It makes the process of dependency management as easy as possible.
Think of the existing framework ecosystem. Right now, you’re forced to live with each framework’s core set of features. You can’t choose to, say, use Eloquent in a CakePHP application. As you can imagine, this truth has lead to an insane process of reinventing the wheel over and over… and over.
Ladies and gentleman, the future of PHP is a modular one. Why install a bloated, massive framework, when you only require a few of its offerings? Well soon you won’t have to. Only require Eloquent in a simple project? Fine – not a problem at all! Simply install it through Composer, and move on!
So, if we’re moving to a more package-based, modular PHP world, how does Laravel fit in? Well, think of it as a predetermined collection of packages, wrapped in a bow! Even better, should you need to update to the latest version of the framework, it’s as easy as running composer update.
As an example of the flexibility that this provides, let’s add the popular Mockery testing library to a Laravel application. Begin with a new Laravel 4 project, and edit its composer.json file to require Mockery.

001 {
 002 “require”: {
 003 “illuminate/foundation”: “>=1.0.0”,
 004 “mockery/mockery”: “dev-master”
 005 },
 006
 007 “autoload”: {
 008 “classmap”: [
 009 “app/controllers”,
 010 “app/models”,
 011 “app/database/migrations”,
 012 “app/tests/TestCase.php”
 013 ]
 014 }
 015 }

Refer to packagist.org for a list of Composer packages, as well as installation instructions. Now that we’ve informed Composer that our application requires Mockery, we can install the applicable dependencies.

001 composer update 

And voila, that’s it! We can now use Mockery within our tests. This is the power of Composer and Laravel 4 at work! We have wheels; let’s stop creating new ones! Hundreds upon hundreds of packages are available through Packagist.org.

001 < ?php 
 002 use Mockery as m; 
 003 class ExampleTest extends PHPUnit_Framework_TestCase {} 

Routes

Most beginner PHP developers aren’t familiar with anything other than the most natural of route systems. Create a directory tree to match your desired URI, and move on. For example, add an index.php file to the following directory: blog/admin/, and now you can access it by browsing to: localhost:8888/blog/admin/index.php. Easy! Well, maybe at first, but you’ll likely find that you need more flexibility and control over which route is triggered in your application.
Laravel takes an incredibly simple and easy-to-use approach to routing. As an example, let’s write the necessary route to display a view for a user’s profile.

001 Route::get(‘users/{id}’, function($id) 
 002 {
 003 // find the user
 004 $user = User::find($id); 005
 006 // display view, and pass user object
 007 return View::make(‘users.profile’)
 008 ->with(‘user’, $user);
 009 });

Now, when a user requests example.com/users/1, the users/profile.php view will be rendered.
Alternatively, we can use traditional controllers to instead handle the logic.

001 Route::get(‘users/{id}’, ‘Users@show’); 
Now, Controllers/Users.php will be responsible for rendering the view – specifically the show method.
 001 < ?php 002 003 class UsersController extends Controller { 004 /** 005 * Display the specified resource. 006 */ 007 public function show($id) 008 { 009 // find the user 010 $user = User::find($id); 011 012 // display view, and pass user object 013 return View::make(‘users.profile’) 014 ->;with(‘user’, $user);
 015 }
 016 }

Easy Authentication

Nearly any web application of any substance will require a form of authentication on some level. Laravel provides a simple but easy to use interface for authenticating users.
Begin by creating a users table with the necessary fields for the username and password. Remember: this is a perfect use-case for a migration!
Laravel can then attempt to login a user – probably based upon user-supplied values from a form. Here’s a basic example, minus the validation aspect.

001 Route::post(‘login’, function() 
 002 { $credentials = array(
 003 ‘username’ => Input::get(‘username’),
 004 ‘password’ => Input::get(‘password’)
 005 ); 
 006
 007 // perform validation 
 008
 009 if ( Auth::attempt($credentials) ) 
 010 { 
 011 // Credentials match. Logged in! 
 return Redirect::to(‘admin/profile’); 
 012 } 
 013 }); 

Note that behind the scenes Laravel will automatically hash the provided password and compare it against what’s stored in the user’s table.
Assuming that the user’s credentials match, the user ID will be stored in the session, and the user will be logged in. Upon subsequent requests, you can grab the currently logged in user’s username with:

001 $user = Auth::user()->username; 

Sending Email

Admit it: sending email through your application is always more complicated than it should be. Not anymore in Laravel 4!
Built on top of the popular SwiftMailer package, you’ll now find a new config/mail.php file in your application. This is where you can specify the necessary credentials to your email provider. Here’s a stripped down version of what you’ll find:

001 < ?php 002 // app/config/mail.php 003 004 return array( 005 ‘host’ => ‘smtp.example.com’,
 006 ‘port’ => 2525,
 007 ‘from’ => array(‘address’ => null, ‘name’ => null),
 008 ‘encryption’ => ‘tls’,
 009 ‘username’ => null,
 010 ‘password’ => null,
 011 );

Simply replace the values with those from your email server, accordingly.
Next, we need a view for the email. Let’s create one called ‘welcome.blade.php’, which will be used when a new member registers for our Justin Bieber fan website.

001 < ?php
 002 // app/views/emails/welcome.blade.php
 003
 004 005
 006 Hi there, {{ $user->name }}. Thanks again for signing up for the latest Justin Bieber news! We’ll look forward to seeing you around.
 007
 008 Thanks,
 009 Management
 010 011 

With everything in place, let’s set up the necessary example route, and send the email.

 001 Route::get(‘/’, function()
 002 {
 003 $user = User::find(1);
 004 $data = [ ‘user’ => $user ];
 005
 006 // email view, data for view, closure to send email
 007 Mail::send(‘emails/welcome’, $data, function($message) use($user)
 008 {
 009 $message
 010 ->to($user->email)
 011 ->subject(‘Welcome Bieber Fan!’)
 012 ->attach(‘images/bieberPhoto. jpg’);
 013 });
 014 return ‘Welcome email sent!’;
 015 });

Pretty simple, eh? We grab the new user from the table, and fire off an email to that user’s associated email address. Thanks to the SwiftMailer functionality, performing seemingly complex actions, such as attaching files, is a cinch! Now, every new member receives a photo of Justin Bieber upon signup. Perfect!

BFFs with Backbone

Laravel 4 makes the process of creating RESTful APIs as simple as humanly possible. The key is in how, by default, JSON will be returned from a route.
Let’s imagine that we need to return a list of all users as JSON. Well, we can accomplish that in a single line.

001 Route::get(‘users’, function()
 002 { 
 003 return User::all(); 
 004 }); 

If you go ahead and run this route, a bit of JSON will be displayed, such as:

001 [{“id”:1,”username”:”jeffrey@example. com”},{“id”:2,”username”:”joe@example.com”}] 

Are you wondering where the password field is? In Laravel, within the table’s associated model, we can specify, via a $hidden property, which fields to hide from JSON output.
Now, with a JavaScript library like Backbone, we can fetch this data with ease.

001 var User = Backbone.Model.extend({});
 002 var UsersCollection = Backbone.Collection. extend({
 003 model: User,
 004 url: ‘/users’
 005 });
 006
 007 var users = new UsersCollection;
 008 users.fetch();
 009
 010 users.toJSON(); // [Object, Object, Object]

What about fetching a single user instead? Well, we’d first need to set up the proper Laravel route:

001 Route::get(‘users/{id}’, function($id) {
002 return User::find($id); 
 003 }); 

As we’ve learned, this will return the JSON for the requested user (minus the password). Next, we create a Backbone model, and fetch the data.

001 var User = Backbone.Model.extend({ 
 002 urlRoot: ‘/users’ 
 003 }); 
 004
 005 var user = new User({ id: 1 }); 
 006 user.fetch(); // { id: 1, username: ‘jeffrey@example.com’ } 

Notice how the brunt of the work is on the
client-side? Our Laravel code is as barebones as it
can possibly be.

Migrations

If you’re exclusively a PHP developer, it’s likely that you haven’t yet experienced the joy of migrations, which were first popularised by the Ruby on Rails framework. Think of migrations as version control for your database. What would happen if, the day after you added that new field to your tasks table, you realised that it wasn’t needed after all? Well, you’d manually remove the field, right? But what about the other developers on your team? Their code may break if you don’t tell them. With migrations however, we merely roll back the previous migration, and continue on with our day! Even better, when pushing changes to your server, a simple php artisan migrate command will automatically update your production database. When combined with Laravel’s Schema Builder, this makes the process of managing databases as easy as possible.
Let’s create a migration to add a new users table to our database. From the command line:

001 php artisan migration:make create_users_ table --table=users --create 

In the snippet above, we specify the name of the table, as well as the –create flag. This is to specify that we’re creating a new table, rather than simply modifying an existing one.
This command will create a new migration file within our application. We can then leverage Laravel’s Schema class to prepare our table’s schema.

001 < ?php
002
003 use IlluminateDatabaseMigrations Migration;
004
005 class CreateTasksTable extends Migration {
006 /**
007 * Run the migrations.
008 */
009 public function up()
010 {
011 Schema::create(‘tasks’, function($table)
012 {
013 $table->increments(‘id’);
 014 $table->string(‘title’);
 015 });
 016 }
 017
 018 /**
 019 * Reverse the migrations.
 020 */
 021 public function down()
 022 {
 023 Schema::drop(‘tasks’);
 024 }
 025 }

Notice how this class offers two methods: up and down, which specify what action Laravel should take when executing a migration, as well as rolling it back.
In this case, on up(), we create a new table, tasks, and specify two fields for the id and title of the task, respectively. When rolling back the migration, we simply drop the table.
Run the migration by returning to the Terminal,
and typing:

001 php artisan migrate 

That’s it! You now have a brand new tasks table with two fields! Uh oh, need to roll it back? Simple:

001 php artisan migrate:rollback 

Goodbye tasks table.

Blade

Laravel’s Blade templating engine provides a clean syntax for views. For example, with regular PHP, to filter through a list of people and echo their respective names within a list item, we might write:

001 < ul> 
 002 <  ?php foreach($people as $p) : ?> 
 003 < li>< ?php echo $p; ?> 
 004 <  ?php endforeach; ?> 
 005 < /ul> 

This syntax can be applied to most of PHP’s control structures. It’s not too bad, but we can do better. Any Laravel view that contains the .blade.php file extension will be parsed accordingly. As a result, the previous snippet can be then replaced with:

 001 < ul> 
 002 @foreach($people as $p) 
 003 < li>{{ $p }}< /li> 
 004 @endforeach 
 005 < /ul> 
 

Notice how variables to be echoed are wrapped within {{ }}, similar to what you’d find in a JavaScript templating engine, like Handlebars.
Blade may also be used for elegant layouts and master pages. Let’s create a base master view to demonstrate this functionality.

 001 // views/layout.blade.php
 002 <  !doctype html>
 003 < html>
 004 < head>
 005 < title>
 006 < /head>
 007 < body>
 008 < div class=”container”>
 009 @yield(‘container’)
 010 < /div>
 011 < /body>
 012 < /html>

The @yield line is key here. This specifies that any child views with a section id of container should be nested there. Let’s next create a new view.

 001 // views/home/hello.blade.php
 002 @layout(‘layout’)
 003 
 004 @section(‘container’)
 005 < h1>Hello, {{ $user->name }}!< /h1>
 006 @endsection

Done! Easy master pages in PHP!

Resourceful Controllers

Without a bit of help, creating a RESTful service in PHP can prove to be somewhat difficult. Well, in Laravel 4, it couldn’t be simpler. The framework offers what we refer to as Restful Resources. Let’s test it out.
Within your routes file, specify a new resource.

001 Route::resource(‘tasks’, ‘TasksController’); 

This line of code designates that we want to create a new resource, tasks, and place the TasksController controller in charge of handling the logic for each route.
When following the principles of REST, this resource will automatically register routes for:

 GET tasks (Show all tasks)
 GET tasks/{id} (Show single task)
 GET tasks/create (Display form to create a new task)
 POST tasks (Create a new task)
 GET task/{id}/edit (Edit single task)
 PUT tasks/{id} (Update task)
 DELETE tasks/{id} (Delete task)

Next, let’s create that TasksController, but, rather than doing it manually, we’ll let Artisan handle the boilerplate.

001 php artisan controller:make TasksController

This will create a new controllers/TasksController.php controller, and fill it with a bit of boilerplate.

 001 < ?php
 002
 003 class TasksController extends Controller {
 004 /**
 005 * Display a listing of the resource.
 006 */
 007 public function index() {}
 008
 009 /**
 010 * Show the form for creating a new resource.
 011 */
 012 public function create() {}
 013
 014 /**
 015 * Store a newly created resource in storage.
 016 */
 017 public function store() {}
 018
 019 /**
 020 * Display the specified resource.
 021 */
 022 public function show($id) {}
 023
 024 /**
 025 * Show the form for editing the specified resource.
 026 */
 027 public function edit($id) {}
 028
 029 /**
 030 * Update the specified resource in storage.
 031 */
 032 public function update($id) {}
 033
 034 /**
 035 * Remove the specified resource from storage.
 036 */
 037 public function destroy($id) {}
 038 }
 

Each of these methods will be triggered when the applicable RESTful route is triggered. So to display a form to create a new task, we’d load the applicable view within the create method, which will be triggered when example.com/tasks/create is requested. That form should POST to /tasks, in which case the store method will be triggered.
It couldn’t be cleaner!

Database Seeding

How many times have you found yourself manually seeding a database table with dummy records, for the purposes of testing? For me, well, it’s a large number! Laravel 4 allows us to specify a seed file for a table.
To try it out, create a new file with the same name as its respective table within the app/database/seeds directory of your application. This file should store an array of arrays, each containing the necessary key-value pairs. Here’s an example:

 001 < ?php
 002 // app/database/seeds/tasks.php
 003 
 004 return [
 005 [ ‘title’ => ‘Go to the store’ ]
 006 [ ‘title’ => ‘Finish Laravel article’ ]
 007 [ ‘title’ => ‘Pick up eggs.’ ]
 008 ]);

We’ve now described three new rows for the tasks table in our database. Let’s seed it.

001 php artisan db:seed 

Done!

Model Setters and Getters

There’s likely a variety of actions that you frequently trigger when setting or getting a field from a database table. For instance, when a user registers, to follow security best practices, we should always hash their password. Rather than manually doing the work, let’s instead update the User model, and specify that when setting a password, it should first be hashed.

001 < ?php
002 // models/User.php
003 
004 class User extends Eloquent {
005 public function setPassword()
006 {
007 return Hash::make( $this->;password );
 008 }
 009 }

Easy! Now, we never have to worry about that piece of the puzzle when registering a new user. Naturally, the reverse option is available as well, should you need process a field’s value before getting it. What if we need to prettify a timestamp or name? This too can be accomplished through the model if you wish.

001 < ?php
002 // models/User.php
003 class User extends Eloquent {
004 public function fullName()
 005 {
006 return $this->firstName . ‘ ‘ . $this->lastName;
 007 }
 008 }

This new fullName() method will now be available to our user instance.

001 echo User::find(1)->fullName(); // John Doe

Community (Conference)

Perhaps more important than anything else, Laravel, in a relatively short timespan, has amassed a thriving, evangelical community, comprised of some of the most influential developers in the PHP community.
Why is this important? Simple: with evangelism comes education and contribution. The biggest hurdle for a new framework is getting the word out, and showing folks how to use it. Luckily, Laravel excels in documentation and tutorials and screencasts – including a full course by yours truly!
Truth is, we’ve barely scratched the surface of what’s possible in Laravel. We’ve yet to cover Laravel’s error handling, PHPUnit integration, eager loading (before and after retrieving collections), and much more. Be sure to refer to the documentation to dig deeper into the framework, and keep your eyes peeled for the official release of Version 4!

×