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](http://fideloper.com/post/39306821065/testable-maintainable-di-containers) 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.