Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
776 lines (451 sloc) 21.9 KB


Release Build Status HHVM Code Quality Code Coverage Packagist

ICanBoogie is a high-performance micro-framework for PHP 5.4+. It is written with speed, flexibility and lightness in mind. ICanBoogie doesn't try to be an all-in-one do-it-all solution but provides the essential features to quickly and easily build web applications. It is easily extensible, and a variety of packages are available to complement its features with rendering, views, routing, operations, internationalization, translation, ORM, facets, mailer…

Together with Brickrouge and Patron, ICanBoogie is one of the components that make the CMS Icybee. You might want to check these projects too.

What does micro mean?

micro means that the core features of ICanBoogie are kept to the essential, the core is simple but greatly extensible. For instance, ICanBoogie won't force an ORM on you, although its ActiveRecord implementation is pretty nice. In the same fashion, its routing mechanisms are quite agnostic and let you use your very own dispatcher if you want to.

Configuration and conventions

ICanBoogie and its components are usually very configurable and come with sensible defaults and a few conventions. Configurations are usually located in "config" folders, while locale messages are usually located in "locale" folders. Components configure themselves thanks to ICanBoogie's Autoconfig feature, and won't require much of you other than a line in your composer.json file.


MooTools, Ruby on Rails, Yii, and of course Bacara.

Working with ICanBoogie

ICanBoogie tries to leverage the magic features of PHP as much as possible: getters/setters, invokable objects, array access, stringifiable objects, closures… to create a coherent framework which requires less typing and most of all less guessing. As a result, applications created with ICanBoogie have readable concise code and fluid flow.

Getters and setters

Magic properties are used in favor of getter and setter methods (e.g. getXxx() or setXxx()). For instance, DateTime instances provide a minute magic property instead of getMinute() and setMinute() methods:


use ICanBoogie\DateTime;

$time = new DateTime('2013-05-17 12:30:45', 'utc');
echo $time;         // 2013-05-17T12:30:45Z
echo $time->minute; // 30

$time->minute += 120;
echo $time;         // 2013-05-17T14:30:45Z

The getter/setter feature provided by icanboogie/accessor, and extended by icanboogie/prototype, allows you to create read-only or write-only properties, façades properties, fallbacks to generate default values. Getters are setters are also often using to control types, lazy load resources, and inject dependencies.

Dependency injection

icanboogie/prototype allows methods to be defined at runtime, and since getters and setters are methods as well, this feature in often used as a mean to inject dependencies. What's great about it is that dependencies are only injected when they are required, not when to instance is created.

The following example demonstrates how a shared database connection is obtained through a db property:


use ICanBoogie\ActiveRecord\Connection;
use ICanBoogie\Prototype;
use ICanBoogie\PrototypeTrait;

 * @property-read Connection $db
class A
    use PrototypeTrait;

    public function truncate()
        $this->db("TRUNCATE my_table");

