study-group-03
Created by Juan Manuel Torres / @onema / onema.io
Follow Live
http://slides.com/onema/http-kernel-2/live
We have learned about the HTTP Reques/Response and how to handle them using the Symfony2 HTTP Foundation Component.
Pretty Urls and.
Resolve Controllers and Arguments.
Created a better controller.
// src/SDPHP/SGFramework/SGFramework.php
class SGFramework {
protected $matcher;
protected $resolver;
// Inject Matcher and Resolver
public function __construct(UrlMatcher $matcher, ControllerResolver $resolver) {
$this->matcher = $matcher;
$this->resolver = $resolver;
}
// Everything else is the same
public function handle(Request $request) {
try {
$parameters = $this->matcher->match($request->getPathInfo());
$request->attributes->add($parameters);
$controller = $this->resolver->getController($request);
$arguments = $this->resolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
} catch (ResourceNotFoundException $e) {
$response = new Response('Not Found: ' . $e->getMessage(), 404);
} catch (\Exception $e) {
$response = new Response('An error occurred: ' . $e->getMessage(), 500);
}
return $response;
}
}
New
Old
// web/app.php
$request = Request::createFromGlobals();
include __DIR__ . '/../app/config/routing.php';
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($routes, $context);
$resolver = new ControllerResolver();
$framework = new SGFramework($matcher, $resolver);
$response = $framework->handle($request);
$response->prepare($request);
$response->send();
Our
Framework!
Extending behavior without inheritance.
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
Implements the Mediator pattern, enabling developers to extend the symfony framework, or use the component in their own projects.
Loose coupling is achieved by communicating with a dispatcher instead of eachother.
Consumer wants to be informed (listen) on certain events.
New consumers (plugins) may listen for events.
When an event occurs the producer informs the dispatcher.
Finally the dispatcher notifies the consummers in order of priority.
// web/app.php
$testEvent = new TestEvent();
$dispatcher = new EventDispatcher();
$dispatcher->addListener('framework.request', array($testEvent, 'onFrameworkRequest'));
$dispatcher->addListener('framework.response', array($testEvent, 'onFrameworkResponse'));
// Initialize framework and give it the request to handle
$framework = new SGFramework($dispatcher, $matcher, $resolver);
Samll update to the Front Controller.
In this case the producer is our SGFramework.
The dispatcher is added to the framework.
// src/SDPHP/SGFramework/SGFramework.php
public function __construct(EventDispatcher $dispatcher,
UrlMatcher $matcher,
ControllerResolver $resolver)
{
$this->dispatcher = $dispatcher;
$this->matcher = $matcher;
$this->resolver = $resolver;
}
public function handle(Request $request)
{
$event = new GenericEvent();
// . . .
$event->setArgument('request', $request);
$this->dispatcher->dispatch('framework.request', $event);
// . . .
}
Create a generic event. These objects hold information about the event.
Add relevant info to event
Dispatch Event
Inject Dispatcher
Update the Framework.
The framework will "produce" events.
// src/SDPHP/StudyGroup03/Event/TestEvent.php
class TestEvent
{
public function onFrameworkRequest(GenericEvent $event)
{
// . . .
}
public function onFrameworkResponse(GenericEvent $event)
{
// . . .
}
}
Test Event: It can be any class.
Modify the request to set a default value other than ES.
public function onFrameworkRequest(GenericEvent $event)
{
// Change Default language
$request = $event->getArgument('request');
$language = $request->cookies->get('language');
if (!isset($language)) {
$request->cookies->set('language', 'DE');
}
}
http://dev.studygroup.com:8080/hello
http://dev.studygroup.com:8080/hello/FR
Hallo Welt
Bonjour tout le monde!
Modify the response to add styles to the content.
public function onFrameworkResponse(GenericEvent $event)
{
$response = $event->getArgument('response');
$content = $response->getContent();
$response->setContent(
'<p style="background:#ccc;...">'
.$content.
'</p>'
);
}
http://dev.studygroup.com:8080/hello/SW
Hujambo dunia
// src/SDPHP/SGFramework/SGFramework.php
use Symfony\Component\HttpKernel\HttpKernelInterface;
class SGFramework implements HttpKernelInterface
{
// . . .
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
{
// . . .
}
}
Implement HttpKernelInterface
We will get a lot of functionality for "free".
Our Framework can be Wrapped arround other libraries to extend functionality.
// web/app.php
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\Store;
// . . .
// Initialize framework and give it the request to handle
$framework = new SGFramework($dispatcher, $matcher, $resolver);
// Add HTTP Caching
$framework = new HttpCache($framework, new Store(__DIR__.'/../app/cache'));
// src/SDPHP/StudyGroup03/Controller/HelloWorldController.php
class HelloWorldController
{
public function translateAction(Request $request)
{
// . . .
$response->setTtl(20);
return $response;
}
}
Enable and test HTTP Caching
Some Frameworks provide the means to call a "Before" and "After" methods in your controller.
BY Juan Manuel Torres / onema.io / @onema / kinojman@gmail.com