Advertisement

Why Laravel is Taking the PHP Community by Storm

by

This Cyber Monday Tuts+ courses will be reduced to just $3 (usually $15). Don't miss out.

I must admit: at one point, I was feeling a bit down on the PHP language. A number of poignant PHP-hate articles were circling the web like a virus, and some of its flagship frameworks, like 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, I found myself reaching for my Ruby toolbelt more and more.

But, then, one day, I discovered a new, elegant framework, called Laravel. At first, I dismissed it as yet another Sinatra clone that would quickly diminish into nothingness, as the lead developer abandoned it. But still, week after week, my social network feeds were in a flurry, praising Laravel's readability. "Could it be," I thought to myself, "that PHP finally has a truly modern framework?"

Learn more about Laravel at http://laravel.com

No longer was I willing to sit on the sidelines; it was time to dig in. A year later, and I'm one of its biggest evangelists. Laravel actually makes PHP fun again! Even better, I no longer believe that PHP is forever doomed to mostly personal sites and ugly WordPress blogs. Nope; in fact, it's this writer's belief that, thanks to Laravel, Composer, and PHP 5.5, we'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?

// Fetch all tasks
$tasks = Task::all();

// Fetch the task with an id of 1
$task = Task::find(1);

// Update a task
$task = Task::find(1);
$task->title = 'Put that cookie down!';
$task->save();

// Create a new task
Task::create([
    'title' => 'Write article'
]);

// Delete a task
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 table relationships, such as a user and his/her respective tasks. In Laravel, after setting a quick lookup method for each model, we can easily handle one-to-one relationship, or any association for that matter. Here's a few examples to whet your appetite.

// Get all tasks by the author with an id of 1
$tasks = User::find(1)->tasks;

// Get the author of a task
$author = Task::find(5)->user()->username;

// Insert a new task by author
$task = new Task([ title: 'Go to store.' ]);
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.

{
    "require": {
        "illuminate/foundation": ">=1.0.0",
        "mockery/mockery": "dev-master"
    },
    "autoload": {
        "classmap": [
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/tests/TestCase.php"
        ]
    }
}

Refer to Packagist.org for a list of available Composer packages, as well as installation instructions.

Now that we've informed Composer that our application requires Mockery, we can install the applicable dependencies.

composer update

And 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.

<?php

use Mockery as m;

class ExampleTest extends PHPUnit_Framework_TestCase {}

Hundreds upon hundreds of packages are available through Packagist.org.


Routes

Most beginning 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.

Route::get('users/{id}', function($id) {
    // find the user
    $user = User::find($id);

    // display view, and pass user object
    return View::make('users.profile')
        ->with('user', $user);
});

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.

Route::get('users/{id}', 'Users@show');

Now, Controllers/Users.php will be responsible for rendering the view - specifically the show method.

<?php

class UsersController extends Controller {
    /**
     * Display the specified resource.
     */
    public function show($id)
    {
        // find the user
        $user = User::find($id);

        // display view, and pass user object
        return View::make('users.profile')
            ->with('user', $user);
    }
}

Easy Authentication

Nearly any web application of substance will require some form of authentication. 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.

Route::post('login', function()
{
    $credentials = array(
        'username' => Input::get('username'),
        'password' => Input::get('password')
    );

    // perform validation

    if ( Auth::attempt($credentials) )
    {
        // Credentials match. Logged in!
        return Redirect::to('admin/profile');
    }
});

Note that, behind the scenes, Laravel will automatically hash the provided password, and compare it against what's stored in the users 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:

$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:

<?php
// app/config/mail.php

return array(
    'host' => 'smtp.example.com',
    'port' => 2525,
    'from' => array('address' => null, 'name' => null),
    'encryption' => 'tls',
    'username' => null,
    'password' => null,
);

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.

<?php
// app/views/emails/welcome.blade.php

<html>
    <body>
        Hi there, {{ $user->name }}. Thanks again for signing up for the latest Justin Bieber news! We'll look forward to seeing you around.

        Thanks,
        Management
    </body>
</html>

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

