View
111
Download
2
Category
Tags:
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!
Recommended