Build smart and powerful web applications with Symfony2
Built around standalone and decoupled components…
… and a full-stack framework based on those components
Application bundles Third party bundles
Standalone Components
Core Bundles Third party libraries
The Symfony2 stack
« A Bundle is a directory that has a well-de"ned structure and can host anything from classes to
controllers and web resources. »
What makes Symfony2 unique?
Symfony2 follows standards & best practices
- RFC2616 - PHPUnit
- Jinja Templates - Design Patterns
Symfony is now easier to install and con"gure
http://symfony.com/download
Download the Standard Edition that hosts the framework, standard bundles and a default application architecture.
Several distributions available
Easy installation and con!guration
Web con!guration Con"gure the database access parameters
Start to use Symfony2 and happy coding J
Want to give it a try?
Symfony2 Philosophy
« Basically, Symfony2 asks you to convert a Request into a Response »
Request handling
class DefaultController extends Controller { /** * @extra:Route("/hello/{name}") */ public function indexAction($name) { // ... do things return new Response(sprintf('Hello %s!', $name)); } }
Request handling
class DefaultController extends Controller { /** * @extra:Route("/hello/{name}") */ public function indexAction($name) { // ... do things return $this->render('HelloBundle:Default:index.html.twig', array('name' => $name)); } }
Request handling
class DefaultController extends Controller { /** * @extra:Route("/schedule") * @extra:Template */ public function indexAction() { $title = 'Confoo 2011 Conferences Schedule'; return array('title' => $title); } }
Templating
{% extends "ConfooConferenceBundle::layout.html.twig" %} {% block content %} <h1> {{ title }} </h1> <ul> <li>Caching on the Edge, by Fabien Potencier</li> <li>HipHop for PHP, by Scott Mac Vicar</li> <li>XDebug, by Derick Rethans</li> <li>...</li> </ul> {% endblock %}
TWIG Template Engine
Twig is a modern template engine for PHP
§ Fast § Concise and rich syntax § Automatic output escaping § Modern features § Extensible § Flexible
Template inheritance
{% extends "ConfooConferenceBundle::layout.html.twig" %} {% block content %} <h1> {{ title }} </h1> <ul> <li>Caching on the Edge, by Fabien Potencier</li> <li>HipHop for PHP, by Scott Mac Vicar</li> <li>XDebug, by Derick Rethans</li> <li>...</li> </ul> {% endblock %}
Template inheritance
{% extends "::base.html.twig" %} {% block body %} <img src="/images/logo.gif" alt="Confoo 2011"/> {% block content %}{% endblock %} {% endblock %}
Template inheritance
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>{% block title %}Welcome!{% endblock %}</title> <link rel="shortcut icon" href="{{ asset('favicon.ico') }}" /> </head> <body> {% block body %}{% endblock %} </body> </html>
Template inheritance
layout.html.twig
index.html.twig
base.html.twig
Smart URIs
Smart URIs
Typical PHP URIs suck!!!
Smart URIs
Native routing mechanism
Smart URIs
class DefaultController extends Controller { /** * @extra:Route("/{year}/talk/{month}/{day}/{slug}") * @extra:Template */ public function showAction($slug, $day, $month, $year) { // Get a talk object from the database $talk = ...; return array('talk' => $talk); } }
Parameter converter
class DefaultController extends Controller { /** * @extra:Route("/talk/{id}") * @extra:Template */ public function showAction(Talk $talk) { return array('talk' => $talk); } }
Easy Debugging
The Web Debug Toolbar
Symfony2 version PHP environment Current environment Current response Recorded logs Timers Memory Queries
Exception stack traces
Exception stack traces
Recorded logs
The Pro!ler application
The Pro!ler application
Database Management
Doctrine 2 Library
§ Database Abstraction Layer on top of PDO
§ Object Relational Mapper
§ Migrations support
§ Object Document Mapper (MongoDB)
§ Object XML Mapper ( XML databases)
De!ning entities as POPO /** * @orm:Entity */class Talk{ /** * @orm:Id * @orm:GeneratedValue * @orm:Column(type="integer") */ public $id; /** @orm:Column(length=80, nullable=false) */ public $title; /** @orm:Column(type="text") */ public $synopsis; /** @orm:Column(type="datetime") */ public $schedule; /** @orm:ManyToMany(targetEntity="Speaker", mappedBy="talks") */ public $speakers;}
Validation
Validation
§ Validate POPOs (properties & methods)
§ Easy con"guration with annotations
§ Easy to customize and extend
Validating Plain PHP Objects
class ContactRequest { /** @validation:NotBlank */ public $message; /** * @validation:Email * @validation:NotBlank */ public $sender; } }
Forms Handling
Forms management
§ Transparent layer on top of your domain object
§ Native CSRF protection
§ Coupled to the Validation framework
§ Twig integration
Designing a basic form class
namespace Confoo\ContactBundle\Form; use Symfony\Component\Form\Form; use Symfony\Component\Form\TextField; use Symfony\Component\Form\TextareaField; use Symfony\Component\Form\CheckboxField; class ContactForm extends Form { protected function configure() { $this->add(new TextField('sender'))); $this->add(new TextareaField('message')); } }
Processing a form
public function contactAction() { $contactRequest = new ContactRequest(); $form = ContactForm::create(...); $form->bind($this->get('request'), $contactRequest); if ($form->isValid()) { // do things with validated data } return array('form' => $form); }
Prototyping the rendering with Twig
{% extends 'ConfooContactBundle::layout.html.twig' %} {% block content %} <form action="#" method="post"> {{ form_field(form) }} <input type="submit" value="Send!" /> </form> {% endblock %}
Functional Testing
Functional testing
Simulating an end-user browsing scenario and testing the Response
Functional Testing
class DefaultControllerTest extends WebTestCase { public function testIndex() { $client = $this->createClient(); $crawler = $client->request('GET', '/schedule'); $this->assertTrue( $crawler->filter('html:contains("Fabien Potencier")')->count() > 0 ); $this->assertTrue($client->getResponse()->headers->has('expires')); } }
HTTP Compliance (RFC2616)
Expiration / Validation
Expiration with Expires
class DefaultController extends Controller { /** * @extra:Route("/schedule") * @extra:Template * @extra:Cache(expires="tomorrow") */ public function indexAction() { $title = 'Confoo 2011 Conferences Schedule'; return array('title' => $title); } }
Expiration with Cache-Control
class DefaultController extends Controller { /** * @extra:Route("/schedule") * @extra:Template * @extra:Cache(maxage="20", s-maxage="20") */ public function indexAction() { $title = 'Confoo 2011 Conferences Schedule'; return array('title' => $title); } }
Native PHP Reverse Proxy Cache
Varnish / Squid
Edge Side Includes
<esi:include src="http://..." />
Security Authentication & Authorization
Thank You!
Recommended