Application File Structure

Before you get started with li3, it’s important to know how your application’s main folder is structured, and where everything should go. Clone yourself a copy of the main repo, and you’ll find an app folder structure that contains:

  • config
  • controllers
  • extensions
  • libraries
  • models
  • resources
  • tests
  • views
  • webroot

Let’s tackle each of these folders one-by-one, covering what each is used for, and how you can best organize your application.

Config

The config folder contains three main pieces: bootstrap files, your connections information, and your routes definitions.

Bootstrapping

The main bootstrap file in the config folder is bootstrap.php. This file is second file PHP will execute in any request cycle, and it loads up the li3 framework along with any other extras that you define there. As such, it’s a great place to place initial application configuration.

The best practice for bootstrapping parts of your application is by writing specific bootstrap files and placing them in config/bootstrap/filename.php. Once written, include the configuration into the main bootstrap file:

  1. // Adding my custom configuration or initialization...
  2. require __DIR__ . '/bootstrap/myconfig.php';

Connections

The connections.php file in config lists the connections you have to external data resources, most often some type of database.

Connections should be listed in this file, as calls to Connections::add(), like so:

  1. Connections::add('default', [
  2. 'type' => 'database',
  3. 'adapter' => 'MySql',
  4. 'host' => 'localhost',
  5. 'login' => 'root',
  6. 'password' => '',
  7. 'database' => 'my_blog'
  8. ]);
  9. Connections::add('couch', [
  10. 'type' => 'http', 'adapter' => 'CouchDb', 'host' => '127.0.0.1', 'port' => 5984
  11. ]);
  12. Connections::add('mongo', ['type' => 'MongoDb', 'database' => 'project']);

The particulars on the adapter will shape how the connection definition is put together, but this list should constitute what you’ve got in connections.php.

Routes

Routes definitions is how you inform the framework how URLs and bits of code match up. At the most basic level, it’s how you tell li3 which controller should respond to a request to a given URL.

For example, I could specify that any request to /login is handled by UsersController::login() like this:

  1. Router::connect('/login', ['controller' => 'users', 'action' => 'login']);

More on routes later, but this file should house all such configuration information.

Controllers

Application controllers are housed here. Each controller is named in CamelCased, plural format (i.e. PostsController.php), and placed here.

Extensions

The extensions folder is meant to store extension classes that you’ve created for your application. Custom helpers, adapters, console commands and data classes.

Adapter

A number of li3 classes extend the lithium\core\Adaptable static class. This class allows you to take a number of different approaches and easily switch out implementations for an application task. Authentication, session handling, and caching are a few examples of li3 functionality that have been made adaptable.

Custom application adapters should be placed in this folder, organized by subfolder. For example, if I created a custom adapter for the Auth class, based on my LDAP setup, I’d create the implementation in /extensions/adapter/auth/Ldap.php.

Command

Custom console applications are placed in command. Commands you create should be built similar to those you see in /lithium/console/command.

As an example, say I created a custom mailer queue, and I need to create a command to fill up the queue with announcement emails and trigger the send process. I’d create a new class called QueueFiller that extends lithium\console\Command, and place it in app/extensions/command/QueueFiller.php.

Once there, running li3 queue-filler from the command line will trigger the logic I’ve written.

Data

Occasionally a new application will require custom data classes to work with a storage engine not already accommodated for by core classes.

If you’ve got some proprietary database, and it’s result objects or query structures are very customized, you’ll extend the classes in the lithium\data namespace (i.e. Source, source\Database or source\Http) and place them here for use in your application.

Helper

Custom view helpers are common need. These classes should extend lithium\template\Helper and be placed in this folder.

Libraries

The libraries folder is meant to house entire li3 applications—or plugins—that your main application makes use of.

Third-party, non-li3 libraries should be placed here as well. If you’re integrating with Facebook, or using part of the Zend Framework in your application, place those files here as well.

Models

Application models are stored here, in CamelCased, plural naming format (i.e. Posts.php).

Resources

The resources folder is used by a li3 application as a non-web viewable storage place for application data. By default globalization files (such as .po string files) and temporary application files are stored there.

As you build your application, the resources folder is a great place for other application data like custom cache files, SQLite databases, or a temporary spot for uploaded files.

The resources is a place where the web server has write access, so make sure to keep that in mind when securing your application.

Tests

The tests folder is where the unit testing framework files for your application reside. The testing setup for li3 is covered elsewhere, but let’s cover what ends up in each of the testing subfolders here.

Cases

All of the actual unit testing logic for the main MVC classes in the application go in the cases folder. Subfolders should already exist inside of cases to prompt you where each sort of test case should go.

Integration

Unit tests in the integration folder test the interaction between two or more classes, or abstract class implementations.

Mocks

Classes in mocks are used to facilitate certain unit tests. For example, if I’m testing a custom model I’ve created, I can create a new class in mocks/data/MockSource.php and use it in my model unit testing logic.

It is recommend that you use subfolder organization that mimics your application’s and li3’s namespacing and folder structure.

Views

The views folder contains any pieces of view-level code in your application. The two main core folders here to note are elements and layouts. Other view folders here contain views organized by controller name.

Elements

Elements are small bits of view code that are used in multiple views. A common navigational element, menu, or form might end up as an element in this folder. Element files are suffixed with a compound extension: the first showing the type of view code, and the last as .php.

Example element filenames might include nav.html.php, animateLink.js.php, or header.xml.php.

Layouts

Views (and the elements they may contain) are rendered inside of view layouts. The layouts for your application reside in this folder, named similar to elements.

A layout named default will be used to render a view if none other has been specified by the controller.

Controller View Folders

Along with the elements and layouts folders, many other controller-specific view folders will reside here.

One default example is the pages folder here that holds all the views for the core PagesController. As you create new controllers and views for your application, create new folders here, named after your controllers.

Webroot

The webroot folder of your application is (ideally) the only place in your application that is web-visible. The index.php file takes care of bootstrapping li3, and the rest of the folders and files here are used for static content delivery.

Things like JavaScript files, images, Flash objects, and movies should end up here for easy access for your web server to deliver to the client.