Screencast Series – Creating Own PHP Framework Using Symfony2 Components – Episode 6
Object Orientation and HTTPKernel Component*

We’ve been stuck with procedural code in our framework for the educational purposes. It is time to grow up and use object oriented style. In this episode we’ll convert our controller to the class. Then we’ll optimize the object instantiation by using another handy Symfony2 Component – HTTPKernel.
Source Code
You can follow along with the screencast, or just simply get the source code for this episode from GitHub
Watch the Screencast
Show Notes
Controller
We’ll take advantage of the fact that the _controller key of our Symfony2 Route component can take any PHP callback as a value. So instead of using a lambda function, we’ll create a class
<?php
// /src/LeapYearController.php
class LeapYearController
{
public function indexAction($request)
{
if (is_leap_year($request->attributes->get('year'))) {
return new Response('Yep, this is a leap year!');
}
return new Response('Nope, this is not a leap year');
}
}
We’ll now update the route rules in our application
// /src/app.php
...
$routes->add('leap_year', new Route('/is_leap_year/{year}', array(
'year' => null,
'_controller' => array(new LeapYearController(), 'indexAction')
)));
...
HTTPKernel
The obvious problem with our approach: even if the requested URL does not match with any of the provided routes the instance of the class will be called. To switch to lazy-loading and use a couple of other cool features we’re going to use HTTPKernel component of Symfony2 suite.
First, we’ll update the composer configuration
// composer.json
{
"require": {
"symfony/class-loader": "2.1.*",
"symfony/http-foundation": "2.1.*",
"symfony/routing": "2.1.*",
"symfony/http-kernel": "2.1.*"
}
}
Then we’ll call the composer utility from the command line to load the new component and update the autoloading behind the scenes
$ php composer.phar update
Updating /src/app.php
Now we can use special notation to specify the controller – a string containing a class name and a method separated with two colons
// /src/app.php
...
$routes->add('leap_year', new Route('/is_leap_year/{year}', array(
'year' => null,
'_controller' => 'LeapYearController::indexAction'
)));
...
Updating /web/front.php
To make the above work we are going to need to do a couple of changes in the front controller. First off we’re going to let the ControllerResolver of the HTTPKernel component to do what it was designed to do by name – resolve the controllers
<?php
// /web/front.php
...
use Symfony\Component\HttpKernel;
...
$resolver = new HttpKernel\Controller\ControllerResolver();
...
// Handle the Request
try {
$request->attributes->add($matcher->match($request->getPathInfo()));
$controller = $resolver->getController($request);
$arguments = $resolver->getArguments($request, $controller);
$response = call_user_func($controller, $arguments);
}
Updating /src/LeapYearController.php
In our final step we’ll be refactoring the controller we have started this episode with. First, we’ll take advantage of the HTTPKernel features that let us name the variables used by the action inside of the controller by their direct names – straight from Route rules. As you might remember we’ve had a dynamical property {year} in our route, so we’ll be using it in the action
<?php
// /src/LeapYearController.php
use Symfony\Component\HttpFoundation\Response;
class LeapYearController
{
public function indexAction($year)
{
if ($this->is_leap_year($year[0])) {
return new Response('Yep, this is a leap year!');
}
return new Response('Nope, this is not a leap year');
}
private function is_leap_year($year = null)
{
if ($year === null) {
$year = date('Y');
}
return 0 == $year % 400 || (0 == $year % 4 && 0 != $year % 100);
}
}
Fabien Potencier – Original Blog
This tutorial is based on the series of articles published by the creator of Symfon2 – Fabien Potencier – http://fabien.potencier.org/article/55/create-your-own-framework-on-top-of-the-symfony2-components-part-6
* Why the train? Well, I’ve been recording this screencast on the train from Münster to Heidelberg.
No Comments