Prototype::from("A")['get_db'] = function(A $a) {

    static $db;

    return $db ?: $db = new Connection("sqlite::memory:");


Objects as strings

If a string represents a serialized set of data ICanBoogie usually provides a class to make its manipulation easy. Instances can be created from strings, and in turn they can be used as strings. This applies to dates and times, time zones, time zone locations, HTTP headers, HTTP responses, database queries, and many more.


use ICanBoogie\DateTime;

$time = new DateTime('2013-05-17 12:30:45', 'Europe/Paris');

echo $time;                           // 2013-05-17T12:30:45+0200
echo $time->minute;                   // 30
echo $time->zone;                     // Europe/Paris
echo $time->zone->offset;             // 7200
echo $time->zone->location;           // FR,48.86667,2.3333348
echo $time->zone->location->latitude; // 48.86667

use ICanBoogie\HTTP\Headers;

$headers = new Headers;
$headers['Cache-Control'] = 'no-cache';
echo $headers['Cache-Control'];       // no-cache

$headers['Cache-Control']->cacheable = 'public';
$headers['Cache-Control']->no_transform = true;
$headers['Cache-Control']->must_revalidate = false;
$headers['Cache-Control']->max_age = 3600;
echo $headers['Cache-Control'];       // public, max-age=3600, no-transform

use ICanBoogie\HTTP\Response;

$response = new Response('ok', 200);
echo $response;                       // HTTP/1.0 200 OK\r\nDate: Fri, 17 May 2013 15:08:21 GMT\r\n\r\nok

echo $app->models['pages']->own->visible->filter_by_nid(12)->order('created_on DESC')->limit(5);
// SELECT * FROM `pages` `page` INNER JOIN `nodes` `node` USING(`nid`) WHERE (`constructor` = ?) AND (`is_online` = ?) AND (siteid = 0 OR siteid = ?) AND (language = "" OR language = ?) AND (`nid` = ?) ORDER BY created_on DESC LIMIT 5

Invokable objects

Objects performing a main action are simply invoked to perform that action. For instance, a prepared database statement is invoked to perform a command:


# DB statements

$statement = $app->models['nodes']->prepare('UPDATE {self} SET title = ? WHERE nid = ?');
$statement("Title 1", 1);
$statement("Title 2", 2);
$statement("Title 3", 3);

This applies to database connections, models, requests, responses, translators… and many more.


$pages = $app->models['pages'];
$pages('SELECT * FROM {self_and_related} WHERE YEAR(created_on) = 2013')->all;


use ICanBoogie\HTTP\Request;

$request = Request::from($_SERVER);
$response = $request();

# I18n translator

use ICanBoogie\I18n\Locale;

$translator = Locale::from('fr')->translator;
echo $translator('I can Boogie'); // Je sais danser le Boogie

Collections as arrays

Collections of objects always provide an array interface, whether they are records in the database, database connections, models, modules, header fields…


$app->models['nodes'][123];   // fetch record with key 123 in nodes
$app->modules['nodes'];       // obtain the Nodes module
$app->connections['primary']; // obtain the primary database connection

$request['param1'];            // fetch param of the request named `param1`, returns `null` if it doesn't exists

$response->headers['Cache-Control'] = 'no-cache';
$response->headers['Content-Type'] = 'text/html; charset=utf-8';

Creating an instance from data

Most classes provide a from() static method that create instances from various data types. This is especially true for sub-classes of the Object class, which can create instances from arrays of properties. ActiveRecords are a perfect example of this feature:


use Icybee\Modules\Nodes\Node;

$node = new Node;
$node->uid = 1;
$node->title = "Title";


$node = Node::from([ 'uid' => 1, 'title' => "Title" ]);

Some classes don't even provide a public constructor and rely solely on the from() method. For instance, Request instances can only by created using the from() method:


use ICanBoogie\HTTP\Request;

# Creating the initial request from the $_SERVER array

$initial_request = Request::from($_SERVER);

# Creating a local XHR post request with some parameters

$custom_request = Request::from([

    'path' => '/path/to/controller',
    'is_post' => true,
    'is_local' => true,
    'is_xhr' => true,

    'request_params' => [

        'param1' => 'value1',
        'param2' => 'value2'



The life and death of your application

Thanks to its Autoconfig system and a few conventions, running your application only requires three lines:


require 'vendor/autoload.php';

$app = ICanBoogie\boot();

1. The first line is pretty common for applications using Composer, it creates and runs its autoloader.

2. On the second line the Core instance is created with the autoconfig, its boot() method is invoked, and the ICanBoogie\Core::boot event is fired. At this point ICanBoogie and low-level components are configured and booted. Your application is ready to process requests.

3. On the third line the application is run, which implies the following:

3.1. The HTTP response code is set to 500, so that if a fatal error occurs the error message won't be sent with the HTTP code 200 (Ok).

3.2. The initial request is obtained and the ICanBoogie\Core::run event is fired with it.

3.3. The request is executed to obtain a response.

3.4. The response is executed to respond to the request. It should set the HTTP code to the appropriate value.

3.5. The ICanBoogie\Core::terminate event is fired at which point the application should be terminated.

Multi-site support

ICanBoogie has built-in multi-site support and can be configured for different domains. Even if you are dealing with only one domain, this feature can be used to provide different configuration for the "dev", "stage", and "production" versions of a same application.

The intended location for your custom application code is in a separate "protected" directory, but another directory can be defined with the app-root autoconfig directive. The directory is relative to the root directive.

ICanBoogie will search for "config" directories to add to the autoconfig. Just like ICanBoogie, packages may use this feature to alter the autoconfig. For instance, icanboogie/module searches for "modules" directories.

Resolving applications paths

The server's name is used to resolve the application paths.

Consider an application root directory with the following directories:


The directory "all" contains resources that are common to all sites. It is always added when present.

To resolve the matching directory, the server's name is first broken into parts and the most specific ones are removed until a corresponding directory is found. For instance, given the server name www.icanboogie.localhost, the following directories are tried: www.icanboogie.localhost, icanboogie.localhost, and finally localhost.

If the server's name cannot be resolved into a directory, "default" is used instead.

Note: "cli" is used as server name when the application is ran from the CLI.


The Autoconfig feature automatically generates a configuration file from the available low-level components participating in the Autoconfig process. Currently, it is used to define configuration constructors, paths to component configurations, paths to locale message catalogs, and paths to modules.

Participating in the autoconfig process

To participate in the autoconfig process, packages need to define their autoconfig fragment in the extra/icanboogie section of their "composer.json" file. The file must match the composer-schema.json schema. The following example demonstrates how an application can specify the path to its configuration and locale messages.

    "extra": {
        "icanboogie": {
            "config-path": "path/to/config",
            "locale-path": "path/to/locale"

Note: Packages can also define their autoconfig fragment in a stand-alone "icanboogie.json" file, beside their "composer.json" file, but using the "composer.json" file is recommended. The file must match the icanboogie-schema.json schema.

Generating the autoconfig file

The autoconfig file is generated after the autoloader is dumped, during the post-autoload-dump event emitted by Composer. Thus, in order for the autoconfig feature to work, a script for the event is required in the root package of the application:

    "scripts": {
        "post-autoload-dump": "ICanBoogie\\Autoconfig\\Hooks::on_autoload_dump"

Obtaining the autoconfig

The autoconfig is obtained using the ICanBoogie\get_autoconfig() function, and can be used as is to instantiate the Core instance. The function also updates the app-root and app-paths values with the resolved application root and and resolved application paths respectively.


namespace ICanBoogie;

$app = new Core(get_autoconfig());

Additionally, the ICanBoogie\AUTOCONFIG_PATHNAME constant defines the absolute pathname to the autoconfig file.

Note: A fatal error is triggered if the autoconfig file does not exists, which might happen if the user forgot to add the post-autoload-dump hook in its "composer.json" file.

Altering the autoconfig at runtime

Filters defined with the autoconfig-filters key are invoked to alter the autoconfig before the get_autoconfig() function returns it. For instance, ICanBoogie uses this feature to add "config" directories found in the application paths (using the multi-site support).

    "extra": {
        "icanboogie": {
            "autoconfig-filters": [ "ICanBoogie\\Autoconfig\\Hooks::filter_autoconfig" ]

Configuring the core

The Core instance is configured with core configuration fragments. The fragment used by your application is usually located in the /protected/all/config/core.php file.

The following example demonstrates how to enable configs caching and how to specify the name of the session and its scope.


// protected/all/config/core.php

return [

    'cache configs' => true,

    'session' => [

            'name' => "ICanBoogie",
            'domain' => ""


Check ICanBoogie's "config/core.php" for a list of the available options and their default values.


The application has booted

The ICanBoogie\Core::boot event of class BootEvent is fired once the application has booted. Third parties may use this event to alter the configuration or the components before the application is ran.

The application is running

The ICanBoogie\Core::run event of class RunEvent is fired when the application is running. Third parties may use this event to alter various states of the application, starting with the initial request.

The application is terminated

The ICanBoogie\Core::terminate event of class TerminateEvent is fired after the response to the initial request was sent and the application is about to be terminated. Third parties may use this event to cleanup loose ends.

Request dispatchers are collected

The ICanBoogie\HTTP\Dispatcher::collect event of class ICanBoogie\HTTP\Dispatcher\CollectEvent is fired when dispatchers are collected, just before the main dispatcher is instantiated. Third parties may use this event to register dispatchers or alter dispatchers.

The following code illustrate how a hello dispatcher, that returns "Hello world!" when the request matches the path "/hello", can be registered.


use ICanBoogie\HTTP\Dispatcher;
use ICanBoogie\HTTP\Request;
use ICanBoogie\HTTP\Response;

$app->events->attach(function(Dispatcher\CollectEvent $event, Dispatcher $target) {

    $event->dispatchers['hello'] = function(Request $request) {

        if ($request->path === '/hello')
            return new Response('Hello world!');


Prototype methods


The app magic property of Object instances returns the Core instance of the application. The property is read-only and is only available after the Core instance has been created.


namespace ICanBoogie;

$o = new Object;
// throw ICanBoogie\PropertyNotDefined;

$app = boot();
$app === $o->app;
// true


The following helper functions are defined:

  • app(): Returns the Core instance, or throws CoreNotInstantiated if it hasn't been instantiated yet.
  • boot(): Instantiates a Core instance with the autoconfig and boots it.
  • log(): Logs a debug message.
  • log_success(): Logs a success message.
  • log_error(): Logs an error message.
  • log_info(): Logs an info message.
  • log_time(): Logs a debug message associated with a timing information.


The minimum requirement is PHP 5.4.

ICanBoogie has been tested with Apache HTTP server on Linux, MacOS, and Windows operating systems. The Apache server must support URL rewriting.


The recommended way to install this package is through Composer:

$ composer require icanboogie/icanboogie

Don't forget to modify the script section of your "composer.json" file if you want to benefit from the autoconfig feature:

    "scripts": {
        "post-autoload-dump": "ICanBoogie\\Autoconfig\\Hooks::on_autoload_dump"

The following packages are required, you might want to check them out:

The following packages can also be installed for additional features:

The following bindings are available to help in integrating components:

Cloning the repository

The package is available on GitHub, its repository can be cloned with the following command line:

$ git clone


The documentation for the package and its dependencies can be generated with the make doc command. The documentation is generated in the docs directory using ApiGen. The package directory can later by cleaned with the make clean command.

The documentation for the complete framework is also available online:


The test suite is ran with the make test command. Composer is automatically installed as well as all dependencies required to run the suite. You can later clean the directory with the make clean command.

The package is continuously tested by Travis CI.

Build Status Code Coverage


ICanBoogie is licensed under the New BSD License - See the LICENSE file for details.

Something went wrong with that request. Please try again.