Route::get('/', function()
{
    $user = User::find(1);
    $data = [ 'user' => $user ];

    // email view, data for view, closure to send email
    Mail::send('emails/welcome', $data, function($message) use($user)
    {
        $message
            ->to($user->email)
            ->subject('Welcome Bieber Fan!')
            ->attach('images/bieberPhoto.jpg');
    });

    return 'Welcome email sent!';
});

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

"Backbone provides structure for your messy spaghetti code!"

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, Chuck, we can accomplish that in a single line.

Route::get('users', function()
{
    return User::all();
});

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

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

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.

var User = Backbone.Model.extend({});
var UsersCollection = Backbone.Collection.extend({
    model: User,
    url: '/users'
});

var users = new UsersCollection;
users.fetch();

users.toJSON(); // [Object, Object, Object]

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

Route::get('users/{id}', function($id) {
    return User::find($id);
});

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.

var User = Backbone.Model.extend({
    urlRoot: '/users'
});

var user = new User({ id: 1 });
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 possible.


Migrations

If you're exclusively a PHP developer, it's likely that you haven't yet experienced the joy of migrations, which were first popularized 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 realized 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 automagically 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:

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, to specify that we're creating a new table, rather than 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.

<?php

use Illuminate\Database\Migrations\Migration;

class CreateTasksTable extends Migration {
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('tasks', function($table)
        {
            $table->increments('id');
            $table->string('title');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        Schema::drop('tasks');
    }
}

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:

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:

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:

<ul>
    <?php foreach($people as $p) : ?>
        <li><?php echo $p; ?></li>
    <?php endforeach; ?>
</ul>

This syntax can be applied to most of PHP's control structures.

That'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:

<ul>
    @foreach($people as $p)
        <li>{{ $p }}</li>
    @endforeach
</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.

// views/layout.blade.php
<!doctype html>
<html>
<head>
    <title></title>
</head>
<body>
    <div class="container">
        @yield('container')
    </div>
</body>
</html>

The @yield line is key. This specifies that any child views with a section id of container should be nested there.

Let's next create a new view.

// views/home/hello.blade.php
@layout('layout')

@section('container')
    <h1>Hello, {{ $user->name }}!</h1>
@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.

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.

php artisan controller:make TasksController

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

<?php

class TasksController extends Controller {
    /**
     * Display a listing of the resource.
     */
    public function index() {}

    /**
     * Show the form for creating a new resource.
     */
    public function create() {}

    /**
     * Store a newly created resource in storage.
     */
    public function store() {}

    /**
     * Display the specified resource.
     */
    public function show($id) {}

    /**
     * Show the form for editing the specified resource.
     */
    public function edit($id) {}

    /**
     * Update the specified resource in storage.
     */
    public function update($id) {}

    /**
     * Remove the specified resource from storage.
     */
    public function destroy($id) {}
}

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!

Refer to UserScape's Vimeo page for the latest official Laravel screencasts


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:

<?php
// app/database/seeds/tasks.php

return [
    [ 'title' => 'Go to the store' ]
    [ 'title' => 'Finish Laravel article' ]
    [ 'title' => 'Pick up eggs.' ]
]);

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

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.

<?php
// models/User.php

class User extends Eloquent {
    public function setPassword()
    {
        return Hash::make( $this->password );
    }
}

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.

<?php
// models/User.php

class User extends Eloquent {
    public function fullName()
    {
        return $this->firstName . ' ' . $this->lastName;
    }
}

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

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, that is composed of some of the most influential developers in the PHP community.

Why is this important? Simple: with evangelism comes both education and contribution. The biggest hurdle for a new framework is getting the word out, and showing folks how to use the dang thing! Luckily, Laravel excels in documentation and tutorials/screencasts around the web - including a full course by yours truly!

Learn the ins and outs of Laravel here at Tuts+ Premium!

The truth is that 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 fantastic documentation to dig deeper into the framework, and keep your eyes peeled for the official release of Version 4!

The popular Nettuts+ community offers a number of Laravel-specific tutorials.

If this article served to be the impetus for your new-found love of PHP and Laravel, perhaps you'll consider attending the first annual Laracon (Conference), scheduled for late February, 2013, in Washington D.C. Maybe I'll see you there!

The first-ever Laravel conference, Laracon, will be held in Washington D.C. on February 22-23, 2013. Learn more at http://conference.laravel.com

Advertisement