Build powerfull and smart web applications with Symfony2

Post on 10-May-2015

11,964 views 4 download

description

Symfony2 first stable release is scheduled for the first week of March 2011. During this session, we will have a look at the new framework architecture and most of its powerfull features. We will show you how Symfony2 implements the MVC pattern and an HTTP request is processed and converted as a response for the end user. Of course, we will talk about the configuration principles and how it's easy to configure Symfony2 project parts like the routing system or the data model. We will also focus on other major components of the framework like the Doctrine2 integration, forms, security (authentication and authorizations) or HTTP cache management.

transcript

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!