PhpBB meets Symfony2

Post on 08-May-2015

8.958 views 6 download

Transcript of PhpBB meets Symfony2

phpBB4 meets Symfony2 Fabien Potencier

symfony 1 vs Symfony2

MVC

namespace Application\HelloBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller;

class HelloController extends Controller { public function indexAction($name) { // Get things from the Model

return $this->render( 'HelloBundle:Hello:index', array('name' => $name) ); } }

<?php $view->extend('HelloBundle::layout') ?>

Hello <?php echo $name ?>!

<html> <head> <title> <?php $view['slots']->output('title') ?> </title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

_content

title

layout

slot

{% extends "HelloBundle::layout" %}

{% block content %} Hello {{ name }}! {% endblock %}

<html> <head> <title> {% block title %}{% endblock %} </title> </head> <body> {% block body %}{% endblock %} </body> </html>

Routing

/blog.php?section=symfony&article_id=18475

web/ index.php

/index.php/blog/2010/08/21/symfony2-meets-phpBB4

/blog/2010/08/21/symfony2-meets-phpBB4

/blog/:year/:month/:day/:slug

post: pattern: /blog/:year/:month/:day/:slug defaults: { _controller: BlogBundle:Post:show }

<routes> <route id="post" pattern="/blog/:year/:month/:day/:slug"> <default key="_controller"> BlogBundle:Post:show </default> </route> </routes>

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route;

$collection = new RouteCollection();

$route = new Route( '/blog/:year/:month/:day/:slug', array('_controller' => 'BlogBundle:Post:show'));

$collection->addRoute('post', $route);

return $collection;

$router ->match('/blog/2010/08/21/sf2-meets-phpBB4')

$router ->generate('post', array('slug' => '...'))

post: pattern: /post/:slug defaults: { _controller: BlogBundle:Post:show }

$router ->generate('post', array('slug' => '...'))

Bundles

.../ SomeBundle/ Controller/ Entity/ Resources/ config/ views/ SomeBundle.php Tests/

public function registerBundleDirs() { return array( 'Application' => __DIR__.'/../src/Application', 'Bundle' => __DIR__.'/../src/Bundle', 'Symfony\Bundle' => __DIR__.'/../src/vendor/symfony/src/Symfony/Bundle', ); }

$this->render('SomeBundle:Hello:index', $params)

hello: pattern: /hello/:name defaults: { _controller: SomeBundle:... }

SomeBundle can be any of

Application\SomeBundle Bundle\SomeBundle Symfony\Bundle\SomeBundle

Environments

Developers Customer End Users

Development Environment

Staging Environment

Production Environment

cache cache cache

debug   debug   debug  

logs   logs   logs  

stats stats stats

Development Environment

Staging Environment

Production Environment

# config/config.yml doctrine.dbal: dbname: mydbname user: root password: %doctrine.dbal_password%

swift.mailer: transport: smtp host: localhost

# config/config_dev.yml imports: - { resource: config.yml }

zend.logger: priority: debug path: %kernel.root_dir%/logs/%kernel.environment%.log

doctrine.dbal: password: ~

swift.mailer: transport: gmail username: xxxxxxxx password: xxxxxxxx

# Doctrine Configuration doctrine.dbal: dbname: xxxxxxxx user: xxxxxxxx password: ~

# Swiftmailer Configuration swift.mailer: transport: smtp encryption: ssl auth_mode: login host: smtp.gmail.com username: xxxxxxxx password: xxxxxxxx

<!-- Doctrine Configuration --> <doctrine:dbal dbname="xxxxxxxx" user="xxxxxxxx" password="" /> <doctrine:orm />

<!-- Swiftmailer Configuration --> <swift:mailer transport="smtp" encryption="ssl" auth_mode="login" host="smtp.gmail.com" username="xxxxxxxx" password="xxxxxxxx" />

// Doctrine Configuration $container->loadFromExtension('doctrine', 'dbal', array( 'dbname' => 'xxxxxxxx', 'user' => 'xxxxxxxx', 'password' => '', )); $container->loadFromExtension('doctrine', 'orm');

// Swiftmailer Configuration $container->loadFromExtension('swift', 'mailer', array( 'transport' => "smtp", 'encryption' => "ssl", 'auth_mode' => "login", 'host' => "smtp.gmail.com", 'username' => "xxxxxxxx", 'password' => "xxxxxxxx", ));

Developer Tools

INFO: Matched route "blog_home" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'index', '_route' => 'blog_home',))

INFO: Using controller "Bundle\BlogBundle\Controller\PostController::indexAction"

INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ ORDER BY s0_.published_at DESC LIMIT 10 (array ())

INFO: Matched route "blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',))

INFO: Using controller "Bundle\BlogBundle\Controller\PostController::showAction »

INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ WHERE s0_.id = ? (array ( 0 => '3456',)) ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught Symfony\Components\RequestHandler\Exception\NotFoundHttpException exception)

INFO: Using controller "Symfony\Framework\WebBundle\Controller\ExceptionController::exceptionAction"

