Post on 18-Dec-2014
description
transcript
¿Quién soy?¿Quién soy?
Raúl Fraile
@raulfraile
PHP/Symfony2 freelance developer
¿Qué hago?¿Qué hago?
SensioLabsSensioLabsConnectConnect
¿Por qué?¿Por qué?
app[_dev].phpapp[_dev].php
Controlador frontal
app[_dev].phpapp[_dev].php
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
bootstrap.php.cachebootstrap.php.cache
Clases/namespaces en
un único fichero.
bootstrap.php.cachebootstrap.php.cache
// app/bootstrap.php.cache
namespace { require_once __DIR__.'/autoload.php'; }
namespace Symfony\Component\DependencyInjection{ interface ContainerAwareInterface { function setContainer(ContainerInterface $container = null); } ...}
bootstrap.php.cachebootstrap.php.cache
Reduce operaciones I/O
bootstrap.php.cachebootstrap.php.cache
Carga autoload.php
autoload.phpautoload.php// app/autoload.php
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = new UniversalClassLoader();$loader->registerNamespaces(array( 'Symfony' => array( __DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'), 'Assetic' => __DIR__.'/../vendor/assetic/src',));$loader->registerPrefixes(array( 'Twig_' => __DIR__.'/../vendor/twig/lib',));
ClassLoaderClassLoader
Autoload de
clases/interfaces en
Symfony2
ClassLoader
ClassLoaderClassLoader
Implementa PSR-0
PSR-0PSR-0
Aprobado por el “Framework Interop Group”
github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
PSR-0PSR-0
Fully Qualified Name
Filesystem
\Symfony\Core\Request\Zend\Mail\Message
[vendor_path]/Symfony/Core/Request.php[vendor_path]/Zend/Mail/Message.php
ClassLoaderClassLoader// namespaced class name$namespace = substr($class, 0, $pos);foreach ($this->namespaces as $ns => $dirs) { if (0 !== strpos($namespace, $ns)) { continue; }
foreach ($dirs as $dir) { $className = substr($class, $pos + 1); $file = $dir . DIR_SEPARATOR . str_replace('\\',DIR_SEPARATOR, $namespace) . DIR_SEPARATOR . str_replace('_', DIR_SEPARATOR, $className) . '.php'; if (file_exists($file)) { return $file; } }}
ClassLoaderClassLoader
$loader->findFile( 'Symfony\Component\HttpFoundation\Request');
/Sites/desymfony/app/../vendor/symfony/src/ Symfony/Component/HttpFoundation/Request.php
app[_dev].phpapp[_dev].php
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
AppKernel.phpAppKernel.php// src/AppKernel.php
use Symfony\Component\HttpKernel\Kernel;use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel{ public function registerBundles() { $bundles = array( new Symfony\Bundle\TwigBundle\TwigBundle(), ... ); return $bundles; }
public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); }}
app[_dev].phpapp[_dev].php
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
EnvironmentDebug
AppKernel.phpAppKernel.php
If (true === $debug) {
} else {
Guarda inicio petición (microtime)
display_errors = 1
error_reporting = -1
DebugUniversalClassLoader
}display_errors = 0
app[_dev].phpapp[_dev].php
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
LoadClassCacheLoadClassCache
Objetivo: mapear FQN y
paths de las principales
clases/interfaces
LoadClassCacheLoadClassCache
Se cachea en
classes.map y
classes.php.meta
app[_dev].phpapp[_dev].php
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
RequestRequest
Componente
HttpFoundation
RequestRequest
Abstracción OO de
una petición HTTP
RequestRequest
GET /index.php HTTP/1.1␍␊ Host: test.com␍␊ Accept-Language:en;q=0.8␍␊ Accept-Encoding:gzip␍␊ User-Agent: Mozilla/5.0␍␊ ␍␊
$_GET
$_POST
$_COOKIE
$_FILES
$_SERVER
Request
queryrequestcookies
filesserver
headers
getHostgetClientIp
...
app[_dev].phpapp[_dev].php
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
HttpKernelHttpKernel
Corazón de Symfony
HttpKernelHttpKernel
Gestiona entorno
formado por bundles,
DIC...
Inicialización de
bundles y DIC
$kernel->boot()$kernel->boot()
Se cargan los bundles
definidos en
AppKernel::registerBundles()
$kernel->initializeBundles()$kernel->initializeBundles()
Se genera usando el
ContainerBuilder del
DependencyInjection
$kernel->initializeContainer()$kernel->initializeContainer()
ContainerBuilderContainerBuilder
// example.com/src/container.phpuse Symfony\Component\DependencyInjection;use Symfony\Component\DependencyInjection\Reference;
$sc = new DependencyInjection\ContainerBuilder(); $sc->register('context', 'Symfony\Component\Routing\RequestContext');$sc->register('matcher', 'Symfony\Component\Routing\Matcher\UrlMatcher') ->setArguments(array($routes, new Reference('context')));
$sc->register('framework', 'Simplex\Framework') ->setArguments(array(new Reference('dispatcher'), new Reference('resolver'))) ;
http://fabien.potencier.org/article/62/create-your-own-framework-on-top-of-the-symfony2-components-part-12
{rootDir}{Environment}
[Debug]ProjectContainer
$kernel->initializeContainer()$kernel->initializeContainer()
Por cada bundle se ejecuta
Bundle::build() y se
registran sus extensiones
$kernel->initializeContainer()$kernel->initializeContainer()
Por cada bundle se asigna
el 'container' y se ejecuta
el boot()
$kernel->boot()$kernel->boot()
Objetivo: Devolver un
objeto Response
$kernel->handle()$kernel->handle()
Se lanza en cuanto
llega la petición
Evento kernel.requestEvento kernel.request
Un listener puede
devolver un Response
y 'finalizar' la ejecución
Evento kernel.requestEvento kernel.request
FrameworkBundle lo
utiliza para rellenar el
valor de _controller
Evento kernel.requestEvento kernel.request
Utiliza un RouterMatcher
(autogenerado por comp.
Routing)
RouterListenerRouterListener
RouterListenerRouterListener
// app/cache/dev/appdevUrlMatcher.php
class appdevUrlMatcher extends RedirectableUrlMatcher{ ... public function match($pathinfo) { ... // _demo_hello if (0 === strpos($pathinfo, '/demo/hello') && preg_match('#^/demo/hello/(?P<name>[^/]+?)$#s', $pathinfo, $m)) { return array_merge($this->mergeDefaults($m, array( '_controller' => 'Acme\\DemoBundle\\Controller\\DemoController::helloAction') ), array( '_route' => '_demo_hello')); } ... }
Encargado de devolver un
controlador + argumentos
a partir de _controller
ControllerResolverControllerResolver
Agrupa componentes y
librerías para crear un
framework MVC
FrameworkBundleFrameworkBundle
Además, ofrece...
FrameworkBundleFrameworkBundle
php app/console
FrameworkBundleFrameworkBundle
FrameworkBundleFrameworkBundle// app/console
#!/usr/bin/env php<?php
require_once __DIR__.'/bootstrap.php.cache';require_once __DIR__.'/AppKernel.php';
use Symfony\Bundle\FrameworkBundle\Console\Application;use Symfony\Component\Console\Input\ArgvInput;
$input = new ArgvInput();$env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');$debug = !$input->hasParameterOption(array('--no-debug', ''));
$kernel = new AppKernel($env, $debug);$application = new Application($kernel);$application->run();
Comandos
FrameworkBundleFrameworkBundle
assets:install
cache:clear
cache:warmup
container:debug
router:dump-apache
router:debug
Controller
FrameworkBundleFrameworkBundle
FrameworkBundleFrameworkBundle
// src/Acme/DemoBundle/Controller/DemoController
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DemoController extends Controller{ public function helloAction($name) { ... }}
Y mucho más: ESI,
WebTestCase,
DataCollectors...
FrameworkBundleFrameworkBundle
Una vez definido el
controlador, se lanza el
evento
Evento kernel.controllerEvento kernel.controller
Se puede cambiar,
pasando un Callable
Evento kernel.controllerEvento kernel.controller
Se lanza si el Controller
no devuelve un objeto
Response
Evento kernel.viewEvento kernel.view
Objetivo: construir un
objeto Response del
return del Controller
Evento kernel.viewEvento kernel.view
Permite reemplazar o
modificar el objeto
Response
Evento kernel.responseEvento kernel.response
Oportunidad para
convertir una Exception
en un Response
Evento kernel.exceptionEvento kernel.exception
Todos heredan de
KernelEvent
EventosEventos
getRequestType(): MASTER_REQUEST o SUB_REQUEST
getKernel();
getRequest();
HTTP/1.1 200 OK Content-type: text/html Date:Thu, 31 May 2012 17:54:50 GMT
<!DOCTYPE HTML> <html lang="es"> <head> <meta charset="utf-8"> ...
Response
Headers
Version
Content
Status code
Status text
Charset
ResponseResponse
// web/app[_env].php
1. require_once __DIR__.'/../app/bootstrap.php.cache';2. require_once __DIR__.'/../app/AppKernel.php';
3. use Symfony\Component\HttpFoundation\Request;
4. $kernel = new AppKernel('dev', true);5. $kernel->loadClassCache();6. $kernel->handle(Request::createFromGlobals())->send();
app[_dev].phpapp[_dev].php
Envía las cabeceras y el
contenido
Response::send()Response::send()
Response::send()Response::send()
https://github.com/raulfraile/internals-desymfony2012
DemoDemo
¡Gracias!
http://www.flickr.com/photos/connectirmeli/7233514862
http://www.flickr.com/photos/barretthall/6070677596
http://www.flickr.com/photos/f-oxymoron/5005673112/
FotografíasFotografías
¿Preguntas?¿Preguntas?