Laravel 4 Application Setup: App library, Autoloading, Binding

I like to create my own library for any application. Similarly, I like keeping the "models" directory clean - I only add Laravel classes (Usually Eloquent instances) inside of the "model" folder.

An application-specific library works well for code which isn't generic enough to warrant its own composer package, and also isn't a direct extension of any Laravel class. An example is business logic code, such as calculations specific to an application.

(The following assumes a clean install of Laravel.)

How do I setup my own library?

I accomplish this by creating a directly inside of the app folder called 'lib'. Then I choose a namespace for my application code - usually whatever I call my application.

Let's start coding project Acme. Here's a directory structure I'd create.

Acme
    app
        lib
            Acme
    commands
    config
    …etc…
    filters.php
    routes.php

A sample class that may go in our Acme library is an Anvil line of products.

// app/lib/Acme/Product/Anvil/AnvilInterface.php
<?php namespace Acme\Product\Anvil;

interface AnvilInterface {

    public function drop();

}

// app/lib/Acme/Product/Anvil/AnvilHeavy.php
<?php namespace Acme\Product\Anvil;

class AnvilHeavy implements AnvilInterface {

    public function drop()
    {
        return "ouch!";
    }

}

Here's what our files look like:

Acme
    app
        lib
            Acme
                Product
                    Anvil
                        AnvilInterface.php
                        AnvilHeavy.php
    commands
    config
    …etc…
    filters.php
    routes.php

.

Autoloading

We now have a home for Acme product library. Let's autoload those libraries. To accomplish this, I edit composer.json, and add to the "autoload" section. Note the addition of the psr-0 section, with the Acme library.

{
    "require": {
        "laravel/framework": "4.0.*"
    },
    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/tests/TestCase.php"
        ],
        "psr-0": {
            "Acme": "app/lib"
        }
    },
    "minimum-stability": "dev"
}

After this is saved, you can run $ php composer.phar dump-autoload;, and Laravel will know how to load those classes. Let's try it out. Edit your routes.php file.

// routes.php
Route::get('/', function()
{
    $anvil = new Acme\Product\AnvilHeavy;
    print_r($anvil);

    return View::make('hello');
});

Run this in your browser. You should see a print out of the AnvilHeavy object.

Binding

As you may know, Laravel's use of IoC containers makes for a powerful tool. This adds to the maintainability and testability of an application.

To bind our Anvil object (add to a container), we can use:

App::bind('Anvil', function()
{
   return new Acme\Product\AnvilHeavy;
});

Later in our application, we can use resolve our AnvilHeavy object:

App::make('Anvil');

What have we learned?

At this point, we have done a few things:

  1. Created a library we can use to add business logic.
  2. Setup autoloading to our library.
  3. Creating a container for our AnvilHeavy product.

Note that I haven't done anything to show the power of containers. This container binding is a contrived example, as the point I want to make here is how to setup your own application-specific library.