Speed up your developments with Symfony2

Preview:

DESCRIPTION

 

Citation preview

Speed Up Your Developments with

Symfony2

Hugo HamonTrainings Manager

hhamon on TwitterInternational speaker

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

Bridges

« A Bundle is a directory that has a well-defined 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 configure

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 configuration

Web configuration

Configure the database access parameters

Start to use Symfony2 and happy coding

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{ /** * @Route("/hello/{name}") */ public function indexAction($name) { // ... do things

return new Response(sprintf('Hello %s!', $name)); }}

class DefaultController extends Controller{ /** * @Route("/hello/{name}") */ public function indexAction($name) { // ... do things

return $this->render( 'SensioHelloBundle:Default:index.html.twig', array('name' => $name) ); }}

Request Handling

class DefaultController extends Controller{ /** * @Route("/schedule") * @Template() */ public function indexAction() { $title = 'Conferences Schedule';

return array('title' => $title); }}

Request Handling

Template vars

{% extends "SensioConferenceBundle::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 %}

View Rendering

Twig is a modern template engine for PHP Fast

Concise and rich syntax Automatic output escaping Modern features Extensible Flexible

Twig Template Engine

{% extends "SensioConferenceBundle::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 %}

index.html.t

wig

Template inheritance

{% extends "::base.html.twig" %}

{% block body %}

<img src="/images/logo.gif" alt="Confoo 2011"/>

{% block content %}{% endblock %}

{% endblock %} layout.html.t

wig

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>

base.html.tw

ig

layout.html.twig

index.html.twig

base.html.twig

Template inheritance

Smart URIs

Native routing

mechanism

Bidirectional

Parameters

constraints support

Smart URIs

class DefaultController extends Controller{ /** * @Route( * "/{year}/talk/{month}/{day}/{slug}", * requirements={ * "year"="\d{4}", * "month"="\d{2}", * "day"="\d{2}" * } * ) * @Template() */ public function showAction($slug, $day, $month, $year) { // ... }}

class DefaultController extends Controller{ /** * @Route("/talk/{id}") * @ParamConverter("talk", class="SensioConferenceBundle:Talk") * @Template() */ public function showAction(Talk $talk) { return array('talk' => $talk); }}

Converts requests parameters to a Doctrine entity.

Doctrine Parameter Converter

EasyDebuggin

g

http://www.flickr.com/photos/artelaphe/

Symfony2 version

PHP environmen

t

Current environment

Current response

Recorded logs

Timers

Memory

Queries

The Web Debug Toolbar

Exception Stack Trace

Exception Stack Trace

Recorded Logs

The Profiler Application

The Profiler Application

http://www.flickr.com/photos/chanceprojects/

Database Abstraction Layer

on top of PDO

Object Relational Mapper

Migrations support

Object Document Mapper

(MongoDB)

Object XML Mapper (XML

databases)

Doctrine2 Support

Data Mapper Implementation

/** * @ORM\Entity() */class Talk{ /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ private $id;

/** @ORM\Column(length=80) */ private $title;

/** @ORM\Column(type="text") */ private $synopsis;

/** @ORM\Column(type="datetime") */ private $schedule;

/** @ORM\ManyToMany(targetEntity="Speaker", mappedBy="talks") */ private $speakers;}

Validation

Validate POPOs

(properties & methods)

Easy configuration with

annotations

Easy to customize and

extend

Validation Framework

namespace Sensio\Bundle\TodoBundle\Entity;

class Task{ private $name; private $dueDate;

public function getName() { return $this->name; }

public function setName($name) { $this->name = $name; }

public function getDueDate() { return $this->dueDate; }

public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; }}

namespace Sensio\Bundle\TodoBundle\Entity;use Symfony\Component\Validator\Constraints as Assert;

class Task{ /** * @Assert\NotBlank() * @Assert\MinLength(5) * @Assert\MaxLength(30) */ private $name;

/** * @Assert\NotBlank() * @Assert\Type() * @Assert\MaxLength(30) */ private $dueDate;

// ...}

Forms Management

http://www.flickr.com/photos/miahz/

Transparent layer on top of

your domain object

Native CSRF protection

Coupled to the Validation

framework

Twig integration

Forms Management

namespace Sensio\Bundle\TodoBundle\Form;

use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\FormBuilder;

class TaskType extends AbstractType{ public function buildForm(FormBuilder $builder, array $options) { $builder->add('task'); $builder->add('dueDate', null, array( 'widget' => 'single_text' )); }

public function getName() { return 'task'; }}

use Sensio\Bundle\TodoBundle\Entity\Task;use Sensio\Bundle\TodoBundle\Form\TaskType;

public function newAction(){ $task = new Task(); $task->setName('Write a blog post'); $task->setDueDate(new \DateTime('tomorrow'));

$form = $this->createForm(new TaskType(), $task);

if ($request->getMethod() == 'POST') { $form->bindRequest($request);

if ($form->isValid()) { // save the task to the database...

return $this->redirect($this->generateUrl('success')); } }}

{% extends 'SensioTodoBundle::layout.html.twig' %}

{% block content %}

<form action="#" method="post">

{{ form_widget(form) }}

<input type="submit" value="Send!" />

</form>

{% endblock %}

Prototyping

Functional Testing

http://www.flickr.com/photos/kenstein/

Simulating an end-

user browsing

Crawling API for links

& forms

Testing internal

objects

Testing the response

Functional Testing

class DefaultControllerTest extends WebTestCase{ public function testIndex() { $client = static::createClient();

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

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

$response = $client->getResponse();

$this->assertTrue($response->headers->has('expires')); }}

Functional Testing

HTTP Compliance (RFC2616)

Expiration / Validation

class DefaultController extends Controller{ /** * @Route("/schedule") * @Template * @Cache(expires="tomorrow") */ public function indexAction() { $title = 'Conferences Schedule';

return array('title' => $title); }}

Expiration – Expires Header Field

class DefaultController extends Controller{ /** * @Route("/schedule") * @Template * @Cache(maxage="20") */ public function indexAction() { $title = 'Conferences Schedule';

return array('title' => $title); }}

Expiration – Cache-Control Header Field

InteractiveCode Generators

$ php app/console generate:bundle

$ php app/console generate:doctrine:crud

Native PHP Reverse Proxy Cache

Varnish / Squid

http://varnish-cache.org

Edge Side Includes

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

No ESI

Edge Side Includes Support

<esi:include … />

With ESI

Edge Side Includes Support

http://www.flickr.com/photos/bwop/

<?xml version="1.0"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> <file source-language="en" datatype="plaintext" original="file.ext"> <body> <trans-unit id="1"> <source>Symfony2 is great</source> <target>J'aime Symfony2</target> </trans-unit> <trans-unit id="2"> <source>My name is %name%!</source> <target>Je m'appelle %name% !</target> </trans-unit> </body> </file></xliff>

{% set message = 'Symfony2 is great' %}

{{ message|trans }}

{% set message = 'My name is %name%!' %}

{{ message|trans({'%name%': 'Hugo'}, "hello") }}

Translating Messages From Twig

http://www.flickr.com/photos/cstein96/

Roadmap for 2.1?

http://www.flickr.com/photos/mkrigsman/

Thank You!