A micro PHP framework
Clone or download
alexbilbie Merge pull request #33 from GrahamCampbell/patch-1
Corrected symfony version constraint
Latest commit a2f7600 Dec 29, 2015
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Remove bad docblock Mar 26, 2015
tests Merge pull request #21 from sagikazarmark/events Feb 22, 2015
.gitignore Various docblock fixes Dec 12, 2014
.scrutinizer.yml Various docblock fixes Dec 12, 2014
.travis.yml Added PHP 7.0 testing Mar 3, 2015
CHANGELOG.md Changelog update Mar 26, 2015
LICENSE.md Create LICENSE.md Oct 2, 2014
README.md Updated README Feb 22, 2015
composer.json Corrected symfony version constraint Dec 26, 2015
phpunit.xml Various docblock fixes Dec 12, 2014

README.md

Proton

Latest Version Software License Build Status Coverage Status Quality Score

Proton is a StackPHP compatible micro framework.

Under the hood it uses League\Route for routing, League\Container for dependency injection, and League\Event for event dispatching.

Installation

Just add "alexbilbie/proton": "~1.4" to your composer.json file.

Setup

Basic usage with anonymous functions:

// index.php
<?php

require __DIR__.'/../vendor/autoload.php';

$app = new Proton\Application();

$app->get('/', function ($request, $response) {
    $response->setContent('<h1>It works!</h1>');
    return $response;
});

$app->get('/hello/{name}', function ($request, $response, $args) {
    $response->setContent(
        sprintf('<h1>Hello, %s!</h1>', $args['name'])
    );
    return $response;
});

$app->run();

Basic usage with controllers:

// index.php
<?php

require __DIR__.'/../vendor/autoload.php';

$app = new Proton\Application();

$app['HomeController'] = function () {
    return new HomeController();
};

$app->get('/', 'HomeController::index'); // calls index method on HomeController class

$app->run();
// HomeController.php
<?php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class HomeController
{
    public function index(Request $request, Response $response, array $args)
    {
        $response->setContent('<h1>It works!</h1>');
        return $response;
    }
}

Basic usage with StackPHP (using Stack\Builder and Stack\Run):

// index.php
<?php
require __DIR__.'/../vendor/autoload.php';

$app = new Proton\Application();

$app->get('/', function ($request, $response) {
    $response->setContent('<h1>It works!</h1>');
    return $response;
});

$stack = (new Stack\Builder())
    ->push('Some/MiddleWare') // This will execute first
    ->push('Some/MiddleWare') // This will execute second
    ->push('Some/MiddleWare'); // This will execute third

$app = $stack->resolve($app);
Stack\run($app); // The app will run after all the middlewares have run

Debugging

By default Proton runs with debug options disabled. To enable debugging add

$app['debug'] = true;

Proton has built in support for Monolog. To access a channel call:

$app->getLogger('channel name');

For more information about channels read this guide - https://github.com/Seldaek/monolog/blob/master/doc/usage.md#leveraging-channels.

Custom exception decoration

$app->setExceptionDecorator(function (\Exception $e) {
    $response = new \Symfony\Component\HttpFoundation\Response;
    $response->setStatusCode(500);
    $response->setContent('Epic fail!');
    return $response;
});

Events

You can intercept requests and responses at three points during the lifecycle:

request.received

$app->subscribe('request.received', function ($event) {
    // access the request using $event->getRequest()
})

This event is fired when a request is received but before it has been processed by the router.

response.created

$app->subscribe('response.created', function ($event) {
    // access the request using $event->getRequest()
    // access the response using $event->getResponse()
})

This event is fired when a response has been created but before it has been output.

response.sent

$app->subscribe('response.sent', function ($event) {
    // access the request using $event->getRequest()
    // access the response using $event->getResponse()
})

This event is fired when a response has been output and before the application lifecycle is completed.

Custom Events

You can fire custom events using the event emitter directly:

// Subscribe
$app->subscribe('custom.event', function ($event, $time) {
    return 'the time is '.$time;
});

// Publish
$app->getEventEmitter()->emit('custom.event', time());

Dependency Injection Container

Proton uses League/Container as its dependency injection container.

You can bind singleton objects into the container from the main application object using ArrayAccess:

$app['db'] = function () {
    $manager = new Illuminate\Database\Capsule\Manager;

    $manager->addConnection([
        'driver'    => 'mysql',
        'host'      => $config['db_host'],
        'database'  => $config['db_name'],
        'username'  => $config['db_user'],
        'password'  => $config['db_pass'],
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci'
    ], 'default');

    $manager->setAsGlobal();

    return $manager;
};

or by accessing the container directly:

$app->getContainer()->singleton('db', function () {
    $manager = new Illuminate\Database\Capsule\Manager;

    $manager->addConnection([
        'driver'    => 'mysql',
        'host'      => $config['db_host'],
        'database'  => $config['db_name'],
        'username'  => $config['db_user'],
        'password'  => $config['db_pass'],
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci'
    ], 'default');

    $manager->setAsGlobal();

    return $manager;
});

Multitons can be added using the add method on the container:

$app->getContainer()->add('foo', function () {
        return new Foo();
});

Service providers can be registered using the register method on the Proton app or addServiceProvider on the container:

$app->register('\My\Service\Provider');
$app->getContainer()->addServiceProvider('\My\Service\Provider');

For more information about service providers check out this page - http://container.thephpleague.com/service-providers/.

For easy testing down the road it is recommended you embrace constructor injection:

$app->getContainer()->add('Bar', function () {
        return new Bar();
});

$app->getContainer()->add('Foo', function () use ($app) {
        return new Foo(
            $app->getContainer()->get('Bar')
        );
});