DEBUG: Notifying (until) event "core.request" to listener "(Symfony\Framework\WebBundle\Listener\RequestParser, resolve)" INFO: Matched route "blog_post" (parameters: array ( '_bundle' => 'BlogBundle', '_controller' => 'Post', '_action' => 'show', '_format' => 'html', 'id' => '3456', '_route' => 'blog_post',)) DEBUG: Notifying (until) event "core.load_controller" to listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" INFO: Using controller "Bundle\BlogBundle\Controller\PostController::showAction" DEBUG: Listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" processed the event "core.load_controller" INFO: Trying to get post "3456" from database INFO: SELECT s0_.id AS id0, s0_.title AS title1, s0_.html_body AS html_body2, s0_.excerpt AS excerpt3, s0_.published_at AS published_at4 FROM sf_weblog_post s0_ WHERE s0_.id = ? (array ( 0 => '3456',)) DEBUG: Notifying (until) event "core.exception" to listener "(Symfony\Framework\WebBundle\Listener\ExceptionHandler, handle)" ERR: Post "3456" not found! (No result was found for query although at least one row was expected.) (uncaught Symfony\Components\RequestHandler\Exception\NotFoundHttpException exception) DEBUG: Notifying (until) event "core.request" to listener "(Symfony\Framework\WebBundle\Listener\RequestParser, resolve)" DEBUG: Notifying (until) event "core.load_controller" to listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" INFO: Using controller "Symfony\Framework\WebBundle\Controller\ExceptionController::exceptionAction" DEBUG: Listener "(Symfony\Framework\WebBundle\Listener\ControllerLoader, resolve)" processed the event "core.load_controller" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Listener\ResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\DataCollector\DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\WebDebugToolbar, handle)" DEBUG: Listener "(Symfony\Framework\WebBundle\Listener\ExceptionHandler, handle)" processed the event "core.exception" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Listener\ResponseFilter, filter)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\DataCollector\DataCollectorManager, handle)" DEBUG: Notifying (filter) event "core.response" to listener "(Symfony\Framework\WebBundle\Debug\WebDebugToolbar, handle)"

Security

XSS / CSRF / SQL Injection

<doctrine:dbal dbname="sfweb" username="root" password="SuperSecretPasswordThatAnyoneCanSee" />

SetEnv SYMFONY__DOCTRINE__DBAL__PASSWORD "foobar"

in a .htaccess or httpd.conf file

%doctrine.dbal.password%

<doctrine:dbal dbname="sfweb" username="root" password="%doctrine.dbal.password%" />

Functional Tests

$client = $this->createClient();

$crawler = $client->request( 'GET', '/hello/Fabien');

$this->assertTrue($crawler->filter( 'html:contains("Hello Fabien")')->count());

$this->assertEquals( 10, $crawler->filter('div.hentry')->count());

$this->assertTrue( $client->getResponse()->isSuccessful());

$crawler = $client->request( 'GET', 'hello/Lucas' );

$link = $crawler->selectLink("Greet Lucas");

$client->click($link);

$form = $crawler->selectButton('submit');

$client->submit($form, array( 'name' => 'Lucas', 'country' => 'France', 'like_symfony' => true, 'photo' => '/path/to/lucas.jpg', ));

$harry = $this->createClient(); $sally = $this->createClient();

$harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages');

$this->assertEquals(201, $harry->getResponse()->getStatusCode());

$this->assertRegExp('/Hello/', $sally->getResponse()->getContent());

$harry = $this->createClient(); $sally = $this->createClient();

$harry->insulate(); $sally->insulate();

$harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages');

$this->assertEquals(201, $harry->getResponse()->getStatusCode()); $this->assertRegExp('/Hello/', $sally->getResponse()->getContent());

Caching

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus.  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

cacheable for 10 seconds cacheable for 5 seconds

main controller

embedded controller

layout

<?php $view->extend('...:layout') ?>

<?php $view['slots']->start('sidebar') ?>

<?php echo $view['actions']->render('...:list') ?>

<?php $view['slots']->stop() ?>

cacheable for 10 seconds

cacheable for 5 seconds

$view['actions']->render('...:list', array( 'standalone' => true, ))

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus.  

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  In  vel  nulla  arcu,  vitae  cursus  nunc.  Integer  semper  turpis  et  enim  por6tor  iaculis.  Nulla  facilisi.  Lorem  ipsum  dolor  sit  amet,  consectetur  adipiscing  elit.  Mauris  vehicula  ves;bulum  dictum.  Aenean  non  velit  tortor.  Nullam  adipiscing  malesuada  aliquam.  Mauris  dignissim,  urna  quis  iaculis  tempus,  justo  libero  por6tor  est,  nec  eleifend  est  elit  vitae  ante.  Curabitur  interdum  luctus  metus,  in  pulvinar  lectus  rutrum  sit  amet.  Duis  gravida,  metus  in  dictum  eleifend,  dolor  risus  ;ncidunt  ligula,  non  volutpat  nulla  sapien  in  elit.  Nulla  rutrum  erat  id  neque  suscipit  eu  ultricies  odio  sollicitudin.  Aliquam  a  mi  vel  eros  placerat  hendrerit.  Phasellus  por6tor,  augue  sit  amet  vulputate  venena;s,  dui  leo  commodo  odio,  a  euismod  turpis  ligula  in  elit.    

<esi:include src="..." />

ESI… or Edge Side Includes

Symf

ony2

Appli

catio

n

Reve

rse Pr

oxy

Clien

t Lorem  ipsum  dolor  sit  amet,    

Lorem  ipsum  dolor  

Lorem  ipsum  dolor  sit  amet,    

Lorem  ipsum  dolor  

1

2

3

4

Symfony2 app

Web Server

Requests

Response

Symfony2 app

Symfony2 HTTP proxy

Web Server

Requests

Response

Symfony2 app

Web Server

Reverse proxy

Requests

Response

HttpKernel: The framework construction kit

namespace Symfony\Component\HttpKernel;

interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2;

public function handle( Request $request = null, $type = self::MASTER_REQUEST, $raw = false); }

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

Request

Response

core.controller

core.response

core.view

core.request

getController()

getArguments()

core.exception

HttpFoundation

HttpKernel

Framework

FrameworkBundle

Routing

Console

SwiftmailerBundle

TwigBundle

DependencyInjection

...

...

Components

Bundles

Event Dispatcher

Templating

DoctrineBundle

ZendBundle

MOD author

Theme author

Core Developer

End Users

Everybody

Questions?