Building Web Applications from Scratch with Laravel

Building Web Applications from Scratch with Laravel

Tutorial Details
  • Topic: Laravel PHP Framework (http://laravel.com)
  • Version: Laravel v3.2.1
  • Difficulty: Intermediate
  • Estimated Completion Time: 1 hour

In this Nettuts+ mini-series, we’ll build a web application from scratch, while diving into a great new PHP framework that’s rapidly picking up steam, called Laravel — a simple and elegant PHP 5.3 framework.

First up, we’ll learn more about Laravel, and why it’s such a great choice for your next PHP-based web application.


Introduction: What is Laravel

Laravel Website

Laravel is a clean and classy framework for PHP web development. Freeing you from spaghetti code, it helps you create wonderful applications, using simple, expressive syntax. Development should be a creative experience that you enjoy, not something that is painful. Enjoy the fresh air!

Laravel is a PHP 5.3 framework that describes itself as a “A Framework For Web Artisans”. According to its author, Taylor Otwell, Laravel strives to bring back the joy to programming by making Laravel simple, elegant, and, most importantly, well-documented.

From my experience with the framework, I would definitely agree that Laravel hits these three points dead-on:

  • Simple – Laravel’s functionalities are easy to understand and implement. If you enjoy how simple and easy CodeIgniter is, then you’ll love Laravel
  • Elegant – most of Laravel’s functions work seamlessly with very little configuration, relying on industry-standard conventions to lessen code-bloat
  • Well-documented – Laravel’s documentation is complete and always up-to-date. The framework creator makes it a point to update the documentation before releasing a new version, ensuring that people who are learning the framework always have the latest documentation.


What Makes Laravel Different?

As with any PHP framework, Laravel boasts a multitude of functions that differentiates it from the rest of the pack. Here are some, which I feel are the most important (Based on http://laravel.com/docs).

Bundles

Bundles are to Laravel as PEAR is to PHP.

Bundles are to Laravel as PEAR is to PHP; they are add-on packages that you can download and plug into your Laravel installation. At the moment, there are quite a few bundles in the Laravel Bundle Repository, with more being added all the time. Laravel comes with a command-line tool called Artisan, which makes it incredibly easy to install bundles.

Bob the Builder

One of my favorite Laravel Bundles, called Bob the Builder adds a useful scaffolding tool to Laravel, and lets you generate different kinds of files and classes suited for Laravel, such as controllers, models, migrations and tests. This functionality is quite similar to what you might expect from Rails generators. To install Bob, simply use the Artisan command-line utility, like so:

php artisan bundle:install bob

Eloquent ORM

The Eloquent ORM is the most advanced PHP ActiveRecord implementation available.

The Eloquent ORM is, by far, one of the best ORM implementations I’ve used. Similar to how Doctrine ORM functions, it makes any work on database records simple and easy. It abstracts most functions that you’ll have on models (i.e. CRUD operations) and provides a flexible way to add more. Additionally, the Eloquent ORM gives you the ability to define model relationships to retrieve records, based on their relationship to another record. For example, you can retrieve all related file records associated with a user by doing:

foreach( $user->Files as $file ) {
    echo $file->name;
}

Migrations

Database migrations are a great utility in any project’s arsenal – especially for projects where multiple developers are involved – by making it easy to keep your database schema up-to-date with other team member’s changes. In Laravel, migrations are built into the framework; they can be executed, via the Artisan command-line utility. Laravel’s own Schema Builder functions are simple enough that anybody should be able to quickly write up a database schema change.

Here’s an example, taken from the Laravel documentation:

Schema::table('users', function($table)
{
    $table->create();
    $table->increments('id');
    $table->string('username');
    $table->string('email');
    $table->string('phone')->nullable();
    $table->text('about');
    $table->timestamps();
});

Unit-Testing

Sane Programmer from the TDD tutorial

Remember this guy? Sane programmer FTW
Image courtesy of http://www.youthedesigner.com

As a believer in Test-Driven Development (Read for more info: The Newbie’s Guide to Test-Driven Development), I love it when a framework has some sort of unit-testing utility baked in. Laravel’s own beautifully integrates with PHPUnit, relying on its status as one of the industry’s best PHP unit testing frameworks. To build a test, simply extend the PHPUnit_Framework_TestCase class, like so:

class MyUnitTest extends PHPUnit_Framework_TestCase
{
    public function somethingShouldBeTrue()
    {
        $this->assertTrue(true);
    }
}

To run your Laravel application’s tests, let’s, again, use the Artisan command-line utility:

php artisan test

That command will run all tests, which are found within the application/tests directory of your Laravel application.

Redis

Redis is a key-value database, similar to CouchDB and MongoDB. It’s used by many web applications to store non-relational data, as opposed to conventional databases (like MySQL), which store records that usually relate to one another. Redis support in Laravel is executed so elegantly to the point that I can’t even begin to describe how easy it is to get up and running.

Once you have your Redis server set up, simply open the database.php file and add your Redis configuration, like so:

'redis' => array(
    'default' => array('host' => '127.0.0.1', 'port' => 6379),
    'staging' => array('host' => 'redis-db-staging.host', 'port' => 6379),
    'production' => array('host' => 'redis-db-production.host', 'port' => 6379),
)

Right off the bat, we can see that Laravel supports multiple Redis configurations, based on your application’s environment. Once you have your Redis configuration in, you can start making calls to Redis, like so:

$redis = Redis::db(); //this gets a Redis object connected to the 'default' configuration
$redis = Redis::db('staging'); //this gets a Redis object connected to the 'staging' configuration
$redis = Redis::db('production'); //this gets a Redis object connected to the 'production' configuration

$redis->set('site', 'Nettuts+');
$site = $redis->get('site');
$sites = $redis->lrange('sites', 0, -1);

Laravel provides a thin client for us, so all Redis commands can be called on the Redis class – Laravel takes care of converting it into the proper Redis query.


Building a Web Application from Scratch with Laravel

Now that we know more about Laravel, it’s time to start building our web application with it! Throughout this mini-series, we’ll be creating our very own Instagram copy, called Instapics. This little app lets you post, like, and comment on photos, as well as follow other users. With that in mind, let’s dive in!


Step 1: Download Laravel and Other Project Files

Before we begin, let’s first ensure that we have a system that can support Laravel. According to the documentation, Laravel requires the following:

  • PHP 5.3.x – Laravel makes use of a lot of PHP 5.3-specific features, like closures, late-static binding and namespaces.
  • The FileInfo library – this is enabled by default in PHP 5.3, but on Windows systems, you might need to add the extension in your PHP.ini configuration file.
  • Mcrypt library – this is used by Laravel for encryption and hash generation, and typically comes pre-installed with PHP.

Once we’re done setting up the environment, let’s download Laravel and all the libraries we’ll be using for Instapics. Download the following files and place them within a web-accessible folder:

Inside Laravel’s root folder, you’ll find a public folder – this is where all publicly accessible files should be stored. Laravel v3.2.1 has some premade folders inside the public folder for our assets, css, img, and js folders. Place the Twitter Bootstrap and jQuery files in their corresponding folders. At this point, your folder structure should look similar to the following:

Folder Structure

Twitter Bootstrap will have some files inside the css, img, and js folders, and jQuery will be inside the js folder.

Step 2: Setup Laravel’s Encryption Key, Pretty URLs and Virtual Host

Before we write any code, we need to set an encyption key for Laravel to use for our application. Laravel uses this to encrypt any data we might need encryption for, such as cookies. Open the application/config/application.php file and find the key setting. Inside, the default value will be YourSecretKeyGoesHere!. Set this to blank; it should look like so:

/*
|--------------------------------------------------------------------------
| Application Key
|--------------------------------------------------------------------------
|
| This key is used by the encryption and cookie classes to generate secure
| encrypted strings and hashes. It is extremely important that this key
| remain secret and should not be shared with anyone. Make it about 32
| characters of random gibberish.
|
*/

'key' => '',

Next, open up a Terminal/Command Prompt, browse to Laravel’s root directory, and use Artisan to generate a key:

php artisan key:generate

This should automatically generate a random 32 character encryption key for Laravel. If you did this correctly, it should now look like the following:

/*
|--------------------------------------------------------------------------
| Application Key
|--------------------------------------------------------------------------
|
| This key is used by the encryption and cookie classes to generate secure
| encrypted strings and hashes. It is extremely important that this key
| remain secret and should not be shared with anyone. Make it about 32
| characters of random gibberish.
|
*/

'key' => 'e9Vo0SQDe5HjsvXWcTogqKluVfEqnfEu',

If you want to regenerate your key, just repeat the steps!


Next, we need to change the configuration so that it can accept pretty-urls and work even without pointing our requests to index.php. In the application/config/application.php file, look for the following:

/*
|--------------------------------------------------------------------------
| Application Index
|--------------------------------------------------------------------------
|
| If you are including the "index.php" in your URLs, you can ignore this.
| However, if you are using mod_rewrite to get cleaner URLs, just set
| this option to an empty string and we'll take care of the rest.
|
*/

'index' => 'index.php',

If we want to enable pretty-urls, just make sure that the index setting is blank, like so:

/*
|--------------------------------------------------------------------------
| Application Index
|--------------------------------------------------------------------------
|
| If you are including the "index.php" in your URLs, you can ignore this.
| However, if you are using mod_rewrite to get cleaner URLs, just set
| this option to an empty string and we'll take care of the rest.
|
*/

'index' => '',

If you’re using this, you need to ensure that you have mod_rewrite enabled on your web server (if you’re on Apache).

Lastly, we’ll need to setup a virtual host for Laravel. This isn’t really necessary in a development environment, but, for production, it’s important that we don’t allow access to the Laravel library and application files. As mentioned above, in the Laravel files you should see a folder, called public, which is where all publicly accessible files should go. In addition to that, we need to make sure that our domain, http://instapics.com only points to the public folder and nowhere else.

Configuring a virtual host depends on which web server you’re using. Here’s an example for the Apache Web Server:

<VirtualHost *:80>
    ServerName instapics.com
	DocumentRoot "D:/Development/htdocs/instapics/public"
	<Directory "D:/Development/htdocs/instapics/public">	
	</Directory>
</VirtualHost>

We should also add the domain, instapics.com, to our hosts files (since this domain doesn’t really exist). In Windows, edit the file C:\Windows\System32\drivers\etc\hosts; in Linux/OSX, you usually edit /etc/hosts. Add this line to the file:

127.0.0.1 instapics.com

This will inform our machine that the domain instapics.com will resolve to 127.0.0.1, which is the local computer.

Step 3: Setup Routing

In Laravel, all requests to the application are mapped to specific functions or controller by Routes. They are responsible for instructing the application where URLs go. For example, if we wanted http://instapics.com/home to render the home view file, we can create the following route within routes.php, found inside the application folder:

Route::any('home', function()
{
    return View::make('home.index');
})

Alternatively, if we instead need to route http://instapics.com/home to a Controller, say, the home.php controller, we might do something like this:

Route::controller('home');

This would route to the home.php contoller file. Any action method there will be made available as well.

An important thing to note here is that by default, Laravel does NOT route to the controllers like other PHP-frameworks do. This is by design. By doing so, we can actually create simple pages without the need to create a controller for it. For example, if we wanted to create a static Contact Us page that just lists down contact information, we can simply do something like this:

Route::any('contact-us', function()
{
    return View::make('home.contact-us');
})

This will route http://instapics.com/contact-us and render the application/views/home/contact-us.php file. Since we don’t really have any dynamic processing on this page, we can just automatically render the view file, saving us the time to create and configure a controller to do so.

There is so much more that we can do with Routes in Laravel that it can stand on its own as its own tutorial. Stuff like:

  • HTTP Verbs – Laravel gives us the ability to create routes, based on the HTTP verb that was used in the request. For example, we can have a GET request to the /home route go somewhere different from where the POST request would go.
  • Wildcards – this lets us route a URL with a wildcard value attached to it (e.g. /user/(:num) where (:num) is the user’s ID)
  • Filters – these let us run some functionality before or after a route is executed, depending on the route that was called. For example, we can create an auth filter that will be called before all routes, except the home and about routes. In CodeIgniter, these are similar to Hooks, but much easier to implement, due to the fact that the filters are based on the routes – so we can implement them for all requests or just some.

For the purposes of this web application, though, we only need a couple of routes. First, a route that maps all requests to controllers by default. Open up the routes.php file, and comment out the default route to the Home controller:

/*
Route::get('/', function()
{
	return View::make('home.index');
});
*/

Below this bit of code, add the following line:

Route::controller(Controller::detect());

This line will map all our requests to all the controllers. If the controller or actions don’t exist, the system will return a 404 response.

Now, we create a route for http://instapics.com/about. Technically, we can just create a about controller, but that would be a waste, since we can just put that within the Home controller. Add the following line after the route we just created:

Route::controller(Controller::detect());
Route::get('about', 'home@about');

This route will direct all requests to http://instapics.com/about to the Home controller, and the About action.


Step 3. Create your First Laravel Controller

Controllers

Controllers anyone?

Controllers in Laravel are found inside the application/controllers folder. By default, the Home controller will accept requests sent to the root of the Laravel application. For example, going to http://instapics.com/ will go to the Home->action_index() method.

To create a controller, simply create a file inside the application/controllers folder. By convention, we’ll want to name the file something descriptive that will also be the name of the controller class. For now, let’s create a new controller for our login mechanism, called “Login”:

class Login_Controller extends Base_Controller
{    
    public function action_index()
    {
        //do our login mechanisms here
        echo 'test'; //echo test so we can test this controller out
    }
}

Next, open your browser and visit http://instapics.com/login. From here, you should see the “test” debug message that we placed. Since, in the routes.php file, we set it to enable routes to all the controller, this should work without any additional configuration. Once you’ve confirmed that it’s working, just remove the debug message. We’ll return to this controller in a future article.

For now, congratulate yourself; you’ve just created your first Laravel controller!

More Controller Fun

Filters

There’s a lot more that we can do with controllers, rather than them just being gateways to the view files. For example, remember the Filters feature that I mentioned earlier in the routes section? Aside from being attached to specific Routes, we can also attach them to specific controllers! Simply create a __constructor method for the controller, and setup the filter there. For example, if we need to ensure that a user is authenticated for all the methods in a controller, we can make use of our example auth filter:

public function __construct() {
    $this->filter('before', 'auth');
}

This will call the auth filter on all actions in this controller. If we wanted to target some specific actions, we can refer to the only method, like so:

public function __construct() {
    $this->filter('before', 'filter_name')->only(array('action', 'actionagain'));
}

We can alternatively use the except method to implement the filter on all actions, except a few:

public function __construct() {
    $this->filter('before', 'filter_name')->except(array('action', 'actionagain'));
}

Notice how expressive this code is?

We can even target a specific HTTP verb:

public function __construct() {
    $this->filter('before', 'filter_name')->except(array('action', 'actionagain'))->on('post');
}

The Base_Controller

Most, if not all, controllers extend the Base_Controller. This gives us a way to define methods that will be the same for all our controllers. For example, if we need to create a logging method to log any controller request:

class Base_Controller extends Controller {

    /**
     * Catch-all method for requests that can't be matched.
     *
     * @param  string    $method
     * @param  array     $parameters
     * @return Response
     */
    public function __call($method, $parameters)
    {
        return Response::error('404');
    }
    
    public function logRequest()
    {
        $route = Request::route();
        Log::log('request', "Controller: {$route->controller} / Action: {$route->controller_action} called at ". date('Y-m-d H:i:s'));
    }
}

Any time we want to log a request, we can just call $this->logRequest(); in any controller.

RESTful Controllers

Laravel’s RESTful controllers makes it easy to add RESTful responses to any Laravel controller. This makes it easy to create, for instance, a RESTful API. To do so, simply add the $restful flag to your controller:

class Api_Controller extends Base_Controller
{

    public $restful = true;

    public function post_authenticate()
    {
        //all POST requests to /api/authenticate will go here
        //any other requests that are NOT POST will NOT go here.
    }
    
    public function get_user()
    {
        $user_id = Input::get('id');
        //get the USER based on $user_id and return it for whoever requested it
    }
    
    public function post_user()
    {
        $email = Input::get('email');
        $password = Input::get('password');

        //Create a new User
        $user = User::create($email, $password);
    }
}

We’ll dive into all of these cool features in future tutorials, but, for now, let’s update the Home controller. We’ll need to add an an action_about method, since we created the http://instapics.com/about route to direct to this method. Open application/controllers/home.php, and update it, like so:

We append action_ to all action methods in our controllers (e.g. action_about). This signals to Laravel that these actions are viewable on the website. Any other methods, which don’t have the action_ prefix, will not be publicly accessible.

class Home_Controller extends Base_Controller {

    public function action_index()
    {
        return View::make('home.index');
    }

    public function action_about()
    {
        return View::make('home.about');
    }
}

Step 4. Create your first Laravel View with the Blade Templating Engine

Laravel supports two ways to generate views for an application:

  • PHP-based Views – these are views that make use of PHP as a templating language.
  • Blade-based Views – these are views that make use of Laravel’s built-in templating engine, called Blade.

The Blade Templating Engine is a templating framework that, similar to how the Smarty Templating Engine works, makes use of customized tags and functions to allow for better separation of presentation logic and application code.

For the sake of simplicity, we’ll be utilizing the Blade Templating Engine, as opposed to the PHP-based views.

All view files that will make use of the Blade Templating Engine needs to have a .blade.php extension. This tells Laravel to use the engine on the view file.

First, let’s create a general purpose layout that we’ll use for all our views. Create the application/views/layouts folder, and inside, create a file, named main.blade.php:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Instapics</title>
        {{ Asset::styles() }}
        {{ Asset::scripts() }}
    </head>

    <body>
        <div class="navbar navbar-fixed-top">
            <div class="navbar-inner">
                <div class="container">
                    <a class="brand" href="home">Instapics</a>
                    <div class="nav-collapse">
                        <ul class="nav">
                            @section('navigation')
                            <li class="active"><a href="home">Home</a></li>
                            @yield_section
                        </ul>
                    </div><!--/.nav-collapse -->
                </div>
            </div>
        </div>

        <div class="container">
            @yield('content')
            <hr>
            <footer>
            <p>&copy; Instapics 2012</p>
            </footer>
        </div> <!-- /container -->
    </body>
</html>

Now that we have our main layout, let's update the index file. Open application/views/home/index.blade.php and update it:

@layout('layouts/main')

@section('navigation')
@parent
<li><a href="/about">About</a></li>
@endsection

@section('content')
<div class="hero-unit">
    <div class="row">
        <div class="span6">
            <h1>Welcome to Instapics!</h1>
            <p>Instapics is a fun way to share photos with family and friends.</p>
            <p>Wow them with your photo-filtering abilities!</p>
            <p>Let them see what a great photographer you are!</p>
            <p><a href="about" class="btn btn-primary btn-large">Learn more &raquo;</a></p>
        </div>
        
        <div class="span4">
            <img src="http://d2o0t5hpnwv4c1.cloudfront.net/2064_laravel/img/phones.png" alt="Instapics!" />
        </div>
    </div>
    
</div>

<!-- Example row of columns -->
<div class="row">
    <div class="span3">
        &nbsp;
    </div>
    <div class="span4">
        <a href="#"><img src="http://d2o0t5hpnwv4c1.cloudfront.net/2064_laravel/img/badge_ios.png" alt="Get it on iOS" /></a>
    </div>
    <div class="span4">
        <a href="#"><img src="http://d2o0t5hpnwv4c1.cloudfront.net/2064_laravel/img/badge_android.png" alt="Get it on Android" /></a>
    </div>
</div>
@endsection

Let's review our view files. In the main layout template, we make use of three functions:

  • The Assets manager (Assets::styles(), Assets::scripts())
  • The @section Blade function (with @yield_section)
  • And the @yield Blade function

Managing Assets

Laravel provides a robust way to load CSS and JS files, via its Assets management functionality. The syntax for adding an asset is Assets::add('[asset name]', '[relative url from the public folder'], '[name of dependency, array of dependencies if multiple]'). The Assets manager also provides support for asset dependencies, which are used to tell Laravel to load the dependency first, before loading the asset.

We'll need to register our assets so that the view files will be able to use them. Open application/controllers/base.php, and add the following code:

public function __construct()
{
    //Assets
    Asset::add('jquery', 'js/jquery-1.7.2.min.js');
    Asset::add('bootstrap-js', 'js/bootstrap.min.js');
    Asset::add('bootstrap-css', 'css/bootstrap.min.css');
    Asset::add('bootstrap-css-responsive', 'css/bootstrap-responsive.min.css', 'bootstrap-css');
    Asset::add('style', 'css/style.css');
    parent::__construct();
}

By doing this, we make it easier to add, remove or update any assets that we need. We put it inside the Base controller's __construct() method to add the assets to all our controllers. To take advantage of this within a view, we simply call Assets::styles() for CSS files, and Assets::scripts() for the JS files in any view file. Laravel automatically determines what the asset type is, based on the file extension, and loads it with the appropriate asset group.

@section (and @yield_section)

Sections let us inject content into the main layout from within a view. To define which part of our main layout is a section, we surround it with @section and @yield_section Blade tags.

In our main view file, we've marked the navigation items as a @section (called navigation). Looking now at the index view file, we append the <>About> navigation link to the navigation bar with the following code:

@section('navigation')
@parent
<li><a href="about">About</a></li>
@endsection

By calling the @parent function, we instruct the view file to inherit the contents of the original section from the main layout. If we were to remove the @parent function, like so:

@section('navigation')
<li><a href="/about">About</a></li>
@endsection

Now, the index view file's navigation section will replace the main layout's navigation entirely. This makes the process of changing the main layout's HTML even more flexible.

@yield

The @yield function is similar to the @section/@yield_section function, but, instead, lets the nested view fill the content entirely. In our index file, we have a @section('content') function that replaces @yield('content').

Now, let's try passing in some variables to our views. First, create a new view file in the application/views/home folder for the About page. Let's call it about.blade.php:

@layout('layouts/main')

@section('navigation')
@parent
<li><a href="about">About</a></li>
@endsection

@section('content')
<div class="row">
    <div class="span3">
        <div class="well sidebar-nav">
            <ul class="nav nav-list">
                <li class="nav-header">Navigation</li>
                @foreach ($sidenav as $sn)
                <li @if ($sn['active']) class="active" @endif>
                    <a href="{{ $sn['url'] }}">{{ $sn['name'] }}</a>
                </li>
                @endforeach
            </ul>
        </div>
    </div>
    <div class="span9">
        <h1>About Instapics</h1>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ullamcorper lectus et sapien volutpat iaculis. Phasellus arcu justo, commodo ac ornare at, pellentesque vitae nulla. Sed id justo mauris, et semper est. Mauris id dui vitae felis hendrerit sollicitudin ut vel nisi. Phasellus a dolor quis tellus sagittis commodo. Suspendisse potenti. Donec sagittis rhoncus sem in venenatis. Nam sit amet leo metus. Mauris eget nisi eu felis interdum venenatis nec sed ipsum. Integer lobortis, risus non pellentesque pharetra, massa augue vulputate sem, quis sagittis arcu tortor sit amet nisi. Ut quis nibh sem. Morbi malesuada, lorem ac tincidunt venenatis, quam erat rhoncus sapien, et tempus quam mauris sit amet metus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam varius dictum lectus non placerat.</p>
        <p>Cras tincidunt, libero eu dignissim egestas, erat purus mattis urna, vitae pellentesque nisi turpis at velit. Vivamus vitae euismod nisi. Duis luctus ante nec neque fermentum vulputate. Phasellus in dolor quis mauris rhoncus consectetur ut quis lacus. Nulla facilisi. Nullam magna velit, accumsan vehicula consectetur a, vestibulum eget neque. Sed feugiat dui quis ligula convallis sed placerat dui dignissim. Aliquam interdum tempus leo, a hendrerit orci ultrices ut. Aliquam sem dolor, auctor eu mattis id, varius a massa. Fusce facilisis, massa id ultricies lacinia, urna nunc sollicitudin massa, sit amet posuere metus justo vitae metus. Vivamus in dolor quam, ut elementum libero. Proin vehicula diam eu diam consectetur ut imperdiet ipsum pulvinar. Cras eu est quis urna semper adipiscing ut et leo. Curabitur tristique consectetur aliquet. Phasellus quam neque, dapibus non eleifend quis, feugiat vel elit.</p>
    </div>
</div>
@endsection

Back in the Home controller, update the action_about() method:

public function action_about()
{
    return View::make('home.about', array(
        'sidenav' => array(
            array(
                'url' => 'home',
                'name' => 'Home',
                'active' => false
            ),
            array(
                'url' => 'about',
                'name' => 'About',
                'active' => true
            )
        )
    ));
}

Reviewing our code, we see that, in the Home controller, we pass in an array of parameters. Right now, these are hardcoded values, but they can come from anywhere - for example, from a model or database. These are passed to the view file, where we make use of some Blade tags to render the parameters.

@foreach ($sidenav as $sn)
...
@endforeach

This lets us loop through the array in our parameters.

<li @if ($sn['active']) class="active" @endif>

This is an if-statement. If we wanted to use an else, it would look like this:

@if ($sn['active'])
    class="active"
@else
    class="notactive"
@endif
<a href="{{ $sn['url'] }}">{{ $sn['name'] }}</a>

This is the most basic Blade tag - it just echoes the variable we set.

Take note that, within most of the Blade tags, we use good 'ol PHP. This makes it easier to write the Blade tags, since we'll be able to use native PHP functions, like isset() or count(). There are also other Blade tags that I wasn't able to use here; you can learn more about them in the Blade documentation. Trust me, it's pretty easy!


Conclusion

After reading this tutorial, we've learned:

  • What Laravel is
  • What makes Laravel different from other PHP frameworks
  • Where to download Laravel
  • How to setup Laravel
  • How Laravel's Routing system works
  • Some other features in Laravel's Routing system
  • How to create your first Laravel Controller
  • Some additional features with Laravel's Controllers
  • How to create your first Laravel View
  • How to use Laravel's Blade Templating Engine

Laravel is truly an amazing framework. It's fast, simple, elegant and so easy to use. It absolutely merits being considered as the framework to be used for your next project.

Next in our Building Web Application from Scratch with Laravel series, we'll learn about one of Laravel's best features: the Eloquent ORM and Fluent Query Builder.

What do you think about Laravel? Are you considering to use it for your next project? Let me know in the comments! And, if you're a Tuts+ Premium member, stay tuned for our upcoming Laravel Essentials course!

Tags: laravel
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://rickkippert.com Rick Kippert

    Great Tutorial! Just noticed you have 2 “Step 3″s.

  • Carlos

    Laravel is such a fun framework to work with.
    Although i had already grasped the basics, this did enlighten me on some points.

    Surprised to see not that many comments here.
    Laravel is still young but very robust and the community is very helpful.

    I totally recommend you check it out.

  • http://inkwell.dotink.org Matthew J. Sahagian

    I’m reminded again why I wrote my own.

    • http://net.tutsplus.com Jeffrey Way

      How so?

      • http://inkwell.dotink.org Matthew J. Sahagian

        Jeffrey, I personally think the number of “conventions” has gotten somewhat out of hand. Learning new frameworks these days essentially becomes learning entirely new coding patterns. I did a bit more research on their site last night, and while I must say it still looks a lot better than the other popular frameworks, it’s all a bit much in my opinion.

        I kinda got a kick out of it after I realized their slogan is “A PHP Framework for Web Artisans” — The slogan for mine is “A PHP Framework for PHP Developers,” which I think sums up some of the differences nicely.

        The “blade” templating style is not inutitive. It means templates at the bottom have to be concerned with what’s at the top. A large number of frameworks employ this to a degree when they do the standard equivalent to the following in every view:

        include(‘header.php’);

        include(‘footer.php’);

        Laravel seems to play mix and match and it ends up with two templates essentially including pieces from one another. While this may be flexible (allowing a very peer-like relationship between templates), it seems unnecessarily confusing.

        I think the split between action_whatever() vs. post_whatever(), put_whatever(), get_whatever() and so indicative of convention getting in the way of writing code, in my opinion. There was some discussion I saw on the forum about the possibility that action_whatever() could become a fallback if you have $restful = true;, but rather than that being a clean solution, because of the existing structure it just becomes another convention to remember.

        On that note, WTF is up with $restful = true? I’d be curious to rip apart the code and see what that actually does *other than* modifying routes to enforce the convention. I wonder, for example, if it throws a “not allowed” if someone were to DELETE on the example above which only implements get, put, and post.

        On Filters… they’re not expressive, they’re just plain long and convoluted. Using a clean enough global hook structure which actions call directly (when and if they need to) might result in *slightly* longer code, but I think, particularly for the example given (auth), that this would produce a lot more clarity of where, when, and why it is occurring. $this->in($my_mind)->isMuchLessExpressiveCode() than class::callHook(‘auth’); at the top of actions that require it.

        Last but not least… bundles and yet another command line tool. Don’t get me wrong, assuming (and it’s not very clear), that bundles are automatically downloaded and installed, the bundle system is perhaps half worth it. However, browsing a few bundles on github, I noticed rather quickly that these were injecting class to file mappings into the autoloader via a method. Again, something I’d be curious to look more behind if I had the time, i.e. is the logic from the bundle.php file appended to some larger bundle config… are all these separate files included during initialization?

        On the issue of the command line tool (particularly when all these things tend to be written in PHP to begin with), I’m not sure why the tendency has not been to do what I have done, which is basically to promote an interactive command line interface. Instead of having “php cli-tool action arg1 arg1″ you can easily make the internal workings of these more transparent and flexible by promoting access to the actual API(s) which make these commands possible. Furthermore, this allows for much more flexibility in terms of scripting or providing web access to the command line actions.

        Other than all of that, it’s not so bad. I see a lot of the ideas that I’ve incorporated into my framework in it. i.e. whenever the return View::make() I’m reminded of my controllers which will generally return View::create() — with nearly identical argument structure it appears too. But then I also saw an example of a controller which just did something like echo ‘string’; and wondered why in Laravel can’t I simply return ‘string’;

        Also, let me lastly clarify by stating that I understand these types of things are never “done” so my intention is not to knock it based on early stages of development and/or different priorities from mine, rather, it’s the replication of ideas from other frameworks (in my mind, the bad ones) which reminds me why I wrote my own. Laravel is much younger than inKWell, and has certainly established itself a lot faster, but it seems like an extension and repackaging of the ideas the lead me to write inKWell rather than something that new or interesting.

    • http://evanbyrne.com Evan

      I thought the same thing. Haha

    • Villi Magg

      @Matthew J. Sahagian, I’ve check your framework out and your screencast on Vimeo and I really like your framework and enjoyed your screencast, and I respect your work and think it’s awesome what your doing. I especially liked your CLI tool having touched Rails a bit from before.

      But, each time I see your posts here it looks like your always just talking down other frameworks. Even though they are potentially good. It’s kind of a bummer when people don’t see the good things and always have to talk down others stuff for the purpose of making them selfs look better.

      I’ve tried your framework and it didn’t work right out of the box and that for me is a big “make or break” factor when it comes to wether or not I’ll continue spending my time on it.

      All in all, with Laravel I got up to speed right from the start, which I think is most important in the web development industry today.

      Still I’ve got me eye on your framework and of course I will check your framework out when there’s an update out. But just wanted to say my opinion.

      Regards.

      • http://inkwell.dotink.org Matthew J. Sahagian

        @Villi

        If you read my longer post you will note that I do find some thing positive in Laravel. Frankly, if I were to use a framework other than mine, this would probably be the one. I drew some parallels between Laravel and my Framework, and I assume those come from the developer’s .NET background. i.e. returning views.

        That said, I’m not going to hold my tongue about the negatives — particularly where I see they might be as a performance issue. I’m more than willing to be educated, but no one ever takes the time to refute my arguments.

        For example, I brought up how the bundles register classes. And no one said “Oh yeah, the bundles will append the autoloader mapping to a single file.” If I install 10 bundles, do I really want 10 files being loaded/included for a single Autoloader::map() call? No.

        There’s other concerns I have which are similar. One of the ideas promoted is this ‘controllers::detect()’ method (or something similar to that), which detects the available routes… how does it do this? Presumably by loading all controller files right away!

        Obviously you can avoid these pitfalls if you “do it a certain way” — much like you can avoid the pitfalls of blade templates and the confusion they might cause by injecting pieces of one another in one another without any discernible hierarchy. I admitted this feature is powerful, but I have valid reasons for why it concerns me.

        What I can gather about the nettuts audience is that it is generally a lot of freelance developers, hobbyists, or very small shop developers who will never be concerned with someone having to pick up their code where they left off. The problem with 99% of modern frameworks is that they rely so heavily on conventions and “their way” of doing things that you can’t simply look at the code and understand it.

        I do not dare call my framework a production release yet, nor do I dare propose that anyone in particular should be using it. It is built first and foremost for myself. While I enjoy keeping the site documentation up as well as making videos for those who are interested, I am not here to say “you should be using my framework and not laravel.” That doesn’t, however, prevent me from saying, “here’s the problems I see with laravel.”

        With regards to your particular troubles. It would have been appreciated and beneficial if you had posted an issue on github when you ran into trouble. I’m not sure when, precisely, that you tried it, but I’m always willing to help someone who is interested in it. One of the things that often throws people after installing it is that there is no fancy default controller/view for when you first install. I.e. it’s not going to sit there and say “Welcome to inKWell yadda yadda.” Indeed, what you do see *looks* broken, and I’m aware of that.

        The framework installs in developer mode which means you see debug dumps, exceptions, etc, etc… so what generally happens is someone installs it, and sees a debug dump from the routing system that basically says “There’s nothing for me to do.” I don’t particularly see a point in creating a fancy hello page when realistically the first thing someone is going to do is wipe it out to replace it with their own stuff.

        If you are truly interested, I would certainly appreciate questions or feedback either on github via issues or directly through e-mail info@dotink.org.

      • http://inkwell.dotink.org Matthew J. Sahagian

        I should also mention that disqus is on the main site, so you can post comments or questions there in relevant sections if you have issues. Getting feedback in a Nettuts comment is a start, but problems can’t be fixed or solved if they’re not actually reported in a useful way. One final note on the issue of releases/updates. I make commits at least once a week generally. Since it is still classed as beta I don’t particularly version them — so if you are generally interested in following the progression of it,, your best bet is to follow it on github.

        Other than that, thanks for trying it.

      • Villi Magg

        @Matt

        Thank you for your reply. I agree with you on many things. I would also not use Controller::detect() and some things in this article which I think you could do differently.

        I also agree with you on the landing page thing. The first thing I do when starting a new project is wipe the landing page out. And it’s natural that when a framework is downloaded that by default it’s in developer mode. Makes sense, I have never heard of a website published with the default landing page from the author of the framework, and naturally when you fire up the framework for the first time the project is likely to be in development. So alot which you say is true. And like I said, your CLI tool is awesome.

        I’ll be sure to send you something when I hit an error when trying your framework. Thanks!

        Best regards,
        Villi

      • http://my.crynobone.com crynobone

        Sorry for replying there, Nettuts only support few hierarchy of replies. I’m not the best to answer some of the question asked by @Matthew J. Sahagian but it should be made clear for everyone who genuinely interested in learning Laravel.

        1.On that note, WTF is up with $restful = true? I’d be curious to rip apart the code and see what that actually does *other than* modifying routes to enforce the convention. I wonder, for example, if it throws a “not allowed” if someone were to DELETE on the example above which only implements get, put, and post.

        $restful = true allow user to use HTTP verbs instead of the default action_method(), and it would return 404 HTTP status if you try to access delete_method() when the method is not define in the Controller.

        Nothing fancy just a nice feature, if you have looked in FuelPHP they started with a Base_Controller, Template_Controller and Rest_Controller (now add Hybrid_Controller to support Template and Rest in a single Controller) while Laravel made it straight away in a single Controller.

        2. On Filters… they’re not expressive, they’re just plain long and convoluted. Using a clean enough global hook structure which actions call directly (when and if they need to) might result in *slightly* longer code, but I think, particularly for the example given (auth), that this would produce a lot more clarity of where, when, and why it is occurring. $this->in($my_mind)->isMuchLessExpressiveCode() than class::callHook(‘auth’); at the top of actions that require it.

        I would see having a single $this->filter(‘before’, ‘auth’)->only(array(‘method’, ‘another’)); would require *slightly* less code than duplicating it on each method that require it, and also you can use ->only() chaining to run the filter on GET, POST, PUT or DELETE rather than having an if condition to check in every action.

        3. Last but not least… bundles and yet another command line tool. Don’t get me wrong, assuming (and it’s not very clear), that bundles are automatically downloaded and installed, the bundle system is perhaps half worth it. However, browsing a few bundles on github, I noticed rather quickly that these were injecting class to file mappings into the autoloader via a method. Again, something I’d be curious to look more behind if I had the time, i.e. is the logic from the bundle.php file appended to some larger bundle config… are all these separate files included during initialization?

        Autoloader class only register the path and class alias, it doesn’t run the class until an executed code require/call it. bundle.php only check which bundle is installed (so you can run php artisan bundle:upgrade bundlename), and either it autostart when needed. It also support ‘handles’ => ‘route-to-bundle’ options which allow bundle to work as a module.

        With the same logic, I wouldn’t think inkWell would load all the class until it’s required too http://inkwell.dotink.org/architecture/autoloading

        On a sidenote, it would mentioning `application` folder is actually a bundle.

        4. Instead of having “php cli-tool action arg1 arg1″ you can easily make the internal workings of these more transparent and flexible by promoting access to the actual API(s) which make these commands possible. Furthermore, this allows for much more flexibility in terms of scripting or providing web access to the command line actions.

        I might not get your argument but couldn’t you use http://laravel.com/docs/artisan/tasks#the-basics

        5. Other than all of that, it’s not so bad. I see a lot of the ideas that I’ve incorporated into my framework in it. i.e. whenever the return View::make() I’m reminded of my controllers which will generally return View::create() — with nearly identical argument structure it appears too. But then I also saw an example of a controller which just did something like echo ‘string’; and wondered why in Laravel can’t I simply return ‘string’;

        Any route/controller can return string, instanceof View or instanceof Response. If a string or View is returned, the router class would prepare an instanceof Response object.

        6. There’s other concerns I have which are similar. One of the ideas promoted is this ‘controllers::detect()’ method (or something similar to that), which detects the available routes… how does it do this? Presumably by loading all controller files right away!

        Controller::detect() use FilesystemIterator to locate the files, it only locate the file and does not load it.

      • http://inkwell.dotink.org Matthew J. Sahagian

        @crynobone

        I understand the differentiation between action_whatever() and post_whatever() for $restful = true; — my point was that HTTP methods are not the only aspects of something being RESTful… and I guess to evidence that point, you have now clarified that it returns 404 rather than 405. If $restful = true; intends to make a controller RESTful, I would hope it actually does so as opposed to, as I said, simply creating alternative route maps. Assuming you’re correct about the behavior, then unfortunately I was correct in my assumption.

        On the issue of filters. I fully admit that it would require less code to used the method as provided. I believe that was the premise of what I said. The issue I have is the clarity of it. I can write some very clever code sometimes that is extremely concise… and I’m usually the only one who is able to understand it short term… long term, I’m generally lucky if I can even understand it. The point I was making was on clarity of code, not brevity. The term used is “expressive” — which seems to mean many different things to many different people.

        I gathered that the Autoloader class only registers the path and the class alias. My point was not about the classes contained in the bundle, but the Autoloader::map() line which is contained within a single bundle file. Presumably this is the method which registers the path and the class. My question was, how is this executed on a per bundle basis? I understand a bundle could have 10 classes and they will be autoloaded based on the Autoloader::map() line, my concern is if I have 10 bundles, is it including 10 files in order to execute their Autoloader::map() lines.

        I believe it is the ‘start.php’ files I’m referring to. Example: https://github.com/cockpito/Cockpito-PHP-Laravel-Bundle/blob/master/start.php

        This is not where I saw the Autoloader::map() call, but is another example. If I have 10 bundles, are 10 start.php files included every time my framework initializes?

        inKWell approaches these types of issues in a much more modular fashion allowing the configuration file to amend requisite system settings, i.e. an autoloader path or ‘root_directory’ for an extension (if indeed it needs it’s own). The equivalent IoC container logic (which is very different from configuration data) would likely be found in the class’s __init() method. This method is run when the class is loaded as opposed to when the framework is initialized.

        Unless you’re suggesting that the bundle’s start.php file is not executed UNTIL a class in that bundle is used, however, that would seem very strange because the start.php files contain directives for the autoloader.

        My argument on the CLI tool is simple. The CLI tool is written in PHP, that is clear since you execute it using php. The CLI tool abstracts Task methods, but also abstracts, presumably, a whole host of additional API calls since there additional options i.e. –database. My point is quite simply that there is little to no need to abstract these… in fact, all it does is make things more convoluted.

        If ‘php artisan class:method’ executes Class_Task::method() why not simply provide an interactive PHP shell in which the user directly types in Class_Task::method()? Instead *yet another convention is born*, classpart::classpart:method which can presumably go on forever, i.e. Really_Long_Name_For_Task is presumably really::long::name::for using the tool… All this does is create another convention which must be learned or would be unclear to someone simply looking at it and obfuscate the actual API which could be useful within web based non-CLI code.

        Using the example link you provided, I cannot help but imagine that there are people out there who do something like this inside their PHP:

        exec(‘php artisan notify:urgent’);

        Particularly if they’re not creating their own tasks, as it is probably unlikely they recognize this is equivalent to doing (new Notify_Task)->urgent();

        While it is good to know that Controllers::detect() does not load every controller file, locating them all does not seem drastically better. I guess what confuses me about methods like this is that Laravel seems to push the idea of explicit routing. I.e. the screencasts as well as tutorials talk about how some sort of convention based routing paradigm was abandoned in favor of explicitly defining routes (which is something I agree with btw)… however, this kinda abandons that notion as far as I can tell, it’s basically saying “We’re going to explicitly define a bunch of non-explicit routes..”

        Also, another thing I noticed just in some screencasts, on this same topic, seems to be that often times you get multiple URLs to a single action. This, I understand, can be difficult to avoid with more dynamic routing, however, from what I could tell Laravel was one of the worst offenders with this pattern, making /collection/index essentially equivalent to /collection/… *shudder*.

      • http://my.crynobone.com crynobone

        I understand the differentiation between action_whatever() and post_whatever() for $restful = true; — my point was that HTTP methods are not the only aspects of something being RESTful… and I guess to evidence that point, you have now clarified that it returns 404 rather than 405. If $restful = true; intends to make a controller RESTful, I would hope it actually does so as opposed to, as I said, simply creating alternative route maps. Assuming you’re correct about the behavior, then unfortunately I was correct in my assumption.

        A pull request to suggest 405 instead of 404 would be helpful if you really interested to make something useful instead of looking at what bads, don’t you think? Yes as I said, nothing fancy just a nice feature to have for those that need it. For example I personally would prefer to avoid checking for $_POST, or manually getting $_DELETE or $_PUT (which is not supported directly by PHP) in all my action. Laravel and most other “RESTful” Controller does it for me. Less code to maintain, less liability.

        The term used is “expressive” — which seems to mean many different things to many different people.

        Couldn’t agree with you more, people who find it expressive would use it while other can choose what the feel the most expressive to them. Why are we arguing tagline again?

        I gathered that the Autoloader class only registers the path and the class alias. My point was not about the classes contained in the bundle, but the Autoloader::map() line which is contained within a single bundle file. Presumably this is the method which registers the path and the class. My question was, how is this executed on a per bundle basis? I understand a bundle could have 10 classes and they will be autoloaded based on the Autoloader::map() line, my concern is if I have 10 bundles, is it including 10 files in order to execute their Autoloader::map() lines.

        Only application while start automatically, while bundle required a configuration to make them autoload in application/bundles.php, even so, Autoloader::map() only add the paths to static array, only during when you request some class e.g: new Cockpito\UDPClient() it would then use spl_autoloader to load the file based on the static array.

        Particularly if they’re not creating their own tasks, as it is probably unlikely they recognize this is equivalent to doing (new Notify_Task)->urgent();

        Only classes that are map into Autoloader can be execute directly, If you need to do make it available from both CLI interface as well as web interface wouldn’t it better to add it as a libraries so Controller\Route and Task use it both. But again it’s matter of perspective whether we like to follow a conversion or code it spaghetti like how we feel like at the moment.

        In any case, I don’t see what’s wrong by `php artisan bundle::task –args`, I couldn’t imagine you can do something like `php inkwell Task::run(‘make me run’, true)` is it?

        While it is good to know that Controllers::detect() does not load every controller file, locating them all does not seem drastically better. I guess what confuses me about methods like this is that Laravel seems to push the idea of explicit routing.

        Laravel was first built without Controller paradigm, it basically Model-View-Route, however by introducing Controller and RESTful some consideration should be considered, I couldn’t say much as I’m still new to Laravel but other framework also does the same with Controller, so do Laravel make a conversion for Controller or follows what other are doing. (You might like it but there would be others who going to as “Why Another CONVENSION”…).

    • cantera25

      @Matthew – I found your comments insightful, but was scared off from Inkwell by the heavy use of static function calls. Could you discuss how Inkwell’s testability compares to Laravel’s?

      • cantera25

        @Matthew – Never mind, looks like you addressed this further down in the chain.

  • http://- lollypopgr

    Great! I hope to post more tutorials like the ones you have build for CI. As always you’re doing a great job. Keep up :-)

  • Matt

    You know… I bet this is an outstanding framework, but it seems like I’m getting hit with another “great” framework everyday.

    Does the world really need yet another php framework?
    Will it get a large enough user base to ensure longevity?
    Will large corporations use it, thus helping those that invest their time learning it get jobs?
    Will I learn it just for personal use?
    Is it really that much better? And by how much?

    • http://lovebyte.co.uk/public/ Nathan

      I would love this framework to become even more popular than CI. It is well documented and an IRC channel if you want the help of other artisans :)

    • http://cartalyst.com Daniel Petrie

      1. I know its just my opinion, but its the best framework I’ve used yet out of CodeIgniter, FuelPHP and Laravel. Everyone has their own preference though. Laravel has taken a much different approach than most of the other frameworks I’ve seen and used, and is much easier to understand.

      2. It already has a fairly large user base for how new it is, and I’ve probably seen it double in size in just the last couple months.

      3. Userscape is built on and uses Laravel. They hired Laravel’s creator and give him time to develop the framework as well. The company I work for is building an Ecommerce engine with Laravel and I know of a few other developers who are making big projects with it also. I haven’t taken a look at the “job market” for it yet though.

      4, 5. All personal preference so I can’t answer that for you

    • http://brianswebdesign.com Brian Temecula

      Well, I can’t say for Laravel, but I got a great job because I use CodeIgniter. I’ve played with Laravel, and I don’t have a reason to switch right now. I guess my mind is so wrapped around CodeIgniter that unless somebody hired me and told me I had to use Laravel, then I probably would use what I know best. I really doubt that large corporations will even know what Laravel or CodeIgniter is, but again, I’m glad some do because knowing CodeIgniter has made a real difference in my wallet. I think if I was really bored and unemployed that I might make a site in Laravel just for better experience with it….

      • http://daylerees.com Dayle Rees

        There are a wide range of frameworks available, often people can’t decide which is the ‘best’ to use. It’s really up to the developer, the best framework will the one that provides the least amount of tiny annoyances, and works seamlessly with your development workflow.

        I used to use CodeIgniter, but became involved with Laravel shortly before version 2 was released. I love its simple expressive syntax, I love the way my code looks, and it’s validation ‘loops’ etc match the way I work. Often I would have to hack at Codeigniter to make it do things my way, but I rarely have to change anything with Laravel.

  • http://lovebyte.co.uk/public/ Nathan

    Hey, I am using the Laravel framework for my web app, took some time to choose the appropriate framework and I nearly went with CI or Yii but I chose Laravel for it’s fast page loads and auth stuff provided.

    This is a great article btw, great and comprehensive introduction into how the Framework works.

  • Jermaine

    The CLI seems nice but the static class architecture and implicit globals leaves a sour taste in my mouth. It’s not an OO framework. If you want OO look at Symfony2, Aura, ZF2, and Nette.

    • Kapil Verma

      Hey … i don’t think you can call laravel non-OO .. cos it is and its core has thorough unit tests written for it. The reason i guess for keeping many class properties public is because of heavy use of closures in this framework (you need stuff to be public to have it accessible in closures) … Laravel doesn’t force a big structure on you .. it just provides a neat and clean set of tools for you to work with. You can use proper OO in your app

  • http://ecustom.ca/ DamonB

    Glad to see Laravel is getting some recognition on Nettuts+! Saw the Twitter exchange between Jeffrey and some of the Laravel devs and looked forward to seeing what came out of it.

    To anyone needing help with any Laravel related problem: I highly suggest you head on over to the Laravel Forums with your problem. We are all very willing to help and share our knowledge.

  • Dave

    Great intro to Laravel. I saw yesterday there was a twitter bootstrap bundle released http://bundles.laravel.com/bundle/bootstrapper might be work using for the rest of the series

    • http://lovebyte.co.uk/public/ Nathan

      Nice find, got to love the he twitter bootstrap, especially for people like myself who are pretty good programmers but not so hot on the UI side lol

    • http://nikkobautista.com Nikko Bautista
      Author

      Thanks! I’ll see if I can use this. Might be a good starting point to teach about bundles :)

  • Brendan

    Fantastic – can’t wait for the next article!

    • Ashit Vora

      Me too :)

  • http://abdusfauzi.com abdusfauzi

    awesome and i have been waiting tutorials for Laravel! i’m totally new on this PHP Framework scene.

  • Brendan

    I tried following this tutorial, except the site i created is in a sub directory of the root folder htdocs (not sure if others would make all their test sites a sub folder?). Just needed to modify one line to make it work.

    For the file application/views/home/index.blade.php

    line 5: About

    I removed the leading “/” – so it becomes:

    About

  • Simon

    What i have waiting for :)! really nice gonna read this in the train on my way for work :D!

    Jeffrey need to make a quick tip video about it :D!

    • http://nikkobautista.com Nikko Bautista
      Author

      I believe he’s working on a premium series for this, which would be a lot more extensive than my series. :) Stay tuned!

  • Ashit Vora

    Awesome Tutorial and awesome Framework. This is the only PHP framework I would love to use after CodeIgniter. Simple yet Awesome.

    Thanks Nikko for such an awesome intro :)

    Would love to have a series on Lavarel.

  • Ashit Vora

    “action” keyword is not needed for RESTful Controller?

    • http://cartalyst.com Daniel Petrie

      With rest controllers, action_ is converted into get_ or post_ generally, depending on the request type sent. I think there has been some discussion about adding in action_ as a fallback, but nothing official yet I believe.

    • http://daylerees.com Dayle Rees

      There’s a pull request for this functionality which I have marked as a Potential Feature. It might be worth +1′ing it if it would be useful to you.

      Thanks!

  • Smith Goldblath

    Nice. Am i wrong or is this framework inspired by symfony or is build on top of symfony2 components?
    In that case, i think it’s better to stay with my good “old” framework (symfony2)…

  • gemina

    Please tell me where is the “Simple” and “Elegant” part? This is another shitty php “framework” with its own syntax like ASD_Blah::LOL() for a simple echo. Those MVC shits are for 15 yo children.

    • http://www.jeffrey-way.com Jeffrey Way

      Yeah…ummm..no.

    • Luglio7

      Lol

  • Robert

    Hi,
    Thanks for the tutorial I checked out the framework’s webpage a couple of days ago. Is it just me or the “dome” button points to the same address as the “download” button.

  • laraveler

    in cotroller __construct filter example, i think that there is “parent::__construct();” missing

  • http://www.petarzivkovic.com Petar Zivkovic

    Looks fantastic.

    As far as PHP frameworks are concerned, I’ve put most of my time into CodeIgniter (a good choice BTW for anyone still wondering about that one) and now I’m looking to get one more under my belt. I was (and still am) considering Zend, but I might hold off on that… it seems like the right choice for enterprise level application development (because of the currently huge application base and maturity).

    It was already mentioned, but I’m curious as to the future job possibilities with this framework. It’s not something that will affect me immediately, but what happens two or three years down the road when you’ve put in thousands of hours only to find out that it never gained traction in the mainstream?

    In either case, I’m intrigued and will take a very serious look into this framework, it looks very exciting.

    Thanks for the great article, looking forward to more.

    Pete.

    • Kapil Verma

      Hey … I can work comfortably in 5-6 php frameworks and can pick up a new one in a matter of days (also i am working on 2 big projects which use laravel cos its really top-class) …. and the best advice i can give you regarding your problem(of putting time into learning a framework which might lose traction after some time) is to learn em all !!! after going through 3-4 of them, you start seeing the common patterns they follow, and picking up new ones isn’t difficult then. Also spend more time on reading the code of the framework. There’s a lot to be learnt in there and it’ll again help you in easily figuring out how a new framework that you want to learn works.

      That said, I’d also advice you to leave behind codeigniter and look at php5.3 frameworks out there … the techniques used in them make them much more intutive, powerful and extensible than codeigniter.

    • http://nikkobautista.com Nikko Bautista
      Author

      Hey Petar,

      I understand your concerns. I myself learned Zend Framework due to it’s nature as an enterprise-grade framework. Afterwards, I learned CodeIgniter as a go-to framework for quick projects, due to it’s popularity and ease-of-use.

      I believe Laravel is on the same path as CodeIgniter – it’s easy to use for quick projects, has a very loyal fan-base and easy to learn as well.

      My suggestion to you would be to learn not a specific framework, but the basics of how these frameworks work. The first framework I learned to use was Symfony – I didn’t spend a lot of time on it and I didn’t use it that much on projects, but learning it made me understand how these frameworks function – what MVC is, how they implement the architecture, how they implement modularity and extensibility.

      My knowledge of Symfony allowed me to learn Zend Framework fairly quickly and be able to use it on a production level. After that, CodeIgniter and Laravel just came to me naturally.

      This way, any framework any possible employer might be using will be easy for you to grasp, since the basics of how any framework works is ingrained at the theoritcal level.

      It’s kinda the same as to how generalist programmers work – basic computer science is implementable in any programming language, which is why it’s easy for them to jump from one type of language to another.

  • http://www.leachcreative.com Andrew

    Great tutorial. This seems like a pretty interesting framework however WP takes care of most everything I need it to do pretty efficiently so I think I’ll stick with it.

    • http://nikkobautista.com Nikko Bautista
      Author

      I’m a firm believer of using the technology that you’re most comfortable with. If WP (I’m assuming this is WordPress?) works best for you, then by all means that should be the framework that you use.

      On the chance that you have a project that escapes the scope of the tool though, I recommend giving Laravel a try :)

      • http://www.leachcreative.com Andrew

        I’ll be sure to give it a shot if WordPress does cut it.

  • http://ylgur.is Kristján Mikaelsson

    Thanks for this epic article!

  • Todd

    WordPress is dogsh*t, wordpress’ codebase is dogsh*t

  • http://www.example.org alxy

    “An important thing to note here is that by default, Laravel does NOT route to the controllers like other PHP-frameworks do. This is by design. By doing so, we can actually create simple pages without the need to create a controller for it.”

    This seems to be a pretty nice feature :) I wondered, why this haven´t been implemented in other FWs yet. I´ll definitely have a look at laravel.
    Btw very nice introduction to it :)

  • http://codivist.com Dave

    Good Tutorial, have been playing Laravel for a few weeks now. Would love to see a tutorial on using Laravel WITHOUT using a database, and using different methods as data delivery such as connecting to an API or whatever.

    • http://nikkobautista.com Nikko Bautista
      Author

      I know what you mean, but most people would prefer the “traditional” tutorial, which would undoubtedly include database access. If you create your models in a decoupled manner though, changing the data source shouldn’t be that difficult :)

  • thecodingdude

    Apparently we need a new framework for every day of the year…*roll eyes*

  • Pierlo

    Laravel really seems a well executed framework, although for the kind of jobs i’m mostly involved in (“corporate” websites that is) I really need a quick-jump backend solution, so I’m going to stick to FuelCMS (crazy nobody seems to mention it anywhere) for the time being until backend bundle for Laravel is released i guess… no time to reinvent the wheel! :-(

  • http://www.ingo-fahrentholz.com Ingo Fahrentholz

    (!) .. RAILS RAILS RAILS .. (!)

  • http://www.larubbish.com moi

    Watch out for the new LaRabbish PHP framework coming out soon.

  • Sidney

    Good framework and article.

    But, looking into simplicity w/ power, Yii is very simpler and more powerful.
    You really should make a NetTut for Yii too.

    Thanks.

    • http://www.novavo.com Dat

      Agreed. I use Yii atm in all my applications, simple & powerful.

  • Boabramah Ernest

    For me I think a lot of frameworks are going to appear now that PHP is becoming awesome with new ways of doing things.

    We have been reinventing the wheel since the time the “DO NOT REINVENT THE WHEEL” was invented.

    When PHP 6 arrive, we will start reinventing the wheel all over again. So Laravel you are welcome.

    Does anyone have a tutorial on the framework robotico with the command line utility househelp written in PHP 12 which comes with an ORM called doMyThingsCosAmLazy and that can be hosted on the heavens platform cos cloud platform is outdated? Jeff if you do not write a tutorial on this for free, I promise I will write my own framework.

    Oh I love this work.

  • Kulugo

    Article is boring. It would have been better if the very contributor of the framework did an article about Laravel.

  • http://kodington.com Peter

    One request/suggestion for next lesson(s), if I may.

    I really find Codeigniter’s “Image Manipulation Class” (http://codeigniter.com/user_guide/libraries/image_lib.html) and FuelPHP’s “Image Class” (http://docs.fuelphp.com/classes/image.html) very useful. Even if you develop only simple blog/news website, you have to use this classes. Does Laravel have similar functionality? I only found one bundle “Resizer”, which seems to have limited functionality compared to CI’s or FuelPHP’s.

    Are you going to cover some image manipulation techniques in future lessons?

    Thank you for nice tutorial, I can hardly wait for part two.

  • http://isawesum.net Denver

    Laravel is fantastic. Been rooting for it for a while now.

  • Simon

    So::many::static::methods. Not liking seeing them used so often in frameworks lately. Comes off as quite lazy.

    Thanks for the tute though.

    • haneul

      you make it sound like being lazy is bad thing for a developer

    • Kapil Verma

      Well the static methods are there mostly to provide a cleaner api (btw most of them are mapped to object methods via __callStatic) .. and aside them being difficult to test, whats everybody’s problem with them .. and afaik , laravel’s core has been tested properly

      • http://inkwell.dotink.org Matthew J. Sahagian

        Static methods are not inherently difficult to test.

        static public function add($num1, $num2) {
        return $num1 + $num2;
        }

        This is actually quite easy to test. The issue with static methods and testing is two fold, I think. Firstly, the tests themselves are created with dependency requirements if calling the methods directly. Secondly, if you begin adding static dependencies.

        As of PHP5.3 I think static methods have gotten easier to test given __callStatic exists, not to mention $class::method() is finally acceptable without having to do call_user_func().

        A lot of the TDD cargo culters that scream about static methods have plenty of dependencies which makes things equally annoying. Object dependencies are not so different unless you have explicit means to deal with dependency injection in a cleaner fashion. Laravel offers an IoC container to cope with that. It’s part of the conspiracy to make PHP more like Java.

      • http://www.jeffrey-way.com Jeffrey Way

        Hey Matt – Any interest in me hiring you to write some content for Nettuts+?

      • http://inkwell.dotink.org Matthew J. Sahagian

        @Jeffrey

        Depends on the topic. Oddly enough, I’m most passionate about CSS (haha). I’m guessing you can see my e-mail since you have some admin rights to this site, feel free to e-mail me directly. If you can’t see my personal e-mail just send it to info@dotink.org.

  • Einion Gruffudd

    I come from a CI background and was looking for something new to play with in my spare time. I tried out a number of these new frameworks, but found that the documentation for laravel was much better than what the others had to offer, they even have a book which you can download, http://leanpub.com/codehappy. Written by the core members, worth getting if you’re serious about learning laravel.

  • Francisc

    How are next parts scheduled? What time distance between them?

  • http://www.integrityinvoice.com Adeniyi

    Seems interesting, looking forward to the next tutorial.

  • http://proxdeveloper.com Pablo Fierro

    This framework looks great, but from seeing how the framework works in this tutorial, I think I’ll stick with the Slim PHP Framework, why ? because it’s stupid simple, very easy to use, lightweight and it doesn’t have anything I don’t need.

    I can create a web app in half the time, it’s just pure joy, I don’t know if Jeffrey has tried it out already, but it did brought to me the joy of using php again.

  • manojt

    Nice tut, but I am having problem loggin into the app, it continues to give the message saying “failed to login”!!

  • http://engelkarte.eu Juli Lee

    The framework is open source is that right?

  • http://kehet.com/ Kehet

    Stupid question, but should it give Unhandled Exception with message
    Directive ‘register_long_arrays’ is deprecated in PHP 5.3 and greater
    with clean new install of laravel?

  • NoxArt

    Wonder how many more thousands of near-identical frameworks are we yet to see. “What Makes Laravel Different?” section of docs contains all the no-brainer stuff that every reasonable FW has (yes, I did read the whole docs).

    I am not saying it is a not a good FW, but I failed to find any reason for creating it.

    BTW Eloquent ORM cannot function like Doctrine2 (target of the link) as D2 managed to abandon the ActiveRecord pattern and uses DataMapper.

    • Kapil Verma

      I gave several php5.3 frameworks a spin before settling down on laravel, IMO, no other frameworks provides as much power and still gets out your way

  • http://www.veb4design.com Nima

    Isn’t this just like symfony2? only less matrue?
    Looks good though

    • Kapil Verma

      Oh no , its a lot easier to work with/get familiar with than symfony2

  • http://www.slideshare.net/waynecordovas/web-application-development-company-in-london-13415723 Benjamin Dyer

    An interesting discussion is worth comment. I think you should write more on this topic, it might not be a taboo subject but generally people are not enough to speak on such topics. To the next. Cheers

  • jeff

    after learn php ,what framework should i learn for start?

    • http://aneesh.info aneeshep

      CodeIgniter will be a good starting point.

      • Spoygg

        Do not start with CI, it is dated. Start with Symfony 2 or Laravel. You will learn better patterns for development.

  • http://shawnang.com/ Shawn Ang

    Looks like a very clean framework to me. How long has it been around, anyone knows?

  • Kevin

    I hope Laravel become the framework of developers that actually develop instead of bitching about frameworks or esoteric design patterns.

  • Yudhy

    Just wanna know before dive into Laravel framework, is it support ODBC (Ms.Access: *.mdb) database? It because at my office, they ask me to use *.mdb databases. I already see the docs on Laravel website and it only support MySQL, SQLite, SQL Server, and PostgreSQL.

  • Yudhy

    Just wanna know before dive into Laravel framework, is it support ODBC (Ms.Access: *.mdb) database? It because at my office, they ask me to use *.mdb databases. I already see the docs on Laravel website and it only support MySQL, SQLite, SQL Server, and PostgreSQL.