KEMBAR78
Symfony | PDF
0% found this document useful (0 votes)
673 views763 pages

Symfony

Uploaded by

Nikolay Ivlev
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
673 views763 pages

Symfony

Uploaded by

Nikolay Ivlev
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 763

Symfony Documentation

2.0

Fabien Potencier

28 September 2011

IFI ymfonyP F F F IFP IFQ F F F F IFR F IFS F PFI PFP PFQ PFR PFS

F F F F F

F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F

S S T U IP IR IS IS IU IV PH PH PI PI PP PQ PQ PR PS PT PU PU PW QQ i

wigD F F F F F D F F F F

QFI F F F F F F F F F QFP F F F F QFQ F F F QFR QFS euring esoures F F F F F F F F F F F F F QFT ghing esoures F F F F F F F F F F F F F QFU F F F F F F F F F F

F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

RFI F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F RFP F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F RFQ sing endors F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

RFR RFS RFT


II

F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

QQ QR QR
35

SFI ymfonyP r SFP ymfonyP versus plt r F F F F F F F SFQ snstlling nd gon(guring ymfony F F F SFR ymfonyP F F F F F SFS gontroller F F F F F F F F F F F F F F F F F SFT outing F F F F F F F F F F F F F F F F F F SFU greting nd using empltes F F F F F F SFV hotrine @A F SFW F F F F F F F F F F F F F F SFIH F F F F F F F F F F F F F F F F SFII F F F F F F F F F F F F F F F F F F SFIP eurity F F F F F F F F F F F F F F F F F F SFIQ r ghe F F F F F F F F F F F F F F F SFIR rnsltions F F F F F F F F F F F F F F F SFIS ervie gontiner F F F F F F F F F F F F F SFIT erformne F F F F F F F F F F F F F F F SFIU snternls F F F F F F F F F F F F F F F F F SFIV es ymfonyP F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F

QW QW RW TQ TV VU IHH IPI IRQ IUH IVS IWW PPT PTH PUV PWQ QIP QIR QQR
337

III

TFI row to grete nd store ymfonyP rojet in git F F F F F F F F F TFP F F F F F F F F F F F F TFQ row to de(ne gontrollers s ervies F F F F F F F F F F F F F F F F F TFR row to fore routes to lwys use r F F F F F F F F F F F F F F TFS row to llow G hrter in route prmeter F F F F F F F F F F TFT row to se esseti for esset wngement F F F F F F F F F F F F F F TFU row to winify tvripts nd tylesheets with s gompressor F TFV row to se esseti por smge yptimiztion with wig puntions F TFW row to epply n esseti pilter to pei( pile ixtension F F F F TFIH row to hndle pile plods with hotrine F F F F F F F F F F F F F F TFII hotrine ixtensionsX imestmpleX luggleD rnsltleD etF TFIP egistering ivent visteners nd usriers F F F F F F F F F F F F F TFIQ row to generte intities from n ixisting htse F F F F F F F F TFIR row to use hotrine9s hfev vyer F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

QQW QQW QRI QRQ QRR QRT QRU QSP QSR QSW QTQ QUH QUI QUQ QUT

ii

TFIS TFIT TFIU TFIV TFIW TFPH TFPI TFPP TFPQ TFPR TFPS TFPT TFPU TFPV TFPW TFQH TFQI TFQP TFQQ TFQR TFQS TFQT TFQU TFQV TFQW TFRH TFRI TFRP TFRQ TFRR TFRS TFRT TFRU TFRV TFRW TFSH TFSI TFSP TFSQ TFSR TFSS TFST TFSU TFSV TFSW

row to work with wultiple intity wngers F F F F F F F F F F F F F F egistering gustom hv puntions F F F F F F F F F F F F F F F F F F row to ustomize porm endering F F F F F F F F F F F F F F F F F F F row to grete gustom porm pield ype F F F F F F F F F F F F F F F row to rete gustom lidtion gonstrint F F F F F F F F F F F F row to wster nd grete new invironments F F F F F F F F F F F F F row to et ixternl rmeters in the ervie gontiner F F F F F F row to se ptory to grete ervies F F F F F F F F F F F F F F F F row to wnge gommon hependenies with rent ervies F F F F row to work with opes F F F F F F F F F F F F F F F F F F F F F F F F row to use doessiontorge to store essions in the htse F F F fundle truture nd fest rties F F F F F F F F F F F F F F F F F F row to use fundle snheritne to yverride prts of fundle F F F F row to expose emnti gon(gurtion for fundle F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F qmil F F F F F F F F F F F F row to ork with imils huring hevelopment F F F F F F F F F F F F row to pool imil F F F F F F F F F F F F F F F F F F F F F F F F F F F row to simulte r euthentition in puntionl est F F F F F row to test the sntertion of severl glients F F F F F F F F F F F F F row to use the ro(ler in puntionl est F F F F F F F F F F F F F F row to test hotrine epositories F F F F F F F F F F F F F F F F F F F row to dd ememer we vogin puntionlity F F F F F F F F F F F row to implement your own oter to lklist s eddresses F F F F F eess gontrol vists @egvsA F F F F F F F F F F F F F F F F F F F F F F edvned egv gonepts F F F F F F F F F F F F F F F F F F F F F F F F row to fore r or r for hi'erent vs F F F F F F F F F F row to ustomize your porm vogin F F F F F F F F F F F F F F F F F F F row to seure ny ervie or wethod in your epplition F F F F F F row to lod eurity sers from the htse @the entity roviderA row to rete ustom ser rovider F F F F F F F F F F F F F F F F F row to rete ustom euthentition rovider F F F F F F F F F F F row to hnge the hefult rget th fehvior F F F F F F F F F F F row to use rnish to speedup my esite F F F F F F F F F F F F F F row to use r insted of wig for empltes F F F F F F F F F F F F row to utolod glsses F F F F F F F F F F F F F F F F F F F F F F F F F row to lote piles F F F F F F F F F F F F F F F F F F F F F F F F F F F F row to rete gonsoleGgommndEvine gommnds F F F F F F F F F F row to optimize your development invironment for deugging F F F wonolog F F F F F F F F F F row to extend glss without using snheritne F F F F F F F F F F F row to ustomize wethod fehvior without using snheritne F F F row to register new equest pormt nd wime ype F F F F F F F row to rete ustom ht golletor F F F F F F F F F F F F F F F F F row to grete ye e ervie in ymfonyP gontroller F F F F

F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F

QVH QVI QVQ QWW QWW RHI RHV RII RIS RPT RQH RQQ RQV RQW RRW RSI RSQ RSS RSU RSU RSV RSW RTQ RTU RUH RUR RUV RUW RVU RWP RWQ RWQ SHQ SHR SHT SII SIQ SIU SPQ SPR SPW SQI SQP SQR SQU iii

TFTH ymfonyP symfony I F F F F F F F F F F F F F F F F F F F F SRI


IV 553

eferene houments UFI prmeworkfundle gon(gurtion @frmeworkA UFP essetifundle gon(gurtion eferene F F F F F UFQ gon(gurtion eferene F F F F F F F F F F F F F UFR eurity gon(gurtion eferene F F F F F F F F UFS wiftmilerfundle gon(gurtion F F F F F F F F UFT wigfundle gon(gurtion eferene F F F F F F UFU gon(gurtion eferene F F F F F F F F F F F F F UFV ero(lerfundle gon(gurtion F F F F F F F F UFW porm ypes eferene F F F F F F F F F F F F F F UFIH wig emplte porm puntion eferene F F F F UFII lidtion gonstrints eferene F F F F F F F F UFIP he hependeny snjetion gs F F F F F F F F F UFIQ ewv F F F F F F F F F F F F F F F F F F F F F F F UFIR equirements for running ymfonyP F F F F F F
Bundles

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

F F F F F F F F F F F F F F

SSU SSU STQ STR SUH SUR SUS SUT SUV SUW TRS TRU UHR UIH UIU
721

V
VI

ymfony i fundles

UPS
727

gontriuting UQI WFI gontriuting gode F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F UQI WFP gontriuting houmenttion F F F F F F F F F F F F F F F F F F F F F F F F F F URP WFQ gommunity F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F URV USQ

iv

ymfony houmenttionD PFH ymfonyP X

ymfony houmenttionD PFH


ymfonyPD IH c F ymfonyPD F E E E D E ymfonyP F X c ymfony S F

1.1 Symfony2

D r SFQFP we D epheF c ymfonyP tndrd iditionD @distriutionA ymfony D E D ymfonyP @ @vendorsA AF ED ymfonyGD X

www/ <- Symfony/ <- app/ cache/ cong/ logs/


S

ymfony houmenttionD PFH

Resources/ bin/ src/ Acme/ DemoBundle/ Controller/ Resources/ ... vendor/ symfony/ doctrine/ ... web/ app.php ...
X @without vendorsAD X

php bin/vendors install

1.2

D D ymfonyP ! vX

http://localhost/Symfony/web/cong.php
E F D F D fypss on(gurtion nd go to the elome pge  ymfonyPX

http://localhost/Symfony/web/app_dev.php/
ymfonyP 3

IF

ymfony houmenttionD PFH

1.3

E E F D D rwvE E F E ymfonyP F X D c ymfonyP versus plt r D E ymfonyPF vD ymfonyP @ pien AX

http://localhost/Symfony/web/app_dev.php/demo/hello/Fabien

IFQF

ymfony houmenttionD PFH

c vX

ppdevFphpX front ontrollerF D E Y GdemoGhelloGpienX D E F


D E @GhelloGpienA @ rello pien3AF
1.3.1

ymfonyP D v E F @ A ppGon(gGroutingFymlF dev E frontE ppBBdevBBFphp E ppGon(gGroutingdevFyml F E D demoE X

# app/cong/routing_dev.yml _welcome: pattern: / defaults: { _controller: AcmeDemoBundle:Welcome:index } _demo: resource: "@AcmeDemoBundle/Controller/DemoController.php" type: annotation prex: /demo
V IF

ymfony houmenttionD PFH

# ...
@ A D E G @FF AF emehemofundleXelomeXindexF X ymfonyP ewv E D ymfonyP wvD r  F E F D E F

1.3.2

@ E rwvEAF E @ 6qi heder@AA rE ymfony ymfonygomponentrttppoundtionequest ymfonygomponentrttppoundtionesponseF D X

use Symfony\Component\HttpFoundation\Response; $name = $request->query->get('name'); return new Response('Hello '.$name, 200, array('Content-Type' => 'text/plain'));
X ymfonyP rD eF  ymfonyP E r F ymfonyP ontroller X emehemofundleXelomeXindexF E E indexetion emehemofundlegontrollerelomegontrollerX

// src/Acme/DemoBundle/Controller/WelcomeController.php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class WelcomeController extends Controller {


IFQF W

ymfony houmenttionD PFH

public function indexAction() { return $this->render('AcmeDemoBundle:Welcome:index.html.twig'); }

X emehemofundlegontrollerelomegontrollerXXindexetion ontrollerD F elomegontroller gontroller D XmethodXymfonyfundleprmeworkfundlegontrollergontrollerXXrender E @emehemofundleXelomeXindexFhtmlFtwigAF E esponseD F D D esponse X

public function indexAction() { $response = $this->render('AcmeDemoBundle:Welcome:index.txt.twig'); $response->headers->set('Content-Type', 'text/plain'); } return $response;

D D esponseD F rwvED tqE gontentEype imgeGjpgF X gontroller F D r rEF  ymfonyPF emehemofundleXelomeXindexFhtmlFtwig E esouresGviewsGelomeGindexFhtmlFtwig emehemofundle @ srGemeGhemofundleAF E F D X

# app/cong/routing_dev.yml _demo:
IH IF

ymfony houmenttionD PFH

resource: "@AcmeDemoBundle/Controller/DemoController.php" type: annotation prex: /demo


ymfonyP ewvD wvD r r F demehemofundleGgontrollerGhemogontrollerFphp srG emeGhemofundleGgontrollerGhemogontrollerFphpF E X

// src/Acme/DemoBundle/Controller/DemoController.php use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template; class DemoController extends Controller { /** * @Route("/hello/{name}", name="_demo_hello") * @Template() */ public function helloAction($name) { return array('name' => $name); } } // ...

doute@A GhelloG{nme}D E helloetion F D D {nme} pleholderF 6nmeF X rD ymfonyP F D D D F E demplte@A ymfonyP D E F F D D emehemofundleXhemoXhelloFhtmlFtwig @ srGemeGhemofundleGesouresGviewsGhemoGhelloFhtmlFtwigAF X doute@A demplte@A F   F IFQF II

ymfony houmenttionD PFH

1.3.3

srGemeGhemofundleGesouresGviewsGhemoGhelloFhtmlFtwig @ emehemofundleXhemoXhelloFhtmlFtwig AX

{# src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig #} {% extends "AcmeDemoBundle::layout.html.twig" %} {% block title "Hello " ~ name %} {% block content %} <h1>Hello {{ name }}!</h1> {% endblock %}
D ymfonyP wig D E r F ymfonyPF
1.3.4 (bundles)

D F F ymfonyP E @ rD D tvript9D D FFFA @D D FFFA F E emehemofundleF F

1.4

D ymfonyPD Y ymfonyPF E  @e heug oolrA E F

IP

IF

ymfony houmenttionD PFH

Y X F

D D F weG @ppFphpAD X

http://localhost/Symfony/web/app.php/demo/hello/Fabien
ephe modrewriteD v ppFphpX

IFRF

IQ

ymfony houmenttionD PFH

http://localhost/Symfony/web/demo/hello/Fabien
D D E weGD vX

http://localhost/demo/hello/Fabien
D ymfonyP ppGheGF @ppdevFphpAD D E F @ppFphpAD D F D F F D X

# app/cong/cong_dev.yml imports: - { resource: cong.yml } web_proler: toolbar: true intercept_redirects: false


dev @ on(gdevFymlA on(gFyml D E F

1.5

3 ymfonyPF D c D ymfonyP F ymfonyP E X F

IR

IF

D ymfonyP IH F E F wig ymfonyPF wig D rF E D we F X wigD rF ymfonyPF

2.1 Twig,

X wigD E F F wig D D E @rwvD wvD gD veD FFFAF wig E X

{{ FFF }}X Y {7 FFF 7}X D Y D E for if F


D D pgetitle nvigtionD X

<!DOCTYPE html> <html>


IS

ymfony houmenttionD PFH

<head> <title>My Webpage</title> </head> <body> <h1>{{ page_title }}</h1> <ul id="navigation"> {% for item in navigation %} <li><a href="{{ item.href }}">{{ item.caption }}</a></li> {% endfor %} </ul> </body> </html>
X {5 FFF 5}F D ymfony render D X

$this->render('AcmeDemoBundle:Demo:hello.html.twig', array( 'name' => $name, ));


D D D E F wig  E D @FAX

{# array('name' => 'Fabien') #} {{ name }} {# array('user' => array('name' => 'Fabien')) #} {{ user.name }} {# force array lookup #} {{ user['name'] }} {# array('user' => new User('Fabien')) #} {{ user.name }} {{ user.getName }} {# force method name lookup #} {{ user.name() }} {{ user.getName() }} {# pass arguments to a method #} {{ user.date('Y-m-d') }}
IT PF

ymfony houmenttionD PFH

X D F D F

2.2

D heder footerF ymfonyPD X F rX D E D F helloFhtmlFtwig lyoutFhtmlFtwig extendsX

{# src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig #} {% extends "AcmeDemoBundle::layout.html.twig" %} {% block title "Hello " ~ name %} {% block content %} <h1>Hello {{ name }}!</h1> {% endblock %}
emehemofundleXXlyoutFhtmlFtwig D c E F XX D FF esouresGviewsGF lyoutFhtmlFtwigX

{# src/Acme/DemoBundle/Resources/views/layout.html.twig #} <div class="symfony-content"> {% block content %} {% endblock %} </div>


{7 lok 7} @ody ontentAD E F D D F helloFhtmlFtwig ontentD D rello pien divFsymfonyEontentF

PFPF

IU

ymfony houmenttionD PFH

2.3 ,

wig D Y ymfonyPD we F
2.3.1

E D F emeddedFhtmlFtwigX

{# src/Acme/DemoBundle/Resources/views/Demo/embedded.html.twig #} Hello {{ name }}


indexFhtmlFtwig D X

{# src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig #} {% extends "AcmeDemoBundle::layout.html.twig" %} {# override the body block from embedded.html.twig #} {% block content %} {% include "AcmeDemoBundle:Demo:embedded.html.twig" %} {% endblock %}

2.3.2

c ejx E D F fny indexD renderX

{# src/Acme/DemoBundle/Resources/views/Demo/index.html.twig #} {% render "AcmeDemoBundle:Demo:fancy" with { 'name': name, 'color': 'green' } %}


rellofundleXrelloXfnyD fny rello D X

// src/Acme/DemoBundle/Controller/DemoController.php class DemoController extends Controller { public function fancyAction($name, $color)


IV PF

ymfony houmenttionD PFH

// create some object, based on the $color variable $object = ...;

} }

return $this->render('AcmeDemoBundle:Demo:fancy.html.twig', array('name' => $name, 'object' => $obje

// ...

2.3.3

we D F vE D pth vED F vE D X

<a href="{{ path('_demo_hello', { 'name': 'Thomas' }) }}">Greet Thomas!</a>


pth F D D D X

// src/Acme/DemoBundle/Controller/DemoController.php use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template; /** * @Route("/hello/{name}", name="_demo_hello") * @Template() */ public function helloAction($name) { return array('name' => $name); }
X url vEX {{ url@9demohello9D { 9nme9X 9homs9 }A }}F

2.3.4 : , JavaScript-

D tvriptE c ymfonyP sset X PFQF D IW

ymfony houmenttionD PFH

<link href="{{ asset('css/blog.css') }}" rel="stylesheet" type="text/css" /> <img src="{{ asset('images/logo.png') }}" />
sset F D we F

2.4

wig F wig doumenttion E isperF

2.5

wig F D D D F ymfonyP PH D F ymfonyPF D F F ED D F IH ymfonyPc

PH

PF

c ymfonyP3 D D F

3.1

D we rwv F E wv e D tyx ejx D F ymfonyP F E xml formtX

// src/Acme/DemoBundle/Controller/DemoController.php use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template; /** * @Route("/hello/{name}", defaults={"_format"="xml"}, name="_demo_hello") * @Template() */ public function helloAction($name) { return array('name' => $name); }
fy using the request formt @s de(ned y the formt vlueAD ymfonyP utomtilly selets the right templteD here helloFxmlFtwigX

<!-- src/Acme/DemoBundle/Resources/views/Demo/hello.xml.twig --> <hello>


PI

ymfony houmenttionD PFH

<name>{{ name }}</name> </hello>


F ymfonyP gontentEype F D {formt} X

// src/Acme/DemoBundle/Controller/DemoController.php use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template;

/** * @Route("/hello/{name}.{_format}", defaults={"_format"="html"}, requirements={"_format"="html|xml|js * @Template() */ public function helloAction($name) { return array('name' => $name); }
he ontroller will now GdemoGhelloGpienFjsonF e lled for vs like GdemoGhelloGpienFxml or

he requirements entry de(nes regulr expressions tht pleholders must mthF sn this exmpleD if you try to request the GdemoGhelloGpienFjs resoureD you will get RHR r errorD s it does not mth the formt requirementF

3.2

D rediret@AX

return $this->redirect($this->generateUrl('_demo_hello', array('name' => 'Lucas')));


he generterl@A is the sme method s the pth@A funtion we used in templtesF st tkes the route nme nd n rry of prmeters s rguments nd returns the ssoited friendly vF forwrd@AF tionsD D E esponseD X

$response = $this->forward('AcmeDemoBundle:Hello:fancy', array('name' => $name, 'color' => 'green')); // do something with the response or return it directly

PP

QF

ymfony houmenttionD PFH

3.3

D E equestX

$request = $this->getRequest(); $request->isXmlHttpRequest(); // is it an Ajax request? $request->getPreferredLanguage(array('en', 'fr')); $request->query->get('page'); // get a $_GET parameter $request->request->get('page'); // get a $_POST parameter
equest ppFrequestX

{{ app.request.query.get('page') }} {{ app.request.parameter('page') }}

3.4

r D ymfonyP E D @ D D we AF ymfonyP ookieD E rF E X

$session = $this->getRequest()->getSession(); // store an attribute for reuse during a later user request $session->set('foo', 'bar'); // in another controller for another request $foo = $session->get('foo'); // set the user locale $session->setLocale('fr');
D X

QFQF

PQ

ymfony houmenttionD PFH

// store a message for the very next request (in a controller) $session->setFlash('notice', 'Congratulations, your action succeeded!'); // display the message back in the next request (in a template) {{ app.session.ash('notice') }}
his is useful when you need to set suess messge efore redireting the user to nother pge @whih will then show the messgeAF

3.5 Securing Resources

he ymfony tndrd idition omes with simple seurity on(gurtion tht (ts most ommon needsX

# app/cong/security.yml security: encoders: Symfony\Component\Security\Core\User\User: plaintext role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] providers: in_memory: users: user: { password: userpass, roles: [ 'ROLE_USER' ] } admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } rewalls: dev: pattern: ^/(_(proler|wdt)|css|images|js)/ security: false login: pattern: ^/demo/secured/login$ security: false secured_area: pattern: ^/demo/secured/ form_login: check_path: /demo/secured/login_check login_path: /demo/secured/login logout: path: /demo/secured/logout
PR QF

ymfony houmenttionD PFH

target: /demo/
his on(gurtion requires users to log in for ny v strting with GdemoGseuredG nd de(nes two vlid usersX user nd dminF woreoverD the dmin user hs yviehwsx roleD whih inludes the yvii role s well @see the rolehierrhy settingAF X por redilityD psswords re stored in ler text in this simple on(gurtionD ut you n use ny hshing lgorithm y tweking the enoders setionF qoing to the httpXGGlolhostGymfonyGweGppdevFphpGdemoGseuredGhello v will utomtilly rediret you to the login form euse this resoure is proteted y (rewllF ou n lso fore the tion to require given role y using the deure nnottion on the ontrollerX

use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template; use JMS\SecurityExtraBundle\Annotation\Secure; /** * @Route("/hello/admin/{name}", name="_demo_secured_hello_admin") * @Secure(roles="ROLE_ADMIN") * @Template() */ public function helloAdminAction($name) { return array('name' => $name); }
xowD log in s user @who does not hve the yviehwsx roleA nd from the seured hello pgeD lik on the rello resoure seured linkF ymfonyP should return RHQ r sttus odeD inditing tht the user is foridden from essing tht resoureF X he ymfonyP seurity lyer is very )exile nd omes with mny di'erent user providers @like one for the hotrine ywA nd uthentition providers @like r siD r digestD or SHW erti(tesAF ed the eurity hpter of the ook for more informtion on how to use nd on(gure themF

3.6 Caching Resources

es soon s your wesite strts to generte more tr0D you will wnt to void generting the sme resoure gin nd ginF ymfonyP uses r he heders to mnge resoures heF por simple hing strtegiesD use the onvenient dghe@A nnottionX QFTF ghing esoures PS

ymfony houmenttionD PFH

use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Cache; /** * @Route("/hello/{name}", name="_demo_hello") * @Template() * @Cache(maxage="86400") */ public function helloAction($name) { return array('name' => $name); }
sn this exmpleD the resoure will e hed for dyF fut you n lso use vlidtion insted of expirtion or omintion of oth if tht (ts your needs etterF esoure hing is mnged y the ymfonyP uiltEin reverse proxyF fut euse hing is mnged using regulr r he hedersD you n reple the uiltEin reverse proxy with rnish or quid nd esily sle your pplitionF X fut wht if you nnot he whole pgesc ymfonyP still hs the solution vi idge ide snludes @isAD whih re supported ntivelyF vern more y reding the r ghe hpter of the ookF

3.7

D D E IH F D F E D ymfonyP F F

PT

QF

3 D c F F E ymfonyD E F

4.1

D ut the diretory struture of the tndrd idition distriution re)ets the typil nd reommended struture of ymfonyP pplitionX

ppGX Y srGX r Y vendorGX he thirdEprty dependeniesY weGX we F


4.1.1 web/

we E D D tvriptF front ontrollerX

// web/app.php require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../app/AppKernel.php'; use Symfony\Component\HttpFoundation\Request;


PU

ymfony houmenttionD PFH

$kernel = new AppKernel('prod', false); $kernel->loadClassCache(); $kernel->handle(Request::createFromGlobals())->send();


he kernel (rst requires the ootstrpFphpFhe (leD whih ootstrps the frmework nd registers the utoloder @see elowAF vike ny front ontrollerD ppFphp uses uernel glssD eppuernelD to ootstrp the pplitionF
4.1.2 app/

eppuernel D ppGF X

registerfundles@A D E Y registergontinergon(gurtion@A @ AY
r utoloding n e on(gured vi ppGutolodFphpX

// app/autoload.php use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( 'Symfony' => array(__DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'), 'Sensio' => __DIR__.'/../vendor/bundles', 'JMS' => __DIR__.'/../vendor/bundles', 'Doctrine\\Common' => __DIR__.'/../vendor/doctrine-common/lib', 'Doctrine\\DBAL' => __DIR__.'/../vendor/doctrine-dbal/lib', 'Doctrine' => __DIR__.'/../vendor/doctrine/lib', 'Monolog' => __DIR__.'/../vendor/monolog/src', 'Assetic' => __DIR__.'/../vendor/assetic/src', 'Metadata' => __DIR__.'/../vendor/metadata/src', )); $loader->registerPrexes(array( 'Twig_Extensions_' => __DIR__.'/../vendor/twig-extensions/lib', 'Twig_' => __DIR__.'/../vendor/twig/lib', )); // ... $loader->registerNamespaceFallbacks(array(
PV RF

ymfony houmenttionD PFH

__DIR__.'/../src', )); $loader->register();


he ymfonygomponentglssvoderniverslglssvoder is used to utolod (les tht respet either the tehnil interoperility stndrds for r SFQ nmespes or the ie nming onvention for lssesF es you n see hereD ll dependenies re stored under the vendorG diretoryD ut this is just onventionF ou n store them wherever you wntD glolly on your server or lolly in your projetsF X sf you wnt to lern more out the )exiility of the ymfonyP utoloderD red the row to utolod glsses reipe in the ookookF

4.2

ymfonyPD F F D c ymfonyP D D F ymfonyPF D F F


4.2.1 Registering a Bundle

en pplition is mde up of undles s de(ned in the registerfundles@A method of the eppuernel lssF ih undle is diretory tht ontins single fundle lss tht desries itX

// app/AppKernel.php public function registerBundles() { $bundles = array( new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), new Symfony\Bundle\AsseticBundle\AsseticBundle(),
RFPF PW

ymfony houmenttionD PFH

);

new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),

if (in_array($this->getEnvironment(), array('dev', 'test'))) { $bundles[] = new Acme\DemoBundle\AcmeDemoBundle(); $bundles[] = new Symfony\Bundle\WebProlerBundle\WebProlerBundle(); $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); } } return $bundles;

sn ddition to the emehemofundle tht we hve lredy tlked outD notie tht the kernel lso enles other undles suh s the prmeworkfundleD hotrinefundleD wiftmilerfundleD nd essetifundle undleF hey re ll prt of the ore frmeworkF
4.2.2 Conguring a Bundle

D E ewvD wvD rF X

# app/cong/cong.yml imports: - { resource: parameters.ini } - { resource: security.yml } framework: secret: %secret% charset: UTF-8 router: { resource: "%kernel.root_dir%/cong/routing.yml" } form: true csrf_protection: true validation: { enable_annotations: true } templating: { engines: ['twig'] } #assets_version: SomeVersionScheme session: default_locale: %locale% auto_start: true # Twig Conguration twig: debug: %kernel.debug% strict_variables: %kernel.debug% # Assetic Conguration
QH RF

ymfony houmenttionD PFH

assetic: debug: %kernel.debug% use_controller: false lters: cssrewrite: ~ # closure: # jar: %kernel.root_dir%/java/compiler.jar # yui_css: # jar: %kernel.root_dir%/java/yuicompressor-2.4.2.jar # Doctrine Conguration doctrine: dbal: driver: %database_driver% host: %database_host% dbname: %database_name% user: %database_user% password: %database_password% charset: UTF8 orm: auto_generate_proxy_classes: %kernel.debug% auto_mapping: true # Swiftmailer Conguration swiftmailer: transport: %mailer_transport% host: %mailer_host% username: %mailer_user% password: %mailer_password% jms_security_extra: secure_controllers: true secure_all_services: false
ih entry like frmework de(nes the on(gurtion for spei( undleF por exmpleD frmework on(gures the prmeworkfundle while swiftmiler on(gures the wiftmilerfundleF @environmentA D F por exmpleD the dev environment lods the on(gdevFyml (leD whih lods the min on(gurtion @iFeF on(gFymlA nd then modi(es it to dd some deugging toolsX

# app/cong/cong_dev.yml imports: - { resource: cong.yml }


RFPF QI

ymfony houmenttionD PFH

framework: router: { resource: "%kernel.root_dir%/cong/routing_dev.yml" } proler: { only_exceptions: false } web_proler: toolbar: true intercept_redirects: false monolog: handlers: main: type: stream path: %kernel.logs_dir%/%kernel.environment%.log level: debug rephp: type: rephp level: info assetic: use_controller: true

4.2.3 Extending a Bundle

sn ddition to eing nie wy to orgnize nd on(gure your odeD undle n extend nother undleF fundle inheritne llows you to override ny existing undle in order to ustomize its ontrollersD templtesD or ny of its (lesF his is where the logil nmes @eFgF demehemofundleGgontrollerGeuredgontrollerFphpA ome in hndyX they strt where the resoure is tully storedF vogil pile xmes hen you wnt to referene (le from undleD use this nottionX dfxhvixewiGpthGtoG(leY ymfonyP will resolve dfxhvixewi to the rel pth to the undleF por instneD the logil pth demehemofundleGgontrollerGhemogontrollerFphp would e onverted to srGemeGhemofundleGgontrollerGhemogontrollerFphpD euse ymfony knows the lotion of the emehemofundleF vogil gontroller xmes por ontrollersD you need to referene method nmes fxhvixewiXgyxyvvixewiXegsyxxewiF QP using por the formt instneD

RF

ymfony houmenttionD PFH emehemofundleXelomeXindex mps to the indexetion emehemofundlegontrollerelomegontroller lssF vogil emplte xmes por templtesD the logil nme emehemofundleXelomeXindexFhtmlFtwig is onverted to the (le pth srGemeGhemofundleGesouresGviewsGelomeGindexFhtmlFtwigF empltes eome even more interesting when you relize they don9t need to e stored on the (lesystemF ou n esily store them in dtse tle for instneF ixtending fundles sf you follow these onventionsD then you n use undle inheritne to override (lesD ontrollers or templtesF por exmpleD you n rete undle E emexewfundle E nd speify tht its prent is emehemofundleF hen ymfony lods the emehemofundleXelomeXindex ontrollerD it will (rst look for the elomegontroller lss in emexewfundle nd then look inside emehemofundleF his mens tht one undle n override lmost ny prt of nother undle3 ho you understnd now why ymfonyP is so )exilec hre your undles etween pplitionsD store them lolly or glollyD your hoieF method from the

4.3 Using Vendors

F E vendorGF ymfonyPD wiftwilerD hotrine ywD wig F

4.4

ymfonyP is proly one of the fstest fullEstk frmeworks roundF fut how n it e so fst if it prses nd interprets tens of ewv nd wv (les for eh requestc he speed is prtly due to its he systemF he pplition on(gurtion is only prsed for the very (rst request nd then ompiled down to plin r ode stored in the ppGheG diretoryF sn the development environmentD ymfonyP is smrt enough to )ush the he when you hnge (leF fut in the prodution environmentD it is your responsiility to ler the he when you updte your ode or hnge its on(gurtionF

RFQF sing endors

QQ

ymfony houmenttionD PFH hen developing we pplitionD things n go wrong in mny wysF he log (les in the ppGlogsG diretory tell you everything out the requests nd help you (x the prolem quiklyF

4.5

@ppGonsoleAD E F D D F D X

php app/console
EEhelp X

php app/console router:debug --help

4.6

D D E ymfonyP F ymfonyP D F D F F D D ymfonyPF E c F

b b b

QR

RF

II

QS

ymfony houmenttionD PFH ymfonyP X

QU

ymfony houmenttionD PFH

QV

5.1 Symfony2 HTTP

gongrtultions3 fy lerning out ymfonyPD you9re well on your wy towrds eing more produtiveD wellErounded nd populr we developer @tullyD you9re on your own for the lst prtAF ymfonyP is uilt to get k to sisX to develop tools tht let you develop fster nd uild more roust pplitionsD while stying out of your wyF ymfony is uilt on the est ides from mny tehnologiesX the tools nd onepts you9re out to lern represent the e'orts of thousnds of peopleD over mny yersF sn other wordsD you9re not just lerning ymfonyD you9re lerning the fundmentls of the weD development est prtiesD nd how to use mny mzing new r lirriesD inside or independent of ymfonyPF oD get redyF rue to the ymfonyP philosophyD this hpter egins y explining the fundmentl onept ommon to we developmentX rF egrdless of your kground or preferred progrmming lngugeD this hpter is mustEred for everyoneF
5.1.1 HTTP is Simple

r @rypertext rnsfer rotool to the geeksA is text lnguge tht llows two mhines to ommunite with eh otherF ht9s it3 por exmpleD when heking for the ltest xkd omiD the following @pproximteA onverstion tkes pleX

QW

ymfony houmenttionD PFH

end while the tul lnguge used is it more formlD it9s still dedEsimpleF r is the term used to desrie this simple textEsed lngugeF end no mtter how you develop on the weD the gol of your server is lwys to understnd simple text requestsD nd return simple text responsesF ymfonyP is uilt from the groundEup round tht relityF hether you relize it or notD r is something you use everydyF ith ymfonyPD you9ll lern how to mster itF IX ivery onverstion on the we strts with requestF he request is text messge reted y lient @eFgF rowserD n ihone ppD etA in speil formt known s rF he lient sends tht request to serverD nd then wits for the responseF ke look t the (rst prt of the intertion @the requestA etween rowser nd the xkd we serverX

sn rEspekD this r request would tully look something like thisX

RH

SF

ymfony houmenttionD PFH

GET / HTTP/1.1 Host: xkcd.com Accept: text/html User-Agent: Mozilla/5.0 (Macintosh)


his simple messge ommunites everything neessry out extly whih resoure the lient is requestingF he (rst line of n r request is the most importnt nd ontins two thingsX the s nd the r methodF he s @eFgF GD GonttD etA is the unique ddress or lotion tht identi(es the resoure the lient wntsF he r method @eFgF qiA de(nes wht you wnt to do with the resoureF r r X qi y hivii

D r D D X

DELETE /blog/15 HTTP/1.1


X r D E rD F hiviiF rE E r F D @rostAD D @eeptA D E @serEegentAF E rF PX D D rD D @ sA @ rAF qiED rEF gonsider the response from the xkd we serverX

SFIF ymfonyP r

RI

ymfony houmenttionD PFH

rnslted into rD the response sent k to the rowser will look something like thisX

HTTP/1.1 200 OK Date: Sat, 02 Apr 2011 21:05:05 GMT Server: lighttpd/1.4.19 Content-Type: text/html <html> <!-- HTML for the xkcd comic --> </html>
he r response ontins the requested resoure @the rwv ontent in this seAD s well s other informtion out the responseF he (rst line is espeilly importnt nd ontins the r response sttus ode @PHH in this seAF he sttus ode ommunites the overll outome of the request k to the lientF s the request suessfulc s there n errorc hi'erent sttus odes exist tht indite suessD n errorD or tht the lient needs to do something @eFgF rediret to nother pgeAF e full list n e found on ikipedi9s vist of r sttus odes rtileF vike the requestD n r response ontins dditionl piees of informtion known s r hedersF por exmpleD one importnt r response heder is gontentEypeF he ody of the sme resoure ould e returned in multiple di'erent formts inluding rwvD wvD or tyx to nme fewF he gontentEype heder tells the lient whih formt is eing returnedF wny other heders existD some of whih re very powerfulF por exmpleD ertin heders n e used to rete powerful hing systemF equestsD esponses nd e hevelopment his requestEresponse onverstion is the fundmentl proess tht drives ll ommunition on the weF end s importnt nd powerful s this proess isD it9s inesply simpleF RP SF

ymfony houmenttionD PFH he most importnt ft is thisX regrdless of the lnguge you useD the type of pplition you uild @weD moileD tyx esAD or the development philosophy you followD the end gol of n pplition is lwys to understnd eh request nd rete nd return the pproprite responseF ymfony is rhiteted to mth this relityF X o lern more out the r spei(tionD red the originl r IFI pg or the r fisD whih is n tive e'ort to lrify the originl spei(tionF e gret tool to hek oth the request nd response heders while rowsing is the vive r reders extension for pirefoxF

5.1.2 Requests and Responses in PHP

o how do you intert with the request nd rete response when using rc sn relityD r strts you it from the whole proessX

<?php $uri = $_SERVER['REQUEST_URI']; $foo = $_GET['foo']; header('Content-type: text/html'); echo 'The URI requested is: '.$uri; echo 'The value of the "foo" parameter is: '.$foo;
es strnge s it soundsD this smll pplition is in ft tking informtion from the r request nd using it to rete n r responseF snsted of prsing the rw r request messgeD r prepres superglol vriles suh s 6ii nd 6qi tht ontin ll the informtion from the requestF imilrlyD insted of returning the rEformtted text responseD you n use the heder@A funtion to rete response heders nd simply print out the tul ontent tht will e the ontent portion of the response messgeF r will rete true r response nd return it to the lientX

HTTP/1.1 200 OK Date: Sat, 03 Apr 2011 02:14:33 GMT Server: Apache/2.2.17 (Unix) Content-Type: text/html The URI requested is: /testing?foo=symfony The value of the "foo" parameter is: symfony

SFIF ymfonyP r

RQ

ymfony houmenttionD PFH


5.1.3 Requests and Responses in Symfony

ymfony provides n lterntive to the rw r pproh vi two lsses tht llow you to intert with the r request nd response in n esier wyF he ymfonygomponentrttppoundtionequest lss is simple ojetEoriented representtion of the r request messgeF ith itD you hve ll the request informtion t your (ngertipsX

use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); // the URI being requested (e.g. /about) minus any query parameters $request->getPathInfo(); // retrieve GET and POST variables respectively $request->query->get('foo'); $request->request->get('bar'); // retrieves an instance of UploadedFile identied by foo $request->les->get('foo'); $request->getMethod(); $request->getLanguages(); // GET, POST, PUT, DELETE, HEAD // an array of languages the client accepts

es onusD the equest lss does lot of work in the kground tht you9ll never need to worry outF por exmpleD the iseure@A method heks the three di'erent vlues in r tht n indite whether or not the user is onneting vi seured onnetion @iFeF httpsAF ymfony lso provides esponse lssX simple r representtion of n r response messgeF his llows your pplition to use n ojetEoriented interfe to onstrut the response tht needs to e returned to the lientX

use Symfony\Component\HttpFoundation\Response; $response = new Response(); $response->setContent('<html><body><h1>Hello world!</h1></body></html>'); $response->setStatusCode(200); $response->headers->set('Content-Type', 'text/html'); // prints the HTTP headers followed by the content $response->send();
sf ymfony o'ered nothing elseD you would lredy hve toolkit for esily essing request informtion nd n ojetEoriented interfe for reting the responseF iven s you lern the mny powerful fetures in ymfonyD keep in mind tht the gol of your pplition is lwys to interpret request nd rete the pproprite response sed on your pplition logiF RR SF

ymfony houmenttionD PFH

X he equest nd esponse lsses re prt of stndlone omponent inluded with ymfony lled rttppoundtionF his omponent n e used entirely independent of ymfony nd lso provides lsses for hndling sessions nd (le uplodsF

5.1.4 The Journey from the Request to the Response

vike r itselfD the equest nd esponse ojets re pretty simpleF he hrd prt of uilding n pplition is writing wht omes in etweenF sn other wordsD the rel work omes in writing the ode tht interprets the request informtion nd retes the responseF our pplition proly does mny thingsD like sending emilsD hndling form sumissionsD sving things to dtseD rendering rwv pges nd proteting ontent with seurityF row n you mnge ll of this nd still keep your ode orgnized nd mintinlec ymfony ws reted to solve these prolems so tht you don9t hve toF he pront gontroller rditionllyD pplitions were uilt so tht eh pge of site ws its own physil (leX

index.php contact.php blog.php


here re severl prolems with this pprohD inluding the in)exiility of the vs @wht if you wnted to hnge logFphp to newsFphp without reking ll of your linkscA nd the ft tht eh (le must mnully inlude some set of ore (les so tht seurityD dtse onnetions nd the look of the site n remin onsistentF e muh etter solution is to use front ontrollerX single r (le tht hndles every request oming into your pplitionF por exmpleX GindexFphp GindexFphpGontt GindexFphpGlog exeutes indexFphp exeutes indexFphp exeutes indexFphp

X sing ephe9s modrewrite @or equivlent with other we serversAD the vs n esily e lened up to e just GD Gontt nd GlogF xowD every request is hndled extly the smeF snsted of individul vs exeuting di'erent r (lesD the front ontroller is lwys exeutedD nd the routing of di'erent vs to di'erent prts of your pplition is done internllyF his solves oth prolems with the originl pprohF elmost ll modern we pps do this E inluding pps like ordressF SFIF ymfonyP r RS

ymfony houmenttionD PFH ty yrgnized fut inside your front ontrollerD how do you know whih pge should e rendered nd how n you render eh in sne wyc yne wy or notherD you9ll need to hek the inoming s nd exeute di'erent prts of your ode depending on tht vlueF his n get ugly quiklyX

// index.php $request = Request::createFromGlobals(); $path = $request->getPathInfo(); // the URL being requested if (in_array($path, array('', '/')) { $response = new Response('Welcome to the homepage.'); } elseif ($path == '/contact') { $response = new Response('Contact us'); } else { $response = new Response('Page not found.', 404); } $response->send();
olving this prolem n e di0ultF portuntely it9s extly wht ymfony is designed to doF he ymfony epplition plow hen you let ymfony hndle eh requestD life is muh esierF ymfony follows the sme simple pttern for every requestX

F SFIX snoming requests re interpreted y the routing nd pssed to ontroller funtions tht return esponse ojetsF RT SF

ymfony houmenttionD PFH ih pge of your site is de(ned in routing on(gurtion (le tht mps di'erent vs to di'erent r funtionsF he jo of eh r funtionD lled ontrollerD is to use informtion from the request E long with mny other tools ymfony mkes ville E to rete nd return esponse ojetF sn other wordsD the ontroller is where your ode goesX it9s where you interpret the request nd rete responseF st9s tht esy3 vet9s reviewX

ih request exeutes front ontroller (leY he routing system determines whih r funtion should e exeuted sed on informtion from the request nd routing on(gurtion you9ve retedY he orret r funtion is exeutedD where your ode retes nd returns the pproprite esponse ojetF
e ymfony equest in etion ithout diving into too muh detilD let9s see this proess in tionF uppose you wnt to dd Gontt pge to your ymfony pplitionF pirstD strt y dding n entry for Gontt to your routing on(gurtion (leX

contact: pattern: /contact defaults: { _controller: AcmeDemoBundle:Main:contact }


X his exmple uses ewv to de(ne the routing on(gurtionF outing on(gurtion n lso e written in other formts suh s wv or rF hen someone visits the Gontt pgeD this route is mthedD nd the spei(ed ontroller is exeutedF es you9ll lern in the routing hpterD the emehemofundleXwinXontt string is short syntx tht points to spei( r method onttetion inside lss lled wingontrollerX

class MainController { public function contactAction() { return new Response('<h1>Contact us!</h1>'); } }


sn this very simple exmpleD the ontroller simply retes esponse ojet with the rwv `hIbgontt us3`GhIbF sn the ontroller hpterD you9ll lern how ontroller n render templtesD llowing your presenttion ode @iFeF nything tht tully writes out rwvA to live in seprte templte (leF his frees up the ontroller to worry only out the hrd stu'X interting with the dtseD hndling sumitted dtD or sending emil messgesF SFIF ymfonyP r RU

ymfony houmenttionD PFH


5.1.5 Symfony2: Build your App, not your Tools.

ou now know tht the gol of ny pp is to interpret eh inoming request nd rete n pproprite responseF es n pplition growsD it eomes more di0ult to keep your ode orgnized nd mintinleF snvrilyD the sme omplex tsks keep oming up over nd over ginX persisting things to the dtseD rendering nd reusing templtesD hndling form sumissionsD sending emilsD vlidting user input nd hndling seurityF he good news is tht none of these prolems is uniqueF ymfony provides frmework full of tools tht llow you to uild your pplitionD not your toolsF ith ymfonyPD nothing is imposed on youX you9re free to use the full ymfony frmeworkD or just one piee of ymfony ll y itselfF tndlone oolsX he ymfonyP gomponents o wht is ymfonyPc pirstD ymfonyP is olletion of over twenty independent lirries tht n e used inside ny r projetF hese lirriesD lled the ymfonyP gomponentsD ontin something useful for lmost ny situtionD regrdless of how your projet is developedF o nme fewX

rttppoundtion E gontins the equest nd esponse lssesD s well s other lsses for hndling sessions nd (le uplodsY outing E owerful nd fst routing system tht llows you to mp spei( s @eFgF GonttA to some informtion out how tht request should e hndled @eFgF exeute the onttetion@A methodAY porm E e fullEfetured nd )exile frmework for reting forms nd hnding form sumissionsY lidtor e system for reting rules out dt nd then vlidting whether or not userEsumitted dt follows those rulesY glssvoder en utoloding lirry tht llows r lsses to e used without needing to mnully require the (les ontining those lssesY emplting e toolkit for rendering templtesD hndling templte inheritne @iFeF templte is deorted with lyoutA nd performing other ommon templte tsksY eurity E e powerful lirry for hndling ll types of seurity inside n pplitionY rnsltion e frmework for trnslting strings in your pplitionF
ih nd every one of these omponents is deoupled nd n e used in ny r projetD regrdless of whether or not you use the ymfonyP frmeworkF ivery prt is mde to e used if needed nd repled when neessryF

RV

SF

ymfony houmenttionD PFH he pull olutionX he ymfonyP prmework o thenD wht is the ymfonyP prmeworkc he ymfonyP prmework is r lirry tht omplishes two distint tsksX IF rovides seletion of omponents @iFeF the ymfonyP gomponentsA nd thirdEprty lirries @eFgF wiftmiler for sending emilsAY PF rovides sensile on(gurtion nd glue lirry tht ties ll of these piees togetherF he gol of the frmework is to integrte mny independent tools in order to provide onsistent experiene for the developerF iven the frmework itself is ymfonyP undle @iFeF pluginA tht n e on(gured or repled entirelyF ymfonyP provides powerful set of tools for rpidly developing we pplitions without imposing on your pplitionF xorml users n quikly strt development y using ymfonyP distriutionD whih provides projet skeleton with sensile defultsF por more dvned usersD the sky is the limitF

5.2 Symfony2 versus Flat PHP

hy is ymfonyP etter thn just opening up (le nd writing )t rc sf you9ve never used r frmeworkD ren9t fmilir with the wg philosophyD or just wonder wht ll the hype is round ymfonyPD this hpter is for youF snsted of telling you tht ymfonyP llows you to develop fster nd etter softwre thn with )t rD you9ll see for yourselfF sn this hpterD you9ll write simple pplition in )t rD nd then reftor it to e more orgnizedF ou9ll trvel through timeD seeing the deisions ehind why we development hs evolved over the pst severl yers to where it is nowF fy the endD you9ll see how ymfonyP n resue you from mundne tsks nd let you tke k ontrol of your odeF
5.2.1 A simple Blog in at PHP

sn this hpterD you9ll uild the token log pplition using only )t rF o eginD rete single pge tht displys log entries tht hve een persisted to the dtseF riting in )t r is quik nd dirtyX

<?php // index.php $link = mysql_connect('localhost', 'myuser', 'mypassword'); mysql_select_db('blog_db', $link);


SFPF ymfonyP versus plt r RW

ymfony houmenttionD PFH

$result = mysql_query('SELECT id, title FROM post', $link); ?> <html> <head> <title>List of Posts</title> </head> <body> <h1>List of Posts</h1> <ul> <?php while ($row = mysql_fetch_assoc($result)): ?> <li> <a href="/show.php?id=<?php echo $row['id'] ?>"> <?php echo $row['title'] ?> </a> </li> <?php endwhile; ?> </ul> </body> </html> <?php mysql_close($link);
ht9s quik to writeD fst to exeuteD ndD s your pp growsD impossile to mintinF here re severl prolems tht need to e ddressedX

xo errorEhekingX ht if the onnetion to the dtse filsc oor orgniztionX sf the pplition growsD this single (le will eome inresingly unmintinleF here should you put ode to hndle form sumissionc row n you vlidte dtc here should ode go for sending emilsc hi0ult to reuse odeX ine everything is in one (leD there9s no wy to reuse ny prt of the pplition for other pges of the logF
X enother prolem not mentioned here is the ft tht the dtse is tied to wyvF hough not overed hereD ymfonyP fully integrtes hotrineD lirry dedited to dtse strtion nd mppingF vet9s get to work on solving these prolems nd moreF

SH

SF

ymfony houmenttionD PFH ssolting the resenttion he ode n immeditely gin from seprting the pplition logi from the ode tht prepres the rwv presenttionX

<?php // index.php $link = mysql_connect('localhost', 'myuser', 'mypassword'); mysql_select_db('blog_db', $link); $result = mysql_query('SELECT id, title FROM post', $link); $posts = array(); while ($row = mysql_fetch_assoc($result)) { $posts[] = $row; } mysql_close($link); // include the HTML presentation code require 'templates/list.php';
he rwv ode is now stored in seprte (le @templtesGlistFphpAD whih is primrily n rwv (le tht uses templteElike r syntxX

<html> <head> <title>List of Posts</title> </head> <body> <h1>List of Posts</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="/read?id=<?php echo $post['id'] ?>"> <?php echo $post['title'] ?> </a> </li> <?php endforeach; ?> </ul> </body> </html>
fy onventionD the (le tht ontins ll of the pplition logi E indexFphp E is known s ontrollerF he term ontroller is word you9ll her lotD regrdless of the lnguge or frmework you useF st refers simply to the re of your ode tht proesses user input nd prepres the responseF SFPF ymfonyP versus plt r SI

ymfony houmenttionD PFH sn this seD our ontroller prepres dt from the dtse nd then inludes templte to present tht dtF ith the ontroller isoltedD you ould esily hnge just the templte (le if you needed to render the log entries in some other formt @eFgF listFjsonFphp for tyx formtAF ssolting the epplition @hominA vogi o fr the pplition ontins only one pgeF fut wht if seond pge needed to use the sme dtse onnetionD or even the sme rry of log postsc eftor the ode so tht the ore ehvior nd dtEess funtions of the pplition re isolted in new (le lled modelFphpX

<?php // model.php function open_database_connection() { $link = mysql_connect('localhost', 'myuser', 'mypassword'); mysql_select_db('blog_db', $link); } return $link;

function close_database_connection($link) { mysql_close($link); } function get_all_posts() { $link = open_database_connection(); $result = mysql_query('SELECT id, title FROM post', $link); $posts = array(); while ($row = mysql_fetch_assoc($result)) { $posts[] = $row; } close_database_connection($link); } return $posts;

X he (lenme modelFphp is used euse the logi nd dt ess of n pplition is trditionlly known s the model lyerF sn wellEorgnized pplitionD the mjority of the ode representing your usiness logi should live in the model @s opposed to living in SP SF

ymfony houmenttionD PFH ontrollerAF end unlike in this exmpleD only portion @or noneA of the model is tully onerned with essing dtseF he ontroller @indexFphpA is now very simpleX

<?php require_once 'model.php'; $posts = get_all_posts(); require 'templates/list.php';


xowD the sole tsk of the ontroller is to get dt from the model lyer of the pplition @the modelA nd to ll templte to render tht dtF his is very simple exmple of the modelEviewEontroller ptternF ssolting the vyout et this pointD the pplition hs een reftored into three distint piees o'ering vrious dvntges nd the opportunity to reuse lmost everything on di'erent pgesF he only prt of the ode tht n9t e reused is the pge lyoutF pix tht y reting new lyoutFphp (leX

<!-- templates/layout.php --> <html> <head> <title><?php echo $title ?></title> </head> <body> <?php echo $content ?> </body> </html>
he templte @templtesGlistFphpA n now e simpli(ed to extend the lyoutX

<?php $title = 'List of Posts' ?> <?php ob_start() ?> <h1>List of Posts</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="/read?id=<?php echo $post['id'] ?>"> <?php echo $post['title'] ?> </a> </li>
SFPF ymfonyP versus plt r SQ

ymfony houmenttionD PFH

<?php endforeach; ?> </ul> <?php $content = ob_get_clean() ?> <?php include 'layout.php' ?>
ou9ve now introdued methodology tht llows for the reuse of the lyoutF nfortuntelyD to omplish thisD you9re fored to use few ugly r funtions @ostrt@AD ogetlen@AA in the templteF ymfonyP uses emplting omponent tht llows this to e omplished lenly nd esilyF ou9ll see it in tion shortlyF
5.2.2 Adding a Blog show Page

he log list pge hs now een reftored so tht the ode is etterEorgnized nd reusleF o prove itD dd log show pgeD whih displys n individul log post identi(ed y n id query prmeterF o eginD rete new funtion in the modelFphp (le tht retrieves n individul log result sed on given idX

// model.php function get_post_by_id($id) { $link = open_database_connection(); $id = mysql_real_escape_string($id); $query = 'SELECT date, title, body FROM post WHERE id = '.$id; $result = mysql_query($query); $row = mysql_fetch_assoc($result); close_database_connection($link); } return $row;

xextD rete new (le lled showFphp E the ontroller for this new pgeX

<?php require_once 'model.php'; $post = get_post_by_id($_GET['id']); require 'templates/show.php';


pinllyD rete the new templte (le E templtesGshowFphp E to render the individul log postX SR SF

ymfony houmenttionD PFH

<?php $title = $post['title'] ?> <?php ob_start() ?> <h1><?php echo $post['title'] ?></h1> <div class="date"><?php echo $post['date'] ?></div> <div class="body"> <?php echo $post['body'] ?> </div> <?php $content = ob_get_clean() ?> <?php include 'layout.php' ?>
greting the seond pge is now very esy nd no ode is duplitedF tillD this pge introdues even more lingering prolems tht frmework n solve for youF por exmpleD missing or invlid id query prmeter will use the pge to rshF st would e etter if this used RHR pge to e renderedD ut this n9t relly e done esily yetF orseD hd you forgotten to len the id prmeter vi the mysqlrelespestring@A funtionD your entire dtse would e t risk for n v injetion ttkF enother mjor prolem is tht eh individul ontroller (le must inlude the modelFphp (leF ht if eh ontroller (le suddenly needed to inlude n dditionl (le or perform some other glol tsk @eFgF enfore seurityAc es it stnds nowD tht ode would need to e dded to every ontroller (leF sf you forget to inlude something in one (leD hopefully it doesn9t relte to seurityFFF
5.2.3 A Front Controller to the Rescue

he solution is to use front ontrollerX single r (le through whih ll requests re proessedF ith front ontrollerD the ss for the pplition hnge slightlyD ut strt to eome more )exileX

Without a front controller /index.php => Blog post list page (index.php executed) /show.php => Blog post show page (show.php executed) With index.php as the front controller /index.php => Blog post list page (index.php executed) /index.php/show => Blog post show page (index.php executed)
X he indexFphp portion of the s n e removed if using ephe rewrite rules @or equivlentAF sn tht seD the resulting s of the log show pge would e simply GshowF hen using front ontrollerD single r (le @indexFphp in this seA renders every requestF SFPF ymfonyP versus plt r SS

ymfony houmenttionD PFH por the log post show pgeD GindexFphpGshow will tully exeute the indexFphp (leD whih is now responsile for routing requests internlly sed on the full sF es you9ll seeD front ontroller is very powerful toolF greting the pront gontroller ou9re out to tke ig step with the pplitionF ith one (le hndling ll requestsD you n entrlize things suh s seurity hndlingD on(gurtion lodingD nd routingF sn this pplitionD indexFphp must now e smrt enough to render the log post list pge or the log post show pge sed on the requested sX

<?php // index.php // load and initialize any global libraries require_once 'model.php'; require_once 'controllers.php'; // route the request internally $uri = $_SERVER['REQUEST_URI']; if ($uri == '/index.php') { list_action(); } elseif ($uri == '/index.php/show' && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>Page Not Found</h1></body></html>'; }
por orgniztionD oth ontrollers @formerly indexFphp nd showFphpA re now r funtions nd eh hs een moved into seprte (leD ontrollersFphpX

function list_action() { $posts = get_all_posts(); require 'templates/list.php'; } function show_action($id) { $post = get_post_by_id($id); require 'templates/show.php'; }
es front ontrollerD indexFphp hs tken on n entirely new roleD one tht inludes loding the ore lirries nd routing the pplition so tht one of the two ontrollers ST SF

ymfony houmenttionD PFH @the listtion@A nd showtion@A funtionsA is lledF sn relityD the front ontroller is eginning to look nd t lot like ymfonyP9s mehnism for hndling nd routing requestsF X enother dvntge of front ontroller is )exile vsF xotie tht the v to the log post show pge ould e hnged from Gshow to Gred y hnging ode in only one lotionF feforeD n entire (le needed to e renmedF sn ymfonyPD vs re even more )exileF fy nowD the pplition hs evolved from single r (le into struture tht is orgnized nd llows for ode reuseF ou should e hppierD ut fr from stis(edF por exmpleD the routing system is (kleD nd wouldn9t reognize tht the list pge @GindexFphpA should e essile lso vi G @if ephe rewrite rules were ddedAF elsoD insted of developing the logD lot of time is eing spent working on the rhiteture of the ode @eFgF routingD lling ontrollersD templtesD etFAF wore time will need to e spent to hndle form sumissionsD input vlidtionD logging nd seurityF hy should you hve to reinvent solutions to ll these routine prolemsc edd ouh of ymfonyP ymfonyP to the resueF fefore tully using ymfonyPD you need to mke sure r knows how to (nd the ymfonyP lssesF his is omplished vi n utoloder tht ymfony providesF en utoloder is tool tht mkes it possile to strt using r lsses without expliitly inluding the (le ontining the lssF pirstD downlod symfony nd ple it into vendorGsymfonyG diretoryF xextD rete n ppGootstrpFphp (leF se it to require the two (les in the pplition nd to on(gure the utoloderX

<?php // bootstrap.php require_once 'model.php'; require_once 'controllers.php'; require_once 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; $loader = new Symfony\Component\ClassLoader\UniversalClassLoader(); $loader->registerNamespaces(array( 'Symfony' => __DIR__.'/vendor/symfony/src', )); $loader->register();
his tells the utoloder where the ymfony lsses reF ith thisD you n strt using ymfony lsses without using the require sttement for the (les tht ontin themF gore to ymfony9s jo is to interpret philosophy is eh request the nd ide tht n pplition9s min return responseF o this endD SU

SFPF ymfonyP versus plt r

ymfony houmenttionD PFH ymfonyP provides oth ymfonygomponentrttppoundtionequest nd ymfonygomponentrttppoundtionesponse lssF hese lsses re ojetEoriented representtions of the rw r request eing proessed nd the r response eing returnedF se them to improve the logX

<?php // index.php require_once 'app/bootstrap.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $uri = $request->getPathInfo(); if ($uri == '/') { $response = list_action(); } elseif ($uri == '/show' && $request->query->has('id')) { $response = show_action($request->query->get('id')); } else { $html = '<html><body><h1>Page Not Found</h1></body></html>'; $response = new Response($html, 404); } // echo the headers and send the response $response->send();
he ontrollers re now responsile for returning esponse ojetF o mke this esierD you n dd new rendertemplte@A funtionD whihD inidentllyD ts quite it like the ymfonyP templting engineX

// controllers.php use Symfony\Component\HttpFoundation\Response; function list_action() { $posts = get_all_posts(); $html = render_template('templates/list.php', array('posts' => $posts)); } return new Response($html);

function show_action($id) { $post = get_post_by_id($id); $html = render_template('templates/show.php', array('post' => $post)); return new Response($html);
SV SF

ymfony houmenttionD PFH

} // helper function to render templates function render_template($path, array $args) { extract($args); ob_start(); require $path; $html = ob_get_clean(); } return $html;

fy ringing in smll prt of ymfonyPD the pplition is more )exile nd relileF he equest provides dependle wy to ess informtion out the r requestF pei(llyD the getthsnfo@A method returns lened s @lwys returning Gshow nd never GindexFphpGshowAF oD even if the user goes to GindexFphpGshowD the pplition is intelligent enough to route the request through showtion@AF he esponse ojet gives )exiility when onstruting the r responseD llowing r heders nd ontent to e dded vi n ojetEoriented interfeF end while the responses in this pplition re simpleD this )exiility will py dividends s your pplition growsF he mple epplition in ymfonyP he log hs ome long wyD ut it still ontins lot of ode for suh simple pplitionF elong the wyD we9ve lso invented simple routing system nd method using ostrt@A nd ogetlen@A to render templtesF sfD for some resonD you needed to ontinue uilding this frmework from srthD you ould t lest use ymfony9s stndlone outing nd emplting omponentsD whih lredy solve these prolemsF snsted of reEsolving ommon prolemsD you n let ymfonyP tke re of them for youF rere9s the sme smple pplitionD now uilt in ymfonyPX

<?php // src/Acme/BlogBundle/Controller/BlogController.php namespace Acme\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class BlogController extends Controller { public function listAction() { $posts = $this->get('doctrine')->getEntityManager() ->createQuery('SELECT p FROM AcmeBlogBundle:Post p')
SFPF ymfonyP versus plt r SW

ymfony houmenttionD PFH

->execute(); } return $this->render('AcmeBlogBundle:Post:list.html.php', array('posts' => $posts));

public function showAction($id) { $post = $this->get('doctrine') ->getEntityManager() ->getRepository('AcmeBlogBundle:Post') ->nd($id); if (!$post) { // cause the 404 page not found to be displayed throw $this->createNotFoundException(); } } return $this->render('AcmeBlogBundle:Post:show.html.php', array('post' => $post));

he two ontrollers re still lightweightF ih uses the hotrine yw lirry to retrieve ojets from the dtse nd the emplting omponent to render templte nd return esponse ojetF he list templte is now quite it simplerX

<!-- src/Acme/BlogBundle/Resources/views/Blog/list.html.php --> <?php $view->extend('::layout.html.php') ?> <?php $view['slots']->set('title', 'List of Posts') ?> <h1>List of Posts</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="<?php echo $view['router']->generate('blog_show', array('id' => $post->getId())) ?>"> <?php echo $post->getTitle() ?> </a> </li> <?php endforeach; ?> </ul>
he lyout is nerly identilX

<!-- app/Resources/views/layout.html.php --> <html> <head> <title><?php echo $view['slots']->output('title', 'Default title') ?></title>
TH SF

ymfony houmenttionD PFH

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


X e9ll leve the show templte s n exeriseD s it should e trivil to rete sed on the list templteF hen ymfonyP9s engine @lled the uernelA oots upD it needs mp so tht it knows whih ontrollers to exeute sed on the request informtionF e routing on(gurtion mp provides this informtion in redle formtX

# app/cong/routing.yml blog_list: pattern: /blog defaults: { _controller: AcmeBlogBundle:Blog:list } blog_show: pattern: /blog/show/{id} defaults: { _controller: AcmeBlogBundle:Blog:show }
xow tht ymfonyP is hndling ll the mundne tsksD the front ontroller is ded simpleF end sine it does so littleD you9ll never hve to touh it one it9s reted @nd if you use ymfonyP distriutionD you won9t even need to rete it3AX

<?php // web/app.php require_once __DIR__.'/../app/bootstrap.php'; require_once __DIR__.'/../app/AppKernel.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('prod', false); $kernel->handle(Request::createFromGlobals())->send();
he front ontroller9s only jo is to initilize ymfonyP9s engine @uernelA nd pss it equest ojet to hndleF ymfonyP9s ore then uses the routing mp to determine whih ontroller to llF tust like eforeD the ontroller method is responsile for returning the (nl esponse ojetF here9s relly not muh else to itF por visul representtion of how ymfonyP hndles eh requestD see the request )ow digrmF

SFPF ymfonyP versus plt r

TI

ymfony houmenttionD PFH here ymfonyP helivers sn the upoming hptersD you9ll lern more out how eh piee of ymfony works nd the reommended orgniztion of projetF por nowD let9s see how migrting the log from )t r to ymfonyP hs improved lifeX

our pplition now hs ler nd onsistently orgnized ode @though ymfony doesn9t fore you into thisAF his promotes reusility nd llows for new developers to e produtive in your projet more quiklyF IHH7 of the ode you write is for your pplitionF ou don9t need to develop or mintin lowElevel utilities suh s utolodingD routingD or rendering ontrollersF ymfonyP gives you ess to open soure tools suh s hotrine nd the empltingD eurityD pormD lidtion nd rnsltion omponents @to nme fewAF he pplition now enjoys fullyE)exile vs thnks to the outing omponentF ymfonyP9s rEentri rhiteture gives you ess to powerful tools suh s r hing powered y ymfonyP9s internl r he or more powerful tools suh s rnishF his is overed in lter hpter ll out hingF
end perhps est of llD y using ymfonyPD you now hve ess to whole set of highE qulity open soure tools developed y the ymfonyP ommunity3 por more informtionD hek out ymfonyPfundlesForg
5.2.4 Better templates

sf you hoose to use itD ymfonyP omes stndrd with templting engine lled wig tht mkes templtes fster to write nd esier to redF st mens tht the smple pplition ould ontin even less ode3 keD for exmpleD the list templte written in wigX

{# src/Acme/BlogBundle/Resources/views/Blog/list.html.twig #} {% extends "::layout.html.twig" %} {% block title %}List of Posts{% endblock %} {% block body %} <h1>List of Posts</h1> <ul> {% for post in posts %} <li> <a href="{{ path('blog_show', { 'id': post.id }) }}"> {{ post.title }} </a> </li> {% endfor %}

TP

SF

ymfony houmenttionD PFH

</ul> {% endblock %}
he orresponding lyoutFhtmlFtwig templte is lso esier to writeX

{# app/Resources/views/layout.html.twig #} <html> <head> <title>{% block title %}Default title{% endblock %}</title> </head> <body> {% block body %}{% endblock %} </body> </html>
wig is wellEsupported in ymfonyPF end while r templtes will lwys e supported in ymfonyPD we9ll ontinue to disuss the mny dvntges of wigF por more informtionD see the templting hpterF
5.2.5 Learn more from the Cookbook

row to use r insted of wig for empltes row to de(ne gontrollers s ervies

5.3 Installing and Conguring Symfony

he gol of this hpter is to get you up nd running with working pplition uilt on top of ymfonyF portuntelyD ymfony o'ers distriutionsD whih re funtionl ymfony strter projets tht you n downlod nd egin developing in immeditelyF X sf you9re looking for instrutions on how est to rete new projet nd store it vi soure ontrolD see sing oure gontrolF

5.3.1 Downloading a Symfony2 Distribution

X pirstD hek tht you hve instlled nd on(gured e server @suh s epheA with r SFQFP or higherF por more informtion on ymfonyP requirementsD see the requirements refereneF SFQF snstlling nd gon(guring ymfony TQ

ymfony houmenttionD PFH

ymfonyP pkges distriutionsD whih re fullyEfuntionl pplitions tht inlude the ymfonyP ore lirriesD seletion of useful undlesD sensile diretory struture nd some defult on(gurtionF hen you downlod ymfonyP distriutionD you9re downloding funtionl pplition skeleton tht n e used immeditely to egin developing your pplitionF trt y visiting the ymfonyP downlod pge t httpXGGsymfonyFomGdownlodF yn this pgeD you9ll see the ymfony tndrd iditionD whih is the min ymfonyP distriutionF rereD you9ll need to mke two hoiesX

hownlod either Ftgz or Fzip rhive E oth re equivlentD downlod whtever you9re more omfortle usingY hownlod the distriution with or without vendorsF sf you hve qit instlled on your omputerD you should downlod ymfonyP without vendorsD s it dds it more )exiility when inluding thirdEprtyGvendor lirriesF
hownlod one of the rhives somewhere under your lol we server9s root diretory nd unpk itF prom xs ommnd lineD this n e done with one of the following ommnds @repling 555 with your tul (lenmeAX

# for .tgz le tar zxvf Symfony_Standard_Vendors_2.0.###.tgz # for a .zip le unzip Symfony_Standard_Vendors_2.0.###.zip
hen you9re (nishedD you should hve ymfonyG diretory tht looks something like thisX

www/ <- your web root directory Symfony/ <- the unpacked archive app/ cache/ cong/ logs/ src/ ... vendor/ ... web/ app.php ...

TR

SF

ymfony houmenttionD PFH pdting endors pinllyD if you downloded the rhive without vendorsD instll the vendors y running the following ommnd from the ommnd lineX

php bin/vendors install


his ommnd downlods ll of the neessry vendor lirries E inluding ymfony itself E into the vendorG diretoryF por more informtion on how thirdEprty vendor lirries re mnged inside ymfonyPD see wnging endor virries with inGvendors nd depsF gon(gurtion nd etup et this pointD ll of the needed thirdEprty lirries now live in the vendorG diretoryF ou lso hve defult pplition setup in ppG nd some smple ode inside the srG diretoryF ymfonyP omes with visul server on(gurtion tester to help mke sure your e server nd r re on(gured to use ymfonyF se the following v to hek your on(gurtionX

http://localhost/Symfony/web/cong.php
sf there re ny issuesD orret them now efore moving onF

SFQF snstlling nd gon(guring ymfony

TS

ymfony houmenttionD PFH etting up ermissions yne ommon issue is tht the ppGhe nd ppGlogs diretories must e writle oth y the we server nd the ommnd line userF yn xs systemD if your we server user is di'erent from your ommnd line userD you n run the following ommnds just one in your projet to ensure tht permissions will e setup properlyF ghnge wwwEdt to the we server user nd yournme to your ommnd line userX IF sing egv on system tht supports hmod C wny systems llow you to use the hmod C ommndF ry this (rstD nd if you get n error E try the next methodX

rm -rf app/cache/* rm -rf app/logs/* sudo chmod +a "www-data allow delete,write,append,le_inherit,directory_inherit" app/cache app/logs sudo chmod +a "yourname allow delete,write,append,le_inherit,directory_inherit" app/cache app/logs
PF sing el on system tht does not support hmod C ome systems don9t support hmod CD ut do support nother utility lled setflF ou my need to enle egv support on your prtition nd instll setfl efore using it @s is the se with untuAD like soX

sudo setfacl -R -m u:www-data:rwx -m u:yourname:rwx app/cache app/logs sudo setfacl -dR -m u:www-data:rwx -m u:yourname:rwx app/cache app/logs
QF ithout using egv sf you don9t hve ess to hnging the egv of the diretoriesD you will need to hnge the umsk so tht the he nd log diretories will e groupEwritle or worldEwritle @depending if the we server user nd the ommnd line user re in the sme group or notAF o hieve thisD put the following line t the eginning of the ppGonsoleD weGppFphp nd weGppdevFphp (lesX

umask(0002); // This will let the permissions be 0775 // or umask(0000); // This will let the permissions be 0777
xote tht using the egv is reommended when you hve ess to them on your server euse hnging the umsk is not thredEsfeF hen everything is (neD lik on qo to the elome pge to request your (rst rel ymfonyP wepgeX

http://localhost/Symfony/web/app_dev.php/
ymfonyP should welome nd ongrtulte you for your hrd work so fr3

TT

SF

ymfony houmenttionD PFH

5.3.2 Beginning Development

xow tht you hve fullyEfuntionl ymfonyP pplitionD you n egin development3 our distriution my ontin some smple ode E hek the iehwiFrst (le inluded with the distriution @open it s text (leA to lern out wht smple ode ws inluded with your distriution nd how you n remove it lterF sf you9re new to ymfonyD join us in the  ymfonyPD where you9ll lern how to rete pgesD hnge on(gurtionD nd do everything else you9ll need in your new pplitionF
5.3.3 Using Source Control

sf you9re using version ontrol system like qit or uversionD you n setup your version ontrol system nd egin ommitting your projet to it s normlF he ymfony tndrd edition is the strting point for your new projetF por spei( instrutions on how est to setup your projet to e stored in gitD see row to grete nd store ymfonyP rojet in gitF

SFQF snstlling nd gon(guring ymfony

TU

ymfony houmenttionD PFH sgnoring the vendorG hiretory sf you9ve downloded the rhive without vendorsD you n sfely ignore the entire vendorG diretory nd not ommit it to soure ontrolF ith qitD this is done y reting nd dding the following to Fgitignore (leX

vendor/
xowD the vendor diretory won9t e ommitted to soure ontrolF his is (ne @tullyD it9s gret3A euse when someone else lones or heks out the projetD heGshe n simply run the php inGvendors instll sript to downlod ll the neessry vendor lirriesF

5.4 Symfony2

ymfonyP D P X

X s @ GoutA E D @r AD ymfonyP D s Y X ! r D E esponseF


D eF E e r F E ! F ymfonyP D F c 3
5.4.1 Hello Symfony!

rello orld3F D E D E vX

http://localhost/app_dev.php/hello/Symfony
ymfony F F X D ymfonyP E F vD D D lolhost TV SF

ymfony houmenttionD PFH weE ymfonyP F D D F E ymfonyPF

X @undleA D @undleAF ymfonyP E D D F D ! @ rAD E E D rED tvsriptE @F AF emerellofundle @ED AD E @ EAX

php app/console generate:bundle --namespace=Acme/HelloBundle --format=yml


srGemeGrellofundleF ppGeppuernelFphp X

// app/AppKernel.php public function registerBundles() { $bundles = array( // ... new Acme\HelloBundle\AcmeHelloBundle(), ); // ... } return $bundles;

D D F IX D ymfonyPD ppGon(gGroutingFymlF D E ymfonyPD wv r F SFRF ymfonyP TW

ymfony houmenttionD PFH D ymfony emerellofundleX

ewv

# app/cong/routing.yml AcmeHelloBundle: resource: "@AcmeHelloBundle/Resources/cong/routing.yml" prex: /


wv

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <import resource="@AcmeHelloBundle/Resources/cong/routing.xml" prex="/" /> </routes>
r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->addCollection( $loader->import('@AcmeHelloBundle/Resources/cong/routing.php'), '/', ); return $collection;
X ymfony esouresGon(gGroutingFymlD emerellofundleF D ppGon(gGroutingFyml E F routingFyml D E D X

ewv

# src/Acme/HelloBundle/Resources/cong/routing.yml hello: pattern: /hello/{name}


UH SF

ymfony houmenttionD PFH

defaults: { _controller: AcmeHelloBundle:Hello:index }


wv

<!-- src/Acme/HelloBundle/Resources/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="hello" pattern="/hello/{name}"> <default key="_controller">AcmeHelloBundle:Hello:index</default> </route> </routes>
r

// src/Acme/HelloBundle/Resources/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('hello', new Route('/hello/{name}', array( '_controller' => 'AcmeHelloBundle:Hello:index', ))); return $collection;
X ptternD sD defults D E F @pleholderA @{nme}A ! @wildrdAF D s GhelloGynD GhelloGpienD D D F D E {nme} D D F X s F E F

PX s GhelloGyn D hello emerellofundleXrelloXindexF SFRF ymfonyP UI

ymfony houmenttionD PFH F emerellofundleXrelloXindex E E indexetion rE emerellofundlegontrollerrelloF emerellofundleX

// src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { }


D ! D r D D ymfony F D D D F D ymfonyP esponseF indexetionD helloX

// src/Acme/HelloBundle/Controller/HelloController.php // ... class HelloController { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }
X esponse D @ rwvED AF 3 D 3 D X

http://localhost/app_dev.php/hello/Ryan
X ou n lso view your pp in the prod environment y visitingX

http://localhost/app.php/hello/Ryan
sf you get n errorD it9s likely euse you need to ler your he y runningX UP SF

ymfony houmenttionD PFH

php app/console cache:clear --env=prod --no-debug


@ A F X ! E F F

QX @rwv A E F D X
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

// src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class HelloController extends Controller { public function indexAction($name) { return $this->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name)); // render a PHP template instead // return $this->render('AcmeHelloBundle:Hello:index.html.php', array('name' => $name));

X D render@A E ymfonyfundleprmeworkfundlegontrollergontroller @es ymfonyfundleprmeworkfundlegontrollergontrollerAD E F use R gontroller TF render@A esponse @E A F D esponseF

SFRF ymfonyP

UQ

ymfony houmenttionD PFH D F ymfonyP ED P X rE D wigF D D F emerellofundleXrelloXindexFhtmlFtwigD E X fundlexmeXgontrollerxmeXempltexme D F GpthGtoGfundlexmeGesouresGviewsGgontrollerxmeGempltexme D emerellofundle ! D rello ! indexFhtmlFtwig X

wig
1 2 3 4 5 6

{# src/Acme/HelloBundle/Resources/views/Hello/index.html.twig #} {% extends '::base.html.twig' %} {% block body %} Hello {{ name }}! {% endblock %}


r

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php --> <?php $view->extend('::base.html.php') ?> Hello <?php echo $view->escape($name) ?>!
wigX

PX extends F @lyoutA F RX lok D odyF D @seFhtmlFtwigA odyF


D XXseFhtmlFtwigD fundlexme gontrollerxme @ @XXA AF D E D ppX

wig

UR

SF

ymfony houmenttionD PFH

{# app/Resources/views/base.html.twig #} <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>{% block title %}Welcome!{% endblock %}</title> {% block stylesheets %}{% endblock %} <link rel="shortcut icon" href="{{ asset('favicon.ico') }}" /> </head> <body> {% block body %}{% endblock %} {% block javascripts %}{% endblock %} </body> </html>
r

<!-- app/Resources/views/base.html.php --> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php $view['slots']->output('title', 'Welcome!') ?></title> <?php $view['slots']->output('stylesheets') ?> <link rel="shortcut icon" href="<?php echo $view['assets']->getUrl('favicon.ico') ?>" /> </head> <body> <?php $view['slots']->output('_content') ?> <?php $view['slots']->output('stylesheets') ?> </body> </html>
rwv ody indexFhtmlFtwigF title indexFhtmlFtwigF title D ! elome3F ! rwv D g D D E F ! F D esponseF D E D esponseF

SFRF ymfonyP

US

ymfony houmenttionD PFH


5.4.2

D E ymfonyPF D ymfonyPF F D ! 3 D ymfony @ A X

ppGX Y srGX r Y vendorGX Y weGX D weE Y


e eE ! E D D tvript F EX

// web/app.php require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../app/AppKernel.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('prod', false); $kernel->loadClassCache(); $kernel->handle(Request::createFromGlobals())->send();
E @ ! ppFphpA E r D E D ymfonyP E uernelED eppuernelD F X E vD D  r E F ED v X

http://localhost/app.php/hello/Ryan
E ppFphp v GhelloGyn E F UT SF

ymfony houmenttionD PFH modrewrite ephe @ E vA ppFphpD vX

http://localhost/hello/Ryan
E D F D F @ppA ED eppuernel ! E F D ppGF D D ymfony F D ! EF

registerfundles@AX D E @F AY registergontinergon(gurtion@AX @F AF
ppG D E ppGon(gG diretory @F AF ppG @ppGheAD @ppGlogsA @ppGesouresAF F

SFRF ymfonyP

UU

ymfony houmenttionD PFH E ppGutolodFphpF srG vendorGF E inlude requireF D ymfonyP E D E D F D ymfonyP sr E eme @ AF D X

Class Name: Acme\HelloBundle\Controller\HelloController Path: src/Acme/HelloBundle/Controller/HelloController.php


D ppGutolodFphpD vendorGF F

@srA D srG F D D F D srG F D D F c


5.4.3

E D F D ymfonyPD F ! ymfonyPF D thirdEprty undlesF F D F X D F

UV

SF

ymfony houmenttionD PFH E D E F flogfundleD porumfundle @ AF E D D rED D D tvriptED F D registerfundles@A eppuernelX

// app/AppKernel.php public function registerBundles() { $bundles = array( new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), new Symfony\Bundle\AsseticBundle\AsseticBundle(), new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { $bundles[] = new Acme\DemoBundle\AcmeDemoBundle(); $bundles[] = new Symfony\Bundle\WebProlerBundle\WebProlerBundle(); $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); } } return $bundles;

registerfundles@A D @ ymfonyAF X D @ E ppGutolodFphpAF

ymfony tndrd idition E F D F

SFRF ymfonyP

UW

ymfony houmenttionD PFH D D E emeestfundle F X eme E D @ efgestfundle efgAF emeestfundleFphpX srGemeGestfundleG

// src/Acme/TestBundle/AcmeTestBundle.php namespace Acme\TestBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class AcmeTestBundle extends Bundle { }


X emeestfundle E F estfundleD estfundle @ estfundleFphpAF ! D E F D D F D D eppuernelX

// app/AppKernel.php public function registerBundles() { $bundles = array( // ... // register your bundles new Acme\TestBundle\AcmeTestBundle(),

); // ... }

return $bundles;

D D F ymfony VH SF

ymfony houmenttionD PFH X

php app/console generate:bundle --namespace=Acme/TestBundle


D D E F F X D D D registerfundles@AF generteXundle F

F D D ymfonyPF emerellofundleD E X

gontrollerG @ rellogontrollerFphpAY esouresGon(gG D @ routingFymlAY esouresGviewsG D @ relloGindexFhtmlFtwigAY esouresGpuliG @D F F F AD E weG ssetsXinstll estsG F
D ! D F D ! F D D D F F
5.4.4

D E F D ewvD wv rF D E ppGon(gG on(gFymlD on(gFxml on(gFphpD X SFRF ymfonyP VI

ymfony houmenttionD PFH

ewv

# app/cong/cong.yml imports: - { resource: parameters.ini } - { resource: security.yml } framework: secret: %secret% charset: UTF-8 router: { resource: "%kernel.root_dir%/cong/routing.yml" } form: true csrf_protection: true validation: { enable_annotations: true } templating: { engines: ['twig'] } #assets_version: SomeVersionScheme session: default_locale: %locale% auto_start: true # Twig Conguration twig: debug: %kernel.debug% strict_variables: %kernel.debug% # ...
wv

<!-- app/cong/cong.xml --> <imports> <import resource="parameters.ini" /> <import resource="security.yml" /> </imports> <framework:cong charset="UTF-8" secret="%secret%"> <framework:router resource="%kernel.root_dir%/cong/routing.xml" /> <framework:form /> <framework:csrf-protection /> <framework:validation annotations="true" /> <framework:templating assets-version="SomeVersionScheme"> <framework:engine id="twig" /> </framework:templating> <framework:session default-locale="%locale%" auto-start="true" /> </framework:cong> <!-- Twig Conguration --> <twig:cong debug="%kernel.debug%" strict-variables="%kernel.debug%" />

VP

SF

ymfony houmenttionD PFH

<!-- ... -->


r

$this->import('parameters.ini'); $this->import('security.yml'); $container->loadFromExtension('framework', array( 'secret' => '%secret%', 'charset' => 'UTF-8', 'router' => array('resource' => '%kernel.root_dir%/cong/routing.php'), 'form' => array(), 'csrf-protection' => array(), 'validation' => array('annotations' => true), 'templating' => array( 'engines' => array('twig'), #'assets_version' => "SomeVersionScheme", ), 'session' => array( 'default_locale' => "%locale%", 'auto_start' => true, ), )); // Twig Conguration $container->loadFromExtension('twig', array( 'debug' => '%kernel.debug%', 'strict_variables' => '%kernel.debug%', )); // ...
X G ! invironmentsF D frmework twigD E F D frmework ymfony prmeworkfundle D E F F F F

SFRF ymfonyP

VQ

ymfony houmenttionD PFH @ewvD wv nd rAF E F X ewvX D Y wvX D ewvF shi @utoompletionAY rX D D E F

5.4.5

F E r @ EAD F D dev E D prod F dev D prod F D F ymfonyP @devD test prodAD F E E F E dev D ppdevFphpX

http://localhost/app_dev.php/hello/Ryan
D D E prodX

http://localhost/app.php/hello/Ryan
prod D D E wig r F D X

php app/console cache:clear --env=prod --no-debug


X weGppFphpD D prod X

$kernel = new AppKernel('prod', false);

VR

SF

ymfony houmenttionD PFH E prod F

X test E F F

eppuernel X

// app/AppKernel.php public function registerContainerConguration(LoaderInterface $loader) { $loader->load(__DIR__.'/cong/cong_'.$this->getEnvironment().'.yml'); }


D Fyml Fxml Fphp wv rF D E F dev F

ewv

# app/cong/cong_dev.yml imports: - { resource: cong.yml } framework: router: { resource: "%kernel.root_dir%/cong/routing_dev.yml" } proler: { only_exceptions: false } # ...
wv

<!-- app/cong/cong_dev.xml --> <imports> <import resource="cong.xml" /> </imports> <framework:cong> <framework:router resource="%kernel.root_dir%/cong/routing_dev.xml" /> <framework:proler only-exceptions="false" /> </framework:cong>
SFRF ymfonyP VS

ymfony houmenttionD PFH

<!-- ... -->


r

// app/cong/cong_dev.php $loader->import('cong.php'); $container->loadFromExtension('framework', array( 'router' => array('resource' => '%kernel.root_dir%/cong/routing_dev.php'), 'proler' => array('only-exceptions' => false), )); // ...
imports inlude r E @on(gFymlA F E D F ! prod test X F E D E E F
5.4.6

3 ymfonyP D E F D D X

! D D @A F R X weG @we ssets front ontrollersAD ppG @AD srG @ AD vendorG @ AY ymfonyP @ A D D Y ppGon(g ewvD wv rY E @ ppFphp ppdevFphpA F

VT

SF

ymfony houmenttionD PFH D F ymfonyPD F

5.5 Controller

e ontroller is r funtion you rete tht tkes informtion from the r request nd onstruts nd returns n r response @s ymfonyP esponse ojetAF he response ould e n rwv pgeD n wv doumentD serilized tyx rryD n imgeD rediretD RHR error or nything else you n drem upF he ontroller ontins whtever ritrry logi your pplition needs to render the ontent of pgeF o see how simple this isD let9s look t ymfonyP ontroller in tionF he following ontroller would render pge tht simply prints rello world3X

use Symfony\Component\HttpFoundation\Response; public function helloAction() { return new Response('Hello world!'); }


he gol of ontroller is lwys the smeX rete nd return esponse ojetF elong the wyD it might red informtion from the requestD lod dtse resoureD send n emilD or set informtion on the user9s sessionF fut in ll sesD the ontroller will eventully return the esponse ojet tht will e delivered k to the lientF here9s no mgi nd no other requirements to worry out3 rere re few ommon exmplesX

gontroller e prepres esponse ojet representing the ontent for the homepge of the siteF gontroller f reds the slug prmeter from the request to lod log entry from the dtse nd rete esponse ojet displying tht logF sf the slug n9t e found in the dtseD it retes nd returns esponse ojet with RHR sttus odeF gontroller g hndles the form sumission of ontt formF st reds the form informtion from the requestD sves the ontt informtion to the dtse nd emils the ontt informtion to the wemsterF pinllyD it retes esponse ojet tht redirets the lient9s rowser to the ontt form thnk you pgeF

SFSF gontroller

VU

ymfony houmenttionD PFH


5.5.1 Requests, Controller, Response Lifecycle

ivery request hndled y ymfonyP projet goes through the sme simple lifeyleF he frmework tkes re of the repetitive tsks nd ultimtely exeutes ontrollerD whih houses your ustom pplition odeX IF ih request is hndled y single front ontroller (le @eFgF ppFphp or ppdevFphpA tht ootstrps the pplitionY PF he outer reds informtion from the request @eFgF the sAD (nds route tht mthes tht informtionD nd reds the ontroller prmeter from the routeY QF he ontroller from the mthed route is exeuted nd the ode inside the ontroller retes nd returns esponse ojetY RF he r heders nd ontent of the esponse ojet re sent k to the lientF greting pge is s esy s reting ontroller @5QA nd mking route tht mps v to tht ontroller @5PAF X hough similrly nmedD front ontroller is di'erent from the ontrollers we9ll tlk out in this hpterF e front ontroller is short r (le tht lives in your we diretory nd through whih ll requests re diretedF e typil pplition will hve prodution front ontroller @eFgF ppFphpA nd development front ontroller @eFgF ppdevFphpAF ou9ll likely never need to editD view or worry out the front ontrollers in your pplitionF

5.5.2 A Simple Controller

hile ontroller n e ny r llle @ funtionD method on n ojetD or glosureAD in ymfonyPD ontroller is usully single method inside ontroller ojetF gontrollers re lso lled tionsF
1 2 3 4 5 6 7 8 9 10 11 12

// src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }

VV

SF

ymfony houmenttionD PFH

X xote tht the ontroller is the indexetion methodD whih lives inside ontroller lss @rellogontrollerAF hon9t e onfused y the nmingX ontroller lss is simply onvenient wy to group severl ontrollersGtions togetherF ypillyD the ontroller lss will house severl ontrollersGtions @eFgF updteetionD deleteetionD etAF his ontroller is pretty strightforwrdD ut let9s wlk through itX

line QX ymfonyP tkes dvntge of r SFQ nmespe funtionlity to nmespe the entire ontroller lssF he use keyword imports the esponse lssD whih our ontroller must returnF line TX he lss nme is the ontention of nme for the ontroller lss @iFeF relloA nd the word gontrollerF his is onvention tht provides onsisteny to ontrollers nd llows them to e referened only y the (rst prt of the nme @iFeF relloA in the routing on(gurtionF line VX ih tion in ontroller lss is su0xed with etion nd is referened in the routing on(gurtion y the tion9s nme @indexAF sn the next setionD you9ll rete route tht mps s to this tionF ou9ll lern how the route9s pleholders @{nme}A eome rguments to the tion method @6nmeAF line IHX he ontroller retes nd returns esponse ojetF
5.5.3 Mapping a URL to a Controller

he new ontroller returns simple rwv pgeF o tully view this pge in your rowserD you need to rete routeD whih mps spei( v pttern to the ontrollerX

ewv

# app/cong/routing.yml hello: pattern: /hello/{name} defaults: { _controller: AcmeHelloBundle:Hello:index }


wv

<!-- app/cong/routing.xml --> <route id="hello" pattern="/hello/{name}"> <default key="_controller">AcmeHelloBundle:Hello:index</default> </route>


r

// app/cong/routing.php $collection->add('hello', new Route('/hello/{name}', array(


SFSF gontroller VW

ymfony houmenttionD PFH

'_controller' => 'AcmeHelloBundle:Hello:index', )));


qoing to GhelloGryn now exeutes the rellogontrollerXXindexetion@A ontroller nd psses in ryn for the 6nme vrileF greting pge mens simply reting ontroller method nd ssoited routeF xotie the syntx used to refer to the ontrollerX emerellofundleXrelloXindexF ymfonyP uses )exile string nottion to refer to di'erent ontrollersF his is the most ommon syntx nd tells ymfonyP to look for ontroller lss lled rellogontroller inside undle nmed emerellofundleF he method indexetion@A is then exeutedF por more detils on the string formt used to referene di'erent ontrollersD see gontroller xming tternF X his exmple ples the routing on(gurtion diretly in the ppGon(gG diretoryF e etter wy to orgnize your routes is to ple eh route in the undle it elongs toF por more informtion on thisD see snluding ixternl outing esouresF

X ou n lern muh more out the routing system in the outing hpterF

oute rmeters s gontroller erguments ou lredy know tht the ontroller prmeter emerellofundleXrelloXindex refers to rellogontrollerXXindexetion@A method tht lives inside the emerellofundle undleF ht9s more interesting is the rguments tht re pssed to tht methodX

<?php // src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class HelloController extends Controller { public function indexAction($name) { // ... } }
he ontroller hs single rgumentD 6nmeD whih orresponds to the {nme} prmeter from the mthed route @ryn in our exmpleAF sn ftD when exeuting your ontrollerD

WH

SF

ymfony houmenttionD PFH ymfonyP mthes eh rgument of the ontroller with prmeter from the mthed routeF ke the following exmpleX

ewv

# app/cong/routing.yml hello: pattern: /hello/{rst_name}/{last_name} defaults: { _controller: AcmeHelloBundle:Hello:index, color: green }


wv

<!-- app/cong/routing.xml --> <route id="hello" pattern="/hello/{rst_name}/{last_name}"> <default key="_controller">AcmeHelloBundle:Hello:index</default> <default key="color">green</default> </route>
r

// app/cong/routing.php $collection->add('hello', new Route('/hello/{rst_name}/{last_name}', array( '_controller' => 'AcmeHelloBundle:Hello:index', 'color' => 'green', )));
he ontroller for this n tke severl rgumentsX

public function indexAction($rst_name, $last_name, $color) { // ... }


xotie tht oth pleholder vriles @{(rstnme}D {lstnme}A s well s the defult olor vrile re ville s rguments in the ontrollerF hen route is mthedD the pleholder vriles re merged with the defults to mke one rry tht9s ville to your ontrollerF wpping route prmeters to ontroller rguments is esy nd )exileF ueep the following guidelines in mind while you developF

he order of the ontroller rguments does not mtter


ymfony is le to mth the prmeter nmes from the route to the vrile nmes in the ontroller method9s signtureF sn other wordsD it relizes tht the {lstnme} prmeter mthes up with the 6lstnme rgumentF he rguments of the ontroller ould e totlly reordered nd still work perfetlyX

public function indexAction($last_name, $color, $rst_name) {


SFSF gontroller WI

ymfony houmenttionD PFH

// ..

ih required ontroller rgument must mth up with routing prmeter


he following would throw untimeixeption euse there is no foo prmeter de(ned in the routeX

public function indexAction($rst_name, $last_name, $color, $foo) { // .. }


wking the rgument optionlD howeverD is perfetly okF he following exmple would not throw n exeptionX

public function indexAction($rst_name, $last_name, $color, $foo = 'bar') { // .. }


xot ll routing prmeters need to e rguments on your ontroller
sfD for exmpleD the lstnme weren9t importnt for your ontrollerD you ould omit it entirelyX

public function indexAction($rst_name, $color) { // .. }


X ivery route lso hs speil route prmeterD whih is equl to the nme of the route tht ws mthed @eFgF helloAF hough not usully usefulD this is eqully ville s ontroller rgumentF

he equest s gontroller ergument por onvenieneD you n lso hve ymfony pss you the equest ojet s n rgument to your ontrollerF his is espeilly onvenient when you9re working with formsD for exmpleX

use Symfony\Component\HttpFoundation\Request; public function updateAction(Request $request) { $form = $this->createForm(...);


WP SF

ymfony houmenttionD PFH

$form->bindRequest($request); // ...

5.5.4 The Base Controller Class

por onvenieneD ymfonyP omes with se gontroller lss tht ssists with some of the most ommon ontroller tsks nd gives your ontroller lss ess to ny resoure it might needF fy extending this gontroller lssD you n tke dvntge of severl helper methodsF edd the use sttement top the gontroller lss nd then modify the rellogontroller to extend itX

// src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController extends Controller { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }
his doesn9t tully hnge nything out how your ontroller worksF sn the next setionD you9ll lern out the helper methods tht the se ontroller lss mkes villeF hese methods re just shortuts to using ore ymfonyP funtionlity tht9s ville to you with or without the use of the se gontroller lssF e gret wy to see the ore funtionlity in tion is to look in the ymfonyfundleprmeworkfundlegontrollergontroller lss itselfF X ixtending the se lss is optionl in ymfonyY it ontins useful shortuts ut nothing mndtoryF ou n lso extend ymfonygomponenthependenysnjetiongontinerewreF he servie ontiner ojet will then e essile vi the ontiner propertyF

X ou n lso de(ne your gontrollers s erviesF

SFSF gontroller

WQ

ymfony houmenttionD PFH


5.5.5 Common Controller Tasks

hough ontroller n do virtully nythingD most ontrollers will perform the sme si tsks over nd over ginF hese tsksD suh s rediretingD forwrdingD rendering templtes nd essing ore serviesD re very esy to mnge in ymfonyPF edireting sf you wnt to rediret the user to nother pgeD use the rediret@A methodX

public function indexAction() { return $this->redirect($this->generateUrl('homepage')); }


he generterl@A method is just helper funtion tht genertes the v for given routeF por more informtionD see the outing hpterF fy defultD the rediret@A method performs QHP @temporryA rediretF o perform QHI @permnentA rediretD modify the seond rgumentX

public function indexAction() { return $this->redirect($this->generateUrl('homepage'), 301); }


X he rediret@A method is simply shortut tht retes esponse ojet tht speilizes in redireting the userF st9s equivlent toX

use Symfony\Component\HttpFoundation\RedirectResponse; return new RedirectResponse($this->generateUrl('homepage'));

porwrding ou n lso esily forwrd to nother ontroller internlly with the forwrd@A methodF snsted of redireting the user9s rowserD it mkes n internl suErequestD nd lls the spei(ed ontrollerF he forwrd@A method returns the esponse ojet tht9s returned from tht ontrollerX

public function indexAction($name) { $response = $this->forward('AcmeHelloBundle:Hello:fancy', array( 'name' => $name,


WR SF

ymfony houmenttionD PFH

));

'color' => 'green'

// further modify the response or return it directly } return $response;

xotie tht the forwrd@A method uses the sme string representtion of the ontroller used in the routing on(gurtionF sn this seD the trget ontroller lss will e rellogontroller inside some emerellofundleF he rry pssed to the method eomes the rguments on the resulting ontrollerF his sme interfe is used when emedding ontrollers into templtes @see imedding gontrollersAF he trget ontroller method should look something like the followingX

public function fancyAction($name, $color) { // ... create and return a Response object }
end just like when reting ontroller for routeD the order of the rguments to fnyetion doesn9t mtterF ymfonyP mthes the index key nmes @eFgF nmeA with the method rgument nmes @eFgF 6nmeAF sf you hnge the order of the rgumentsD ymfonyP will still pss the orret vlue to eh vrileF X vike other se gontroller methodsD the forwrd method is just shortut for ore ymfonyP funtionlityF e forwrd n e omplished diretly vi the httpkernel servieF e forwrd returns esponse ojetX

$httpKernel = $this->container->get('http_kernel'); $response = $httpKernel->forward('AcmeHelloBundle:Hello:fancy', array( 'name' => $name, 'color' => 'green', ));

endering empltes hough not requirementD most ontrollers will ultimtely render templte tht9s responsile for generting the rwv @or other formtA for the ontrollerF he renderiew@A method renders templte nd returns its ontentF he ontent from the templte n e used to rete esponse ojetX

$content = $this->renderView('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));

SFSF gontroller

WS

ymfony houmenttionD PFH

return new Response($content);


his n even e done in just one step with the render@A methodD whih returns esponse ojet ontining the ontent from the templteX

return $this->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));


sn oth sesD the esouresGviewsGrelloGindexFhtmlFtwig emerellofundle will e renderedF templte inside the

he ymfony templting engine is explined in gret detil in the emplting hpterF X he renderiew method is shortut to diret use of the templting servieF he templting servie n lso e used diretlyX

$templating = $this->get('templating'); $content = $templating->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));

eessing other ervies hen extending the se ontroller lssD you n ess ny ymfonyP servie vi the get@A methodF rere re severl ommon servies you might needX

$request = $this->getRequest(); $templating = $this->get('templating'); $router = $this->get('router'); $mailer = $this->get('mailer');


here re ountless other servies ville nd you re enourged to de(ne your ownF o list ll ville serviesD use the ontinerXdeug onsole ommndX

php app/console container:debug


por more informtionD see the ervie gontiner hpterF
5.5.6 Managing Errors and 404 Pages

hen things re not foundD you should ply well with the r protool nd return RHR responseF o do thisD you9ll throw speil type of exeptionF sf you9re extending the se ontroller lssD do the followingX

WT

SF

ymfony houmenttionD PFH

public function indexAction() { $product = // retrieve the object from database if (!$product) { throw $this->createNotFoundException('The product does not exist'); } } return $this->render(...);

he retexotpoundixeption@A method retes speil xotpoundrttpixeption ojetD whih ultimtely triggers RHR r response inside ymfonyF yf ourseD you9re free to throw ny ixeption lss in your ontroller E ymfonyP will utomtilly return SHH r response odeF

throw new \Exception('Something went wrong!');


sn every seD styled error pge is shown to the end user nd full deug error pge is shown to the developer @when viewing the pge in deug modeAF foth of these error pges n e ustomizedF por detilsD red the   ookook reipeF
5.5.7 Managing the Session

ymfonyP provides nie session ojet tht you n use to store informtion out the user @e it rel person using rowserD otD or we servieA etween requestsF fy defultD ymfonyP stores the ttriutes in ookie y using the ntive r sessionsF toring nd retrieving informtion from the session n e esily hieved from ny ontrollerX

$session = $this->getRequest()->getSession(); // store an attribute for reuse during a later user request $session->set('foo', 'bar'); // in another controller for another request $foo = $session->get('foo'); // set the user locale $session->setLocale('fr');
hese ttriutes will remin on the user for the reminder of tht user9s sessionF

SFSF gontroller

WU

ymfony houmenttionD PFH plsh wessges ou n lso store smll messges tht will e stored on the user9s session for extly one dditionl requestF his is useful when proessing formX you wnt to rediret nd hve speil messge shown on the next requestF hese types of messges re lled )sh messgesF por exmpleD imgine you9re proessing form sumitX

public function updateAction() { $form = $this->createForm(...); $form->bindRequest($this->getRequest()); if ($form->isValid()) { // do some sort of processing $this->get('session')->setFlash('notice', 'Your changes were saved!'); } } return $this->redirect($this->generateUrl(...));

return $this->render(...);

efter proessing the requestD the ontroller sets notie )sh messge nd then rediretsF he nme @notieA isn9t signi(nt E it9s just wht you9re using to identify the type of the messgeF sn the templte of the next tionD the following ode ould e used to render the notie messgeX

wig

{% if app.session.hasFlash('notice') %} <div class="ash-notice"> {{ app.session.ash('notice') }} </div> {% endif %}


r

<?php if ($view['session']->hasFlash('notice')): ?> <div class="ash-notice"> <?php echo $view['session']->getFlash('notice') ?> </div> <?php endif; ?>
fy designD )sh messges re ment to live for extly one request @they9re gone in )shAF WV SF

ymfony houmenttionD PFH hey9re designed to e used ross redirets extly s you9ve done in this exmpleF
5.5.8 The Response Object

he only requirement for ontroller is to return esponse ojetF he ymfonygomponentrttppoundtionesponse lss is r strtion round the r response E the textEsed messge (lled with r heders nd ontent tht9s sent k to the lientX

// create a simple Response with a 200 status code (the default) $response = new Response('Hello '.$name, 200); // create a JSON-response with a 200 status code $response = new Response(json_encode(array('name' => $name))); $response->headers->set('Content-Type', 'application/json');
X he heders property is ymfonygomponentrttppoundtionrederfg ojet with severl useful methods for reding nd mutting the esponse hedersF he heder nmes re normlized so tht using gontentEype is equivlent to ontentEtype or even ontenttypeF

5.5.9 The Request Object

fesides the vlues of the routing pleholdersD the ontroller lso hs ess to the equest ojet when extending the se gontroller lssX

$request = $this->getRequest(); $request->isXmlHttpRequest(); // is it an Ajax request? $request->getPreferredLanguage(array('en', 'fr')); $request->query->get('page'); // get a $_GET parameter $request->request->get('page'); // get a $_POST parameter
vike the esponse ojetD the request heders re stored in rederfg ojet nd re esily essileF

SFSF gontroller

WW

ymfony houmenttionD PFH


5.5.10 Final Thoughts

henever you rete pgeD you9ll ultimtely need to write some ode tht ontins the logi for tht pgeF sn ymfonyD this is lled ontrollerD nd it9s r funtion tht n do nything it needs in order to return the (nl esponse ojet tht will e returned to the userF o mke life esierD you n hoose to extend se gontroller lssD whih ontins shortut methods for mny ommon ontroller tsksF por exmpleD sine you don9t wnt to put rwv ode in your ontrollerD you n use the render@A method to render nd return the ontent from templteF sn other hptersD you9ll see how the ontroller n e used to persist nd feth ojets from dtseD proess form sumissionsD hndle hing nd moreF
5.5.11 Learn more from the Cookbook

row to de(ne gontrollers s ervies

5.6 Routing

feutiful vs re n solute must for ny serious we pplitionF his mens leving ehind ugly vs like indexFphpcrtileidaSU in fvor of something like GredGintroEtoE symfonyF rving )exiility is even more importntF ht if you need to hnge the v of pge from Glog to Gnewsc row mny links should you need to hunt down nd updte to mke the hngec sf you9re using ymfony9s routerD the hnge is simpleF he ymfonyP router lets you de(ne retive vs tht you mp to di'erent res of your pplitionF fy the end of this hpterD you9ll e le toX

grete omplex routes tht mp to ontrollers qenerte vs inside templtes nd ontrollers vod routing resoures from undles @or nywhere elseA heug your routes
5.6.1 Routing in Action

e route is mp from v pttern to ontrollerF por exmpleD suppose you wnt to mth ny v like GlogGmyEpost or GlogGllEoutEsymfony nd send it to ontroller IHH SF

ymfony houmenttionD PFH tht n look up nd render tht log entryF he route is simpleX

ewv

# app/cong/routing.yml blog_show: pattern: /blog/{slug} defaults: { _controller: AcmeBlogBundle:Blog:show }


wv

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog_show" pattern="/blog/{slug}"> <default key="_controller">AcmeBlogBundle:Blog:show</default> </route> </routes>
r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog_show', new Route('/blog/{slug}', array( '_controller' => 'AcmeBlogBundle:Blog:show', ))); return $collection;
he pttern de(ned y the logshow route ts like GlogGB where the wildrd is given the nme slugF por the v GlogGmyElogEpostD the slug vrile gets vlue of myElogEpostD whih is ville for you to use in your ontroller @keep redingAF he ontroller prmeter is speil key tht tells ymfony whih ontroller should e exeuted when v mthes this routeF he ontroller string is lled the logil nmeF st follows pttern tht points to spei( r lss nd methodX

// src/Acme/BlogBundle/Controller/BlogController.php namespace Acme\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class BlogController extends Controller


SFTF outing IHI

ymfony houmenttionD PFH

public function showAction($slug) { $blog = // use the $slug varible to query the database return $this->render('AcmeBlogBundle:Blog:show.html.twig', array( 'blog' => $blog, ));

gongrtultions3 ou9ve just reted your (rst route nd onneted it to ontrollerF xowD when you visit GlogGmyEpostD the showetion ontroller will e exeuted nd the 6slug vrile will e equl to myEpostF his is the gol of the ymfonyP routerX to mp the v of request to ontrollerF elong the wyD you9ll lern ll sorts of triks tht mke mpping even the most omplex vs esyF
5.6.2 Routing: Under the Hood

hen request is mde to your pplitionD it ontins n ddress to the ext resoure tht the lient is requestingF his ddress is lled the vD @or sAD nd ould e GonttD GlogGredEmeD or nything elseF ke the following r request for exmpleX

GET /blog/my-blog-post
he gol of the ymfonyP routing system is to prse this v nd determine whih ontroller should e exeutedF he whole proess looks like thisX IF he request is hndled y the ymfonyP front ontroller @eFgF ppFphpAY PF he ymfonyP ore @iFeF uernelA sks the router to inspet the requestY QF he router mthes the inoming v to spei( route nd returns informtion out the routeD inluding the ontroller tht should e exeutedY RF he ymfonyP uernel exeutes the ontrollerD whih ultimtely returns esponse ojetF
5.6.3 Creating Routes

ymfony lods ll the routes for your pplition from single routing on(gurtion (leF he (le is usully ppGon(gGroutingFymlD ut n e on(gured to e nything @inluding n wv or r (leA vi the pplition on(gurtion (leX

ewv
IHP SF

ymfony houmenttionD PFH

F SFPX he routing lyer is tool tht trnsltes the inoming v into spei( ontroller to exeuteF

# app/cong/cong.yml framework: # ... router: { resource: "%kernel.root_dir%/cong/routing.yml" }


wv

<!-- app/cong/cong.xml --> <framework:cong ...> <!-- ... --> <framework:router resource="%kernel.root_dir%/cong/routing.xml" /> </framework:cong>
r

// app/cong/cong.php $container->loadFromExtension('framework', array( // ... 'router' => array('resource' => '%kernel.root_dir%/cong/routing.php'), ));
X iven though ll routes re loded from single (leD it9s ommon prtie to inlude dditionl routing resoures from inside the (leF ee the snluding ixternl outing esoures setion for more informtionF

SFTF outing

IHQ

ymfony houmenttionD PFH fsi oute gon(gurtion he(ning route is esyD nd typil pplition will hve lots of routesF e si route onsists of just two prtsX the pttern to mth nd defults rryX

ewv

_welcome: pattern: / defaults: { _controller: AcmeDemoBundle:Main:homepage }


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="_welcome" pattern="/"> <default key="_controller">AcmeDemoBundle:Main:homepage</default> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('_welcome', new Route('/', array( '_controller' => 'AcmeDemoBundle:Main:homepage', ))); return $collection;
his route mthes the homepge @GA nd mps it to the emehemofundleXwinXhomepge ontrollerF he ontroller string is trnslted y ymfonyP into n tul r funtion nd exeutedF ht proess will e explined shortly in the gontroller xming ttern setionF outing with leholders yf ourse the routing system supports muh more interesting routesF wny routes will ontin one or more nmed wildrd pleholdersX

ewv

IHR

SF

ymfony houmenttionD PFH

blog_show: pattern: /blog/{slug} defaults: { _controller: AcmeBlogBundle:Blog:show }


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog_show" pattern="/blog/{slug}"> <default key="_controller">AcmeBlogBundle:Blog:show</default> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog_show', new Route('/blog/{slug}', array( '_controller' => 'AcmeBlogBundle:Blog:show', ))); return $collection;
he pttern will mth nything tht looks like GlogGBF iven etterD the vlue mthing the {slug} pleholder will e ville inside your ontrollerF sn other wordsD if the v is GlogGhelloEworldD 6slug vrileD with vlue of helloEworldD will e ville in the ontrollerF his n e usedD for exmpleD to lod the log post mthing tht stringF he pttern will notD howeverD mth simply GlogF ht9s euseD y defultD ll pleholders re requiredF his n e hnged y dding pleholder vlue to the defults rryF equired nd yptionl leholders o mke things more exitingD dd new route tht displys list of ll the ville log posts for this imginry log pplitionX

ewv

blog: pattern: /blog


SFTF outing IHS

ymfony houmenttionD PFH

defaults: { _controller: AcmeBlogBundle:Blog:index }


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog" pattern="/blog"> <default key="_controller">AcmeBlogBundle:Blog:index</default> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog', new Route('/blog', array( '_controller' => 'AcmeBlogBundle:Blog:index', ))); return $collection;
o frD this route is s simple s possile E it ontins no pleholders nd will only mth the ext v GlogF fut wht if you need this route to support pgintionD where GlogGP displys the seond pge of log entriesc pdte the route to hve new {pge} pleholderX

ewv

blog: pattern: /blog/{page} defaults: { _controller: AcmeBlogBundle:Blog:index }


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog" pattern="/blog/{page}"> <default key="_controller">AcmeBlogBundle:Blog:index</default> </route>
IHT SF

ymfony houmenttionD PFH

</routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog', new Route('/blog/{page}', array( '_controller' => 'AcmeBlogBundle:Blog:index', ))); return $collection;
vike the {slug} pleholder eforeD the vlue mthing {pge} will e ville inside your ontrollerF sts vlue n e used to determine whih set of log posts to disply for the given pgeF fut hold on3 ine pleholders re required y defultD this route will no longer mth on simply GlogF snstedD to see pge I of the logD you9d need to use the v GlogGI3 ine tht9s no wy for rih we pp to ehveD modify the route to mke the {pge} prmeter optionlF his is done y inluding it in the defults olletionX

ewv

blog: pattern: /blog/{page} defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 }


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog" pattern="/blog/{page}"> <default key="_controller">AcmeBlogBundle:Blog:index</default> <default key="page">1</default> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection();


SFTF outing IHU

ymfony houmenttionD PFH

$collection->add('blog', new Route('/blog/{page}', array( '_controller' => 'AcmeBlogBundle:Blog:index', 'page' => 1, ))); return $collection;
fy dding pge to the defults keyD the {pge} pleholder is no longer requiredF he v Glog will mth this route nd the vlue of the pge prmeter will e set to IF he v GlogGP will lso mthD giving the pge prmeter vlue of PF erfetF Glog GlogGI GlogGP {pge} a I {pge} a I {pge} a P

edding equirements ke quik look t the routes tht hve een reted so frX

ewv

blog: pattern: /blog/{page} defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 } blog_show: pattern: /blog/{slug} defaults: { _controller: AcmeBlogBundle:Blog:show }
wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog" pattern="/blog/{page}"> <default key="_controller">AcmeBlogBundle:Blog:index</default> <default key="page">1</default> </route> <route id="blog_show" pattern="/blog/{slug}"> <default key="_controller">AcmeBlogBundle:Blog:show</default> </route> </routes>

IHV

SF

ymfony houmenttionD PFH

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog', new Route('/blog/{page}', array( '_controller' => 'AcmeBlogBundle:Blog:index', 'page' => 1, ))); $collection->add('blog_show', new Route('/blog/{show}', array( '_controller' => 'AcmeBlogBundle:Blog:show', ))); return $collection;
gn you spot the prolemc xotie tht oth routes hve ptterns tht mth v9s tht look like GlogGBF he ymfony router will lwys hoose the (rst mthing route it (ndsF sn other wordsD the logshow route will never e mthedF snstedD v like GlogGmyE logEpost will mth the (rst route @logA nd return nonsense vlue of myElogEpost to the {pge} prmeterF v GlogGP GlogGmyElogEpost route log log prmeters {pge} a P {pge} a myElogEpost

he nswer to the prolem is to dd route requirementsF he routes in this exmple would work perfetly if the GlogG{pge} pttern only mthed vs where the {pge} portion is n integerF portuntelyD regulr expression requirements n esily e dded for eh prmeterF por exmpleX

ewv

blog: pattern: /blog/{page} defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 } requirements: page: \d+
wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="blog" pattern="/blog/{page}">


SFTF outing IHW

ymfony houmenttionD PFH

<default key="_controller">AcmeBlogBundle:Blog:index</default> <default key="page">1</default> <requirement key="page">\d+</requirement> </route> </routes>


r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('blog', new Route('/blog/{page}', array( '_controller' => 'AcmeBlogBundle:Blog:index', 'page' => 1, ), array( 'page' => '\d+', ))); return $collection;
he dC requirement is regulr expression tht sys tht the vlue of the {pge} prmeter must e digit @iFeF numerAF he log route will still mth on v like GlogGP @euse P is numerAD ut it will no longer mth v like GlogGmyElogEpost @euse myE logEpost is not numerAF es resultD v like GlogGmyElogEpost will now properly mth the logshow routeF v GlogGP GlogGmyElogEpost route log logshow prmeters {pge} a P {slug} a myElogEpost

irlier outes lwys in ht this ll mens is tht the order of the routes is very importntF sf the logshow route were pled ove the log routeD the v GlogGP would mth logshow insted of log sine the {slug} prmeter of logshow hs no requirementsF fy using proper ordering nd lever requirementsD you n omplish just out nythingF ine the prmeter requirements re regulr expressionsD the omplexity nd )exiility of eh requirement is entirely up to youF uppose the homepge of your pplition is ville in two di'erent lngugesD sed on the vX

ewv

homepage: pattern: /{culture} defaults: { _controller: AcmeDemoBundle:Main:homepage, culture: en }


IIH SF

ymfony houmenttionD PFH

requirements: culture: en|fr


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="homepage" pattern="/{culture}"> <default key="_controller">AcmeDemoBundle:Main:homepage</default> <default key="culture">en</default> <requirement key="culture">en|fr</requirement> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('homepage', new Route('/{culture}', array( '_controller' => 'AcmeDemoBundle:Main:homepage', 'culture' => 'en', ), array( 'culture' => 'en|fr', ))); return $collection;
por inoming requestsD the {ulture} portion of the v is mthed ginst the regulr expression @en|frAF G Gen Gfr Ges {ulture} a en {ulture} a en {ulture} a fr won9t mth this route

edding r wethod equirements sn ddition to the vD you n lso mth on the method of the inoming request @iFeF qiD riehD yD D hiviiAF uppose you hve ontt form with two ontrollers E one for displying the form @on qi requestA nd one for proessing the form when SFTF outing III

ymfony houmenttionD PFH it9s sumitted @on y requestAF his n e omplished with the following route on(gurtionX

ewv

contact: pattern: /contact defaults: { _controller: AcmeDemoBundle:Main:contact } requirements: _method: GET contact_process: pattern: /contact defaults: { _controller: AcmeDemoBundle:Main:contactProcess } requirements: _method: POST
wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="contact" pattern="/contact"> <default key="_controller">AcmeDemoBundle:Main:contact</default> <requirement key="_method">GET</requirement> </route> <route id="contact_process" pattern="/contact"> <default key="_controller">AcmeDemoBundle:Main:contactProcess</default> <requirement key="_method">POST</requirement> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('contact', new Route('/contact', array( '_controller' => 'AcmeDemoBundle:Main:contact', ), array( '_method' => 'GET', ))); $collection->add('contact_process', new Route('/contact', array(
IIP SF

ymfony houmenttionD PFH

'_controller' => 'AcmeDemoBundle:Main:contactProcess', ), array( '_method' => 'POST', ))); return $collection;
hespite the ft tht these two routes hve identil ptterns @GonttAD the (rst route will mth only qi requests nd the seond route will mth only y requestsF his mens tht you n disply the form nd sumit the form vi the sme vD while using distint ontrollers for the two tionsF X sf no method requirement is spei(edD the route will mth on ll methodsF vike the other requirementsD the method requirement is prsed s regulr expressionF o mth qi or y requestsD you n use qi|yF edvned outing ixmple et this pointD you hve everything you need to rete powerful routing struture in ymfonyF he following is n exmple of just how )exile the routing system n eX

ewv

article_show: pattern: /articles/{culture}/{year}/{title}.{_format} defaults: { _controller: AcmeDemoBundle:Article:show, _format: html } requirements: culture: en|fr _format: html|rss year: \d+
wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="article_show" pattern="/articles/{culture}/{year}/{title}.{_format}"> <default key="_controller">AcmeDemoBundle:Article:show</default> <default key="_format">html</default> <requirement key="culture">en|fr</requirement> <requirement key="_format">html|rss</requirement> <requirement key="year">\d+</requirement>
SFTF outing IIQ

ymfony houmenttionD PFH

</route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('homepage', new Route('/articles/{culture}/{year}/{title}.{_format}', array( '_controller' => 'AcmeDemoBundle:Article:show', '_format' => 'html', ), array( 'culture' => 'en|fr', '_format' => 'html|rss', 'year' => '\d+', ))); return $collection;
es you9ve seenD this route will only mth if the {ulture} portion of the v is either en or fr nd if the {yer} is numerF his route lso shows how you n use period etween pleholders insted of slshF vs mthing this route might look likeX

GrtilesGenGPHIHGmyEpost GrtilesGfrGPHIHGmyEpostFrss
he peil formt outing rmeter his exmple lso highlights the speil formt routing prmeterF hen using this prmeterD the mthed vlue eomes the request formt of the equest ojetF ltimtelyD the request formt is used for suh things suh s setting the gontentE ype of the response @eFgF json request formt trnsltes into gontentEype of pplitionGjsonAF st n lso e used in the ontroller to render di'erent templte for eh vlue of formtF he formt prmeter is very powerful wy to render the sme ontent in di'erent formtsF

peil outing rmeters es you9ve seenD eh routing prmeter or defult vlue is eventully ville s n rgument in the ontroller methodF edditionllyD there re three prmeters tht re speilX eh dds unique piee of funtionlity inside your pplitionX

ontrollerX es you9ve seenD this prmeter is used to determine whih ontroller is exeuted when the route is mthedY
IIR SF

ymfony houmenttionD PFH

formtX sed to set the request formt @red moreAY loleX sed to set the lole on the session @red moreAY
5.6.4 Controller Naming Pattern

ivery route must hve ontroller prmeterD whih dittes whih ontroller should e exeuted when tht route is mthedF his prmeter uses simple string pttern lled the logil ontroller nmeD whih ymfony mps to spei( r method nd lssF he pttern hs three prtsD eh seprted y olonX undleXontrollerXtion por exmpleD ontroller vlue of emeflogfundleXflogXshow mensX fundle emeflogfundle gontroller glss floggontroller wethod xme showetion

he ontroller might look like thisX

// src/Acme/BlogBundle/Controller/BlogController.php namespace Acme\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class BlogController extends Controller { public function showAction($slug) { // ... } }
xotie tht ymfony dds the string gontroller to the lss nme @flog ab floggontrollerA nd etion to the method nme @show ab showetionAF ou ould lso refer to this ontroller using its fullyEquli(ed lss nme nd methodX emeflogfundlegontrollerfloggontrollerXXshowetionF fut if you follow some simple onventionsD the logil nme is more onise nd llows more )exiilityF X sn ddition to using the logil nme or the fullyEquli(ed lss nmeD ymfony supports third wy of referring to ontrollerF his method uses just one olon seprtor @eFgF servienmeXindexetionA nd refers to the ontroller s servie @see row to de(ne gontrollers s erviesAF

SFTF outing

IIS

ymfony houmenttionD PFH


5.6.5 Route Parameters and Controller Arguments

he route prmeters @eFgF {slug}A re espeilly importnt euse eh is mde ville s n rgument to the ontroller methodX

public function showAction($slug) { // ... }


sn relityD the entire defults olletion is merged with the prmeter vlues to form single rryF ih key of tht rry is ville s n rgument on the ontrollerF sn other wordsD for eh rgument of your ontroller methodD ymfony looks for route prmeter of tht nme nd ssigns its vlue to tht rgumentF sn the dvned exmple oveD ny omintion @in ny orderA of the following vriles ould e used s rguments to the showetion@A methodX

6ulture 6yer 6title 6formt 6ontroller


ine the pleholders nd defults olletion re merged togetherD even the 6ontroller vrile is villeF por more detiled disussionD see oute rmeters s gontroller ergumentsF X ou n lso use speil 6route vrileD whih is set to the nme of the route tht ws mthedF

5.6.6 Including External Routing Resources

ell routes re loded vi single on(gurtion (le E usully ppGon(gGroutingFyml @see greting outes oveAF gommonlyD howeverD you9ll wnt to lod routes from other plesD like routing (le tht lives inside undleF his n e done y importing tht (leX

ewv

# app/cong/routing.yml acme_hello: resource: "@AcmeHelloBundle/Resources/cong/routing.yml"


wv
IIT SF

ymfony houmenttionD PFH

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <import resource="@AcmeHelloBundle/Resources/cong/routing.xml" /> </routes>


r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection(); $collection->addCollection($loader->import("@AcmeHelloBundle/Resources/cong/routing.php")); return $collection;


X hen importing resoures from ewvD the key @eFgF mehelloA is meninglessF tust e sure tht it9s unique so no other lines override itF he resoure key lods the given routing resoureF sn this exmple the resoure is the full pth to (leD where the demerellofundle shortut syntx resolves to the pth of tht undleF he imported (le might look like thisX

ewv

# src/Acme/HelloBundle/Resources/cong/routing.yml acme_hello: pattern: /hello/{name} defaults: { _controller: AcmeHelloBundle:Hello:index }


wv

<!-- src/Acme/HelloBundle/Resources/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="acme_hello" pattern="/hello/{name}"> <default key="_controller">AcmeHelloBundle:Hello:index</default> </route> </routes>
SFTF outing IIU

ymfony houmenttionD PFH

// src/Acme/HelloBundle/Resources/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('acme_hello', new Route('/hello/{name}', array( '_controller' => 'AcmeHelloBundle:Hello:index', ))); return $collection;
he routes from this (le re prsed nd loded in the sme wy s the min routing (leF re(xing smported outes ou n lso hoose to provide pre(x for the imported routesF por exmpleD suppose you wnt the mehello route to hve (nl pttern of GdminGhelloG{nme} insted of simply GhelloG{nme}X

ewv

# app/cong/routing.yml acme_hello: resource: "@AcmeHelloBundle/Resources/cong/routing.yml" prex: /admin


wv

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <import resource="@AcmeHelloBundle/Resources/cong/routing.xml" prex="/admin" /> </routes>
r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection();


IIV SF

ymfony houmenttionD PFH

$collection->addCollection($loader->import("@AcmeHelloBundle/Resources/cong/routing.php"), '/admin return $collection;


he string Gdmin will now e prepended to the pttern of eh route loded from the new routing resoureF
5.6.7 Visualizing & Debugging Routes

hile dding nd ustomizing routesD it9s helpful to e le to visulize nd get detiled informtion out your routesF e gret wy to see every route in your pplition is vi the routerXdeug onsole ommndF ixeute the ommnd y running the following from the root of your projetF

php app/console router:debug


he ommnd will print helpful list of ll the on(gured routes in your pplitionX

homepage ANY / contact GET /contact contact_process POST /contact article_show ANY /articles/{culture}/{year}/{title}.{_format} blog ANY /blog/{page} blog_show ANY /blog/{slug}
ou n lso get very spei( informtion on single route y inluding the route nme fter the ommndX

php app/console router:debug article_show

5.6.8 Generating URLs

he routing system should lso e used to generte vsF sn relityD routing is iE diretionl systemX mpping the v to ontrollerCprmeters nd routeCprmeters k to vF he XmethodXymfonygomponentoutingouterXXmth nd XmethodXymfonygomponentoutingouterXXgenerte methods form this iE diretionl systemF ke the logshow exmple route from erlierX

$params = $router->match('/blog/my-blog-post'); // array('slug' => 'my-blog-post', '_controller' => 'AcmeBlogBundle:Blog:show') $uri = $router->generate('blog_show', array('slug' => 'my-blog-post')); // /blog/my-blog-post

SFTF outing

IIW

ymfony houmenttionD PFH o generte vD you need to speify the nme of the route @eFgF logshowA nd ny wildrds @eFgF slug a myElogEpostA used in the pttern for tht routeF ith this informtionD ny v n esily e genertedX

class MainController extends Controller { public function showAction($slug) { // ... } $url = $this->get('router')->generate('blog_show', array('slug' => 'my-blog-post'));

sn n upoming setionD you9ll lern how to generte vs from inside templtesF qenerting esolute vs fy defultD the router will generte reltive vs @eFgF GlogAF o generte n solute vD simply pss true to the third rgument of the generte@A methodX

$router->generate('blog_show', array('slug' => 'my-blog-post'), true); // http://www.example.com/blog/my-blog-post


X he host tht9s used when generting n solute v is the host of the urrent equest ojetF his is deteted utomtilly sed on server informtion supplied y rF hen generting solute vs for sripts run from the ommnd lineD you9ll need to mnully set the desired host on the equest ojetX

$request->headers->set('HOST', 'www.example.com');

qenerting vs with uery trings he generte method tkes n rry of wildrd vlues to generte the sF fut if you pss extr onesD they will e dded to the s s query stringX

$router->generate('blog', array('page' => 2, 'category' => 'Symfony')); // /blog/2?category=Symfony


qenerting vs from templte he most ommon ple to generte v is from within templte when linking etween pges in your pplitionF his is done just s eforeD ut using templte helper funtionX IPH SF

ymfony houmenttionD PFH

wig

<a href="{{ path('blog_show', { 'slug': 'my-blog-post' }) }}"> Read this blog post. </a>
r

<a href="<?php echo $view['router']->generate('blog_show', array('slug' => 'my-blog-post')) ?>"> Read this blog post. </a>
esolute vs n lso e genertedF

wig

<a href="{{ url('blog_show', { 'slug': 'my-blog-post' }) }}"> Read this blog post. </a>
r

<a href="<?php echo $view['router']->generate('blog_show', array('slug' => 'my-blog-post'), true) ?>"> Read this blog post. </a>

5.6.9 Summary

outing is system for mpping the v of inoming requests to the ontroller funtion tht should e lled to proess the requestF st oth llows you to speify eutiful vs nd keeps the funtionlity of your pplition deoupled from those vsF outing is twoEwy mehnismD mening tht it should lso e used to generte vsF
5.6.10 Learn more from the Cookbook

row to fore routes to lwys use r

5.7 Creating and using Templates

es you knowD the ontroller is responsile for hndling eh request tht omes into ymfonyP pplitionF sn relityD the ontroller delegtes the most of the hevy work to other ples so tht ode n e tested nd reusedF hen ontroller needs to generte rwvD g or ny other ontentD it hnds the work o' to the templting engineF sn this hpterD you9ll lern how to write powerful templtes tht n e used to return ontent SFUF greting nd using empltes IPI

ymfony houmenttionD PFH to the userD populte emil odiesD nd moreF ou9ll lern shortutsD lever wys to extend templtes nd how to reuse templte odeF
5.7.1 Templates

e templte is simply text (le tht n generte ny textEsed formt @rwvD wvD gD ve FFFAF he most fmilir type of templte is r templte E text (le prsed y r tht ontins mix of text nd r odeX

<!DOCTYPE html> <html> <head> <title>Welcome to Symfony!</title> </head> <body> <h1><?php echo $page_title ?></h1> <ul id="navigation"> <?php foreach ($navigation as $item): ?> <li> <a href="<?php echo $item->getHref() ?>"> <?php echo $item->getCaption() ?> </a> </li> <?php endforeach; ?> </ul> </body> </html>
fut ymfonyP pkges n even more powerful templting lnguge lled wigF wig llows you to write oniseD redle templtes tht re more friendly to we designers ndD in severl wysD more powerful thn r templtesX

<!DOCTYPE html> <html> <head> <title>Welcome to Symfony!</title> </head> <body> <h1>{{ page_title }}</h1> <ul id="navigation"> {% for item in navigation %} <li><a href="{{ item.href }}">{{ item.caption }}</a></li> {% endfor %} </ul>
IPP SF

ymfony houmenttionD PFH

</body> </html>
wig de(nes two types of speil syntxX

{{ FFF }}X ys somethingX prints vrile or the result of n expression to the templteY {7 FFF 7}X hoes somethingX tg tht ontrols the logi of the templteY it is used to exeute sttements suh s forEloops for exmpleF
X here is third syntx used for reting ommentsX {5 this is omment 5}F his syntx n e used ross multiple lines like the rEequivlent GB omment BG syntxF wig lso ontins (ltersD whih modify ontent efore eing renderedF he following mkes the title vrile ll upperse efore rendering itX

{{ title | upper }}
wig omes with long list of tgs nd (lters tht re ville y defultF ou n even dd your own extensions to wig s neededF X egistering wig extension is s esy s reting new servie nd tgging it with twigFextension tgF es you9ll see throughout the doumenttionD wig lso supports funtions nd new funtions n e esily ddedF por exmpleD the following uses stndrd for tg nd the yle funtion to print ten div tgsD with lternting oddD even lssesX

{% for i in 0..10 %} <div class="{{ cycle(['odd', 'even'], i) }}"> <!-- some HTML here --> </div> {% endfor %}
hroughout this hpterD templte exmples will e shown in oth wig nd rF

SFUF greting nd using empltes

IPQ

ymfony houmenttionD PFH hy wigc wig templtes re ment to e simple nd won9t proess r tgsF his is y designX the wig templte system is ment to express presenttionD not progrm logiF he more you use wigD the more you9ll ppreite nd ene(t from this distintionF end of ourseD you9ll e loved y we designers everywhereF wig n lso do things tht r n9tD suh s true templte inheritne @wig templtes ompile down to r lsses tht inherit from eh otherAD whitespe ontrolD sndoxingD nd the inlusion of ustom funtions nd (lters tht only 'et templtesF wig ontins little fetures tht mke writing templtes esier nd more oniseF ke the following exmpleD whih omines loop with logil if sttementX

<ul> {% for user in users %} <li>{{ user.username }}</li> {% else %} <li>No users found</li> {% endfor %} </ul>

wig emplte ghing wig is fstF ih wig templte is ompiled down to ntive r lss tht is rendered t runtimeF he ompiled lsses re loted in the ppGheG{environment}Gtwig diretory @where {environment} is the environmentD suh s dev or prodA nd in some ses n e useful while deuggingF ee for more informtion on environmentsF hen deug mode is enled @ommon in the dev environmentAD wig templte will e utomtilly reompiled when hnges re mde to itF his mens tht during development you n hppily mke hnges to wig templte nd instntly see the hnges without needing to worry out lering ny heF hen deug mode is disled @ommon in the prod environmentAD howeverD you must ler the wig he diretory so tht the wig templtes will regenerteF ememer to do this when deploying your pplitionF
5.7.2 Template Inheritance and Layouts

wore often thn notD templtes in projet shre ommon elementsD like the hederD footerD sider or moreF sn ymfonyPD we like to think out this prolem di'erentlyX templte n e deorted y nother oneF his works extly the sme s r lssesX templte inheritne llows you to uild se lyout templte tht ontins ll the ommon elements of your site de(ned s loks @think r lss with se methodsAF e hild

IPR

SF

ymfony houmenttionD PFH templte n extend the se lyout nd override ny of its loks @think r sulss tht overrides ertin methods of its prent lssAF pirstD uild se lyout (leX

wig

{# app/Resources/views/base.html.twig #} <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>{% block title %}Test Application{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block body %}{% endblock %} </div> </body> </html>
r

<!-- app/Resources/views/base.html.php --> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php $view['slots']->output('title', 'Test Application') ?></title> </head> <body> <div id="sidebar"> <?php if ($view['slots']->has('sidebar'): ?> <?php $view['slots']->output('sidebar') ?> <?php else: ?> <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> <?php endif; ?>
SFUF greting nd using empltes IPS

ymfony houmenttionD PFH

</div> <div id="content"> <?php $view['slots']->output('body') ?> </div> </body> </html>


X hough the disussion out templte inheritne will e in terms of wigD the philosophy is the sme etween wig nd r templtesF his templte de(nes the se rwv skeleton doument of simple twoEolumn pgeF sn this exmpleD three {7 lok 7} res re de(ned @titleD sider nd odyAF ih lok my e overridden y hild templte or left with its defult implementtionF his templte ould lso e rendered diretlyF sn tht se the titleD sider nd ody loks would simply retin the defult vlues used in this templteF e hild templte might look like thisX

wig

{# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {% extends '::base.html.twig' %} {% block title %}My cool blog posts{% endblock %} {% block body %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
r

<!-- src/Acme/BlogBundle/Resources/views/Blog/index.html.php --> <?php $view->extend('::base.html.php') ?> <?php $view['slots']->set('title', 'My cool blog posts') ?> <?php $view['slots']->start('body') ?> <?php foreach ($blog_entries as $entry): ?> <h2><?php echo $entry->getTitle() ?></h2> <p><?php echo $entry->getBody() ?></p> <?php endforeach; ?> <?php $view['slots']->stop() ?>
IPT SF

ymfony houmenttionD PFH

X he prent templte is identi(ed y speil string syntx @XXseFhtmlFtwigA tht indites tht the templte lives in the ppGesouresGviews diretory of the projetF his nming onvention is explined fully in emplte xming nd votionsF he key to templte inheritne is the {7 extends 7} tgF his tells the templting engine to (rst evlute the se templteD whih sets up the lyout nd de(nes severl loksF he hild templte is then renderedD t whih point the title nd ody loks of the prent re repled y those from the hildF hepending on the vlue of logentriesD the output might look like thisX

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>My cool blog posts</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> </div> <div id="content"> <h2>My rst post</h2> <p>The body of the rst post.</p> <h2>Another post</h2> <p>The body of the second post.</p> </div> </body> </html>
xotie tht sine the hild templte didn9t de(ne sider lokD the vlue from the prent templte is used instedF gontent within {7 lok 7} tg in prent templte is lwys used y defultF ou n use s mny levels of inheritne s you wntF sn the next setionD ommon threeE level inheritne model will e explined long with how templtes re orgnized inside ymfonyP projetF hen working with templte inheritneD here re some tips to keep in mindX

sf you use {7 extends 7} in templteD it must e the (rst tg in tht templteF he more {7 lok 7} tgs you hve in your se templtesD the etterF ememerD
SFUF greting nd using empltes IPU

ymfony houmenttionD PFH hild templtes don9t hve to de(ne ll prent loksD so rete s mny loks in your se templtes s you wnt nd give eh sensile defultF he more loks your se templtes hveD the more )exile your lyout will eF

sf you (nd yourself dupliting ontent in numer of templtesD it proly mens you should move tht ontent to {7 lok 7} in prent templteF sn some sesD etter solution my e to move the ontent to new templte nd inlude it @see snluding other empltesAF sf you need to get the ontent of lok from the prent templteD you n use the {{ prent@A }} funtionF his is useful if you wnt to dd to the ontents of prent lok insted of ompletely overriding itX

{% block sidebar %} <h3>Table of Contents</h3> ... {{ parent() }} {% endblock %}

5.7.3 Template Naming and Locations

fy defultD templtes n live in two di'erent lotionsX

ppGesouresGviewsGX he pplitions views diretory n ontin pplitionEwide se templtes @iFeF your pplition9s lyoutsA s well s templtes tht override undle templtes @see yverriding fundle empltesAY pthGtoGundleGesouresGviewsGX ih undle houses its templtes in its esouresGviews diretory @nd sudiretoriesAF he mjority of templtes will live inside undleF
ymfonyP uses undleXontrollerXtemplte string syntx for templtesF his llows for severl di'erent types of templtesD eh whih lives in spei( lotionX

emeflogfundleXflogXindexFhtmlFtwigX his syntx is used to speify templte for spei( pgeF he three prts of the stringD eh seprted y olon @XAD men the followingX
! emeflogfundleX @undleA the templte lives inside the emeflogfundle @eFgF srGemeGflogfundleAY ! flogX @ontrollerA indites tht the templte lives inside the flog sudiretory of esouresGviewsY ! indexFhtmlFtwigX @templteA the tul nme of the (le is indexFhtmlFtwigF essuming tht the emeflogfundle lives t srGemeGflogfundleD the (nl pth to the lyout would e srGemeGflogfundleGesouresGviewsGflogGindexFhtmlFtwigF

IPV

SF

ymfony houmenttionD PFH

emeflogfundleXXlyoutFhtmlFtwigX his syntx refers to se templte tht9s spei( to the emeflogfundleF ine the middleD ontrollerD portion is missing @eFgF flogAD the templte lives t esouresGviewsGlyoutFhtmlFtwig inside emeflogfundleF XXseFhtmlFtwigX his syntx refers to n pplitionEwide se templte or lyoutF xotie tht the string egins with two olons @XXAD mening tht oth the undle nd ontroller portions re missingF his mens tht the templte is not loted in ny undleD ut insted in the root ppGesouresGviewsG diretoryF
sn the yverriding fundle empltes setionD you9ll (nd out how eh templte living inside the emeflogfundleD for exmpleD n e overridden y pling templte of the sme nme in the ppGesouresGemeflogfundleGviewsG diretoryF his gives the power to override templtes from ny vendor undleF X ropefully the templte nming syntx looks fmilir E it9s the sme nming onvention used to refer to gontroller xming tternF

emplte u0x he undleXontrollerXtemplte formt of eh templte spei(es where the templte (le is lotedF ivery templte nme lso hs two extensions tht speify the formt nd engine for tht templteF

emeflogfundleXflogXindexFhtmlFtwig E rwv formtD wig engine emeflogfundleXflogXindexFhtmlFphp E rwv formtD r engine emeflogfundleXflogXindexFssFtwig E g formtD wig engine
fy defultD ny ymfonyP templte n e written in either wig or rD nd the lst prt of the extension @eFgF Ftwig or FphpA spei(es whih of these two engines should e usedF he (rst prt of the extensionD @eFgF FhtmlD FssD etA is the (nl formt tht the templte will generteF nlike the engineD whih determines how ymfonyP prses the templteD this is simply n orgniztionl tti used in se the sme resoure needs to e rendered s rwv @indexFhtmlFtwigAD wv @indexFxmlFtwigAD or ny other formtF por more informtionD red the emplte pormts setionF X he ville engines n e on(gured nd even new engines ddedF ee emplting gon(gurtion for more detilsF

5.7.4 Tags and Helpers

ou lredy understnd the sis of templtesD how they9re nmed nd how to use templte inheritneF he hrdest prts re lredy ehind youF sn this setionD you9ll lern out SFUF greting nd using empltes IPW

ymfony houmenttionD PFH lrge group of tools ville to help perform the most ommon templte tsks suh s inluding other templtesD linking to pges nd inluding imgesF ymfonyP omes undled with severl speilized wig tgs nd funtions tht ese the work of the templte designerF sn rD the templting system provides n extensile helper system tht provides useful fetures in templte ontextF e9ve lredy seen few uiltEin wig tgs @{7 lok 7} 8 {7 extends 7}A s well s n exmple of r helper @6view9slots9AF vet9s lern few moreF snluding other empltes ou9ll often wnt to inlude the sme templte or ode frgment on severl di'erent pgesF por exmpleD in n pplition with news rtilesD the templte ode displying n rtile might e used on the rtile detil pgeD on pge displying the most populr rtilesD or in list of the ltest rtilesF hen you need to reuse hunk of r odeD you typilly move the ode to new r lss or funtionF he sme is true for templtesF fy moving the reused templte ode into its own templteD it n e inluded from ny other templteF pirstD rete the templte tht you9ll need to reuseF

wig

{# src/Acme/ArticleBundle/Resources/views/Article/articleDetails.html.twig #} <h1>{{ article.title }}</h1> <h3 class="byline">by {{ article.authorName }}</h3> <p> {{ article.body }} </p>
r

<!-- src/Acme/ArticleBundle/Resources/views/Article/articleDetails.html.php --> <h2><?php echo $article->getTitle() ?></h2> <h3 class="byline">by <?php echo $article->getAuthorName() ?></h3> <p> <?php echo $article->getBody() ?> </p>
snluding this templte from ny other templte is simpleX

wig

{# src/Acme/ArticleBundle/Resources/Article/list.html.twig #} {% extends 'AcmeArticleBundle::layout.html.twig' %}


IQH SF

ymfony houmenttionD PFH

{% block body %} <h1>Recent Articles<h1> {% for article in articles %} {% include 'AcmeArticleBundle:Article:articleDetails.html.twig' with {'article': article} %} {% endfor %} {% endblock %}
r

<!-- src/Acme/ArticleBundle/Resources/Article/list.html.php --> <?php $view->extend('AcmeArticleBundle::layout.html.php') ?> <?php $view['slots']->start('body') ?> <h1>Recent Articles</h1>

<?php foreach ($articles as $article): ?> <?php echo $view->render('AcmeArticleBundle:Article:articleDetails.html.php', array('article' => $a <?php endforeach; ?> <?php $view['slots']->stop() ?>
he templte is inluded using the {7 inlude 7} tgF xotie tht the templte nme follows the sme typil onventionF he rtilehetilsFhtmlFtwig templte uses n rtile vrileF his is pssed in y the listFhtmlFtwig templte using the with ommndF X he {9rtile9X rtile} syntx is the stndrd wig syntx for hsh mps @iFeF n rry with nmed keysAF sf we needed to pss in multiple elementsD it would look like thisX {9foo9X fooD 9r9X r}F

imedding gontrollers sn some sesD you need to do more thn inlude simple templteF uppose you hve sider in your lyout tht ontins the three most reent rtilesF etrieving the three rtiles my inlude querying the dtse or performing other hevy logi tht n9t e done from within templteF he solution is to simply emed the result of n entire ontroller from your templteF pirstD rete ontroller tht renders ertin numer of reent rtilesX

// src/Acme/ArticleBundle/Controller/ArticleController.php class ArticleController extends Controller { public function recentArticlesAction($max = 3) {


SFUF greting nd using empltes IQI

ymfony houmenttionD PFH

// make a database call or other logic to get the "$max" most recent articles $articles = ...; } return $this->render('AcmeArticleBundle:Article:recentList.html.twig', array('articles' => $articles));

he reentvist templte is perfetly strightforwrdX

wig

{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {% for article in articles %} <a href="/article/{{ article.slug }}"> {{ article.title }} </a> {% endfor %}
r

<!-- src/Acme/ArticleBundle/Resources/views/Article/recentList.html.php --> <?php foreach ($articles in $article): ?> <a href="/article/<?php echo $article->getSlug() ?>"> <?php echo $article->getTitle() ?> </a> <?php endforeach; ?>
X xotie tht we9ve heted nd hrdoded the rtile v in this exmple @eFgF GrtileGBslugBAF his is d prtieF sn the next setionD you9ll lern how to do this orretlyF o inlude the ontrollerD you9ll need to refer to it using the stndrd string syntx for ontrollers @iFeF undleXontrollerXtionAX

wig

{# app/Resources/views/base.html.twig #} ... <div id="sidebar"> {% render "AcmeArticleBundle:Article:recentArticles" with {'max': 3} %} </div>


r

<!-- app/Resources/views/base.html.php --> ...


IQP SF

ymfony houmenttionD PFH

<div id="sidebar"> <?php echo $view['actions']->render('AcmeArticleBundle:Article:recentArticles', array('max' => 3)) ?> </div>
henever you (nd tht you need vrile or piee of informtion tht you don9t hve ess to in templteD onsider rendering ontrollerF gontrollers re fst to exeute nd promote good ode orgniztion nd reuseF vinking to ges greting links to other pges in your pplition is one of the most ommon jos for templteF snsted of hrdoding vs in templtesD use the pth wig funtion @or the router helper in rA to generte vs sed on the routing on(gurtionF vterD if you wnt to modify the v of prtiulr pgeD ll you9ll need to do is hnge the routing on(gurtionY the templtes will utomtilly generte the new vF pirstD link to the welome pgeD whih is essile vi the following routing on(gurtionX

ewv

_welcome: pattern: / defaults: { _controller: AcmeDemoBundle:Welcome:index }


wv

<route id="_welcome" pattern="/"> <default key="_controller">AcmeDemoBundle:Welcome:index</default> </route>


r

$collection = new RouteCollection(); $collection->add('_welcome', new Route('/', array( '_controller' => 'AcmeDemoBundle:Welcome:index', ))); return $collection;
o link to the pgeD just use the pth wig funtion nd refer to the routeX

wig

<a href="{{ path('_welcome') }}">Home</a>


r

SFUF greting nd using empltes

IQQ

ymfony houmenttionD PFH

<a href="<?php echo $view['router']->generate('_welcome') ?>">Home</a>


es expetedD this will generte the v GF vet9s see how this works with more omplited routeX

ewv

article_show: pattern: /article/{slug} defaults: { _controller: AcmeArticleBundle:Article:show }


wv

<route id="article_show" pattern="/article/{slug}"> <default key="_controller">AcmeArticleBundle:Article:show</default> </route>


r

$collection = new RouteCollection(); $collection->add('article_show', new Route('/article/{slug}', array( '_controller' => 'AcmeArticleBundle:Article:show', ))); return $collection;
sn this seD you need to speify oth the route nme @rtileshowA nd vlue for the {slug} prmeterF sing this routeD let9s revisit the reentvist templte from the previous setion nd link to the rtiles orretlyX

wig

{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {% for article in articles %} <a href="{{ path('article_show', { 'slug': article.slug }) }}"> {{ article.title }} </a> {% endfor %}
r

<!-- src/Acme/ArticleBundle/Resources/views/Article/recentList.html.php --> <?php foreach ($articles in $article): ?> <a href="<?php echo $view['router']->generate('article_show', array('slug' => $article->getSlug()) ?> <?php echo $article->getTitle() ?> </a> <?php endforeach; ?>

IQR

SF

ymfony houmenttionD PFH X ou n lso generte n solute v y using the url wig funtionX

<a href="{{ url('_welcome') }}">Home</a>


he sme n e done in r templtes y pssing third rgument to the generte@A methodX

<a href="<?php echo $view['router']->generate('_welcome', array(), true) ?>">Home</a>

vinking to essets empltes lso ommonly refer to imgesD tvsriptD stylesheets nd other ssetsF yf ourse you ould hrdEode the pth to these ssets @eFgF GimgesGlogoFpngAD ut ymfonyP provides more dynmi option vi the ssets wig funtionX

wig

<img src="{{ asset('images/logo.png') }}" alt="Symfony!" /> <link href="{{ asset('css/blog.css') }}" rel="stylesheet" type="text/css" />
r

<img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" alt="Symfony!" /> <link href="<?php echo $view['assets']->getUrl('css/blog.css') ?>" rel="stylesheet" type="text/css" />
he sset funtion9s min purpose is to mke your pplition more portleF sf your pplition lives t the root of your host @eFgF httpXGGexmpleFomAD then the rendered pths should e GimgesGlogoFpngF fut if your pplition lives in sudiretory @eFgF httpXGGexmpleFomGmyppAD eh sset pth should render with the sudiretory @eFgF GmyppGimgesGlogoFpngAF he sset funtion tkes re of this y determining how your pplition is eing used nd generting the orret pths ordinglyF edditionllyD if you use the sset funtionD ymfony n utomtilly ppend query string to your ssetD in order to gurntee tht updted stti ssets won9t e hed when deployedF por exmpleD GimgesGlogoFpng might look like GimgesGlogoFpngcvPF por more informtionD see the ssetsversion on(gurtion optionF
5.7.5 Including Stylesheets and Javascripts in Twig

xo site would e omplete without inluding tvsript (les nd stylesheetsF sn ymfonyD the inlusion of these ssets is hndled elegntly y tking dvntge of ymfony9s templte inheritneF

SFUF greting nd using empltes

IQS

ymfony houmenttionD PFH X his setion will teh you the philosophy ehind inluding stylesheet nd tvsript ssets in ymfonyF ymfony lso pkges nother lirryD lled essetiD whih follows this philosophy ut llows you to do muh more interesting things with those ssetsF por more informtion on using esseti see row to se esseti for esset wngementF trt y dding two loks to your se templte tht will hold your ssetsX one lled stylesheets inside the hed tg nd nother lled jvsripts just ove the losing ody tgF hese loks will ontin ll of the stylesheets nd tvsripts tht you9ll need throughout your siteX

{# 'app/Resources/views/base.html.twig' #} <html> <head> {# ... #} {% block stylesheets %} <link href="{{ asset('/css/main.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} </head> <body> {# ... #} {% block javascripts %} <script src="{{ asset('/js/main.js') }}" type="text/javascript"></script> {% endblock %} </body> </html>
ht9s esy enough3 fut wht if you need to inlude n extr stylesheet or tvsript from hild templtec por exmpleD suppose you hve ontt pge nd you need to inlude onttFss stylesheet just on tht pgeF prom inside tht ontt pge9s templteD do the followingX

{# src/Acme/DemoBundle/Resources/views/Contact/contact.html.twig #} {# extends '::base.html.twig' #} {% block stylesheets %} {{ parent() }} <link href="{{ asset('/css/contact.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} {# ... #}
sn the hild templteD you simply override the stylesheets lok nd put your new stylesheet tg inside of tht lokF yf ourseD sine you wnt to dd to the prent lok9s ontent @nd not tully reple itAD you should use the prent@A wig funtion to inlude everything IQT SF

ymfony houmenttionD PFH from the stylesheets lok of the se templteF he end result is pge tht inludes oth the minFss nd onttFss stylesheetsF
5.7.6 Conguring and using the templating Service

he hert of the templte system in ymfonyP is the templting ingineF his speil ojet is responsile for rendering templtes nd returning their ontentF hen you render templte in ontrollerD for exmpleD you9re tully using the templting engine servieF por exmpleX

return $this->render('AcmeArticleBundle:Article:index.html.twig');
is equivlent to

$engine = $this->container->get('templating'); $content = $engine->render('AcmeArticleBundle:Article:index.html.twig'); return $response = new Response($content);


he templting engine @or servieA is preon(gured to work utomtilly inside ymfonyPF st nD of ourseD e on(gured further in the pplition on(gurtion (leX

ewv

# app/cong/cong.yml framework: # ... templating: { engines: ['twig'] }


wv

<!-- app/cong/cong.xml --> <framework:templating> <framework:engine id="twig" /> </framework:templating>


r

// app/cong/cong.php $container->loadFromExtension('framework', array( // ... 'templating' => array( 'engines' => array('twig'), ), ));
everl on(gurtion options re ville nd re overed in the gon(gurtion eppendixF

SFUF greting nd using empltes

IQU

ymfony houmenttionD PFH X he twig engine is mndtory to use the wepro(ler @s well s mny thirdE prty undlesAF

5.7.7 Overriding Bundle Templates

he ymfonyP ommunity prides itself on reting nd mintining high qulity undles @see ymfonyPfundlesForgA for lrge numer of di'erent feturesF yne you use thirdEprty undleD you9ll likely need to override nd ustomize one or more of its templtesF uppose you9ve inluded the imginry openEsoure emeflogfundle in your projet @eFgF in the srGemeGflogfundle diretoryAF end while you9re relly hppy with everythingD you wnt to override the log list pge to ustomize the mrkup spei(lly for your pplitionF fy digging into the flog ontroller of the emeflogfundleD you (nd the followingX

public function indexAction() { $blogs = // some logic to retrieve the blogs } $this->render('AcmeBlogBundle:Blog:index.html.twig', array('blogs' => $blogs));

hen the emeflogfundleXflogXindexFhtmlFtwig is renderedD ymfonyP tully looks in two di'erent lotions for the templteX IF ppGesouresGemeflogfundleGviewsGflogGindexFhtmlFtwig PF srGemeGflogfundleGesouresGviewsGflogGindexFhtmlFtwig o override the undle templteD just opy the indexFhtmlFtwig templte from the undle to ppGesouresGemeflogfundleGviewsGflogGindexFhtmlFtwig @the ppGesouresGemeflogfundle diretory won9t existD so you9ll need to rete itAF ou9re now free to ustomize the templteF his logi lso pplies to se undle templtesF uppose lso tht eh templte in emeflogfundle inherits from se templte lled emeflogfundleXXlyoutFhtmlFtwigF tust s eforeD ymfonyP will look in the following two ples for the templteX IF ppGesouresGemeflogfundleGviewsGlyoutFhtmlFtwig PF srGemeGflogfundleGesouresGviewsGlyoutFhtmlFtwig yne ginD to override the templteD just opy it from the undle to ppGesouresGemeflogfundleGviewsGlyoutFhtmlFtwigF ou9re now free to ustomize this opy s you see (tF sf you tke step kD you9ll see tht ymfonyP lwys strts y looking in the ppGesouresG{fxhvixewi}GviewsG diretory for templteF sf the templte doesn9t exist thereD it ontinues y heking inside the esouresGviews diretory of the undle itselfF IQV SF

ymfony houmenttionD PFH his mens tht ll undle templtes n e overridden y pling them in the orret ppGesoures sudiretoryF yverriding gore empltes ine the ymfonyP frmework itself is just undleD ore templtes n e overridden in the sme wyF por exmpleD the ore wigfundle ontins numer of di'erent exeption nd error templtes tht n e overridden y opying eh from the esouresGviewsGixeption diretory of the wigfundle toD you guessed itD the ppGesouresGwigfundleGviewsGixeption diretoryF
5.7.8 Three-level Inheritance

yne ommon wy to use inheritne is to use threeElevel pprohF his method works perfetly with the three di'erent types of templtes we9ve just overedX

grete ppGesouresGviewsGseFhtmlFtwig (le tht ontins the min lyout for your pplition @like in the previous exmpleAF snternllyD this templte is lled XXseFhtmlFtwigY grete templte for eh setion of your siteF por exmpleD n emeflogfundleD would hve templte lled emeflogfundleXXlyoutFhtmlFtwig tht ontins only log setionEspei( elementsY

{# src/Acme/BlogBundle/Resources/views/layout.html.twig #} {% extends '::base.html.twig' %} {% block body %} <h1>Blog Application</h1> {% block content %}{% endblock %} {% endblock %}
grete individul templtes for eh pge nd mke eh extend the pproprite setion templteF por exmpleD the index pge would e lled something lose to emeflogfundleXflogXindexFhtmlFtwig nd list the tul log postsF

{# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {% extends 'AcmeBlogBundle::layout.html.twig' %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
SFUF greting nd using empltes IQW

ymfony houmenttionD PFH xotie tht this templte extends the setion templte E@emeflogfundleXXlyoutFhtmlFtwigA whih inEturn extends the se pplition lyout @XXseFhtmlFtwigAF his is the ommon threeElevel inheritne modelF hen uilding your pplitionD you my hoose to follow this method or simply mke eh pge templte extend the se pplition templte diretly @eFgF {7 extends 9XXseFhtmlFtwig9 7}AF he threeEtemplte model is estEprtie method used y vendor undles so tht the se templte for undle n e esily overridden to properly extend your pplition9s se lyoutF
5.7.9 Output Escaping

hen generting rwv from templteD there is lwys risk tht templte vrile my output unintended rwv or dngerous lientEside odeF he result is tht dynmi ontent ould rek the rwv of the resulting pge or llow mliious user to perform gross ite ripting @A ttkF gonsider this lssi exmpleX

wig

Hello {{ name }}
r

Hello <?php echo $name ?>


smgine tht the user enters the following ode s hisGher nmeX

<script>alert('hello!')</script>
ithout ny output espingD the resulting templte will use tvript lert ox to pop upX

Hello <script>alert('hello!')</script>
end while this seems hrmlessD if user n get this frD tht sme user should lso e le to write tvript tht performs mliious tions inside the seure re of n unknowingD legitimte userF he nswer to the prolem is output espingF ith output esping onD the sme templte will render hrmlesslyD nd literlly print the sript tg to the sreenX

Hello &lt;script&gt;alert(&#39;helloe&#39;)&lt;/script&gt;
he wig nd r templting systems pproh the prolem in di'erent wysF sf you9re using wigD output esping is on y defult nd you9re protetedF sn rD output esping is not utomtiD mening you9ll need to mnully espe where neessryF

IRH

SF

ymfony houmenttionD PFH yutput isping in wig sf you9re using wig templtesD then output esping is on y defultF his mens tht you9re proteted outEofEtheEox from the unintentionl onsequenes of userEsumitted odeF fy defultD the output esping ssumes tht ontent is eing esped for rwv outputF sn some sesD you9ll need to disle output esping when you9re rendering vrile tht is trusted nd ontins mrkup tht should not e espedF uppose tht dministrtive users re le to write rtiles tht ontin rwv odeF fy defultD wig will espe the rtile odyF o render it normllyD dd the rw (lterX {{ rtileFody | rw }}F ou n lso disle output esping inside {7 lok 7} re or for n entire templteF por more informtionD see yutput isping in the wig doumenttionF yutput isping in r yutput esping is not utomti when using r templtesF his mens tht unless you expliitly hoose to espe vrileD you9re not protetedF o use output espingD use the speil espe@A view methodX

Hello <?php echo $view->escape($name) ?>


fy defultD the espe@A method ssumes tht the vrile is eing rendered within n rwv ontext @nd thus the vrile is esped to e sfe for rwvAF he seond rgument lets you hnge the ontextF por exmpleD to output something in tvript stringD use the js ontextX

var myMsg = 'Hello <?php echo $view->escape($name, 'js') ?>';

5.7.10 Template Formats

empltes re generi wy to render ontent in ny formtF end while in most ses you9ll use templtes to render rwv ontentD templte n just s esily generte tvriptD gD wv or ny other formt you n drem ofF por exmpleD the sme resoure is often rendered in severl di'erent formtsF o render n rtile index pge in wvD simply inlude the formt in the templte nmeX

wv templte nmeX emeertilefundleXertileXindexFxmlFtwig wv templte (lenmeX indexFxmlFtwig


sn relityD this is nothing more thn nming onvention nd the templte isn9t tully rendered di'erently sed on its formtF sn mny sesD you my wnt to llow single ontroller to render multiple di'erent formts sed on the request formtF por tht resonD ommon pttern is to do the followingX SFUF greting nd using empltes IRI

ymfony houmenttionD PFH

public function indexAction() { $format = $this->getRequest()->getRequestFormat(); } return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig');

he getequestpormt on the equest ojet defults to htmlD ut n return ny other formt sed on the formt requested y the userF he request formt is most often mnged y the routingD where route n e on(gured so tht Gontt sets the request formt to html while GonttFxml sets the formt to xmlF por more informtionD see the edvned ixmple in the outing hpterF o rete links tht inlude the formt prmeterD inlude formt key in the prmeter hshX

wig

<a href="{{ path('article_show', {'id': 123, '_format': 'pdf'}) }}"> PDF Version </a>
r

<a href="<?php echo $view['router']->generate('article_show', array('id' => 123, '_format' => 'pdf')) ?> PDF Version </a>

5.7.11 Final Thoughts

he templting engine in ymfony is powerful tool tht n e used eh time you need to generte presenttionl ontent in rwvD wv or ny other formtF end though templtes re ommon wy to generte ontent in ontrollerD their use is not mndtoryF he esponse ojet returned y ontroller n e reted with our without the use of templteX

// creates a Response object whose content is the rendered template $response = $this->render('AcmeArticleBundle:Article:index.html.twig'); // creates a Response object whose content is simple text $response = new Response('response content');
ymfony9s templting engine is very )exile nd two di'erent templte renderers re ville y defultX the trditionl r templtes nd the sleek nd powerful wig templtesF foth support templte hierrhy nd ome pkged with rih set of helper funtions ple of performing the most ommon tsksF IRP SF

ymfony houmenttionD PFH yverllD the topi of templting should e thought of s powerful tool tht9s t your disposlF sn some sesD you my not need to render templteD nd in ymfonyPD tht9s solutely (neF
5.7.12 Learn more from the Cookbook

row to use r insted of wig for empltes

5.8 Doctrine ()

D E F D ymfony hotrineD D E D F hotrine F X hotrine F hotrine ywD @ wyvD ostgrev wirosoft vAF D row to use hotrine9s hfev vyer F wongohf hotrine yhwF GundlesGhotrinewongohffundleGindexF

5.8.1 :

D hotrine E E F D rodutD F emetorefundleX

php app/console generate:bundle --namespace=Acme/StoreBundle

SFVF hotrine @A

IRQ

ymfony houmenttionD PFH F ppGon(gGprmetersFiniX

;app/cong/parameters.ini [parameters] database_driver = pdo_mysql database_host = localhost database_name = test_project database_user = root database_password = password
X prmetersFini F E D D hotrineX

doctrine: dbal: driver: %database_driver% host: %database_host% dbname: %database_name% user: %database_user% password: %database_password%
D E F @ A D E D epheF row to et ixternl rmeters in the ervie gontinerF hotrine D X

php app/console doctrine:database:create


@entityA D D F hotrine D rodut F intity emetorefundleX

// src/Acme/StoreBundle/Entity/Product.php namespace Acme\StoreBundle\Entity;

IRR

SF

ymfony houmenttionD PFH

class Product { protected $name; protected $price; } protected $description;

E D D E E E F E rEF X hotrineD hotrine X

php app/console doctrine:generate:entity --entity="AcmeStoreBundle:Product" --elds="name:string(255) price:

hotrine D F D hotrine F rE X

hotrineD  D hotrine rodut F D ewvD wv rodut X X e undle n ept only one metdt de(nition formtF por exmpleD it9s not possile to mix ewv metdt de(nitions with nnotted r entity lss de(nitionsF SFVF hotrine @A IRS

ymfony houmenttionD PFH

ennottions

// src/Acme/StoreBundle/Entity/Product.php namespace Acme\StoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="product") */ class Product { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @ORM\Column(type="string", length=100) */ protected $name; /** * @ORM\Column(type="decimal", scale=2) */ protected $price; /** * @ORM\Column(type="text") */ protected $description;

ewv

# src/Acme/StoreBundle/Resources/cong/doctrine/Product.orm.yml Acme\StoreBundle\Entity\Product: type: entity table: product id: id: type: integer generator: { strategy: AUTO }
IRT SF

ymfony houmenttionD PFH

elds: name: type: string length: 100 price: type: decimal scale: 2 description: type: text
wv

<!-- src/Acme/StoreBundle/Resources/cong/doctrine/Product.orm.xml --> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Acme\StoreBundle\Entity\Product" table="product"> <id name="id" type="integer" column="id"> <generator strategy="AUTO" /> </id> <eld name="name" column="name" type="string" length="100" /> <eld name="price" column="price" type="decimal" scale="2" /> <eld name="description" column="description" type="text" /> </entity> </doctrine-mapping>
X tle D FF hotrine llows you to hoose from wide vriety of di'erent (eld typesD eh with their own optionsF por informtion on the ville (eld typesD see the hotrine pield ypes eferene setionF FX ou n lso hek out hotrine9s fsi wpping houmenttion for ll detils out mpping informtionF sf you use nnottionsD you9ll need to prepend ll nnottions with yw @eFgF ywgolumn@FFAAD whih is not shown in hotrine9s doumenttionF ou9ll lso need to inlude the use hotrineywwpping s ywY sttementD whih imports the yw nnottions pre(xF

SFVF hotrine @A

IRU

ymfony houmenttionD PFH X fe reful tht your lss nme nd properties ren9t mpped to proteted v keyword @suh s group or userAF por exmpleD if your entity lss nme is qroupD thenD y defultD your tle nme will e groupD whih will use n v error in some enginesF ee hotrine9s eserved v keywords doumenttion on how to properly espe these nmesF X hen using nother lirry or progrm @ieF hoxygenA tht uses nnottionsD you should ple the dsgnoreennottion nnottion on the lss to indite whih nnottions ymfony should ignoreF por exmpleD to prevent the dfn nnottion from throwing n exeptionD dd the followingX

/** * @IgnoreAnnotation("fn") */ class Product

qenerting qetters nd etters iven though hotrine now knows how to persist rodut ojet to the dtseD the lss itself isn9t relly useful yetF ine rodut is just regulr r lssD you need to rete getter nd setter methods @eFgF getxme@AD setxme@AA in order to ess its properties @sine the properties re protetedAF portuntelyD hotrine n do this for you y runningX

php app/console doctrine:generate:entities Acme/StoreBundle/Entity/Product


his ommnd mkes sure tht ll of the getters nd setters re generted for the rodut lssF his is sfe ommnd E you n run it over nd over ginX it only genertes getters nd setters tht don9t exist @iFeF it doesn9t reple your existing methodsAF X he dotrineXgenerteXentities ommnd sves kup of the originl rodutFphp nmed rodutFphp~F sn some sesD the presene of this (le n use gnnot redelre lss errorF st n e sfely removedF ou n lso generte ll known entities @iFeF ny r lss with hotrine mpping informtionA of undle or n entire nmespeX

php app/console doctrine:generate:entities AcmeStoreBundle php app/console doctrine:generate:entities Acme


X hotrine doesn9t re whether your properties re proteted or privteD or whether or not you hve getter or setter funtion for propertyF he getters nd setters re generted here only euse you9ll need them to intert with your r ojetF IRV SF

ymfony houmenttionD PFH

greting the htse lesGhem ou now hve usle rodut lss with mpping informtion so tht hotrine knows extly how to persist itF yf ourseD you don9t yet hve the orresponding produt tle in your dtseF portuntelyD hotrine n utomtilly rete ll the dtse tles needed for every known entity in your pplitionF o do thisD runX

php app/console doctrine:schema:update --force


X etullyD this ommnd is inredily powerfulF st ompres wht your dtse should look like @sed on the mpping informtion of your entitiesA with how it tully looksD nd genertes the v sttements needed to updte the dtse to where it should eF sn other wordsD if you dd new property with mpping metdt to rodut nd run this tsk ginD it will generte the lter tle sttement needed to dd tht new olumn to the existing produts tleF en even etter wy to tke dvntge of this funtionlity is vi migrtionsD whih llow you to generte these v sttements nd store them in migrtion lsses tht n e run systemtilly on your prodution server in order to trk nd migrte your dtse shem sfely nd relilyF our dtse now hs fullyEfuntionl produt tle with olumns tht mth the metdt you9ve spei(edF ersisting yjets to the htse xow tht you hve mpped rodut entity nd orresponding produt tleD you9re redy to persist dt to the dtseF prom inside ontrollerD this is pretty esyF edd the following method to the hefultgontroller of the undleX
1 2 3 4 5 6 7 8 9 10 11 12

// src/Acme/StoreBundle/Controller/DefaultController.php use Acme\StoreBundle\Entity\Product; use Symfony\Component\HttpFoundation\Response; // ... public function createAction() { $product = new Product(); $product->setName('A Foo Bar'); $product->setPrice('19.99'); $product->setDescription('Lorem ipsum dolor');

SFVF hotrine @A

IRW

ymfony houmenttionD PFH

13 14 15 16 17 18

$em = $this->getDoctrine()->getEntityManager(); $em->persist($product); $em->ush(); } return new Response('Created product id '.$product->getId());

X sf you9re following long with this exmpleD you9ll need to rete route tht points to this tion to see it in workF vet9s wlk through this exmpleX

lines VEII sn this setionD you instntite nd work with the 6produt ojet like ny otherD norml r ojetY line IQ his line fethes hotrine9s entity mnger ojetD whih is responsile for hndling the proess of persisting nd fething ojets to nd from the dtseY line IR he persist@A method tells hotrine to mnge the 6produt ojetF his does not tully use query to e mde to the dtse @yetAF line IS hen the )ush@A method is lledD hotrine looks through ll of the ojets tht it9s mnging to see if they need to e persisted to the dtseF sn this exmpleD the 6produt ojet hs not een persisted yetD so the entity mnger exeutes n sxi query nd row is reted in the produt tleF
X sn ftD sine hotrine is wre of ll your mnged entitiesD when you ll the )ush@A methodD it lultes n overll hngeset nd exeutes the most e0ient queryGqueries possileF por exmpleD if you persist totl of IHH rodut ojets nd then susequently ll )ush@AD hotrine will rete single prepred sttement nd reEuse it for eh insertF his pttern is lled nit of orkD nd it9s used euse it9s fst nd e0ientF hen reting or updting ojetsD the work)ow is lwys the smeF sn the next setionD you9ll see how hotrine is smrt enough to utomtilly issue n hei query if the reord lredy exists in the dtseF X hotrine provides lirry tht llows you to progrmmtilly lod testing dt into your projet @iFeF (xture dtAF por informtionD see GundlesGhotrinepixturesfundleGindexF

ISH

SF

ymfony houmenttionD PFH F D E rodut idX

public function showAction($id) { $product = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product') ->nd($id); if (!$product) { throw $this->createNotFoundException('No product found for id '.$id); } } // do something, like pass the $product object into a template

hen you query for prtiulr type of ojetD you lwys use wht9s known s its repositoryF ou n think of repository s r lss whose only jo is to help you feth entities of ertin lssF ou n ess the repository ojet for n entity lss viX

$repository = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product');


X he emetorefundleXrodut string is shortut you n use nywhere in hotrine insted of the full lss nme of the entity @iFeF emetorefundleintityrodutAF es long s your entity lives under the intity nmespe of your undleD this will workF yne you hve your repositoryD you hve ess to ll sorts of helpful methodsX

// query by the primary key (usually "id") $product = $repository->nd($id); // dynamic method names to nd based on a column value $product = $repository->ndOneById($id); $product = $repository->ndOneByName('foo'); // nd *all* products $products = $repository->ndAll(); // nd a group of products based on an arbitrary column value $products = $repository->ndByPrice(19.99);
X yf ourseD you n lso issue omplex queriesD whih you9ll lern more out in the uerying for yjets setionF SFVF hotrine @A ISI

ymfony houmenttionD PFH

ou n lso tke dvntge of the useful (ndfy nd (ndynefy methods to esily feth ojets sed on multiple onditionsX

// query for one product matching be name and price $product = $repository->ndOneBy(array('name' => 'foo', 'price' => 19.99)); // query for all products matching the name, ordered by price $product = $repository->ndBy( array('name' => 'foo'), array('price' => 'ASC') );
X hen you render ny pgeD you n see how mny queries were mde in the ottom right orner of the we deug toolrF

sf you lik the ionD the pro(ler will openD showing you the ext queries tht were mdeF

pdting n yjet yne you9ve fethed n ojet from hotrineD updting it is esyF uppose you hve route tht mps produt id to n updte tion in ontrollerX

public function updateAction($id) { $em = $this->getDoctrine()->getEntityManager(); $product = $em->getRepository('AcmeStoreBundle:Product')->nd($id); if (!$product) { throw $this->createNotFoundException('No product found for id '.$id); } $product->setName('New product name!'); $em->ush();
ISP SF

ymfony houmenttionD PFH

return $this->redirect($this->generateUrl('homepage'));

pdting n ojet involves just three stepsX IF fething the ojet from hotrineY PF modifying the ojetY QF lling )ush@A on the entity mnger xotie tht lling 6emEbpersist@6produtA isn9t neessryF ell tht this method simply tells hotrine to mnge or wth the 6produt ojetF sn this seD sine you fethed the 6produt ojet from hotrineD it9s lredy mngedF heleting n yjet heleting n ojet is very similrD ut requires ll to the remove@A method of the entity mngerX

$em->remove($product); $em->ush();
es you might expetD the remove@A method noti(es hotrine tht you9d like to remove the given entity from the dtseF he tul hivii queryD howeverD isn9t tully exeuted until the )ush@A method is lledF
5.8.2 Querying for Objects

ou9ve lredy seen how the repository ojet llows you to run si queries without ny workX

$repository->nd($id); $repository->ndOneByName('Foo');
yf ourseD hotrine lso llows you to write more omplex queries using the hotrine uery vnguge @hvAF hv is similr to v exept tht you should imgine tht you9re querying for one or more ojets of n entity lss @eFgF rodutA insted of querying for rows on tle @eFgF produtAF hen querying in hotrineD you hve two optionsX writing pure hotrine queries or using hotrine9s uery fuilderF

SFVF hotrine @A

ISQ

ymfony houmenttionD PFH uerying for yjets with hv smging tht you wnt to query for produtsD ut only return produts tht ost more thn IWFWWD ordered from hepest to most expensiveF prom inside ontrollerD do the followingX

$em = $this->getDoctrine()->getEntityManager(); $query = $em->createQuery( 'SELECT p FROM AcmeStoreBundle:Product p WHERE p.price > :price ORDER BY p.price ASC' )->setParameter('price', '19.99'); $products = $query->getResult();
sf you9re omfortle with vD then hv should feel very nturlF he iggest di'erene is tht you need to think in terms of ojets insted of rows in dtseF por this resonD you selet from emetorefundleXrodut nd then lis it s pF he getesult@A method returns n rry of resultsF sf you9re querying for just one ojetD you n use the getingleesult@A method instedX

$product = $query->getSingleResult();
X he getingleesult@A method throws hotrineywxoesultixeption exeption if no results re returned nd hotrineywxonniqueesultixeption if more thn one result is returnedF sf you use this methodD you my need to wrp it in tryE th lok nd ensure tht only one result is returned @if you9re querying on something tht ould fesily return more thn one resultAX

$query = $em->createQuery('SELECT ....') ->setMaxResults(1); try { $product = $query->getSingleResult(); } catch (\Doctrine\Orm\NoResultException $e) { $product = null; } // ...
he hv syntx is inredily powerfulD llowing you to esily join etween entities @the topi of reltions will e overed lterAD groupD etF por more informtionD see the o0il hotrine hotrine uery vnguge doumenttionF

ISR

SF

ymfony houmenttionD PFH etting rmeters ke note of the setrmeter@A methodF hen working with hotrineD it9s lwys good ide to set ny externl vlues s pleholdersD whih ws done in the ove queryX

... WHERE p.price > :price ...


ou n then set the vlue of the prie pleholder y lling the setrmeter@A methodX

->setParameter('price', '19.99')
sing prmeters insted of pling vlues diretly in the query string is done to prevent v injetion ttks nd should lwys e doneF sf you9re using multiple prmetersD you n set their vlues t one using the setrmeters@A methodX

->setParameters(array( 'price' => '19.99', 'name' => 'Foo', ))

sing hotrine9s uery fuilder snsted of writing the queries diretlyD you n lterntively use hotrine9s ueryfuilder to do the sme jo using nieD ojetEoriented interfeF sf you use n shiD you n lso tke dvntge of utoEompletion s you type the method nmesF prom inside ontrollerX

$repository = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product'); $query = $repository->createQueryBuilder('p') ->where('p.price > :price') ->setParameter('price', '19.99') ->orderBy('p.price', 'ASC') ->getQuery(); $products = $query->getResult();
he ueryfuilder ojet ontins every method neessry to uild your queryF fy lling the getuery@A methodD the query uilder returns norml uery ojetD whih is the sme ojet you uilt diretly in the previous setionF por more informtion on hotrine9s uery fuilderD onsult hotrine9s uery fuilder doumenttionF

SFVF hotrine @A

ISS

ymfony houmenttionD PFH gustom epository glsses sn the previous setionsD you egn onstruting nd using more omplex queries from inside ontrollerF sn order to isolteD test nd reuse these queriesD it9s good ide to rete ustom repository lss for your entity nd dd methods with your query logi thereF o do thisD dd the nme of the repository lss to your mpping de(nitionF

ennottions

// src/Acme/StoreBundle/Entity/Product.php namespace Acme\StoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass="Acme\StoreBundle\Repository\ProductRepository") */ class Product { //... }
ewv

# src/Acme/StoreBundle/Resources/cong/doctrine/Product.orm.yml Acme\StoreBundle\Entity\Product: type: entity repositoryClass: Acme\StoreBundle\Repository\ProductRepository # ...


wv

<!-- src/Acme/StoreBundle/Resources/cong/doctrine/Product.orm.xml --> <!-- ... --> <doctrine-mapping> <entity name="Acme\StoreBundle\Entity\Product" repository-class="Acme\StoreBundle\Repository\ProductRepository"> <!-- ... --> </entity> </doctrine-mapping>
hotrine n generte the repository lss for you y running the sme ommnd used erlier to generte the missing getter nd setter methodsX

php app/console doctrine:generate:entities Acme


xextD dd new method E (ndellyrderedfyxme@A E to the newly generted repository IST SF

ymfony houmenttionD PFH lssF his method will query for ll of the rodut entitiesD ordered lphetillyF

// src/Acme/StoreBundle/Repository/ProductRepository.php namespace Acme\StoreBundle\Repository; use Doctrine\ORM\EntityRepository; class ProductRepository extends EntityRepository { public function ndAllOrderedByName() { return $this->getEntityManager() ->createQuery('SELECT p FROM AcmeStoreBundle:Product p ORDER BY p.name ASC') ->getResult(); } }
X he entity mnger n e essed vi 6thisEbgetintitywnger@A from inside the repositoryF ou n use this new method just like the defult (nder methods of the repositoryX

$em = $this->getDoctrine()->getEntityManager(); $products = $em->getRepository('AcmeStoreBundle:Product') ->ndAllOrderedByName();


X hen using ustom repository lssD you still hve ess to the defult (nder methods suh s (nd@A nd (ndell@AF

5.8.3 Entity Relationships/Associations

uppose tht the produts in your pplition ll elong to extly one tegoryF sn this seD you9ll need gtegory ojet nd wy to relte rodut ojet to gtegory ojetF trt y reting the gtegory entityF ine you know tht you9ll eventully need to persist the lss through hotrineD you n let hotrine rete the lss for youF

php app/console doctrine:generate:entity --entity="AcmeStoreBundle:Category" --elds="name:string(255)"


his tsk genertes the gtegory entity for youD with n id (eldD nme (eld nd the ssoited getter nd setter funtionsF

SFVF hotrine @A

ISU

ymfony houmenttionD PFH eltionship wpping wetdt o relte the gtegory nd rodut entitiesD strt y reting produts property on the gtegory lssX

// src/Acme/StoreBundle/Entity/Category.php // ... use Doctrine\Common\Collections\ArrayCollection; class Category { // ... /** * @ORM\OneToMany(targetEntity="Product", mappedBy="category") */ protected $products; public function __construct() { $this->products = new ArrayCollection(); }

pirstD sine gtegory ojet will relte to mny rodut ojetsD produts rry property is dded to hold those rodut ojetsF eginD this isn9t done euse hotrine needs itD ut insted euse it mkes sense in the pplition for eh gtegory to hold n rry of rodut ojetsF X he ode in the onstrut@A method is importnt euse hotrine requires the 6produts property to e n errygolletion ojetF his ojet looks nd ts lmost extly like n rryD ut hs some dded )exiilityF sf this mkes you unomfortleD don9t worryF tust imgine tht it9s n rry nd you9ll e in good shpeF xextD sine eh rodut lss n relte to extly one gtegory ojetD you9ll wnt to dd 6tegory property to the rodut lssX

// src/Acme/StoreBundle/Entity/Product.php // ... class Product { // ... /** * @ORM\ManyToOne(targetEntity="Category", inversedBy="products")


ISV SF

ymfony houmenttionD PFH

* @ORM\JoinColumn(name="category_id", referencedColumnName="id") */ protected $category;

pinllyD now tht you9ve dded new property to oth the gtegory nd rodut lssesD tell hotrine to generte the missing getter nd setter methods for youX

php app/console doctrine:generate:entities Acme


sgnore the hotrine metdt for momentF ou now hve two lsses E gtegory nd rodut with nturl oneEtoEmny reltionshipF he gtegory lss holds n rry of rodut ojets nd the rodut ojet n hold one gtegory ojetF sn other words E you9ve uilt your lsses in wy tht mkes sense for your needsF he ft tht the dt needs to e persisted to dtse is lwys seondryF xowD look t the metdt ove the 6tegory property on the rodut lssF he informtion here tells dotrine tht the relted lss is gtegory nd tht it should store the id of the tegory reord on tegoryid (eld tht lives on the produt tleF sn other wordsD the relted gtegory ojet will e stored on the 6tegory propertyD ut ehind the senesD hotrine will persist this reltionship y storing the tegory9s id vlue on tegoryid olumn of the produt tleF

SFVF hotrine @A

ISW

ymfony houmenttionD PFH

he metdt ove the 6produts property of the gtegory ojet is less importntD nd simply tells hotrine to look t the rodutFtegory property to (gure out how the reltionship is mppedF fefore you ontinueD e sure to tell hotrine to dd the new tegory tleD nd produtFtegoryid olumnD nd new foreign keyX

php app/console doctrine:schema:update --force


X his tsk should only e relly used during developmentF por more roust method of systemtilly updting your prodution dtseD red out hotrine migrtionsF

ITH

SF

ymfony houmenttionD PFH ving elted intities xowD let9s see the ode in tionF smgine you9re inside ontrollerX

// ... use Acme\StoreBundle\Entity\Category; use Acme\StoreBundle\Entity\Product; use Symfony\Component\HttpFoundation\Response; // ... class DefaultController extends Controller { public function createProductAction() { $category = new Category(); $category->setName('Main Products'); $product = new Product(); $product->setName('Foo'); $product->setPrice(19.99); // relate this product to the category $product->setCategory($category); $em = $this->getDoctrine()->getEntityManager(); $em->persist($category); $em->persist($product); $em->ush(); return new Response( 'Created product id: '.$product->getId().' and category id: '.$category->getId() );

xowD single row is dded to oth the tegory nd produt tlesF he produtFtegoryid olumn for the new produt is set to whtever the id is of the new tegoryF hotrine mnges the persistene of this reltionship for youF pething elted yjets hen you need to feth ssoited ojetsD your work)ow looks just like it did eforeF pirstD feth 6produt ojet nd then ess its relted gtegoryX

public function showAction($id) { $product = $this->getDoctrine()


SFVF hotrine @A ITI

ymfony houmenttionD PFH

->getRepository('AcmeStoreBundle:Product') ->nd($id); $categoryName = $product->getCategory()->getName(); } // ...

sn this exmpleD you (rst query for rodut ojet sed on the produt9s idF his issues query for just the produt dt nd hydrtes the 6produt ojet with tht dtF vterD when you ll 6produtEbgetgtegory@AEbgetxme@AD hotrine silently mkes seond query to (nd the gtegory tht9s relted to this rodutF st prepres the 6tegory ojet nd returns it to youF

ht9s importnt is the ft tht you hve esy ess to the produt9s relted tegoryD ut the tegory dt isn9t tully retrieved until you sk for the tegory @iFeF it9s lzily lodedAF ou n lso query in the other diretionX

public function showProductAction($id) { $category = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Category') ->nd($id);

ITP

SF

ymfony houmenttionD PFH

$products = $category->getProducts(); } // ...

sn this seD the sme things oursX you (rst query out for single gtegory ojetD nd then hotrine mkes seond query to retrieve the relted rodut ojetsD ut only oneGif you sk for them @iFeF when you ll Ebgetroduts@AAF he 6produts vrile is n rry of ll rodut ojets tht relte to the given gtegory ojet vi their tegoryid vlueF eltionships nd roxy glsses his lzy loding is possile euseD when neessryD hotrine returns proxy ojet in ple of the true ojetF vook gin t the ove exmpleX

$product = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product') ->nd($id); $category = $product->getCategory(); // prints "Proxies\AcmeStoreBundleEntityCategoryProxy" echo get_class($category);
his proxy ojet extends the true gtegory ojetD nd looks nd ts extly like itF he di'erene is thtD y using proxy ojetD hotrine n dely querying for the rel gtegory dt until you tully need tht dt @eFgF until you ll 6tegoryE bgetxme@AAF he proxy lsses re generted y hotrine nd stored in the he diretoryF end though you9ll proly never even notie tht your 6tegory ojet is tully proxy ojetD it9s importnt to keep in mindF sn the next setionD when you retrieve the produt nd tegory dt ll t one @vi joinAD hotrine will return the true gtegory ojetD sine nothing needs to e lzily lodedF

toining to elted eords sn the ove exmplesD two queries were mde E one for the originl ojet @eFgF gtegoryA nd one for the relted ojet@sA @eFgF the rodut ojetsAF X ememer tht you n see ll of the queries mde during request vi the we deug toolrF yf ourseD if you know up front tht you9ll need to ess oth ojetsD you n void SFVF hotrine @A ITQ

ymfony houmenttionD PFH the seond query y issuing join in the originl queryF edd the following method to the rodutepository lssX

// src/Acme/StoreBundle/Repository/ProductRepository.php public function ndOneByIdJoinedToCategory($id) { $query = $this->getEntityManager() ->createQuery(' SELECT p, c FROM AcmeStoreBundle:Product p JOIN p.category c WHERE p.id = :id' )->setParameter('id', $id); try { return $query->getSingleResult(); } catch (\Doctrine\ORM\NoResultException $e) { return null; }

xowD you n use this method in your ontroller to query for rodut ojet nd its relted gtegory with just one queryX

public function showAction($id) { $product = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product') ->ndOneByIdJoinedToCategory($id); $category = $product->getCategory(); } // ...

wore snformtion on essoitions his setion hs een n introdution to one ommon type of entity reltionshipD the oneEtoEmny reltionshipF por more dvned detils nd exmples of how to use other types of reltions @eFgF oneEtoEoneD mnyEtoEmnyAD see hotrine9s essoition wpping houmenttionF X sf you9re using nnottionsD you9ll need to prepend ll nnottions with yw @eFgF ywyneownyAD whih is not re)eted in hotrine9s doumenttionF ou9ll lso need to inlude the use hotrineywwpping s ywY sttementD whih imports the yw nnottions pre(xF ITR SF

ymfony houmenttionD PFH

5.8.4 Conguration

hotrine is highly on(gurleD though you proly won9t ever need to worry out most of its optionsF o (nd out more out on(guring hotrineD see the hotrine setion of the referene mnulF
5.8.5 Lifecycle Callbacks

ometimesD you need to perform n tion right efore or fter n entity is insertedD updtedD or deletedF hese types of tions re known s lifeyle llksD s they9re llk methods tht you need to exeute during di'erent stges of the lifeyle of n entity @eFgF the entity is insertedD updtedD deletedD etAF sf you9re using nnottions for your metdtD strt y enling the lifeyle llksF his is not neessry if you9re using ewv or wv for your mppingX

/** * @ORM\Entity() * @ORM\HasLifecycleCallbacks() */ class Product { // ... }


xowD you n tell hotrine to exeute method on ny of the ville lifeyle eventsF por exmpleD suppose you wnt to set reted dte olumn to the urrent dteD only when the entity is (rst persisted @iFeF insertedAX

ennottions

/** * @ORM\prePersist */ public function setCreatedValue() { $this->created = new \DateTime(); }


ewv

# src/Acme/StoreBundle/Resources/cong/doctrine/Product.orm.yml Acme\StoreBundle\Entity\Product: type: entity


SFVF hotrine @A ITS

ymfony houmenttionD PFH

# ... lifecycleCallbacks: prePersist: [ setCreatedValue ]


wv

<!-- src/Acme/StoreBundle/Resources/cong/doctrine/Product.orm.xml --> <!-- ... --> <doctrine-mapping> <entity name="Acme\StoreBundle\Entity\Product"> <!-- ... --> <lifecycle-callbacks> <lifecycle-callback type="prePersist" method="setCreatedValue" /> </lifecycle-callbacks> </entity> </doctrine-mapping>
X he ove exmple ssumes tht you9ve reted nd mpped reted property @not shown hereAF xowD right efore the entity is (rst persistedD hotrine will utomtilly ll this method nd the reted (eld will e set to the urrent dteF his n e repeted for ny of the other lifeyle eventsD whih inludeX

preemove postemove preersist postersist prepdte postpdte postvod lodglsswetdt


por more informtion on wht these lifeyle events men nd lifeyle llks in generlD see hotrine9s vifeyle ivents doumenttion

ITT

SF

ymfony houmenttionD PFH vifeyle gllks nd ivent visteners xotie tht the setgretedlue@A method reeives no rgumentsF his is lwys the se for lifeyle llks nd is intentionlX lifeyle llks should e simple methods tht re onerned with internlly trnsforming dt in the entity @eFgF setting retedGupdted (eldD generting slug vlueAF sf you need to do some hevier lifting E like perform logging or send n emil E you should register n externl lss s n event listener or susrier nd give it ess to whtever resoures you needF por more informtionD see egistering ivent visteners nd usriersF

5.8.6 Doctrine Extensions: Timestampable, Sluggable, etc.

hotrine is quite )exileD nd numer of thirdEprty extensions re ville tht llow you to esily perform repeted nd ommon tsks on your entitiesF hese inlude thing suh s luggleD imestmpleD voggleD rnsltleD nd reeF por more informtion on how to (nd nd use these extensionsD see the ookook rtile out using ommon hotrine extensionsF
5.8.7 Doctrine Field Types Reference

hotrine omes with lrge numer of (eld types villeF ih of these mps r dt type to spei( olumn type in whtever dtse you9re usingF he following types re supported in hotrineX

trings
! string @used for shorter stringsA ! text @used for lrger stringsA

xumers
! integer ! smllint ! igint ! deiml ! )ot

htes nd imes @use hteime ojet for these (elds in rA


! dte ! time SFVF hotrine @A ITU

ymfony houmenttionD PFH ! dtetime

yther ypes
! oolen ! ojet @serilized nd stored in gvyf (eldA ! rry @serilized nd stored in gvyf (eldA por more informtionD see hotrine9s wpping ypes doumenttionF pield yptions ih (eld n hve set of options pplied to itF he ville options inlude type @defults to stringAD nmeD lengthD unique nd nullleF ke few nnottions exmplesX

/** * A string eld with length 255 that cannot be null * (reecting the default values for the "type", "length" and *nullable* options) * * @ORM\Column() */ protected $name; /** * A string eld of length 150 that persists to an "email_address" column * and has a unique index. * * @ORM\Column(name="email_address", unique="true", length="150") */ protected $email;
X here re few more options not listed hereF por more detilsD see hotrine9s roperty wpping doumenttion

5.8.8 Console Commands

he hotrineP yw integrtion o'ers severl onsole ommnds under the dotrine nmespeF o view the ommnd list you n run the onsole without ny rgumentsX

php app/console
e list of ville ommnd will print outD mny of whih strt with the dotrineX pre(xF ou n (nd out more informtion out ny of these ommnds @or ny ymfony ommndA y

ITV

SF

ymfony houmenttionD PFH running the help ommndF por exmpleD to get detils out the dotrineXdtseXrete tskD runX

php app/console help doctrine:database:create


ome notle or interesting tsks inludeX

dotrineXensureEprodutionEsettings E heks to see if the urrent environment is on(gured e0iently for produtionF his should lwys e run in the prod environmentX

php app/console doctrine:ensure-production-settings --env=prod


dotrineXmppingXimport E llows hotrine to introspet n existing dtse nd rete mpping informtionF por more informtionD see row to generte intities from n ixisting htseF dotrineXmppingXinfo E tells you ll of the entities tht hotrine is wre of nd whether or not there re ny si errors with the mppingF dotrineXqueryXdql nd dotrineXqueryXsql E llow you to exeute hv or v queries diretly from the ommnd lineF
X o e le to lod dt (xtures to your dtseD you will need to hve the hotrinepixturesfundle undle instlledF o lern how to do itD red the GundlesGhotrinepixturesfundleGindex entry of the doumenttionF

5.8.9 Summary

ith hotrineD you n fous on your ojets nd how they9re useful in your pplition nd worry out dtse persistene seondF his is euse hotrine llows you to use ny r ojet to hold your dt nd relies on mpping metdt informtion to mp n ojet9s dt to prtiulr dtse tleF end even though hotrine revolves round simple oneptD it9s inredily powerfulD llowing you to rete omplex queries nd susrie to events tht llow you to tke di'erent tions s ojets go through their persistene lifeyleF por more informtion out hotrineD see the hotrine setion of the ookookD whih inludes the following rtilesX

GundlesGhotrinepixturesfundleGindex hotrine ixtensionsX imestmpleX luggleD rnsltleD etF

SFVF hotrine @A

ITW

ymfony houmenttionD PFH

5.9

D F ymfonyPF
5.9.1

ymfonyP rnitD E F rnitD D F X ymfonyP rnit QFSFII F rnit estsG X

<!-- app/phpunit.xml.dist --> <phpunit bootstrap="../src/autoload.php"> <testsuites> <testsuite name="Project Test Suite"> <directory>../src/*/*Bundle/Tests</directory> </testsuite> </testsuites> ... </phpunit>
X

# $ phpunit -c app/ # phpunit $ cd app/ $ phpunit


X EEovergeEhtmlF

IUH

SF

ymfony houmenttionD PFH


5.9.2

ymfonyP rnitF E estsGF E emerellofundlewodelertile emeGrellofundleGestsGwodelGertileestFphpF srGutolodFphp @ E phpunitFxmlFdistAF X

# Controller $ phpunit -c app src/Acme/HelloBundle/Tests/Controller/ # Model $ phpunit -c app src/Acme/HelloBundle/Tests/Model/ # Article $ phpunit -c app src/Acme/HelloBundle/Tests/Model/ArticleTest.php # Bundle $ phpunit -c app src/Acme/HelloBundle/

5.9.3

@ AF D E rnit D X

Y Y Y Y F
D D E F D ymfonyP eestgseF hemogontrollerD X

// src/Acme/DemoBundle/Tests/Controller/DemoControllerTest.php namespace Acme\DemoBundle\Tests\Controller;


SFWF IUI

ymfony houmenttionD PFH

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class DemoControllerTest extends WebTestCase { public function testIndex() { $client = static::createClient(); $crawler = $client->request('GET', '/demo/hello/Fabien'); } $this->assertTrue($crawler->lter('html:contains("Hello Fabien")')->count() > 0);

reteglient@A D X

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


request@A grwlerD esponseD F X grwler D esponse wv rwv F esponse 6lientEbgetesponse@AEbgetgontent@AF ou n set the ontentEtype of the request to tyx y dding rgyxixi9 ab pplitionGjson9F

X he full signture of the request@A method isX

request($method, $uri, array $parameters = array(), array $les = array(), array $server = array(), $content = null, $changeHistory = true )
D grwlerD E th g D glientX

$link = $crawler->lter('a:contains("Greet")')->eq(1)->link(); $crawler = $client->click($link);


IUP SF

ymfony houmenttionD PFH X D E D X

$form = $crawler->selectButton('submit')->form(); // - $form['name'] = 'Lucas'; // $crawler = $client->submit($form);


porm D X

// input $form['name'] = 'Lucas'; // option radio $form['country']->select('France'); // checkbox $form['like_symfony']->tick(); // $form['photo']->upload('/path/to/lucas.jpg');


D sumit@AX

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

// CSS . $this->assertTrue($crawler->lter('h1')->count() > 0);


esponse D E E D esponse wvGrwvX

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

SFWF

IUQ

ymfony houmenttionD PFH F D X

// CSS . $this->assertTrue($crawler->lter($selector)->count() > 0); // CSS n . $this->assertEquals($count, $crawler->lter($selector)->count()); // . $this->assertTrue($client->getResponse()->headers->contains($key, $value)); // regexp. $this->assertRegExp($regexp, $client->getResponse()->getContent()); // . $this->assertTrue($client->getResponse()->isSuccessful()); $this->assertTrue($client->getResponse()->isNotFound()); $this->assertEquals(200, $client->getResponse()->getStatusCode()); // . $this->assertTrue($client->getResponse()->isRedirect('google.com'));

5.9.4

r D F X frowseruit grwlerF

ymfonyPX

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


request@A r v grwlerF grwler hyw esponseF E X

IUR

SF

ymfony houmenttionD PFH

$link = $crawler->selectLink('Go elsewhere...')->link(); $crawler = $client->click($link); $form = $crawler->selectButton('validate')->form(); $crawler = $client->submit($form, array('name' => 'Fabien'));
lik@A sumit@A grwlerF F D sumitD r vD es F F X vink porm grwlerF request@AX

// $client->request('POST', '/submit', array('name' => 'Fabien')); // use Symfony\Component\HttpFoundation\File\UploadedFile; $photo = new UploadedFile('/path/to/photo.jpg', 'photo.jpg', 'image/jpeg', 123); // $photo = array('tmp_name' => '/path/to/photo.jpg', 'name' => 'photo.jpg', 'type' => 'image/jpeg', 'size' => $client->request('POST', '/submit', array('name' => 'Fabien'), array('photo' => $photo));

// HTTP $client->request('DELETE', '/post/12', array(), array(), array('PHP_AUTH_USER' => 'username', 'PHP_AU


X porm sumissions re gretly simpli(ed y using rwler ojet @see elowAF D F followedirets@AX

$client->followRedirects(false);
D E followediret@AX

$crawler = $client->followRedirect();
D D E SFWF IUS

ymfony houmenttionD PFH r X

$client->insulate();
D X

$client->back(); $client->forward(); $client->reload(); // . $client->restart();


D X

$history = $client->getHistory(); $cookieJar = $client->getCookieJar();


D X

$request = $client->getRequest(); $response = $client->getResponse(); $crawler = $client->getCrawler();


D gontiner uernelX

$container = $client->getContainer(); $kernel = $client->getKernel();


gontiner E esponseF E F E X

$container = $client->getContainer();

IUT

SF

ymfony houmenttionD PFH r F X D F

D D E X

$prole = $client->getProle();
r D E esponse F E D followediret@AX

// -, (, ) // $crawler = $client->followRedirect();
D followedirets@AX

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

5.9.5 Crawler

grwler F rwv D D F

SFWF

IUU

ymfony houmenttionD PFH grwler grwler F X

use Symfony\Component\DomCrawler\Crawler; $crawler = new Crawler($html, $url);


X vD vE D X

rwv Y wv Y hywhoumentY hywxodevistY hywxodeY F


D X ddrwvhoument@A ddwvhoument@A ddhywhoument@A ddhywxodevist@A ddhywxode@A ddxodes@A dd@A jueryD grwler hyw rwvGwvX rwv wv hywhoument hywxodevist hywxode

IUV

SF

ymfony houmenttionD PFH (lter@9hI9A (lterpth@9hI9A eq@IA (rst@A lst@A silings@A nextell@A previousell@A prents@A hildren@A redue@6lmdA D g D th D flse

D F F grwler X

$crawler ->lter('h1') ->reduce(function ($node, $i) { if (!$node->getAttribute('class')) { return false; } }) ->rst();


X ount@A D grwlerX ount@6rwlerA

grwler X

// $crawler->attr('class'); // $crawler->text(); // (_text ) $crawler->extract(array('_text', 'href')); // lambda $data = $crawler->each(function ($node, $i) {
SFWF IUW

ymfony houmenttionD PFH

});

return $node->getAttribute('href');

D seletvink@A X

$crawler->selectLink('Click here');
D D D D ltF lik@A vinkD link@AX

$link = $crawler->link(); $client->click($link);


X links@A vink F

D seletfutton@AX

$crawler->selectButton('submit');
D D F F Y es D F seletfutton@A utton input sumitY X

vlueY id lt Y id nme uttonF


D D form@A E pormD X

$form = $crawler->form();

IVH

SF

ymfony houmenttionD PFH form@A D E X

$form = $crawler->form(array( 'name' => 'Fabien', 'like_symfony' => true, ));


r D E X

$form = $crawler->form(array(), 'DELETE');


pormX

$client->submit($form);
sumit@AX

$client->submit($form, array( 'name' => 'Fabien', 'like_symfony' => true, ));


D porm E X

// $form['name'] = 'Fabien';
es X

// option radio $form['country']->select('France'); // checkbox $form['like_symfony']->tick(); // $form['photo']->upload('/path/to/lucas.jpg');


X D D getlues@AF D getpiles@AF gethplues@A gethppiles@A D r @ r AF

SFWF

IVI

ymfony houmenttionD PFH


5.9.6

rnit rnitD phpunitFxmlFdistF phpunitFxmlD E F X phpunitFxmlFdist phpunitFxmlF D  D phpunit @ endorBfundleestsAF F D E thirdEprty X

<!-- hello/phpunit.xml.dist --> <testsuites> <testsuite name="Project Test Suite"> <directory>../src/*/*Bundle/Tests</directory> <directory>../src/Acme/Bundle/*Bundle/Tests</directory> </testsuite> </testsuites>
D `(lterbX

<lter> <whitelist> <directory>../src</directory> <exclude> <directory>../src/*/*Bundle/Resources</directory> <directory>../src/*/*Bundle/Tests</directory> <directory>../src/Acme/Bundle/*Bundle/Resources</directory> <directory>../src/Acme/Bundle/*Bundle/Tests</directory> </exclude> </whitelist> </lter>
D D uernelD testD F F D X IVP SF

ymfony houmenttionD PFH

ewv

# app/cong/cong_test.yml imports: - { resource: cong_dev.yml } framework: error_handler: false test: ~ web_proler: toolbar: false intercept_redirects: false monolog: handlers: main: type: stream path: %kernel.logs_dir%/%kernel.environment%.log level: debug
wv

<!-- app/cong/cong_test.xml --> <container> <imports> <import resource="cong_dev.xml" /> </imports> <webproler:cong toolbar="false" intercept-redirects="false" /> <framework:cong error_handler="false"> <framework:test /> </framework:cong> <monolog:cong> <monolog:main type="stream" path="%kernel.logs_dir%/%kernel.environment%.log" level="debug" /> </monolog:cong> </container>
r
SFWF IVQ

ymfony houmenttionD PFH

// app/cong/cong_test.php $loader->import('cong_dev.php'); $container->loadFromExtension('framework', array( 'error_handler' => false, 'test' => true, )); $container->loadFromExtension('web_proler', array( 'toolbar' => false, 'intercept-redirects' => false, )); $container->loadFromExtension('monolog', array( 'handlers' => array( 'main' => array('type' => 'stream', 'path' => '%kernel.logs_dir%/%kernel.environment%.log' 'level' => 'debug') )));
@testA @trueAD D reteglient@A X

$client = static::createClient(array( 'environment' => 'my_test_env', 'debug' => false, ));


E r D E reteglient@AX

$client = static::createClient(array(), array( 'HTTP_HOST' => 'en.example.com', 'HTTP_USER_AGENT' => 'MySuperBrowser/1.0', ));
r X

$client->request('GET', '/', array(), array( 'HTTP_HOST' => 'en.example.com', 'HTTP_USER_AGENT' => 'MySuperBrowser/1.0', ));
X D testFlientFlss testFlientF

IVR

SF

ymfony houmenttionD PFH


5.9.7

row to simulte r euthentition in puntionl est row to test the sntertion of severl glients row to use the ro(ler in puntionl est

5.10

F F weEF ymfonyP lidtorD E F tQHQ fen lidtion spei(tionF c tv rc D D F D rF


5.10.1

E F E D E r D E X

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; class Author { public $name; }


D E F D D F D @ E @onstrintsAA D F @wvD wvD E rAF D 6nme D X

ewv

SFIHF

IVS

ymfony houmenttionD PFH

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: name: - NotBlank: ~


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\NotBlank() */ public $name; }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <?xml version="1.0" encoding="UTF-8" ?> <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/ <class name="Acme\BlogBundle\Entity\Author"> <property name="name"> <constraint name="NotBlank" /> </property> </class> </constraint-mapping>
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; class Author { public $name; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('name', new NotBlank());
IVT SF

ymfony houmenttionD PFH

X roteted privte D @F AF

vlidtor ervie euthor vlidte E vlidtor @ ymfonygomponentlidtorlidtorAF vlidtor iX @FF A F D F E X

use Symfony\Component\HttpFoundation\Response; use Acme\BlogBundle\Entity\Author; // ... public function indexAction() { $author = new Author(); // ... do something to the $author object $validator = $this->get('validator'); $errors = $validator->validate($author); if (count($errors) > 0) { return new Response(print_r($errors, true)); } else { return new Response('The author is valid! Yes!'); }

6nme D X

Acme\BlogBundle\Author.name: This value should not be blank


nme D F X wost of the timeD you won9t intert diretly with the vlidtor servie or need to worry out printing out the errorsF wost of the timeD you9ll use vlidtion indiretly when hndling sumitted form dtF por more informtionD see the F

SFIHF

IVU

ymfony houmenttionD PFH ou ould lso pss the olletion of errors into templteF

if (count($errors) > 0) { return $this->render('AcmeBlogBundle:Author:validate.html.twig', array( 'errors' => $errors, )); } else { // ... }
D X

wig

{# src/Acme/BlogBundle/Resources/views/Author/validate.html.twig #} <h3>The author has the following errors</h3> <ul> {% for error in errors %} <li>{{ error.message }}</li> {% endfor %} </ul>
r

<!-- src/Acme/BlogBundle/Resources/views/Author/validate.html.php --> <h3>The author has the following errors</h3> <ul> <?php foreach ($errors as $error): ?> <li><?php echo $error->getMessage() ?></li> <?php endforeach; ?> </ul>
X  @onstrint violtionAAD ymfonygomponentlidtorgonstrintioltionF @ E

vlidtor F D vlidtor E F ymfony vlidtor D F pieldirrorD IVV SF

ymfony houmenttionD PFH F he typil form sumission work)ow looks like the following from inside ontrollerX

use Acme\BlogBundle\Entity\Author; use Acme\BlogBundle\Form\AuthorType; use Symfony\Component\HttpFoundation\Request; // ... public function updateAction(Request $request) { $author = new Acme\BlogBundle\Entity\Author(); $form = $this->createForm(new AuthorType(), $author); if ($request->getMethod() == 'POST') { $form->bindRequest($request); if ($form->isValid()) { // the validation passed, do something with the $author object } $this->redirect($this->generateUrl('...'));

return $this->render('BlogBundle:Author:form.html.twig', array( 'form' => $form->createView(), ));

X his exmple uses n euthorype form lssD whih is not shown hereF D pormsF
5.10.2

he ymfonyP vlidtor is enled y defultD ut you must expliitly enle nnottions if you9re using the nnottion method to speify your onstrintsX

ewv

# app/cong/cong.yml framework: validation: { enable_annotations: true }


wv

SFIHF

IVW

ymfony houmenttionD PFH

<!-- app/cong/cong.xml --> <framework:cong> <framework:validation enable_annotations="true" /> </framework:cong>


r

// app/cong/cong.php $container->loadFromExtension('framework', array('validation' => array( 'enable_annotations' => true, )));

5.10.3

vlidtor @FF E AF D D vlidtorF r D E F D X  F ymfonyP X E D F D D F ymfonyP F F ome onstrintsD like xotflnkD re simple wheres othersD like the ghoie onstrintD hve severl on(gurtion options villeF uppose tht the euthor lss hs nother propertyD gender tht n e set to either mle or femleX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: gender: - Choice: { choices: [male, female], message: Choose a valid gender. }

IWH

SF

ymfony houmenttionD PFH

ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Choice( * choices = { "male", "female" }, * message = "Choose a valid gender." *) */ public $gender; }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <?xml version="1.0" encoding="UTF-8" ?> <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/ <class name="Acme\BlogBundle\Entity\Author"> <property name="gender"> <constraint name="Choice"> <option name="choices"> <value>male</value> <value>female</value> </option> <option name="message">Choose a valid gender.</option> </constraint> </property> </class> </constraint-mapping>
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; class Author { public $gender; public static function loadValidatorMetadata(ClassMetadata $metadata)
SFIHF IWI

ymfony houmenttionD PFH

$metadata->addPropertyConstraint('gender', new Choice(array( 'choices' => array('male', 'female'), 'message' => 'Choose a valid gender.', )));

he options of onstrint n lwys e pssed in s n rryF ome onstrintsD howeverD lso llow you to pss the vlue of oneD defultD option in ple of the rryF sn the se of the ghoie onstrintD the hoies options n e spei(ed in this wyF

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: gender: - Choice: [male, female]


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Choice({"male", "female"}) */ protected $gender; }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <?xml version="1.0" encoding="UTF-8" ?> <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/ <class name="Acme\BlogBundle\Entity\Author"> <property name="gender"> <constraint name="Choice"> <value>male</value> <value>female</value> </constraint> </property>
IWP SF

ymfony houmenttionD PFH

</class> </constraint-mapping>
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\Choice; class Author { protected $gender; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('gender', new Choice(array('male', 'female'))); }

his is purely ment to mke the on(gurtion of the most ommon option of onstrint shorter nd quikerF sf you9re ever unsure of how to speify n optionD either hek the es doumenttion for the onstrint or ply it sfe y lwys pssing in n rry of options @the (rst method shown oveAF
5.10.4

@ nmeA E E @ getpullxmeAF he (rst is the most ommon nd esy to useD ut the seond llows you to speify more omplex vlidtion rulesF F ymfonyP E privteD proteted puli F E D 6(rstxme euthor E Q F

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: rstName:


SFIHF IWQ

ymfony houmenttionD PFH

- NotBlank: ~ - MinLength: 3
ennottions

// Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\NotBlank() * @Assert\MinLength(3) */ private $rstName; }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Author"> <property name="rstName"> <constraint name="NotBlank" /> <constraint name="MinLength">3</constraint> </property> </class>
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\MinLength; class Author { private $rstName; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('rstName', new NotBlank()); $metadata->addPropertyConstraint('rstName', new MinLength(3)); }

IWR

SF

ymfony houmenttionD PFH F ymfonyP E puli D get isF D F D E F por exmpleD suppose you wnt to mke sure tht pssword (eld doesn9t mth the (rst nme of the user @for seurity resonsAF ou n do this y reting n issswordvegl methodD nd then sserting tht this method must return trueX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: getters: passwordLegal: - "True": { message: "The password cannot match your rst name" }
ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\True(message = "The password cannot match your rst name") */ public function isPasswordLegal() { // return true or false } }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Author"> <getter property="passwordLegal"> <constraint name="True"> <option name="message">The password cannot match your rst name</option> </constraint> </getter> </class>
r

SFIHF

IWS

ymfony houmenttionD PFH

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\True; class Author { public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addGetterConstraint('passwordLegal', new True(array( 'message' => 'The password cannot match your rst name', ))); } }
xowD rete the issswordvegl@A methodD nd inlude the logi you needX

public function isPasswordLegal() { return ($this->rstName != $this->password); }


X D @get isA @mppingAF @ A F

glsses ome onstrints pply to the entire lss eing vlidtedF por exmpleD the gllk onstrint is generi onstrint tht9s pplied to the lss itselfF hen tht lss is vlidtedD methods spei(ed y tht onstrint re simply exeuted so tht eh n provide more ustom vlidtionF
5.10.5 Validation Groups

o frD you9ve een le to dd onstrints to lss nd sk whether or not tht lss psses ll of the de(ned onstrintsF sn some sesD howeverD you9ll need to vlidte n ojet ginst only some of the onstrints on tht lssF o do thisD you n orgnize eh onstrint into one or more vlidtion groupsD nd then pply vlidtion ginst just one group of onstrintsF por exmpleD suppose you hve ser lssD whih is used oth when user registers nd when user updtes hisGher ontt informtion lterX

IWT

SF

ymfony houmenttionD PFH

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\User: properties: email: - Email: { groups: [registration] } password: - NotBlank: { groups: [registration] } - MinLength: { limit: 7, groups: [registration] } city: - MinLength: 2
ennottions

// src/Acme/BlogBundle/Entity/User.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Security\Core\User\UserInterface use Symfony\Component\Validator\Constraints as Assert; class User implements UserInterface { /** * @Assert\Email(groups={"registration"}) */ private $email; /** * @Assert\NotBlank(groups={"registration"}) * @Assert\MinLength(limit=7, groups={"registration"}) */ private $password; /** * @Assert\MinLength(2) */ private $city;

wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\User"> <property name="email"> <constraint name="Email"> <option name="groups"> <value>registration</value>
SFIHF IWU

ymfony houmenttionD PFH

</option> </constraint> </property> <property name="password"> <constraint name="NotBlank"> <option name="groups"> <value>registration</value> </option> </constraint> <constraint name="MinLength"> <option name="limit">7</option> <option name="groups"> <value>registration</value> </option> </constraint> </property> <property name="city"> <constraint name="MinLength">7</constraint> </property> </class>
r

// src/Acme/BlogBundle/Entity/User.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\MinLength; class User { public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('email', new Email(array( 'groups' => array('registration') ))); $metadata->addPropertyConstraint('password', new NotBlank(array( 'groups' => array('registration') ))); $metadata->addPropertyConstraint('password', new MinLength(array( 'limit' => 7, 'groups' => array('registration') )));

IWV

SF

ymfony houmenttionD PFH

$metadata->addPropertyConstraint('city', new MinLength(3));

ith this on(gurtionD there re two vlidtion groupsX

hefult E ontins the onstrints not ssigned to ny other groupY registrtion E ontins the onstrints on the emil nd pssword (elds onlyF
o tell the vlidtor to use spei( groupD pss one or more group nmes s the seond rgument to the vlidte@A methodX

$errors = $validator->validate($author, array('registration'));


yf ourseD you9ll usully work with vlidtion indiretly through the form lirryF por informtion on how to use vlidtion groups inside formsD see F
5.10.6

ymfonyP vlidtor D E D F D D E E F D D F


5.10.7

row to rete gustom lidtion gonstrint

5.11

rwv D D F ymfonyP pormD E F D F X ymfony ! D ymfonyP F D ymfonyP porm gomponent qithuF

SFIIF

IWW

ymfony houmenttionD PFH


5.11.1

D D F D F D D D skD X

// src/Acme/TaskBundle/Entity/Task.php namespace Acme\TaskBundle\Entity; class Task { protected $task; protected $dueDate; public function getTask() { return $this->task; } public function setTask($task) { $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) { $this->dueDate = $dueDate; }

X D D D E D emeskfundle @ E AX

php app/console generate:bundle --namespace=Acme/TaskBundle


E r D E ymfony F r D @FF E AF D PHH SF

ymfony houmenttionD PFH sk @ rwv AD F D skD E rwv F ymfonyP F X

// src/Acme/TaskBundle/Controller/DefaultController.php namespace Acme\TaskBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Acme\TaskBundle\Entity\Task; use Symfony\Component\HttpFoundation\Request; class DefaultController extends Controller { public function newAction(Request $request) { // create a task and give it some dummy data for this example $task = new Task(); $task->setTask('Write a blog post'); $task->setDueDate(new \DateTime('tomorrow')); $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm(); return $this->render('AcmeTaskBundle:Default:new.html.twig', array( 'form' => $form->createView(), ));

X D E F D greting porm glssesD D D E F D ymfonyP F E  E SFIIF PHI

ymfony houmenttionD PFH F X tsk duehteD E tsk duehte skF  @E D textD dteAD D D rwv @EA F ymfonyP D @E AF F E  @ 6formE breteiew@A AD X

wig

{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} <form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" /> </form>
r

<!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php -->

<form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view[ <?php echo $view['form']->widget($form) ?> <input type="submit" /> </form>

X D tsknew PHP SF

ymfony houmenttionD PFH emeskfundleXhefultXnewF 3 formwidget@formAD E @ AF D F D D F  F D D D tsk E tsk 6tsk @FF  AF X D rwv F X D E tskD getsk@A setsk@A skF D D   D form G F foolen isset @D isulished@AA @D getulished@AAF

E F D E F X

// ... public function newAction(Request $request) { // just setup a fresh $task object (remove the dummy data) $task = new Task(); $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm(); if ($request->getMethod() == 'POST') { $form->bindRequest($request); if ($form->isValid()) { // perform some action, such as saving the task to the database

SFIIF

PHQ

ymfony houmenttionD PFH

} }

return $this->redirect($this->generateUrl('task_success'));

// ...

D D E tsk duehte 6tskF indequest@AF X indequest@A F F E X IF qiF Y PF @FF yAD @ AD Y QF D D 6tsk @D AD D @D thnk you suessAF X E F

5.11.2 Form Validation

E F ymfonyP @D skAF D D E 6tsk F 6formE bislid@A D 6tsk E F @ A F D F PHR SF

ymfony houmenttionD PFH tsk duehte D duehte hteime F

ewv

# Acme/TaskBundle/Resources/cong/validation.yml Acme\TaskBundle\Entity\Task: properties: task: - NotBlank: ~ dueDate: - NotBlank: ~ - Type: \DateTime


ennottions

// Acme/TaskBundle/Entity/Task.php use Symfony\Component\Validator\Constraints as Assert; class Task { /** * @Assert\NotBlank() */ public $task; /** * @Assert\NotBlank() * @Assert\Type("\DateTime") */ protected $dueDate;

wv

<!-- Acme/TaskBundle/Resources/cong/validation.xml --> <class name="Acme\TaskBundle\Entity\Task"> <property name="task"> <constraint name="NotBlank" /> </property> <property name="dueDate"> <constraint name="NotBlank" /> <constraint name="Type"> <value>\DateTime</value> </constraint> </property> </class>
r
SFIIF PHS

ymfony houmenttionD PFH

// Acme/TaskBundle/Entity/Task.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Type; class Task { // ... public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('task', new NotBlank()); $metadata->addPropertyConstraint('dueDate', new NotBlank()); $metadata->addPropertyConstraint('dueDate', new Type('\DateTime'));

3 D D E F rwvS rwvSD E F required F D rwvSD E D F rwv D F E D novlidte form formnovlidte F D E D @D AF ! ymfonyPD F X D F

PHT

SF

ymfony houmenttionD PFH D D X

$form = $this->createFormBuilder($users, array( 'validation_groups' => array('registration'), ))->add(...) ;


@ AD gethefultyptions@A X

public function getDefaultOptions(array $options) { return array( 'validation_groups' => array('registration') ); }


registrtion E F
5.11.3

ymfony D E D X ext pields

text textre emil integer money numer pssword perent serh url

SFIIF

PHU

ymfony houmenttionD PFH ghoie pields

hoie entity ountry lnguge lole timezone


hte nd ime pields

dte dtetime time irthdy


yther pields

hekox (le rdio


pield qroups

olletion repeted
ridden pields

hidden srf

PHV

SF

ymfony houmenttionD PFH fse pields

(eld form
F his topi is overed in the row to grete gustom porm pield ype rtile of the ookookF D F D duehte F D dte (eld D @ AX

->add('dueDate', 'date', array('widget' => 'single_text'))

D D F @ AF required requiredD E F D required trueF D D rwvS E D F D flse required D rwvS F D true required F D @D  E EAD D xotflnk xotxull ymfonyF D required D E F

SFIIF

PHW

ymfony houmenttionD PFH


5.11.4 

D skD ymfony F D ymfony  F ymfonyD D D tsk textD duehte dteX

public function newAction() { $task = new Task(); $form = $this->createFormBuilder($task) ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) ->getForm();

 D dd@A @ nullAF @ duehteAD  F X D D E  D E  @ D AF

  D ymfony  E F X D rwv D rwvS F D @D essertwxvengthAF E D D F

requiredX required D @FF E xotflnk xotxullA hotrine @FF nullleAF D F


PIH SF

ymfony houmenttionD PFH

minlengthX E D minlength D @ winvength winA hotrine @ AF mxlengthX minlengthD  F


X  D  ymfony @FF null dd@AAF  D X

->add('task', null, array('min_length' => 4))

5.11.5

D D D D F D E X FF on(gurtionElokX

.. code-block:: html+jinja {# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} <form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}> {{ form_errors(form) }} {{ form_row(form.task) }} {{ form_row(form.dueDate) }} {{ form_rest(form) }} <input type="submit" /> </form> .. code-block:: html+php <!-- // src/Acme/TaskBundle/Resources/views/Default/newAction.html.php -->

<form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view['for <?php echo $view['form']->errors($form) ?> <?php echo $view['form']->row($form['task']) ?> <?php echo $view['form']->row($form['dueDate']) ?>
SFIIF PII

ymfony houmenttionD PFH

<?php echo $view['form']->rest($form) ?> <input type="submit" /> </form>


X

formentype@formA E D E entypea4multiprtGformEdt4Y formerrors@formA E @ E AY formrow@formFduehteA E D D rwv @D duehteA div @ E AY formrest@formA E F @ D D E AF gpF


formrowD D rwv div @ AF porm heming D formrow F formrow E @ D AF D E D F D formrowX

wig

{{ form_errors(form) }} <div> {{ form_label(form.task) }} {{ form_errors(form.task) }} {{ form_widget(form.task) }} </div> <div>


PIP SF

ymfony houmenttionD PFH

{{ form_label(form.dueDate) }} {{ form_errors(form.dueDate) }} {{ form_widget(form.dueDate) }} </div> {{ form_rest(form) }}


r

<?php echo $view['form']->errors($form) ?> <div> <?php echo $view['form']->label($form['task']) ?> <?php echo $view['form']->errors($form['task']) ?> <?php echo $view['form']->widget($form['task']) ?> </div> <div> <?php echo $view['form']->label($form['dueDate']) ?> <?php echo $view['form']->errors($form['dueDate']) ?> <?php echo $view['form']->widget($form['dueDate']) ?> </div> <?php echo $view['form']->rest($form) ?>
D X

wig

{{ form_label(form.task, 'Task Description') }}


r

<?php echo $view['form']->label($form['task'], 'Task Description') ?>


D D F D E ttrD F tsk(eld X

wig

{{ form_widget(form.task, { 'attr': {'class': 'task_eld'} }) }}


r

SFIIF

PIQ

ymfony houmenttionD PFH

<?php echo $view['form']->widget($form['task'], array( 'attr' => array('class' => 'task_eld'), )) ?>
wig emplte puntion eferene sf you9re using wigD full referene of the form rendering funtions is ville in the referene mnulF ed this to know everything out the helpers ville nd the options tht n e used with ehF
5.11.6 Creating Form Classes

es you9ve seenD form n e reted nd used diretly in ontrollerF roweverD etter prtie is to uild the form in seprteD stndlone r lssD whih n then e reused nywhere in your pplitionF grete new lss tht will house the logi for uilding the tsk formX

// src/Acme/TaskBundle/Form/Type/TaskType.php namespace Acme\TaskBundle\Form\Type; 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'; }

his new lss ontins ll the diretions needed to rete the tsk form @note tht the getxme@A method should return unique identi(er for this form typeAF st n e used to quikly uild form ojet in the ontrollerX

// src/Acme/TaskBundle/Controller/DefaultController.php

PIR

SF

ymfony houmenttionD PFH

// add this new use statement at the top of the class use Acme\TaskBundle\Form\Type\TaskType; public function newAction() { $task = // ... $form = $this->createForm(new TaskType(), $task); } // ...

ling the form logi into its own lss mens tht the form n e esily reused elsewhere in your projetF his is the est wy to rete formsD ut the hoie is ultimtely up to youF etting the dtlss ivery form needs to know the nme of the lss tht holds the underlying dt @eFgF emeskfundleintityskAF sullyD this is just guessed sed o' of the ojet pssed to the seond rgument to reteporm @iFeF 6tskAF vterD when you egin emedding formsD this will no longer e su0ientF oD while not lwys neessryD it9s generlly good ide to expliitly speify the dtlss option y dd the following to your form type lssX

public function getDefaultOptions(array $options) { return array( 'data_class' => 'Acme\TaskBundle\Entity\Task', ); }

5.11.7 Forms and Doctrine

he gol of form is to trnslte dt from n ojet @eFgF skA to n rwv form nd then trnslte userEsumitted dt k to the originl ojetF es suhD the topi of persisting the sk ojet to the dtse is entirely unrelted to the topi of formsF futD if you9ve on(gured the sk lss to e persisted vi hotrine @iFeF you9ve dded mpping metdt for itAD then persisting it fter form sumission n e done when the form is vlidX

if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $em->persist($task); $em->ush(); return $this->redirect($this->generateUrl('task_success'));


SFIIF PIS

ymfony houmenttionD PFH

}
sfD for some resonD you don9t hve ess to your originl 6tsk ojetD you n feth it from the formX

$task = $form->getData();
por more informtionD see the hotrine yw hpterF he key thing to understnd is tht when the form is oundD the sumitted dt is trnsferred to the underlying ojet immeditelyF sf you wnt to persist tht dtD you simply need to persist the ojet itself @whih lredy ontins the sumitted dtAF
5.11.8 Embedded Forms

yftenD you9ll wnt to uild form tht will inlude (elds from mny di'erent ojetsF por exmpleD registrtion form my ontin dt elonging to ser ojet s well s mny eddress ojetsF portuntelyD this is esy nd nturl with the form omponentF imedding ingle yjet uppose tht eh sk elongs to simple gtegory ojetF trtD of ourseD y reting the gtegory ojetX

// src/Acme/TaskBundle/Entity/Category.php namespace Acme\TaskBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Category { /** * @Assert\NotBlank() */ public $name; }
xextD dd new tegory property to the sk lssX

// ... class Task { // ...

PIT

SF

ymfony houmenttionD PFH

/** * @Assert\Type(type="Acme\TaskBundle\Entity\Category") */ protected $category; // ... public function getCategory() { return $this->category; } public function setCategory(Category $category = null) { $this->category = $category; }

xow tht your pplition hs een updted to re)et the new requirementsD rete form lss so tht gtegory ojet n e modi(ed y the userX

// src/Acme/TaskBundle/Form/Type/CategoryType.php namespace Acme\TaskBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; class CategoryType extends AbstractType { public function buildForm(FormBuilder $builder, array $options) { $builder->add('name'); } public function getDefaultOptions(array $options) { return array( 'data_class' => 'Acme\TaskBundle\Entity\Category', ); } public function getName() { return 'category'; }

SFIIF

PIU

ymfony houmenttionD PFH he end gol is to llow the gtegory of sk to e modi(ed right inside the tsk form itselfF o omplish thisD dd tegory (eld to the skype ojet whose type is n instne of the new gtegoryype lssX

public function buildForm(FormBuilder $builder, array $options) { // ... } $builder->add('category', new CategoryType());

he (elds from gtegoryype n now e rendered longside those from the skype lssF ender the gtegory (elds in the sme wy s the originl sk (eldsX

wig

{# ... #} <h3>Category</h3> <div class="category"> {{ form_row(form.category.name) }} </div> {{ form_rest(form) }} {# ... #}


r

<!-- ... --> <h3>Category</h3> <div class="category"> <?php echo $view['form']->row($form['category']['name']) ?> </div> <?php echo $view['form']->rest($form) ?> <!-- ... -->
hen the user sumits the formD the sumitted dt for the gtegory (elds re used to onstrut n instne of gtegoryD whih is then set on the tegory (eld of the sk instneF he gtegory instne is essile nturlly vi 6tskEbgetgtegory@A nd n e persisted to the dtse or used however you needF imedding golletion of porms ou n lso emed olletion of forms into one formF his is done y using the olletion (eld typeF por more informtionD see the olletion (eld type refereneF PIV SF

ymfony houmenttionD PFH


5.11.9 Form Theming

ivery prt of how form is rendered n e ustomizedF ou9re free to hnge how eh form row rendersD hnge the mrkup used to render errorsD or even ustomize how textre tg should e renderedF xothing is o'ElimitsD nd di'erent ustomiztions n e used in di'erent plesF ymfony uses templtes to render eh nd every prt of formD suh s lel tgsD input tgsD error messges nd everything elseF sn wigD eh form frgment is represented y wig lokF o ustomize ny prt of how form rendersD you just need to override the pproprite lokF sn rD eh form frgment is rendered vi n individul templte (leF o ustomize ny prt of how form rendersD you just need to override the existing templte y reting new oneF o understnd how this worksD let9s ustomize the formrow frgment nd dd lss ttriute to the div element tht surrounds eh rowF o do thisD rete new templte (le tht will store the new mrkupX

wig

{# src/Acme/TaskBundle/Resources/views/Form/elds.html.twig #} {% block eld_row %} {% spaceless %} <div class="form_row"> {{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }} </div> {% endspaceless %} {% endblock eld_row %}
r

<!-- src/Acme/TaskBundle/Resources/views/Form/eld_row.html.php --> <div class="form_row"> <?php echo $view['form']->label($form, $label) ?> <?php echo $view['form']->errors($form) ?> <?php echo $view['form']->widget($form, $parameters) ?> </div>
he (eldrow form frgment is used when rendering most (elds vi the formrow funtionF o tell the form omponent to use your new (eldrow frgment de(ned oveD dd the following to the top of the templte tht renders the formX

wig
SFIIF PIW

ymfony houmenttionD PFH

{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} {% form_theme form 'AcmeTaskBundle:Form:elds.html.twig' %} <form ...>


r

<!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php --> <?php $view['form']->setTheme($form, array('AcmeTaskBundle:Form')) ?> <form ...>


he formtheme tg @in wigA imports the frgments de(ned in the given templte nd uses them when rendering the formF sn other wordsD when the formrow funtion is lled lter in this templteD it will use the (eldrow lok from your ustom theme @insted of the defult (eldrow lok tht ships with ymfonyAF o ustomize ny portion of formD you just need to override the pproprite frgmentF unowing extly whih lok or (le to override is the sujet of the next setionF por more extensive disussionD see row to ustomize porm enderingF porm prgment xming sn ymfonyD every prt form tht is rendered E rwv form elementsD errorsD lelsD et E is de(ned in se themeD whih is olletion of loks in wig nd olletion of templte (les in rF sn wigD every lok needed is de(ned in single templte (le @formdivlyoutFhtmlFtwigA tht lives inside the wig fridgeF snside this (leD you n see every lok needed to render form nd every defult (eld typeF sn rD the frgments re individul templte (lesF fy defult they re loted in the esouresGviewsGporm diretory of the frmework undle @view on qitruAF ih frgment nme follows the sme si pttern nd is roken up into two pieesD seprted y single undersore hrter @AF e few exmples reX

(eldrow E used y formrow to render most (eldsY textrewidget E used y formwidget to render textre (eld typeY (elderrors E used y formerrors to render errors for (eldY
ih frgment follows the sme si ptternX typeprtF he type portion orresponds to the (eld type eing rendered @eFgF textreD hekoxD dteD etA wheres the prt portion

PPH

SF

ymfony houmenttionD PFH orresponds to wht is eing rendered @eFgF lelD widgetD errorsD etAF fy defultD there re R possile prts of form tht n e renderedX lel widget errors row @eFgF @eFgF @eFgF @eFgF (eldlelA (eldwidgetA (elderrorsA (eldrowA renders renders renders renders the the the the (eld9s (eld9s (eld9s (eld9s lel rwv representtion errors entire row @lelD widget 8 errorsA

X here re tully Q other prts E rowsD restD nd entype E ut you should rrely if ever need to worry out overriding themF fy knowing the (eld type @eFgF textreA nd whih prt you wnt to ustomize @eFgF widgetAD you n onstrut the frgment nme tht needs to e overridden @eFgF textrewidgetAF emplte prgment snheritne sn some sesD the frgment you wnt to ustomize will pper to e missingF por exmpleD there is no textreerrors frgment in the defult themes provided with ymfonyF o how re the errors for textre (eld renderedc he nswer isX vi the (elderrors frgmentF hen ymfony renders the errors for textre typeD it looks (rst for textreerrors frgment efore flling k to the (elderrors frgmentF ih (eld type hs prent type @the prent type of textre is (eldAD nd ymfony uses the frgment for the prent type if the se frgment doesn9t existF oD to override the errors for only textre (eldsD opy the (elderrors frgmentD renme it to textreerrors nd ustomize itF o override the defult error rendering for ll (eldsD opy nd ustomize the (elderrors frgment diretlyF X he prent type of eh (eld type is ville in the form type referene for eh (eld typeF

qlol porm heming sn the ove exmpleD you used the formtheme helper @in wigA to import the ustom form frgments into just tht formF ou n lso tell ymfony to import form ustomiztions ross your entire projetF

Twig
o utomtilly inlude the ustomized loks from the (eldsFhtmlFtwig templte reted erlier in ll templtesD modify your pplition on(gurtion (leX

SFIIF

PPI

ymfony houmenttionD PFH

ewv

# app/cong/cong.yml twig: form: resources: - 'AcmeTaskBundle:Form:elds.html.twig' # ...


wv

<!-- app/cong/cong.xml --> <twig:cong ...> <twig:form> <resource>AcmeTaskBundle:Form:elds.html.twig</resource> </twig:form> <!-- ... --> </twig:cong>
r

// app/cong/cong.php $container->loadFromExtension('twig', array( 'form' => array('resources' => array( 'AcmeTaskBundle:Form:elds.html.twig', )) // ... ));
eny loks inside the (eldsFhtmlFtwig templte re now used glolly to de(ne form outputF

PPP

SF

ymfony houmenttionD PFH gustomizing porm yutput ll in ingle pile with wig sn wigD you n lso ustomize form lok right inside the templte where tht ustomiztion is neededX

{% extends '::base.html.twig' %} {# import "_self" as the form theme #} {% form_theme form _self %} {# make the form fragment customization #} {% block eld_row %} {# custom eld row output #} {% endblock eld_row %} {% block content %} {# ... #} {{ form_row(form.task) }} {% endblock %}
he {7 formtheme form self 7} tg llows form loks to e ustomized diretly inside the templte tht will use those ustomiztionsF se this method to quikly mke form output ustomiztions tht will only ever e needed in single templteF

PHP
o utomtilly inlude the ustomized templtes from the emeGskfundleGesouresGviewsGporm diretory reted erlier in ll templtesD modify your pplition on(gurtion (leX

ewv

# app/cong/cong.yml framework: templating: form: resources: - 'AcmeTaskBundle:Form' # ...


wv

<!-- app/cong/cong.xml --> <framework:cong ...>


SFIIF PPQ

ymfony houmenttionD PFH

<framework:templating> <framework:form> <resource>AcmeTaskBundle:Form</resource> </framework:form> </framework:templating> <!-- ... --> </framework:cong>


r

// app/cong/cong.php $container->loadFromExtension('framework', array( 'templating' => array('form' => array('resources' => array( 'AcmeTaskBundle:Form', ))) // ... ));
eny frgments inside the emeGskfundleGesouresGviewsGporm diretory re now used glolly to de(ne form outputF
5.11.10 CSRF Protection

gp E or grossEsite request forgery E is method y whih mliious user ttempts to mke your legitimte users unknowingly sumit dt tht they don9t intend to sumitF portuntelyD gp ttks n e prevented y using gp token inside your formsF he good news is thtD y defultD ymfony emeds nd vlidtes gp tokens utomtilly for youF his mens tht you n tke dvntge of the gp protetion without doing nythingF sn ftD every form in this hpter hs tken dvntge of the gp protetion3 gp protetion works y dding hidden (eld to your form E lled token y defult E tht ontins vlue tht only you nd your user knowsF his ensures tht the user E not some other entity E is sumitting the given dtF ymfony utomtilly vlidtes the presene nd ury of this tokenF he token (eld is hidden (eld nd will e utomtilly rendered if you inlude the formrest@A funtion in your templteD whih ensures tht ll unErendered (elds re outputF he gp token n e ustomized on formEyEform sisF por exmpleX

class TaskType extends AbstractType { // ...

PPR

SF

ymfony houmenttionD PFH

public function getDefaultOptions(array $options) { return array( 'data_class' => 'Acme\TaskBundle\Entity\Task', 'csrf_protection' => true, 'csrf_eld_name' => '_token', // a unique key to help generate the secret token 'intention' => 'task_item', ); } } // ...

o disle gp protetionD set the srfprotetion option to flseF gustomiztions n lso e mde glolly in your projetF por more informtionD see the form on(gurtion referene setionF X he intention option is optionl ut gretly enhnes the seurity of the generted token y mking it di'erent for eh formF

5.11.11 Final Thoughts

ou now know ll of the uilding loks neessry to uild omplex nd funtionl forms for your pplitionF hen uilding formsD keep in mind tht the (rst gol of form is to trnslte dt from n ojet @skA to n rwv form so tht the user n modify tht dtF he seond gol of form is to tke the dt sumitted y the user nd to reEpply it to the ojetF here9s still muh more to lern out the powerful world of formsD suh s how to hndle (le uplods with hotrine or how to rete form where dynmi numer of suEforms n e dded @eFgF todo list where you n keep dding more (elds vi tvsript efore sumittingAF ee the ookook for these topisF elsoD e sure to len on the (eld type referene doumenttionD whih inludes exmples of how to use eh (eld type nd its optionsF
5.11.12 Learn more from the Cookbook

row to hndle pile plods with hotrine pile pield eferene greting gustom pield ypes row to ustomize porm endering
SFIIF PPS

ymfony houmenttionD PFH

5.12 Security

eurity is twoEstep proess whose gol is to prevent user from essing resoure tht heGshe should not hve ess toF sn the (rst step of the proessD the seurity system identi(es who the user is y requiring the user to sumit some sort of identi(tionF his is lled uthentitionD nd it mens tht the system is trying to (nd out who you reF yne the system knows who you reD the next step is to determine if you should hve ess to given resoureF his prt of the proess is lled uthoriztionD nd it mens tht the system is heking to see if you hve privileges to perform ertin tionF

ine the est wy to lern is to see n exmpleD let9s dive right inF X ymfony9s seurity omponent is ville s stndlone r lirry for use inside ny r projetF

5.12.1 Basic Example: HTTP Authentication

he seurity omponent n e on(gured vi your pplition on(gurtionF sn ftD most stndrd seurity setups re just mtter of using the right on(gurtionF he following on(gurtion tells ymfony to seure ny v mthing GdminGB nd to sk the user for redentils using si r uthentition @iFeF the oldEshool usernmeGpssword oxAX PPT SF

ymfony houmenttionD PFH

ewv

# app/cong/security.yml security: rewalls: secured_area: pattern: ^/ anonymous: ~ http_basic: realm: "Secured Demo Area" access_control: - { path: ^/admin, roles: ROLE_ADMIN } providers: in_memory: users: ryan: { password: ryanpass, roles: 'ROLE_USER' } admin: { password: kitten, roles: 'ROLE_ADMIN' } encoders: Symfony\Component\Security\Core\User\User: plaintext
wv

<!-- app/cong/security.xml --> <srv:container xmlns="http://symfony.com/schema/dic/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:srv="http://symfony.com/schema/dic/services" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services <cong> <rewall name="secured_area" pattern="^/"> <anonymous /> <http-basic realm="Secured Demo Area" /> </rewall> <access-control> <rule path="^/admin" role="ROLE_ADMIN" /> </access-control> <provider name="in_memory"> <user name="ryan" password="ryanpass" roles="ROLE_USER" /> <user name="admin" password="kitten" roles="ROLE_ADMIN" /> </provider> <encoder class="Symfony\Component\Security\Core\User\User" algorithm="plaintext" /> </cong>
SFIPF eurity PPU

ymfony houmenttionD PFH

</srv:container>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'secured_area' => array( 'pattern' => '^/', 'anonymous' => array(), 'http_basic' => array( 'realm' => 'Secured Demo Area', ), ), ), 'access_control' => array( array('path' => '^/admin', 'role' => 'ROLE_ADMIN'), ), 'providers' => array( 'in_memory' => array( 'users' => array( 'ryan' => array('password' => 'ryanpass', 'roles' => 'ROLE_USER'), 'admin' => array('password' => 'kitten', 'roles' => 'ROLE_ADMIN'), ), ), ), 'encoders' => array( 'Symfony\Component\Security\Core\User\User' => 'plaintext', ), ));
X e stndrd ymfony distriution seprtes the seurity on(gurtion into seprte (le @eFgF ppGon(gGseurityFymlAF sf you don9t hve seprte seurity (leD you n put the on(gurtion diretly into your min on(g (le @eFgF ppGon(gGon(gFymlAF he end result of this on(gurtion is fullyEfuntionl seurity system tht looks like the followingX

here re two users in the system @ryn nd dminAY sers uthentite themselves vi the si r uthentition promptY eny v mthing GdminGB is seuredD nd only the dmin user n ess itY ell vs not mthing GdminGB re essile y ll users @nd the user is never prompted to loginAF

PPV

SF

ymfony houmenttionD PFH vet9s look rie)y t how seurity works nd how eh prt of the on(gurtion omes into plyF
5.12.2 How Security Works: Authentication and Authorization

ymfony9s seurity system works y determining who user is @iFeF uthentitionA nd then heking to see if tht user should hve ess to spei( resoure or vF pirewlls @euthentitionA hen user mkes request to v tht9s proteted y (rewllD the seurity system is tivtedF he jo of the (rewll is to determine whether or not the user needs to e uthentitedD nd if he doesD to send response k to the user inititing the uthentition proessF e (rewll is tivted when the v of n inoming request mthes the on(gured (rewll9s regulr expression pttern on(g vlueF sn this exmpleD the pttern @GA will mth every inoming requestF he ft tht the (rewll is tivted does not menD howeverD tht the r uthentition usernme nd pssword ox is displyed for every vF por exmpleD ny user n ess Gfoo without eing prompted to uthentiteF

SFIPF eurity

PPW

ymfony houmenttionD PFH his works (rst euse the (rewll llows nonymous users vi the nonymous on(gurtion prmeterF sn other wordsD the (rewll doesn9t require the user to fully uthentite immeditelyF end euse no speil role is needed to ess Gfoo @under the essontrol setionAD the request n e ful(lled without ever sking the user to uthentiteF sf you remove the nonymous keyD the (rewll will lwys mke user fully uthentite immeditelyF eess gontrols @euthoriztionA sf user requests GdminGfooD howeverD the proess ehves di'erentlyF his is euse of the essontrol on(gurtion setion tht sys tht ny v mthing the regulr expression pttern Gdmin @iFeF Gdmin or nything mthing GdminGBA requires the yviehwsx roleF oles re the sis for most uthoriztionX user n ess GdminGfoo only if it hs the yviehwsx roleF

vike eforeD when the user originlly mkes the requestD the (rewll doesn9t sk for ny identi(tionF roweverD s soon s the ess ontrol lyer denies the user ess PQH SF

ymfony houmenttionD PFH @euse the nonymous user doesn9t hve the yviehwsx roleAD the (rewll jumps into tion nd initites the uthentition proessF he uthentition proess depends on the uthentition mehnism you9re usingF por exmpleD if you9re using the form login uthentition methodD the user will e redireted to the login pgeF sf you9re using r uthentitionD the user will e sent n r RHI response so tht the user sees the usernme nd pssword oxF he user now hs the opportunity to sumit its redentils k to the pplitionF sf the redentils re vlidD the originl request n e reEtriedF

sn this exmpleD the user ryn suessfully uthentites with the (rewllF fut sine ryn doesn9t hve the yviehwsx roleD he9s still denied ess to GdminGfooF ltimtelyD this mens tht the user will see some sort of messge inditing tht ess hs een deniedF X hen ymfony denies the user essD the user sees n error sreen nd reeives RHQ r sttus ode @poriddenAF ou n ustomize the ess denied error sreen y following the diretions in the irror ges ookook entry to ustomize the RHQ error pgeF

SFIPF eurity

PQI

ymfony houmenttionD PFH pinllyD if the dmin user requests GdminGfooD similr proess tkes pleD exept nowD fter eing uthentitedD the ess ontrol lyer will let the request pss throughX

he request )ow when user requests proteted resoure is strightforwrdD ut inredily )exileF es you9ll see lterD uthentition n e hndled in ny numer of wysD inluding vi form loginD FSHW erti(teD or y uthentiting the user vi witterF egrdless of the uthentition methodD the request )ow is lwys the smeX IF e user esses proteted resoureY PF he pplition redirets the user to the login formY QF he user sumits its redentils @eFgF usernmeGpsswordAY RF he (rewll uthentites the userY SF he uthentited user reEtries the originl requestF X he ext proess tully depends little it on whih uthentition mehnism you9re usingF por exmpleD when using form loginD the user sumits its redentils to one v tht proesses the form @eFgF GloginhekA nd then is redireted k to the originlly requested v @eFgF GdminGfooAF fut with r uthentitionD the user sumits its redentils diretly to the originl v @eFgF GdminGfooA nd then the pge is PQP SF

ymfony houmenttionD PFH returned to the user in tht sme request @iFeF no rediretAF hese types of idiosynrsies shouldn9t use you ny prolemsD ut they9re good to keep in mindF

X ou9ll lso lern lter how nything n e seured in ymfonyPD inluding spei( ontrollersD ojetsD or even r methodsF

5.12.3 Using a Traditional Login Form

o frD you9ve seen how to lnket your pplition eneth (rewll nd then protet ess to ertin res with rolesF fy using r euthentitionD you n e'ortlessly tp into the ntive usernmeGpssword ox o'ered y ll rowsersF roweverD ymfony supports mny uthentition mehnisms out of the oxF por detils on ll of themD see the eurity gon(gurtion efereneF sn this setionD you9ll enhne this proess y llowing the user to uthentite vi trditionl rwv login formF pirstD enle form login under your (rewllX

ewv

# app/cong/cong.yml security: rewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: /login check_path: /login_check
wv

<!-- app/cong/cong.xml --> <srv:container xmlns="http://symfony.com/schema/dic/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:srv="http://symfony.com/schema/dic/services" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services <cong> <rewall name="secured_area" pattern="^/"> <anonymous /> <form-login login_path="/login" check_path="/login_check" />
SFIPF eurity PQQ

ymfony houmenttionD PFH

</rewall> </cong> </srv:container>


r

// app/cong/cong.php $container->loadFromExtension('security', array( 'rewalls' => array( 'secured_area' => array( 'pattern' => '^/', 'anonymous' => array(), 'form_login' => array( 'login_path' => '/login', 'check_path' => '/login_check', ), ), ), ));
X sf you don9t need to ustomize your loginpth or hekpth vlues @the vlues used here re the defult vluesAD you n shorten your on(gurtionX

ewv

form_login: ~
wv

<form-login />
r

'form_login' => array(),


xowD when the seurity system initites the uthentition proessD it will rediret the user to the login form @Glogin y defultAF smplementing this login form visully is your joF pirstD rete two routesX one tht will disply the login form @iFeF GloginA nd one tht will hndle the login form sumission @iFeF GloginhekAX

ewv

# app/cong/routing.yml login: pattern: /login defaults: { _controller: AcmeSecurityBundle:Security:login }

PQR

SF

ymfony houmenttionD PFH

login_check: pattern: /login_check


wv

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="login" pattern="/login"> <default key="_controller">AcmeSecurityBundle:Security:login</default> </route> <route id="login_check" pattern="/login_check" /> </routes>
r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('login', new Route('/login', array( '_controller' => 'AcmeDemoBundle:Security:login', ))); $collection->add('login_check', new Route('/login_check', array())); return $collection;
X ou will not need to implement ontroller for the Gloginhek v s the (rewll will utomtilly th nd proess ny form sumitted to this vF st9s optionlD ut helpfulD to rete route so tht you n use it to generte the form sumission v in the login templte elowF xotie tht the nme of the login route isn9t importntF ht9s importnt is tht the v of the route @GloginA mthes the loginpth on(g vlueD s tht9s where the seurity system will rediret users tht need to loginF xextD rete the ontroller tht will disply the login formX

// src/Acme/SecurityBundle/Controller/Main; namespace Acme\SecurityBundle\Controller;


SFIPF eurity PQS

ymfony houmenttionD PFH

use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Security\Core\SecurityContext; class SecurityController extends Controller { public function loginAction() { $request = $this->getRequest(); $session = $request->getSession(); // get the login error if there is one if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); } else { $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); } return $this->render('AcmeSecurityBundle:Security:login.html.twig', array( // last username entered by the user 'last_username' => $session->get(SecurityContext::LAST_USERNAME), 'error' => $error, ));

hon9t let this ontroller onfuse youF es you9ll see in momentD when the user sumits the formD the seurity system utomtilly hndles the form sumission for youF sf the user hd sumitted n invlid usernme or psswordD this ontroller reds the form sumission error from the seurity system so tht it n e displyed k to the userF sn other wordsD your jo is to disply the login form nd ny login errors tht my hve ourredD ut the seurity system itself tkes re of heking the sumitted usernme nd pssword nd uthentiting the userF pinllyD rete the orresponding templteX

wig

{# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #} {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('login_check') }}" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label>
PQT SF

ymfony houmenttionD PFH

<input type="password" id="password" name="_password" /> {# #} If you want to control the URL the user is redirected to on success (more details below) <input type="hidden" name="_target_path" value="/account" />

<input type="submit" name="login" /> </form>


r

<?php // src/Acme/SecurityBundle/Resources/views/Security/login.html.php ?> <?php if ($error): ?> <div><?php echo $error->getMessage() ?></div> <?php endif; ?> <form action="<?php echo $view['router']->generate('login_check') ?>" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="<?php echo $last_username ?>" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <!-If you want to control the URL the user is redirected to on success (more details below) <input type="hidden" name="_target_path" value="/account" /> --> <input type="submit" name="login" /> </form>
X he error vrile pssed into the templte is n instne of ymfonygomponenteuritygoreixeptioneuthentitionixeptionF st my ontin more informtion E or even sensitive informtion E out the uthentition filureD so use it wisely3 he form hs very few requirementsF pirstD y sumitting the form to Gloginhek @vi the loginhek routeAD the seurity system will interept the form sumission nd proess the form for you utomtillyF eondD the seurity system expets the sumitted (elds to e lled usernme nd pssword @these (eld nmes n e on(guredAF end tht9s it3 hen you sumit the formD the seurity system will utomtilly hek the user9s redentils nd either uthentite the user or send the user k to the login form where the error n e displyedF

SFIPF eurity

PQU

ymfony houmenttionD PFH vet9s review the whole proessX IF he user tries to ess resoure tht is protetedY PF he (rewll initites the uthentition proess y redireting the user to the login form @GloginAY QF he Glogin pge renders login form vi the route nd ontroller reted in this exmpleY RF he user sumits the login form to GloginhekY SF he seurity system interepts the requestD heks the user9s sumitted redentilsD uthentites the user if they re orretD nd sends the user k to the login form if they re notF fy defultD if the sumitted redentils re orretD the user will e redireted to the originl pge tht ws requested @eFgF GdminGfooAF sf the user originlly went stright to the login pgeD he9ll e redireted to the homepgeF his n e highly ustomizedD llowing you toD for exmpleD rediret the user to spei( vF por more detils on this nd how to ustomize the form login proess in generlD see row to ustomize your porm voginF

PQV

SF

ymfony houmenttionD PFH evoid gommon itflls hen setting up your login formD wth out for few ommon pitfllsF IF grete the orret routes pirstD e sure tht you9ve de(ned the Glogin nd Gloginhek routes orretly nd tht they orrespond to the loginpth nd hekpth on(g vluesF e mison(gurtion here n men tht you9re redireted to RHR pge insted of the login pgeD or tht sumitting the login form does nothing @you just see the login form over nd over ginAF PF fe sure the login pge isn9t seure elsoD e sure tht the login pge does not require ny roles to e viewedF por exmpleD the following on(gurtion E whih requires the yviehwsx role for ll vs @inluding the Glogin vAD will use rediret loopX ewv

access_control: - { path: ^/, roles: ROLE_ADMIN }


wv

<access-control> <rule path="^/" role="ROLE_ADMIN" /> </access-control>


r

'access_control' => array( array('path' => '^/', 'role' => 'ROLE_ADMIN'), ),


emoving the ess ontrol on the Glogin v (xes the prolemX ewv

access_control: - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/, roles: ROLE_ADMIN }


wv

<access-control> <rule path="^/login" role="IS_AUTHENTICATED_ANONYMOUSLY" /> <rule path="^/" role="ROLE_ADMIN" /> </access-control>
r

'access_control' => array( array('path' => '^/login', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), array('path' => '^/', 'role' => 'ROLE_ADMIN'), ),
elsoD if your (rewll does not llow for nonymous usersD you9ll need to rete speil (rewll tht llows nonymous users for the login pgeX ewv SFIPF eurity rewalls:

login_rewall: pattern: ^/login$

PQW

ymfony houmenttionD PFH


5.12.4 Authorization

he (rst step in seurity is lwys uthentitionX the proess of verifying who the user isF ith ymfonyD uthentition n e done in ny wy E vi form loginD si r euthentitionD or even vi peookF yne the user hs een uthentitedD uthoriztion eginsF euthoriztion provides stndrd nd powerful wy to deide if user n ess ny resoure @ vD model ojetD method llD FFFAF his works y ssigning spei( roles to eh userD nd then requiring di'erent roles for di'erent resouresF he proess of uthoriztion hs two di'erent sidesX IF he user hs spei( set of rolesY PF e resoure requires spei( role in order to e essedF sn this setionD you9ll fous on how to seure di'erent resoures @eFgF vsD method llsD etA with di'erent rolesF vterD you9ll lern more out how roles re reted nd ssigned to usersF euring pei( v tterns he most si wy to seure prt of your pplition is to seure n entire v ptternF ou9ve seen this lredy in the (rst exmple of this hpterD where nything mthing the regulr expression pttern Gdmin requires the yviehwsx roleF ou n de(ne s mny v ptterns s you need E eh is regulr expressionF

ewv

# app/cong/cong.yml security: # ... access_control: - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN } - { path: ^/admin, roles: ROLE_ADMIN }
wv

<!-- app/cong/cong.xml --> <cong> <!-- ... --> <rule path="^/admin/users" role="ROLE_SUPER_ADMIN" /> <rule path="^/admin" role="ROLE_ADMIN" /> </cong>
r

PRH

SF

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('security', array( // ... 'access_control' => array( array('path' => '^/admin/users', 'role' => 'ROLE_SUPER_ADMIN'), array('path' => '^/admin', 'role' => 'ROLE_ADMIN'), ), ));
X repending the pth with ensures tht only vs eginning with the pttern re mthedF por exmpleD pth of simply Gdmin @without the A would orretly mth GdminGfoo ut would lso mth vs like GfooGdminF por eh inoming requestD ymfonyP tries to (nd mthing ess ontrol rule @the (rst one winsAF sf the user isn9t uthentited yetD the uthentition proess is initited @iFeF the user is given hne to loginAF roweverD if the user is uthentited ut doesn9t hve the required roleD n ymfonygomponenteuritygoreixeptioneessheniedixeption exeption is thrownD whih you n hndle nd turn into nie ess denied error pge for the userF ee for more informtionF ine ymfony uses the (rst ess ontrol rule it mthesD v like GdminGusersGnew will mth the (rst rule nd require only the yviiehwsx roleF eny v like GdminGlog will mth the seond rule nd require yviehwsxF euring y s gertin situtions my rise when you my need to restrit ess to given route sed on sF his is prtiulrly relevnt in the se of idge ide snludes @isAD for exmpleD whih utilize route nmed internlF hen is is usedD the internl route is required y the gtewy he to enle di'erent hing options for susetions within given pgeF his route omes with the Ginternl pre(x y defult in the stndrd edition @ssuming you9ve unommented those lines from the routing (leAF rere is n exmple of how you might seure this route from outside essX

ewv

# app/cong/security.yml security: # ... access_control: - { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
wv

SFIPF eurity

PRI

ymfony houmenttionD PFH

<access-control> <rule path="^/_internal" role="IS_AUTHENTICATED_ANONYMOUSLY" ip="127.0.0.1" /> </access-control>


r

'access_control' => array( array('path' => '^/_internal', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'ip' => '127.0.0 ),
euring y ghnnel wuh like seuring sed on sD requiring the use of v is s simple s dding new essontrol entryX

ewv

# app/cong/security.yml security: # ... access_control: - { path: ^/cart/checkout, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: http
wv

<access-control> <rule path="^/cart/checkout" role="IS_AUTHENTICATED_ANONYMOUSLY" requires_channel: h </access-control>


r

'access_control' => array( array('path' => '^/cart/checkout', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'requires_ch ),
euring gontroller roteting your pplition sed on v ptterns is esyD ut my not e (neEgrined enough in ertin sesF hen neessryD you n esily fore uthoriztion from inside ontrollerX

use Symfony\Component\Security\Core\Exception\AccessDeniedException // ... public function helloAction($name) {


PRP SF

ymfony houmenttionD PFH

if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); } } // ...

ou n lso hoose to instll nd use the optionl tweurityixtrfundleD whih n seure your ontroller using nnottionsX

use JMS\SecurityExtraBundle\Annotation\Secure; /** * @Secure(roles="ROLE_ADMIN") */ public function helloAction($name) { // ... }


por more informtionD see the tweurityixtrfundle doumenttionF sf you9re using ymfony9s tndrd histriutionD this undle is ville y defultF sf notD you n esily downlod nd instll itF euring other ervies sn ftD nything in ymfony n e proteted using strtegy similr to the one seen in the previous setionF por exmpleD suppose you hve servie @iFeF r lssA whose jo is to send emils from one user to notherF ou n restrit use of this lss E no mtter where it9s eing used from E to users tht hve spei( roleF por more informtion on how you n use the seurity omponent to seure di'erent servies nd methods in your pplitionD see row to seure ny ervie or wethod in your epplitionF eess gontrol vists @egvsAX euring sndividul htse yjets smgine you re designing log system where your users n omment on your postsF xowD you wnt user to e le to edit his own ommentsD ut not those of other usersF elsoD s the dmin userD you yourself wnt to e le to edit ll ommentsF he seurity omponent omes with n optionl ess ontrol list @egvA system tht you n use when you need to ontrol ess to individul instnes of n ojet in your systemF ithout egvD you n seure your system so tht only ertin users n edit log omments in generlF fut with egvD you n restrit or llow ess on ommentEyEomment sisF SFIPF eurity PRQ

ymfony houmenttionD PFH por more informtionD see the ookook rtileX eess gontrol vists @egvsAF
5.12.5 Users

sn the previous setionsD you lerned how you n protet di'erent resoures y requiring set of roles for resoureF sn this setion we9ll explore the other side of uthoriztionX usersF here do sers ome fromc @ser rovidersA huring uthentitionD the user sumits set of redentils @usully usernme nd psswordAF he jo of the uthentition system is to mth those redentils ginst some pool of usersF o where does this list of users ome fromc sn ymfonyPD users n ome from nywhere E on(gurtion (leD dtse tleD we servieD or nything else you n drem upF enything tht provides one or more users to the uthentition system is known s user providerF ymfonyP omes stndrd with the two most ommon user providersX one tht lods users from on(gurtion (le nd one tht lods users from dtse tleF

Specifying Users in a Conguration File


he esiest wy to speify your users is diretly in on(gurtion (leF sn ftD you9ve seen this lredy in the exmple in this hpterF

ewv

# app/cong/cong.yml security: # ... providers: default_provider: users: ryan: { password: ryanpass, roles: 'ROLE_USER' } admin: { password: kitten, roles: 'ROLE_ADMIN' }
wv

<!-- app/cong/cong.xml --> <cong> <!-- ... --> <provider name="default_provider"> <user name="ryan" password="ryanpass" roles="ROLE_USER" /> <user name="admin" password="kitten" roles="ROLE_ADMIN" /> </provider> </cong>
PRR SF

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('security', array( // ... 'providers' => array( 'default_provider' => array( 'users' => array( 'ryan' => array('password' => 'ryanpass', 'roles' => 'ROLE_USER'), 'admin' => array('password' => 'kitten', 'roles' => 'ROLE_ADMIN'), ), ), ), ));
his user provider is lled the inEmemory user providerD sine the users ren9t stored nywhere in dtseF he tul user ojet is provided y ymfony @ymfonygomponenteuritygoreserserAF X eny user provider n lod users diretly from on(gurtion y speifying the users on(gurtion prmeter nd listing the users eneth itF X sf your usernme is ompletely numeri @eFgF UUA or ontins dsh @eFgF userEnmeAD you should use tht lterntive syntx when speifying users in ewvX

users: - { name: 77, password: pass, roles: 'ROLE_USER' } - { name: user-name, password: pass, roles: 'ROLE_USER' }
por smller sitesD this method is quik nd esy to setupF por more omplex systemsD you9ll wnt to lod your users from the dtseF

Loading Users from the Database


sf you9d like to lod your users vi the hotrine ywD you n esily do this y reting ser lss nd on(guring the entity providerF ith this pprohD you9ll (rst rete your own ser lssD whih will e stored in the dtseF

// src/Acme/UserBundle/Entity/User.php namespace Acme\UserBundle\Entity; use Symfony\Component\Security\Core\User\UserInterface; use Doctrine\ORM\Mapping as ORM;


SFIPF eurity PRS

ymfony houmenttionD PFH

/** * @ORM\Entity */ class User implements UserInterface { /** * @ORM\Column(type="string", length="255") */ protected $username; } // ...

es fr s the seurity system is onernedD the only requirement for your ustom user lss is tht it implements the ymfonygomponenteuritygoresersersnterfe interfeF his mens tht your onept of user n e nythingD s long s it implements this interfeF X he user ojet will e serilized nd sved in the session during requestsD therefore it is reommended tht you implement the erilizle interfe in your user ojetF his is espeilly importnt if your ser lss hs prent lss with privte propertiesF xextD on(gure n entity user providerD nd point it to your ser lssX

ewv

# app/cong/security.yml security: providers: main: entity: { class: Acme\UserBundle\Entity\User, property: username }


wv

<!-- app/cong/security.xml --> <cong> <provider name="main"> <entity class="Acme\UserBundle\Entity\User" property="username" /> </provider> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'providers' => array(


PRT SF

ymfony houmenttionD PFH

));

),

'main' => array( 'entity' => array('class' => 'Acme\UserBundle\Entity\User', 'property' => 'username'), ),

ith the introdution of this new providerD the uthentition system will ttempt to lod ser ojet from the dtse y using the usernme (eld of tht lssF X his exmple is just ment to show you the si ide ehind the entity providerF por full working exmpleD see row to lod eurity sers from the htse @the entity roviderAF por more informtion on reting your own ustom provider @eFgF if you needed to lod users vi we servieAD see row to rete ustom ser roviderF inoding the ser9s ssword o frD for simpliityD ll the exmples hve stored the users9 psswords in plin text @whether those users re stored in on(gurtion (le or in dtse somewhereAF yf ourseD in rel pplitionD you9ll wnt to enode your users9 psswords for seurity resonsF his is esily omplished y mpping your ser lss to one of severl uiltEin enodersF por exmpleD to store your users in memoryD ut osure their psswords vi shID do the followingX

ewv

# app/cong/cong.yml security: # ... providers: in_memory: users: ryan: { password: bb87a29949f3a1ee0559f8a57357487151281386, roles: 'ROLE_USER' } admin: { password: 74913f5cd5f61ec0bcfdb775414c2fb3d161b620, roles: 'ROLE_ADMIN' } encoders: Symfony\Component\Security\Core\User\User: algorithm: sha1 iterations: 1 encode_as_base64: false
wv

<!-- app/cong/cong.xml --> <cong>


SFIPF eurity PRU

ymfony houmenttionD PFH

<!-- ... --> <provider name="in_memory"> <user name="ryan" password="bb87a29949f3a1ee0559f8a57357487151281386" roles="ROLE_USER <user name="admin" password="74913f5cd5f61ec0bcfdb775414c2fb3d161b620" roles="ROLE_ADM </provider>

<encoder class="Symfony\Component\Security\Core\User\User" algorithm="sha1" iterations="1" enc </cong>


r

// app/cong/cong.php $container->loadFromExtension('security', array( // ... 'providers' => array( 'in_memory' => array( 'users' => array( 'ryan' => array('password' => 'bb87a29949f3a1ee0559f8a57357487151281386', 'roles' => 'ROL 'admin' => array('password' => '74913f5cd5f61ec0bcfdb775414c2fb3d161b620', 'roles' => 'RO ), ), ), 'encoders' => array( 'Symfony\Component\Security\Core\User\User' => array( 'algorithm' => 'sha1', 'iterations' => 1, 'encode_as_base64' => false, ), ), ));
fy setting the itertions to I nd the enodesseTR to flseD the pssword is simply run through the shI lgorithm one time nd without ny extr enodingF ou n now lulte the hshed pssword either progrmmtilly @eFgF hsh@9shI9D 9rynpss9AA or vi some online tool like funtionsEonlineFom sf you9re reting your users dynmilly @nd storing them in dtseAD you n use even tougher hshing lgorithms nd then rely on n tul pssword enoder ojet to help you enode psswordsF por exmpleD suppose your ser ojet is emeserfundleintityser @like in the ove exmpleAF pirstD on(gure the enoder for tht userX

ewv

# app/cong/cong.yml security: # ... encoders:


PRV SF

ymfony houmenttionD PFH

Acme\UserBundle\Entity\User: sha512
wv

<!-- app/cong/cong.xml --> <cong> <!-- ... --> <encoder class="Acme\UserBundle\Entity\User" algorithm="sha512" /> </cong>
r

// app/cong/cong.php $container->loadFromExtension('security', array( // ... 'encoders' => array( 'Acme\UserBundle\Entity\User' => 'sha512', ),

));

sn this seD you9re using the stronger shSIP lgorithmF elsoD sine you9ve simply spei(ed the lgorithm @shSIPA s stringD the system will defult to hshing your pssword SHHH times in row nd then enoding it s seTRF sn other wordsD the pssword hs een gretly ofusted so tht the hshed pssword n9t e deoded @iFeF you n9t determine the pssword from the hshed psswordAF sf you hve some sort of registrtion form for usersD you9ll need to e le to determine the hshed pssword so tht you n set it on your userF xo mtter wht lgorithm you on(gure for your user ojetD the hshed pssword n lwys e determined in the following wy from ontrollerX

$factory = $this->get('security.encoder_factory'); $user = new Acme\UserBundle\Entity\User(); $encoder = $factory->getEncoder($user); $password = $encoder->encodePassword('ryanpass', $user->getSalt()); $user->setPassword($password);
etrieving the ser yjet efter uthentitionD the ser ojet of the urrent user n e essed vi the seurityFontext servieF prom inside ontrollerD this will look likeX

SFIPF eurity

PRW

ymfony houmenttionD PFH

public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); }


X enonymous users re tehnilly uthentitedD mening tht the iseuthentited@A method of n nonymous user ojet will return trueF o hek if your user is tully uthentitedD hek for the serixsgeihpvv roleF

sing wultiple ser roviders ih uthentition mehnism @eFgF r euthentitionD form loginD etA uses extly one user providerD nd will use the (rst delred user provider y defultF fut wht if you wnt to speify few users vi on(gurtion nd the rest of your users in the dtsec his is possile y reting new provider tht hins the two togetherX

ewv

# app/cong/security.yml security: providers: chain_provider: providers: [in_memory, user_db] in_memory: users: foo: { password: test } user_db: entity: { class: Acme\UserBundle\Entity\User, property: username }
wv

<!-- app/cong/cong.xml --> <cong> <provider name="chain_provider"> <provider>in_memory</provider> <provider>user_db</provider> </provider> <provider name="in_memory"> <user name="foo" password="test" /> </provider> <provider name="user_db"> <entity class="Acme\UserBundle\Entity\User" property="username" /> </provider> </cong>

PSH

SF

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('security', array( 'providers' => array( 'chain_provider' => array( 'providers' => array('in_memory', 'user_db'), ), 'in_memory' => array( 'users' => array( 'foo' => array('password' => 'test'), ), ), 'user_db' => array( 'entity' => array('class' => 'Acme\UserBundle\Entity\User', 'property' => 'username'), ), ), ));
xowD ll uthentition mehnisms will use the hinproviderD sine it9s the (rst spei(edF he hinprovider willD in turnD try to lod the user from oth the inmemory nd userd providersF X sf you hve no resons to seprte your inmemory users from your userd usersD you n omplish this even more esily y omining the two soures into single providerX

ewv

# app/cong/security.yml security: providers: main_provider: users: foo: { password: test } entity: { class: Acme\UserBundle\Entity\User, property: username }
wv

<!-- app/cong/cong.xml --> <cong> <provider name=="main_provider"> <user name="foo" password="test" /> <entity class="Acme\UserBundle\Entity\User" property="username" /> </provider> </cong>
r

SFIPF eurity

PSI

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('security', array( 'providers' => array( 'main_provider' => array( 'users' => array( 'foo' => array('password' => 'test'), ), 'entity' => array('class' => 'Acme\UserBundle\Entity\User', 'property' => 'username'), ), ), ));
ou n lso on(gure the (rewll or individul uthentition mehnisms to use spei( providerF eginD unless provider is spei(ed expliitlyD the (rst provider is lwys usedX

ewv

# app/cong/cong.yml security: rewalls: secured_area: # ... provider: user_db http_basic: realm: "Secured Demo Area" provider: in_memory form_login: ~
wv

<!-- app/cong/cong.xml --> <cong> <rewall name="secured_area" pattern="^/" provider="user_db"> <!-- ... --> <http-basic realm="Secured Demo Area" provider="in_memory" /> <form-login /> </rewall> </cong>
r

// app/cong/cong.php $container->loadFromExtension('security', array( 'rewalls' => array( 'secured_area' => array( // ... 'provider' => 'user_db',
PSP SF

ymfony houmenttionD PFH

));

),

),

'http_basic' => array( // ... 'provider' => 'in_memory', ), 'form_login' => array(),

sn this exmpleD if user tries to login vi r uthentitionD the uthentition system will use the inmemory user providerF fut if the user tries to login vi the form loginD the userd provider will e used @sine it9s the defult for the (rewll s wholeAF por more informtion out user provider nd (rewll on(gurtionD see the eurity gon(gurtion efereneF
5.12.6 Roles

he ide of role is key to the uthoriztion proessF ih user is ssigned set of roles nd then eh resoure requires one or more rolesF sf the user hs the required rolesD ess is grntedF ytherwise ess is deniedF oles re pretty simpleD nd re silly strings tht you n invent nd use s needed @though roles re ojets internllyAF por exmpleD if you need to strt limiting ess to the log dmin setion of your wesiteD you ould protet tht setion using yvifvyqehwsx roleF his role doesn9t need to e de(ned nywhere E you n just strt using itF X ell roles must egin with the yvi pre(x to e mnged y ymfonyPF sf you de(ne your own roles with dedited ole lss @more dvnedAD don9t use the yvi pre(xF

rierrhil oles snsted of ssoiting mny roles to usersD you n de(ne role inheritne rules y reting role hierrhyX

ewv

# app/cong/security.yml security: role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]


SFIPF eurity PSQ

ymfony houmenttionD PFH

wv

<!-- app/cong/security.xml --> <cong> <role id="ROLE_ADMIN">ROLE_USER</role> <role id="ROLE_SUPER_ADMIN">ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH</role> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'role_hierarchy' => array( 'ROLE_ADMIN' => 'ROLE_USER', 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), ), ));
sn the ove on(gurtionD users with yviehwsx role will lso hve the yvii roleF he yviiehwsx role hs yviehwsxD yvievvyihysgr nd yvii @inherited from yviehwsxAF
5.12.7 Logging Out

sullyD you9ll lso wnt your users to e le to log outF portuntelyD the (rewll n hndle this utomtilly for you when you tivte the logout on(g prmeterX

ewv

# app/cong/cong.yml security: rewalls: secured_area: # ... logout: path: /logout target: / # ...
wv

<!-- app/cong/cong.xml --> <cong> <rewall name="secured_area" pattern="^/"> <!-- ... --> <logout path="/logout" target="/" /> </rewall>
PSR SF

ymfony houmenttionD PFH

<!-- ... --> </cong>


r

// app/cong/cong.php $container->loadFromExtension('security', array( 'rewalls' => array( 'secured_area' => array( // ... 'logout' => array('path' => 'logout', 'target' => '/'), ), ), // ... ));
yne this is on(gured under your (rewllD sending user to Glogout @or whtever you on(gure the pth to eAD will unEuthentite the urrent userF he user will then e sent to the homepge @the vlue de(ned y the trget prmeterAF foth the pth nd trget on(g prmeters defult to wht9s spei(ed hereF sn other wordsD unless you need to ustomize themD you n omit them entirely nd shorten your on(gurtionX

ewv

logout: ~
wv

<logout />
r

'logout' => array(),


xote tht you will not need to implement ontroller for the Glogout v s the (rewll tkes re of everythingF ou myD howeverD wnt to rete route so tht you n use it to generte the vX

ewv

# app/cong/routing.yml logout: pattern: /logout


wv

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

SFIPF eurity

PSS

ymfony houmenttionD PFH

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="logout" pattern="/logout" /> </routes>
r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('logout', new Route('/logout', array())); return $collection;
yne the user hs een logged outD he will e redireted to whtever pth is de(ned y the trget prmeter ove @eFgF the homepgeAF por more informtion on on(guring the logoutD see the eurity gon(gurtion efereneF
5.12.8 Access Control in Templates

sf you wnt to hek if the urrent user hs role inside templteD use the uiltEin helper funtionX

wig

{% if is_granted('ROLE_ADMIN') %} <a href="...">Delete</a> {% endif %}


r

<?php if ($view['security']->isGranted('ROLE_ADMIN')): ?> <a href="...">Delete</a> <?php endif; ?>


X sf you use this funtion nd re not t v where there is (rewll tiveD n exeption will e thrownF eginD it9s lmost lwys good ide to hve min (rewll tht overs ll vs @s hs een shown in this hpterAF

PST

SF

ymfony houmenttionD PFH


5.12.9 Access Control in Controllers

sf you wnt to hek if the urrent user hs role in your ontrollerD use the isqrnted method of the seurity ontextX

public function indexAction() { // show dierent content to admin users if($this->get('security.context')->isGranted('ADMIN')) { // Load admin content here } // load other regular content here }
X e (rewll must e tive or n exeption will e thrown when the isqrnted method is lledF ee the note ove out templtes for more detilsF

5.12.10 Impersonating a User

ometimesD it9s useful to e le to swith from one user to nother without hving to logout nd login gin @for instne when you re deugging or trying to understnd ug user sees tht you n9t reprodueAF his n e esily done y tivting the swithuser (rewll listenerX

ewv

# app/cong/security.yml security: rewalls: main: # ... switch_user: true


wv

<!-- app/cong/security.xml --> <cong> <rewall> <!-- ... --> <switch-user /> </rewall> </cong>
r

SFIPF eurity

PSU

ymfony houmenttionD PFH

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main'=> array( // ... 'switch_user' => true ), ), ));
o swith to nother userD just dd query string with the swithuser prmeter nd the usernme s the vlue to the urrent vX httpXGGexmpleFomGsomewherecswithuserathoms o swith k to the originl userD use the speil exit usernmeX httpXGGexmpleFomGsomewherecswithuseraexit yf ourseD this feture needs to e mde ville to smll group of usersF fy defultD ess is restrited to users hving the yvievvyihysgr roleF he nme of this role n e modi(ed vi the role settingF por extr seurityD you n lso hnge the query prmeter nme vi the prmeter settingX

ewv

# app/cong/security.yml security: rewalls: main: // ... switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
wv

<!-- app/cong/security.xml --> <cong> <rewall> <!-- ... --> <switch-user role="ROLE_ADMIN" parameter="_want_to_be_this_user" /> </rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main'=> array(


PSV SF

ymfony houmenttionD PFH

));

),

),

// ... 'switch_user' => array('role' => 'ROLE_ADMIN', 'parameter' => '_want_to_be_this_user'),

5.12.11 Stateless Authentication

fy defultD ymfonyP relies on ookie @the essionA to persist the seurity ontext of the userF fut if you use erti(tes or r uthentition for instneD persistene is not needed s redentils re ville for eh requestF sn tht seD nd if you don9t need to store nything else etween requestsD you n tivte the stteless uthentition @whih mens tht no ookie will e ever reted y ymfonyPAX

ewv

# app/cong/security.yml security: rewalls: main: http_basic: ~ stateless: true


wv

<!-- app/cong/security.xml --> <cong> <rewall stateless="true"> <http-basic /> </rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('http_basic' => array(), 'stateless' => true), ), ));
X sf you use form loginD ymfonyP will rete ookie even if you set stteless to trueF

SFIPF eurity

PSW

ymfony houmenttionD PFH


5.12.12 Final Words

eurity n e deep nd omplex issue to solve orretly in your pplitionF portuntelyD ymfony9s seurity omponent follows wellEproven seurity model sed round uthentition nd uthoriztionF euthentitionD whih lwys hppens (rstD is hndled y (rewll whose jo is to determine the identity of the user through severl di'erent methods @eFgF r uthentitionD login formD etAF sn the ookookD you9ll (nd exmples of other methods for hndling uthentitionD inluding how to implement rememer me ookie funtionlityF yne user is uthentitedD the uthoriztion lyer n determine whether or not the user should hve ess to spei( resoureF wost ommonlyD roles re pplied to vsD lsses or methods nd if the urrent user doesn9t hve tht roleD ess is deniedF he uthoriztion lyerD howeverD is muh deeperD nd follows system of voting so tht multiple prties n determine if the urrent user should hve ess to given resoureF pind out more out this nd other topis in the ookookF
5.12.13 Learn more from the Cookbook

poring rGr flklist users y s ddress with ustom voter eess gontrol vists @egvsA row to dd ememer we vogin puntionlity

5.13 HTTP Cache

he nture of rih we pplitions mens tht they9re dynmiF xo mtter how e0ient your pplitionD eh request will lwys ontin more overhed thn serving stti (leF end for most e pplitionsD tht9s (neF ymfonyP is lightning fstD nd unless you9re doing some serious hevyEliftingD eh request will ome k quikly without putting too muh stress on your serverF fut s your site growsD tht overhed n eome prolemF he proessing tht9s normlly performed on every request should e done only oneF his is extly wht hing ims to omplishF
5.13.1 Caching on the Shoulders of Giants

he most e'etive wy to improve performne of n pplition is to he the full output of pge nd then ypss the pplition entirely on eh susequent requestF yf ourseD PTH SF

ymfony houmenttionD PFH this isn9t lwys possile for highly dynmi wesitesD or is itc sn this hpterD we9ll show you how the ymfonyP he system works nd why we think this is the est possile pprohF he ymfonyP he system is di'erent euse it relies on the simpliity nd power of the r he s de(ned in the r spei(tionF snsted of reinventing hing methodologyD ymfonyP emres the stndrd tht de(nes si ommunition on the eF yne you understnd the fundmentl r vlidtion nd expirtion hing modelsD you9ll e redy to mster the ymfonyP he systemF por the purposes of lerning how to he with ymfonyPD we9ll over the sujet in four stepsX

tep IX e gtewy heD or reverse proxyD is n independent lyer tht sits in front of your pplitionF he reverse proxy hes responses s they9re returned from your pplition nd nswers requests with hed responses efore they hit your pplitionF ymfonyP provides its own reverse proxyD ut ny reverse proxy n e usedF tep PX r he heders re used to ommunite with the gtewy he nd ny other hes etween your pplition nd the lientF ymfonyP provides sensile defults nd powerful interfe for interting with the he hedersF tep QX r expirtion nd vlidtion re the two models used for determining whether hed ontent is fresh @n e reused from the heA or stle @should e regenerted y the pplitionAF tep RX idge ide snludes @isA llow r he to e used to he pge frgments @even nested frgmentsA independentlyF ith isD you n even he n entire pge for TH minutesD ut n emedded sider for only S minutesF
ine hing with r isn9t unique to ymfonyD mny rtiles lredy exist on the topiF sf you9re new to r hingD we highly reommend yn omyko9s rtile hings ghes hoF enother inEdepth resoure is wrk xottinghm9s ghe utorilF
5.13.2 Caching with a Gateway Cache

hen hing with rD the he is seprted from your pplition entirely nd sits etween your pplition nd the lient mking the requestF he jo of the he is to ept requests from the lient nd pss them k to your pplitionF he he will lso reeive responses k from your pplition nd forwrd them on to the lientF he he is the middleEmn of the requestEresponse ommunition etween the lient nd your pplitionF elong the wyD the he will store eh response tht is deemed hele @ee sntrodution to r ghingAF sf the sme resoure is requested ginD the he sends the hed response to the lientD ignoring your pplition entirelyF

SFIQF r ghe

PTI

ymfony houmenttionD PFH his type of he is known s r gtewy he nd mny exist suh s rnishD quid in reverse proxy modeD nd the ymfonyP reverse proxyF ypes of ghes fut gtewy he isn9t the only type of heF sn ftD the r he heders sent y your pplition re onsumed nd interpreted y up to three di'erent types of hesX

frowser hesX ivery rowser omes with its own lol he tht is minly useful for when you hit k or for imges nd other ssetsF he rowser he is privte he s hed resoures ren9t shred with nyone elseF roxy hesX e proxy is shred he s mny people n e ehind single oneF st9s usully instlled y lrge orportions nd ss to redue lteny nd network tr0F qtewy hesX vike proxyD it9s lso shred he ut on the server sideF snstlled y network dministrtorsD it mkes wesites more slleD relile nd performntF
X qtewy hes re sometimes referred to s reverse proxy hesD surrogte hesD or even r elertorsF

X he signi(ne of privte versus shred hes will eome more ovious s we tlk out hing responses ontining ontent tht is spei( to extly one user @eFgF ount informtionAF ih response from your pplition will likely go through one or oth of the (rst two he typesF hese hes re outside of your ontrol ut follow the r he diretions set in the responseF ymfonyP everse roxy ymfonyP omes with reverse proxy @lso lled gtewy heA written in rF inle it nd hele responses from your pplition will strt to e hed right wyF snstlling it is just s esyF ih new ymfonyP pplition omes with preEon(gured hing kernel @eppgheA tht wrps the defult one @eppuernelAF he hing uernel is the reverse proxyF o enle hingD modify the ode of front ontroller to use the hing kernelX

// web/app.php require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../app/AppKernel.php';


PTP SF

ymfony houmenttionD PFH

require_once __DIR__.'/../app/AppCache.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('prod', false); $kernel->loadClassCache(); // wrap the default AppKernel with the AppCache one $kernel = new AppCache($kernel); $kernel->handle(Request::createFromGlobals())->send();
he hing kernel will immeditely t s reverse proxy E hing responses from your pplition nd returning them to the lientF X he he kernel hs speil getvog@A method tht returns string representtion of wht hppened in the he lyerF sn the development environmentD use it to deug nd vlidte your he strtegyX

error_log($kernel->getLog());
he eppghe ojet hs sensile defult on(gurtionD ut it n e (nely tuned vi set of options you n set y overriding the getyptions@A methodX

// app/AppCache.php class AppCache extends Cache { protected function getOptions() { return array( 'debug' => false, 'default_ttl' => 0, 'private_headers' => array('Authorization', 'Cookie'), 'allow_reload' => false, 'allow_revalidate' => false, 'stale_while_revalidate' => 2, 'stale_if_error' => 60, ); } }
X nless overridden in getyptions@AD the deug option will e set to utomtilly e the deug vlue of the wrpped eppuernelF rere is list of the min optionsX

defultttlX he numer of seonds tht he entry should e onsidered fresh when


SFIQF r ghe PTQ

ymfony houmenttionD PFH no expliit freshness informtion is provided in responseF ixpliit gheEgontrol or ixpires heders override this vlue @defultX HAY

privtehedersX et of request heders tht trigger privte gheEgontrol ehvior on responses tht don9t expliitly stte whether the response is puli or privte vi gheEgontrol diretiveF @defultX euthoriztion nd gookieAY llowrelodX pei(es whether the lient n fore he relod y inluding gheEgontrol noEhe diretive in the requestF et it to true for ompline with pg PTIT @defultX flseAY llowrevlidteX pei(es whether the lient n fore he revlidte y inluding gheEgontrol mxEgeaH diretive in the requestF et it to true for ompline with pg PTIT @defultX flseAY stlewhilerevlidteX pei(es the defult numer of seonds @the grnulrity is the seond s the esponse v preision is seondA during whih the he n immeditely return stle response while it revlidtes it in the kground @defultX PAY this setting is overridden y the stleEwhileErevlidte r gheE gontrol extension @see pg SVTIAY stleiferrorX pei(es the defult numer of seonds @the grnulrity is the seondA during whih the he n serve stle response when n error is enountered @defultX THAF his setting is overridden y the stleEifEerror r gheEgontrol extension @see pg SVTIAF
sf deug is trueD ymfonyP utomtilly dds EymfonyEghe heder to the response ontining useful informtion out he hits nd missesF ghnging from one everse roxy to enother he ymfonyP reverse proxy is gret tool to use when developing your wesite or when you deploy your wesite to shred host where you nnot instll nything eyond r odeF fut eing written in rD it nnot e s fst s proxy written in gF ht9s why we highly reommend you to use rnish or quid on your prodution servers if possileF he good news is tht the swith from one proxy server to nother is esy nd trnsprent s no ode modi(tion is needed in your pplitionF trt esy with the ymfonyP reverse proxy nd upgrde lter to rnish when your tr0 inresesF por more informtion on using rnish with ymfonyPD see the row to use rnish ookook hpterF

X he performne of the ymfonyP reverse proxy is independent of the omplexity of the pplitionF ht9s euse the pplition kernel is only ooted when the request needs to e forwrded to itF

PTR

SF

ymfony houmenttionD PFH


5.13.3 Introduction to HTTP Caching

o tke dvntge of the ville he lyersD your pplition must e le to ommunite whih responses re hele nd the rules tht govern whenGhow tht he should eome stleF his is done y setting r he heders on the responseF X ueep in mind tht r is nothing more thn the lnguge @ simple text lngugeA tht we lients @eFgF rowsersA nd we servers use to ommunite with eh otherF hen we tlk out r hingD we9re tlking out the prt of tht lnguge tht llows lients nd servers to exhnge informtion relted to hingF r spei(es four response he heders tht we9re onerned withX

gheEgontrol ixpires ig vstEwodi(ed


he most importnt nd verstile heder is the gheEgontrol hederD whih is tully olletion of vrious he informtionF X ih of the heders will e explined in full detil in the r ixpirtion nd lidtion setionF

he gheEgontrol reder he gheEgontrol heder is unique in tht it ontins not oneD ut vrious piees of informtion out the heility of responseF ih piee of informtion is seprted y ommX gheEgontrolX privteD mxEgeaHD mustErevlidte gheEgontrolX mxEgeaQTHHD mustErevlidte ymfony provides n strtion round the gheEgontrol heder to mke its retion more mngeleX

$response = new Response(); // mark the response as either public or private $response->setPublic(); $response->setPrivate(); // set the private or shared max age
SFIQF r ghe PTS

ymfony houmenttionD PFH

$response->setMaxAge(600); $response->setSharedMaxAge(600); // set a custom Cache-Control directive $response->headers->addCacheControlDirective('must-revalidate', true);


uli vs rivte esponses foth gtewy nd proxy hes re onsidered shred hes s the hed ontent is shred y more thn one userF sf userEspei( response were ever mistkenly stored y shred heD it might e returned lter to ny numer of di'erent usersF smgine if your ount informtion were hed nd then returned to every susequent user who sked for their ount pge3 o hndle this situtionD every response my e set to e puli or privteX

puliX sndites tht the response my e hed y oth privte nd shred hesY privteX sndites tht ll or prt of the response messge is intended for single user nd must not e hed y shred heF
ymfony onservtively defults eh response to e privteF o tke dvntge of shred hes @like the ymfonyP reverse proxyAD the response will need to e expliitly set s puliF fe wethods r hing only works for sfe r methods @like qi nd riehAF feing sfe mens tht you never hnge the pplition9s stte on the server when serving the request @you n of ourse log informtionD he dtD etAF his hs two very resonle onsequenesX

ou should never hnge the stte of your pplition when responding to qi or rieh requestF iven if you don9t use gtewy heD the presene of proxy hes men tht ny qi or rieh request my or my not tully hit your serverF hon9t expet D y or hivii methods to heF hese methods re ment to e used when mutting the stte of your pplition @eFgF deleting log postAF ghing them would prevent ertin requests from hitting nd mutting your pplitionF
ghing ules nd hefults r IFI llows hing nything y defult unless there is n expliit gheEgontrol hederF sn prtieD most hes do nothing when requests hve ookieD n uthoriztion hederD use nonEsfe method @iFeF D yD hiviiAD or when responses hve rediret sttus odeF

PTT

SF

ymfony houmenttionD PFH ymfonyP utomtilly sets sensile nd onservtive gheEgontrol heder when none is set y the developer y following these rulesX

sf no he heder is de(ned @gheEgontrolD ixpiresD ig or vstEwodi(edAD gheE gontrol is set to noEheD mening tht the response will not e hedY sf gheEgontrol is empty @ut one of the other he heders is presentAD its vlue is set to privteD mustErevlidteY fut if t lest one gheEgontrol diretive is setD nd no puli9 or privte diretives hve een expliitly ddedD ymfonyP dds the privte diretive utomtilly @exept when sEmxge is setAF
5.13.4 HTTP Expiration and Validation

he r spei(tion de(nes two hing modelsX

ith the expirtion modelD you simply speify how long response should e onsidered fresh y inluding gheEgontrol ndGor n ixpires hederF ghes tht understnd expirtion will not mke the sme request until the hed version rehes its expirtion time nd eomes stleF hen pges re relly dynmi @iFeF their representtion hnges oftenAD the vlidtion model model is often neessryF ith this modelD the he stores the responseD ut sks the server on eh request whether or not the hed response is still vlidF he pplition uses unique response identi(er @the itg hederA ndGor timestmp @the vstEwodi(ed hederA to hek if the pge hs hnged sine eing hedF
he gol of oth models is to never generte the sme response twie y relying on he to store nd return fresh responsesF eding the r pei(tion he r spei(tion de(nes simple ut powerful lnguge in whih lients nd servers n ommuniteF es we developerD the requestEresponse model of the spei(tion domintes our workF nfortuntelyD the tul spei(tion doument E pg PTIT E n e di0ult to redF here is n onEgoing e'ort @r fisA to rewrite the pg PTITF st does not desrie new version of rD ut mostly lri(es the originl r spei(tionF he orgniztion is lso improved s the spei(tion is split into seven prtsY everything relted to r hing n e found in two dedited prts @R E gonditionl equests nd T E ghingX frowser nd intermediry hesAF es we developerD we strongly urge you to red the spei(tionF sts lrity nd power E even more thn ten yers fter its retion E is invluleF hon9t e putEo' y the pperne of the spe E its ontents re muh more eutiful thn its overF

SFIQF r ghe

PTU

ymfony houmenttionD PFH ixpirtion he expirtion model is the more e0ient nd strightforwrd of the two hing models nd should e used whenever possileF hen response is hed with n expirtionD the he will store the response nd return it diretly without hitting the pplition until it expiresF he expirtion model n e omplished using one of twoD nerly identilD r hedersX ixpires or gheEgontrolF ixpirtion with the ixpires reder eording to the r spei(tionD the ixpires heder (eld gives the dteGtime fter whih the response is onsidered stleF he ixpires heder n e set with the setixpires@A esponse methodF st tkes hteime instne s n rgumentX

$date = new DateTime(); $date->modify('+600 seconds'); $response->setExpires($date);


he resulting r heder will look like thisX

Expires: Thu, 01 Mar 2011 16:00:00 GMT


X he setixpires@A method utomtilly onverts the dte to the qw timezone s required y the spei(tionF he ixpires heder su'ers from two limittionsF pirstD the loks on the e server nd the he @eFgF the rowserA must e synhronizedF henD the spei(tion sttes tht rGIFI servers should not send ixpires dtes more thn one yer in the futureF ixpirtion with the gheEgontrol reder feuse of the ixpires heder limittionsD most of the timeD you should use the gheEgontrol heder instedF ell tht the gheEgontrol heder is used to speify mny di'erent he diretivesF por expirtionD there re two diretivesD mxEge nd sEmxgeF he (rst one is used y ll hesD wheres the seond one is only tken into ount y shred hesX

// Sets the number of seconds after which the response // should no longer be considered fresh $response->setMaxAge(600);

PTV

SF

ymfony houmenttionD PFH

// Same as above but only for shared caches $response->setSharedMaxAge(600);


he gheEgontrol heder would tke on the following formt @it my hve dditionl diretivesAX

Cache-Control: max-age=600, s-maxage=600


lidtion hen resoure needs to e updted s soon s hnge is mde to the underlying dtD the expirtion model flls shortF ith the expirtion modelD the pplition won9t e sked to return the updted response until the he (nlly eomes stleF he vlidtion model ddresses this issueF nder this modelD the he ontinues to store responsesF he di'erene is thtD for eh requestD the he sks the pplition whether or not the hed response is still vlidF sf the he is still vlidD your pplition should return QHR sttus ode nd no ontentF his tells the he tht it9s ok to return the hed responseF nder this modelD you minly sve ndwidth s the representtion is not sent twie to the sme lient @ QHR response is sent instedAF fut if you design your pplition refullyD you might e le to get the re minimum dt needed to send QHR response nd sve g lso @see elow for n implementtion exmpleAF X he QHR sttus ode mens xot wodi(edF st9s importnt euse with this sttus ode do not ontin the tul ontent eing requestedF snstedD the response is simply lightEweight set of diretions tht tell he tht it should use its stored versionF vike with expirtionD there re two di'erent r heders tht n e used to implement the vlidtion modelX ig nd vstEwodi(edF lidtion with the ig reder he ig heder is string heder @lled the entityEtgA tht uniquely identi(es one representtion of the trget resoureF st9s entirely generted nd set y your pplition so tht you n tellD for exmpleD if the Gout resoure tht9s stored y the he is upEtoEdte with wht your pplition would returnF en ig is like (ngerprint nd is used to quikly ompre if two di'erent versions of resoure re equivlentF vike (ngerprintsD eh ig must e unique ross ll representtions of the sme resoureF vet9s wlk through simple implementtion tht genertes the ig s the mdS of the ontentX

SFIQF r ghe

PTW

ymfony houmenttionD PFH

public function indexAction() { $response = $this->render('MyBundle:Main:index.html.twig'); $response->setETag(md5($response->getContent())); $response->isNotModied($this->getRequest()); } return $response;

he esponseXXisxotwodi(ed@A method ompres the ig sent with the equest with the one set on the esponseF sf the two mthD the method utomtilly sets the esponse sttus ode to QHRF his lgorithm is simple enough nd very generiD ut you need to rete the whole esponse efore eing le to ompute the igD whih is suEoptimlF sn other wordsD it sves on ndwidthD ut not g ylesF sn the yptimizing your gode with lidtion setionD we9ll show how vlidtion n e used more intelligently to determine the vlidity of he without doing so muh workF X ymfonyP lso supports wek igs y pssing true s the seond rgument to the XmethodXymfonygomponentrttppoundtionesponseXXsetig methodF

lidtion with the vstEwodi(ed reder he vstEwodi(ed heder is the seond form of vlidtionF eording to the r spei(tionD he vstEwodi(ed heder (eld indites the dte nd time t whih the origin server elieves the representtion ws lst modi(edF sn other wordsD the pplition deides whether or not the hed ontent hs een updted sed on whether or not it9s een updted sine the response ws hedF por instneD you n use the ltest updte dte for ll the ojets needed to ompute the resoure representtion s the vlue for the vstEwodi(ed heder vlueX

public function showAction($articleSlug) { // ... $articleDate = new \DateTime($article->getUpdatedAt()); $authorDate = new \DateTime($author->getUpdatedAt()); $date = $authorDate > $articleDate ? $authorDate : $articleDate; $response->setLastModied($date); $response->isNotModied($this->getRequest());
PUH SF

ymfony houmenttionD PFH

return $response;

he esponseXXisxotwodi(ed@A method ompres the sfEwodi(edEine heder sent y the request with the vstEwodi(ed heder set on the responseF sf they re equivlentD the esponse will e set to QHR sttus odeF X he sfEwodi(edEine request heder equls the vstEwodi(ed heder of the lst response sent to the lient for the prtiulr resoureF his is how the lient nd server ommunite with eh other nd deide whether or not the resoure hs een updted sine it ws hedF

yptimizing your gode with lidtion he min gol of ny hing strtegy is to lighten the lod on the pplitionF ut nother wyD the less you do in your pplition to return QHR responseD the etterF he esponseXXisxotwodi(ed@A method does extly tht y exposing simple nd e0ient ptternX

public function showAction($articleSlug) { // Get the minimum information to compute // the ETag or the Last-Modied value // (based on the Request, data is retrieved from // a database or a key-value store for instance) $article = // ... // create a Response with a ETag and/or a Last-Modied header $response = new Response(); $response->setETag($article->computeETag()); $response->setLastModied($article->getPublishedAt()); // Check that the Response is not modied for the given Request if ($response->isNotModied($this->getRequest())) { // return the 304 Response immediately return $response; } else { // do more work here - like retrieving more data $comments = // ... // or render a template with the $response you've already started return $this->render( 'MyBundle:MyController:article.html.twig', array('article' => $article, 'comments' => $comments),
SFIQF r ghe PUI

ymfony houmenttionD PFH

);

$response

hen the esponse is not modi(edD the isxotwodi(ed@A utomtilly sets the response sttus ode to QHRD removes the ontentD nd removes some heders tht must not e present for QHR responses @see XmethodXymfonygomponentrttppoundtionesponseXXsetxotwodi(edAF rying the esponse o frD we9ve ssumed tht eh s hs extly one representtion of the trget resoureF fy defultD r hing is done y using the s of the resoure s the he keyF sf two people request the sme s of hele resoureD the seond person will reeive the hed versionF ometimes this isn9t enough nd di'erent versions of the sme s need to e hed sed on one or more request heder vluesF por instneD if you ompress pges when the lient supports itD ny given s hs two representtionsX one when the lient supports ompressionD nd one when it does notF his determintion is done y the vlue of the eeptEinoding request hederF sn this seD we need the he to store oth ompressed nd unompressed version of the response for the prtiulr s nd return them sed on the request9s eeptEinoding vlueF his is done y using the ry response hederD whih is ommEseprted list of di'erent heders whose vlues trigger di'erent representtion of the requested resoureX

Vary: Accept-Encoding, User-Agent


X his prtiulr ry heder would he di'erent versions of eh resoure sed on the s nd the vlue of the eeptEinoding nd serEegent request hederF he esponse ojet o'ers len interfe for mnging the ry hederX

// set one vary header $response->setVary('Accept-Encoding'); // set multiple vary headers $response->setVary(array('Accept-Encoding', 'User-Agent'));
he setry@A method tkes heder nme or n rry of heder nmes for whih the response vriesF

PUP

SF

ymfony houmenttionD PFH ixpirtion nd lidtion ou n of ourse use oth vlidtion nd expirtion within the sme esponseF es expirtion wins over vlidtionD you n esily ene(t from the est of oth worldsF sn other wordsD y using oth expirtion nd vlidtionD you n instrut the he to serve the hed ontentD while heking k t some intervl @the expirtionA to verify tht the ontent is still vlidF wore esponse wethods he esponse lss provides mny more methods relted to the heF rere re the most useful onesX

// Marks the Response stale $response->expire(); // Force the response to return a proper 304 response with no content $response->setNotModied();
edditionllyD most heErelted r heders n e set vi the single setghe@A methodX

// Set cache settings in one call $response->setCache(array( 'etag' => $etag, 'last_modied' => $date, 'max_age' => 10, 's_maxage' => 10, 'public' => true, // 'private' => true, ));

5.13.5 Using Edge Side Includes

qtewy hes re gret wy to mke your wesite perform etterF fut they hve one limittionX they n only he whole pgesF sf you n9t he whole pges or if prts of pge hs more dynmi prtsD you re out of lukF portuntelyD ymfonyP provides solution for these sesD sed on tehnology lled isD or idge ide snludesF ekm % wrote this spei(tion lmost IH yers goD nd it llows spei( prts of pge to hve di'erent hing strtegy thn the min pgeF he is spei(tion desries tgs you n emed in your pges to ommunite with the gtewy heF ynly one tg is implemented in ymfonyPD inludeD s this is the only useful one outside of ekm ontextX %

<html> <body>
SFIQF r ghe PUQ

ymfony houmenttionD PFH

Some content <!-- Embed the content of another page here --> <esi:include src="http://..." /> More content </body> </html>
X xotie from the exmple tht eh is tg hs fullyEquli(ed vF en is tg represents pge frgment tht n e fethed vi the given vF hen request is hndledD the gtewy he fethes the entire pge from its he or requests it from the kend pplitionF sf the response ontins one or more is tgsD these re proessed in the sme wyF sn other wordsD the gtewy he either retrieves the inluded pge frgment from its he or requests the pge frgment from the kend pplition ginF hen ll the is tgs hve een resolvedD the gtewy he merges eh into the min pge nd sends the (nl ontent to the lientF ell of this hppens trnsprently t the gtewy he level @iFeF outside of your pplitionAF es you9ll seeD if you hoose to tke dvntge of is tgsD ymfonyP mkes the proess of inluding them lmost e'ortlessF sing is in ymfonyP pirstD to use isD e sure to enle it in your pplition on(gurtionX

ewv

# app/cong/cong.yml framework: # ... esi: { enabled: true }


wv

<!-- app/cong/cong.xml --> <framework:cong ...> <!-- ... --> <framework:esi enabled="true" /> </framework:cong>
r

PUR

SF

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('framework', array( // ... 'esi' => array('enabled' => true), ));
xowD suppose we hve pge tht is reltively sttiD exept for news tiker t the ottom of the ontentF ith isD we n he the news tiker independent of the rest of the pgeF

public function indexAction() { $response = $this->render('MyBundle:MyController:index.html.twig'); $response->setSharedMaxAge(600); } return $response;

sn this exmpleD we9ve given the fullEpge he lifetime of ten minutesF xextD let9s inlude the news tiker in the templte y emedding n tionF his is done vi the render helper @ee templtingEemeddingEontroller for more detilsAF es the emedded ontent omes from nother pge @or ontroller for tht mtterAD ymfonyP uses the stndrd render helper to on(gure is tgsX

wig

{% render '...:news' with {}, {'standalone': true} %}


r

<?php echo $view['actions']->render('...:news', array(), array('standalone' => true)) ?>


fy setting stndlone to trueD you tell ymfonyP tht the tion should e rendered s n is tgF ou might e wondering why you would wnt to use helper insted of just writing the is tg yourselfF ht9s euse using helper mkes your pplition work even if there is no gtewy he instlledF vet9s see how it worksF hen stndlone is flse @the defultAD ymfonyP merges the inluded pge ontent within the min one efore sending the response to the lientF fut when stndlone is trueD nd if ymfonyP detets tht it9s tlking to gtewy he tht supports isD it genertes n is inlude tgF fut if there is no gtewy he or if it does not support isD ymfonyP will just merge the inluded pge ontent within the min one s it would hve done were stndlone set to flseF X ymfonyP detets if gtewy he supports is vi nother ekm % spei(tion tht is supported out of the ox y the ymfonyP reverse proxyF

SFIQF r ghe

PUS

ymfony houmenttionD PFH he emedded tion n now speify its own hing rulesD entirely independent of the mster pgeF

public function newsAction() { // ... } $response->setSharedMaxAge(60);

ith isD the full pge he will e vlid for THH seondsD ut the news omponent he will only lst for TH seondsF e requirement of isD howeverD is tht the emedded tion e essile vi v so the gtewy he n feth it independently of the rest of the pgeF yf ourseD n tion n9t e essed vi v unless it hs route tht points to itF ymfonyP tkes re of this vi generi route nd ontrollerF por the is inlude tg to work properlyD you must de(ne the internl routeX

ewv

# app/cong/routing.yml _internal: resource: "@FrameworkBundle/Resources/cong/routing/internal.xml" prex: /_internal


wv

<!-- app/cong/routing.xml --> <?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing

<import resource="@FrameworkBundle/Resources/cong/routing/internal.xml" prex="/_internal" /> </routes>


r

// app/cong/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route;

$collection->addCollection($loader->import('@FrameworkBundle/Resources/cong/routing/internal.xml', ' return $collection;

PUT

SF

ymfony houmenttionD PFH X ine this route llows ll tions to e essed vi vD you might wnt to protet it y using the ymfonyP (rewll feture @y llowing ess to your reverse proxy9s s rngeAF ee the euring y s setion of the eurity ghpter for more informtion on how to do thisF yne gret dvntge of this hing strtegy is tht you n mke your pplition s dynmi s needed nd t the sme timeD hit the pplition s little s possileF X yne you strt using isD rememer to lwys use the sEmxge diretive insted of mxEgeF es the rowser only ever reeives the ggregted resoureD it is not wre of the suEomponentsD nd so it will oey the mxEge diretive nd he the entire pgeF end you don9t wnt thtF he render helper supports two other useful optionsX

ltX used s the lt ttriute on the is tgD whih llows you to speify n lterntive v to e used if the sr nnot e foundY ignoreerrorsX if set to trueD n onerror ttriute will e dded to the is with vlue of ontinue inditing thtD in the event of filureD the gtewy he will simply remove the is tg silentlyF
5.13.6 Cache Invalidation

here re only two hrd things in gomputer ieneX he invlidtion nd nming thingsF !hil urlton ou should never need to invlidte hed dt euse invlidtion is lredy tken into ount ntively in the r he modelsF sf you use vlidtionD you never need to invlidte nything y de(nitionY nd if you use expirtion nd need to invlidte resoureD it mens tht you set the expires dte too fr wy in the futureF X st9s lso euse there is no invlidtion mehnism tht you n use ny reverse proxy without hnging nything in your pplition odeF etullyD ll reverse proxies provide wys to purge hed dtD ut you should void them s muh s possileF he most stndrd wy is to purge the he for given v y requesting it with the speil qi r methodF rere is how you n on(gure the ymfonyP reverse proxy to support the qi r methodX

// app/AppCache.php class AppCache extends Cache


SFIQF r ghe PUU

ymfony houmenttionD PFH

protected function invalidate(Request $request) { if ('PURGE' !== $request->getMethod()) { return parent::invalidate($request); } $response = new Response(); if (!$this->store->purge($request->getUri())) { $response->setStatusCode(404, 'Not purged'); } else { $response->setStatusCode(200, 'Purged'); } } return $response;

X ou must protet the qi r method somehow to void rndom people purging your hed dtF

5.13.7 Summary

ymfonyP ws designed to follow the proven rules of the rodX rF ghing is no exeptionF wstering the ymfonyP he system mens eoming fmilir with the r he models nd using them e'etivelyF his mens thtD insted of relying only on ymfonyP doumenttion nd ode exmplesD you hve ess to world of knowledge relted to r hing nd gtewy hes suh s rnishF
5.13.8 Learn more from the Cookbook

row to use rnish to speedup my esite

5.14 Translations

he term interntionliztion refers to the proess of strting strings nd other loleE spei( piees out of your pplition nd into lyer where they n e trnslted nd onverted sed on the user9s lole @iFeF lnguge nd ountryAF por textD this mens wrpping eh with funtion ple of trnslting the text @or messgeA into the lnguge of the userX

PUV

SF

ymfony houmenttionD PFH

// text will *always* print out in English echo 'Hello World'; // text can be translated into the end-user's language or default to English echo $translator->trans('Hello World');
X he term lole refers roughly to the user9s lnguge nd ountryF st n e ny string tht your pplition then uses to mnge trnsltions nd other formt di'erenes @eFgF urreny formtAF e reommended the syTQWEI lnguge odeD n undersore @AD then the syQITT ountry ode @eFgF frp for prenhGprneAF sn this hpterD we9ll lern how to prepre n pplition to support multiple loles nd then how to rete trnsltions for multiple lolesF yverllD the proess hs severl ommon stepsX IF inle nd on(gure ymfony9s rnsltion omponentY PF estrt strings @iFeF messgesA y wrpping them in lls to the rnsltorY QF grete trnsltion resoures for eh supported lole tht trnslte eh messge in the pplitionY RF hetermineD set nd mnge the user9s lole in the sessionF
5.14.1 Conguration

rnsltions re hndled y rnsltor servie tht uses the user9s lole to lookup nd return trnslted messgesF fefore using itD enle the rnsltor in your on(gurtionX

ewv

# app/cong/cong.yml framework: translator: { fallback: en }


wv

<!-- app/cong/cong.xml --> <framework:cong> <framework:translator fallback="en" /> </framework:cong>


r

// app/cong/cong.php $container->loadFromExtension('framework', array(


SFIRF rnsltions PUW

ymfony houmenttionD PFH

));

'translator' => array('fallback' => 'en'),

he fllk option de(nes the fllk lole when trnsltion does not exist in the user9s loleF X hen trnsltion does not exist for loleD the trnsltor (rst tries to (nd the trnsltion for the lnguge @fr if the lole is frp for instneAF sf this lso filsD it looks for trnsltion using the fllk loleF he lole used in trnsltions is the one stored in the user sessionF
5.14.2 Basic Translation

rnsltion of text is done through the trnsltor servie @ymfonygomponentrnsltionrnsltorAF o trnslte lok of text @lled messgeAD use the XmethodXymfonygomponentrnsltionrnsltorXXtrns methodF upposeD for exmpleD tht we9re trnslting simple messge from inside ontrollerX

public function indexAction() { $t = $this->get('translator')->trans('Symfony2 is great'); } return new Response($t);

hen this ode is exeutedD ymfonyP will ttempt to trnslte the messge ymfonyP is gret sed on the lole of the userF por this to workD we need to tell ymfonyP how to trnslte the messge vi trnsltion resoureD whih is olletion of messge trnsltions for given loleF his ditionry of trnsltions n e reted in severl di'erent formtsD vspp eing the reommended formtX

wv

<!-- messages.fr.xli --> <?xml version="1.0"?> <xli version="1.2" xmlns="urn:oasis:names:tc:xli:document:1.2"> <le source-language="en" datatype="plaintext" original="le.ext"> <body> <trans-unit id="1"> <source>Symfony2 is great</source> <target>J'aime Symfony2</target> </trans-unit> </body>
PVH SF

ymfony houmenttionD PFH

</le> </xli>
r

// messages.fr.php return array( 'Symfony2 is great' => 'J\'aime Symfony2', );


ewv

# messages.fr.yml Symfony2 is great: J'aime Symfony2


xowD if the lnguge of the user9s lole is prenh @eFgF frp or frfiAD the messge will e trnslted into t9ime ymfonyPF he rnsltion roess o tully trnslte the messgeD ymfonyP uses simple proessX

he lole of the urrent userD whih is stored in the sessionD is determinedY e tlog of trnslted messges is loded from trnsltion resoures de(ned for the lole @eFgF frpAF wessges from the fllk lole re lso loded nd dded to the tlog if they don9t lredy existF he end result is lrge ditionry of trnsltionsF ee wessge gtlogues for more detilsY sf the messge is loted in the tlogD the trnsltion is returnedF sf notD the trnsltor returns the originl messgeF
hen using the trns@A methodD ymfonyP looks for the ext string inside the pproprite messge tlog nd returns it @if it existsAF wessge leholders ometimesD messge ontining vrile needs to e trnsltedX

public function indexAction($name) { $t = $this->get('translator')->trans('Hello '.$name); } return new Response($t);

SFIRF rnsltions

PVI

ymfony houmenttionD PFH roweverD reting trnsltion for this string is impossile sine the trnsltor will try to look up the ext messgeD inluding the vrile portions @eFgF rello yn or rello pienAF snsted of writing trnsltion for every possile itertion of the 6nme vrileD we n reple the vrile with pleholderX

public function indexAction($name) { $t = $this->get('translator')->trans('Hello %name%', array('%name%' => $name)); } new Response($t);

ymfonyP will now look for trnsltion of the rw messge @rello 7nme7A nd then reple the pleholders with their vluesF greting trnsltion is done just s eforeX

wv

<!-- messages.fr.xli --> <?xml version="1.0"?> <xli version="1.2" xmlns="urn:oasis:names:tc:xli:document:1.2"> <le source-language="en" datatype="plaintext" original="le.ext"> <body> <trans-unit id="1"> <source>Hello %name%</source> <target>Bonjour %name%</target> </trans-unit> </body> </le> </xli>
r

// messages.fr.php return array( 'Hello %name%' => 'Bonjour %name%', );


ewv

# messages.fr.yml 'Hello %name%': Hello %name%


X he pleholders n tke on ny form s the full messge is reonstruted using the r strtr funtionF roweverD the 7vr7 nottion is required when trnslting in wig templtesD nd is overll sensile onvention to followF es we9ve seenD reting trnsltion is twoEstep proessX PVP SF

ymfony houmenttionD PFH IF estrt the messge tht needs to e trnslted y proessing it through the rnsltorF PF grete trnsltion for the messge in eh lole tht you hoose to supportF he seond step is done y reting messge tlogues tht de(ne the trnsltions for ny numer of di'erent lolesF
5.14.3 Message Catalogues

hen messge is trnsltedD ymfonyP ompiles messge tlogue for the user9s lole nd looks in it for trnsltion of the messgeF e messge tlogue is like ditionry of trnsltions for spei( loleF por exmpleD the tlogue for the frp lole might ontin the following trnsltionX ymfonyP is qret ab t9ime ymfonyP st9s the responsiility of the developer @or trnsltorA of n interntionlized pplition to rete these trnsltionsF rnsltions re stored on the (lesystem nd disovered y ymfonyD thnks to some onventionsF X ih time you rete new trnsltion resoure @or instll undle tht inludes trnsltion resoureAD e sure to ler your he so tht ymfony n disover the new trnsltion resoureX

php app/console cache:clear

rnsltion votions nd xming gonventions ymfonyP looks for messge (les @iFeF trnsltionsA in two lotionsX

por messges found in undleD the orresponding messge (les should live in the esouresGtrnsltionsG diretory of the undleY o override ny undle trnsltionsD ppGesouresGtrnsltions diretoryF
ple messge (les in the

he (lenme of the trnsltions is lso importnt s ymfonyP uses onvention to determine detils out the trnsltionsF ih messge (le must e nmed ording to the following ptternX dominFloleFloderX

dominX en optionl wy to orgnize messges into groups @eFgF dminD nvigtion or the defult messgesA E see sing wessge hominsY loleX he lole tht the trnsltions re for @eFgF enqfD enD etAY loderX row ymfonyP should lod nd prse the (le @eFgF xli'D php or ymlAF
SFIRF rnsltions PVQ

ymfony houmenttionD PFH he loder n e the nme of ny registered loderF fy defultD ymfony provides the following lodersX

xli'X vspp (leY phpX r (leY ymlX ewv (leF


he hoie of whih loder to use is entirely up to you nd is mtter of tsteF X ou n lso store trnsltions in dtseD or ny other storge y providing ustom lss implementing the ymfonygomponentrnsltionvodervodersnterfe interfeF ee gustom rnsltion voders elow to lern how to register ustom lodersF

greting rnsltions ih (le onsists of series of idEtrnsltion pirs for the given domin nd loleF he id is the identi(er for the individul trnsltionD nd n e the messge in the min lole @eFgF ymfony is gretA of your pplition or unique identi(er @eFgF symfonyPFgret E see the sider elowAX

wv

<!-- src/Acme/DemoBundle/Resources/translations/messages.fr.xli --> <?xml version="1.0"?> <xli version="1.2" xmlns="urn:oasis:names:tc:xli:document:1.2"> <le source-language="en" datatype="plaintext" original="le.ext"> <body> <trans-unit id="1"> <source>Symfony2 is great</source> <target>J'aime Symfony2</target> </trans-unit> <trans-unit id="2"> <source>symfony2.great</source> <target>J'aime Symfony2</target> </trans-unit> </body> </le> </xli>
r

// src/Acme/DemoBundle/Resources/translations/messages.fr.php return array( 'Symfony2 is great' => 'J\'aime Symfony2',

PVR

SF

ymfony houmenttionD PFH

);

'symfony2.great'

=> 'J\'aime Symfony2',

ewv

# src/Acme/DemoBundle/Resources/translations/messages.fr.yml Symfony2 is great: J'aime Symfony2 symfony2.great: J'aime Symfony2


ymfonyP will disover these (les nd use them when trnslting either ymfonyP is gret or symfonyPFgret into prenh lnguge lole @eFgF frp or frfiAF

SFIRF rnsltions

PVS

ymfony houmenttionD PFH sing el or ueyword wessges his exmple illustrtes the two di'erent philosophies when reting messges to e trnsltedX

$t = $translator->trans('Symfony2 is great'); $t = $translator->trans('symfony2.great');


sn the (rst methodD messges re written in the lnguge of the defult lole @inglish in this seAF ht messge is then used s the id when reting trnsltionsF sn the seond methodD messges re tully keywords tht onvey the ide of the messgeF he keyword messge is then used s the id for ny trnsltionsF sn this seD trnsltions must e mde for the defult lole @iFeF to trnslte symfonyPFgret to ymfonyP is gretAF he seond method is hndy euse the messge key won9t need to e hnged in every trnsltion (le if we deide tht the messge should tully red ymfonyP is relly gret in the defult loleF he hoie of whih method to use is entirely up to youD ut the keyword formt is often reommendedF edditionllyD the php nd yml (le formts support nested ids to void repeting yourself if you use keywords insted of rel text for your idsX ewv

symfony2: is: great: Symfony2 is great amazing: Symfony2 is amazing has: bundles: Symfony2 has bundles user: login: Login
r

return array( 'symfony2' => array( 'is' => array( 'great' => 'Symfony2 is great', 'amazing' => 'Symfony2 is amazing', ), 'has' => array( 'bundles' => 'Symfony2 has bundles', ), ), 'user' => array( 'login' => 'Login', ), );
he multiple levels re )ttened into single idGtrnsltion pirs y dding dot @FA PVT SF etween every levelD therefore the ove exmples re equivlent to the followingX ewv

symfony2.is.great: Symfony2 is great

ymfony houmenttionD PFH


5.14.4 Using Message Domains

es we9ve seenD messge (les re orgnized into the di'erent loles tht they trnslteF he messge (les n lso e orgnized further into dominsF hen reting messge (lesD the domin is the (rst portion of the (lenmeF he defult domin is messgesF por exmpleD suppose thtD for orgniztionD trnsltions were split into three di'erent dominsX messgesD dmin nd nvigtionF he prenh trnsltion would hve the following messge (lesX

messgesFfrFxli' dminFfrFxli' nvigtionFfrFxli'


hen trnslting strings tht re not in the defult domin @messgesAD you must speify the domin s the third rgument of trns@AX

$this->get('translator')->trans('Symfony2 is great', array(), 'admin');


ymfonyP will now look for the messge in the dmin domin of the user9s loleF
5.14.5 Handling the User's Locale

he lole of the urrent user is stored in the session nd is essile vi the session servieX

$locale = $this->get('session')->getLocale(); $this->get('session')->setLocale('en_US');


pllk nd hefult vole sf the lole hsn9t een set expliitly in the sessionD the fllklole on(gurtion prmeter will e used y the rnsltorF he prmeter defults to en @see gon(gurtionAF elterntivelyD you n gurntee tht lole is set on the user9s session y de(ning defultlole for the session servieX

ewv

# app/cong/cong.yml framework: session: { default_locale: en }


wv

<!-- app/cong/cong.xml --> <framework:cong>


SFIRF rnsltions PVU

ymfony houmenttionD PFH

<framework:session default-locale="en" /> </framework:cong>


r

// app/cong/cong.php $container->loadFromExtension('framework', array( 'session' => array('default_locale' => 'en'), ));


he vole nd the v ine the lole of the user is stored in the sessionD it my e tempting to use the sme v to disply resoure in mny di'erent lnguges sed on the user9s loleF por exmpleD httpXGGwwwFexmpleFomGontt ould show ontent in inglish for one user nd prenh for nother userF nfortuntelyD this violtes fundmentl rule of the eX tht prtiulr v returns the sme resoure regrdless of the userF o further muddy the prolemD whih version of the ontent would e indexed y serh enginesc e etter poliy is to inlude the lole in the vF his is fullyEsupported y the routing system using the speil lole prmeterX

ewv

contact: pattern: /{_locale}/contact defaults: { _controller: AcmeDemoBundle:Contact:index, _locale: en } requirements: _locale: en|fr|de
wv

<route id="contact" pattern="/{_locale}/contact"> <default key="_controller">AcmeDemoBundle:Contact:index</default> <default key="_locale">en</default> <requirement key="_locale">en|fr|de</requirement> </route>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('contact', new Route('/{_locale}/contact', array( '_controller' => 'AcmeDemoBundle:Contact:index', '_locale' => 'en',
PVV SF

ymfony houmenttionD PFH

), array( '_locale' )));

=> 'en|fr|de'

return $collection;
hen using the speil lole prmeter in routeD the mthed lole will utomtilly e set on the user9s sessionF sn other wordsD if user visits the s GfrGonttD the lole fr will utomtilly e set s the lole for the user9s sessionF ou n now use the user9s lole to rete routes to other trnslted pges in your pplitionF
5.14.6 Pluralization

wessge plurliztion is tough topi s the rules n e quite omplexF por instneD here is the mthemti representtion of the ussin plurliztion rulesX

(($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) &&
es you n seeD in ussinD you n hve three di'erent plurl formsD eh given n index of HD I or PF por eh formD the plurl is di'erentD nd so the trnsltion is lso di'erentF hen trnsltion hs di'erent forms due to plurliztionD you n provide ll the forms s string seprted y pipe @|AX

'There is one apple|There are %count% apples'

o trnslte plurlized messgesD use the XmethodXymfonygomponentrnsltionrnsltorXXtrnsg methodX

$t = $this->get('translator')->transChoice( 'There is one apple|There are %count% apples', 10, array('%count%' => 10) );
he seond rgument @IH in this exmpleAD is the numer of ojets eing desried nd is used to determine whih trnsltion to use nd lso to populte the 7ount7 pleholderF fsed on the given numerD the trnsltor hooses the right plurl formF sn inglishD most words hve singulr form when there is extly one ojet nd plurl form for ll other numers @HD PD QFFFAF oD if ount is ID the trnsltor will use the (rst string @here is one ppleA s the trnsltionF ytherwise it will use here re 7ount7 pplesF rere is the prenh trnsltionX

SFIRF rnsltions

PVW

ymfony houmenttionD PFH

'Il y a %count% pomme|Il y a %count% pommes'


iven if the string looks similr @it is mde of two suEstrings seprted y pipeAD the prenh rules re di'erentX the (rst form @no plurlA is used when ount is H or IF oD the trnsltor will utomtilly use the (rst string @sl y 7ount7 pommeA when ount is H or IF ih lole hs its own set of rulesD with some hving s mny s six di'erent plurl forms with omplex rules ehind whih numers mp to whih plurl formF he rules re quite simple for inglish nd prenhD ut for ussinD you9d my wnt hint to know whih rule mthes whih stringF o help trnsltorsD you n optionlly tg eh stringX

'one: There is one apple|some: There are %count% apples' 'none_or_one: Il y a %count% pomme|some: Il y a %count% pommes'
he tgs re relly only hints for trnsltors nd don9t 'et the logi used to determine whih plurl form to useF he tgs n e ny desriptive string tht ends with olon @XAF he tgs lso do not need to e the sme in the originl messge s in the trnslted oneF ixpliit sntervl lurliztion he esiest wy to plurlize messge is to let ymfonyP use internl logi to hoose whih string to use sed on given numerF ometimesD you9ll need more ontrol or wnt di'erent trnsltion for spei( ses @for HD or when the ount is negtiveD for exmpleAF por suh sesD you n use expliit mth intervlsX

'{0} There is no apples|{1} There is one apple|]1,19] There are %count% apples|[20,Inf] There are many apples'
he intervls follow the sy QIEII nottionF he ove string spei(es four di'erent intervlsX extly HD extly ID PEIWD nd PH nd higherF ou n lso mix expliit mth rules nd stndrd rulesF sn this seD if the ount is not mthed y spei( intervlD the stndrd rules tke e'et fter removing the expliit rulesX

'{0} There is no apples|[20,Inf] There are many apples|There is one apple|a_few: There are %count% apples'
por exmpleD for I ppleD the stndrd rule here is one pple will e usedF por PEIW pplesD the seond stndrd rule here re 7ount7 pples will e seletedF en ymfonygomponentrnsltionsntervl n represent (nite set of numersX

{1,2,3,4}
yr numers etween two other numersX

[1, +Inf[ ]-1,2[


PWH SF

ymfony houmenttionD PFH he left delimiter n e @inlusiveA or @exlusiveAF he right delimiter n e @exlusiveA or @inlusiveAF feside numersD you n use Esnf nd Csnf for the in(niteF
5.14.7 Translations in Templates

wost of the timeD trnsltion ours in templtesF ymfonyP provides ntive support for oth wig nd r templtesF wig empltes ymfonyP provides speilized wig tgs @trns nd trnshoieA to help with messge trnsltion of stti loks of textX

{% trans %}Hello %name%{% endtrans %} {% transchoice count %} {0} There is no apples|{1} There is one apple|]1,Inf] There are %count% apples {% endtranschoice %}
he trnshoie tg utomtilly gets the 7ount7 vrile from the urrent ontext nd psses it to the trnsltorF his mehnism only works when you use pleholder following the 7vr7 ptternF X sf you need to use the perent hrter @7A in stringD espe it y douling itX {7 trns 7}erentX 7perent777{7 endtrns 7} ou n lso speify the messge domin nd pss some dditionl vrilesX

{% trans with {'%name%': 'Fabien'} from "app" %}Hello %name%{% endtrans %} {% transchoice count with {'%name%': 'Fabien'} from "app" %} {0} There is no apples|{1} There is one apple|]1,Inf] There are %count% apples {% endtranschoice %}
he trns nd trnshoie (lters n e used to trnslte vrile texts nd omplex expressionsX

{{ message | trans }} {{ message | transchoice(5) }} {{ message | trans({'%name%': 'Fabien'}, "app") }} {{ message | transchoice(5, {'%name%': 'Fabien'}, 'app') }}
SFIRF rnsltions PWI

ymfony houmenttionD PFH

X sing the trnsltion tgs or (lters hve the sme e'etD ut with one sutle di'ereneX utomti output esping is only pplied to vriles trnslted using (lterF sn other wordsD if you need to e sure tht your trnslted vrile is not output espedD you must pply the rw (lter fter the trnsltion (lterX

{# text translated between tags is never escaped #} {% trans %} <h3>foo</h3> {% endtrans %} {% set message = '<h3>foo</h3>' %} {# a variable translated via a lter is escaped by default #} {{ message | trans | raw }} {# but static strings are never escaped #} {{ '<h3>foo</h3>' | trans }}

r empltes he trnsltor servie is essile in r templtes through the trnsltor helperX

<?php echo $view['translator']->trans('Symfony2 is great') ?> <?php echo $view['translator']->transChoice( '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples', 10, array('%count%' => 10) ) ?>

5.14.8 Forcing the Translator Locale

hen trnslting messgeD ymfonyP uses the lole from the user9s session or the fllk lole if neessryF ou n lso mnully speify the lole to use for trnsltionX

$this->get('translator')->trans( 'Symfony2 is great', array(), 'messages', 'fr_FR', ); $this->get('translator')->trans(


PWP SF

ymfony houmenttionD PFH

);

'{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples', 10, array('%count%' => 10), 'messages', 'fr_FR',

5.14.9 Translating Database Content

he trnsltion of dtse ontent should e hndled y hotrine through the rnsltle ixtensionF por more informtionD see the doumenttion for tht lirryF
5.14.10 Summary

ith the ymfonyP rnsltion omponentD reting n interntionlized pplition no longer needs to e pinful proess nd oils down to just few si stepsX

estrt messges in your pplition y wrpping eh in either the XmethodXymfonygomponentrnsltionrnsltorXXtrns or XmethodXymfonygomponentrnsltionrnsltorXXtrnsghoie methodsY rnslte eh messge into multiple loles y reting trnsltion messge (lesF ymfonyP disovers nd proesses eh (le euse its nme follows spei( onventionY wnge the user9s loleD whih is stored in the sessionF

5.15 Service Container

e modern r pplition is full of ojetsF yne ojet my filitte the delivery of emil messges while nother my llow you to persist informtion into dtseF sn your pplitionD you my rete n ojet tht mnges your produt inventoryD or nother ojet tht proesses dt from thirdEprty esF he point is tht modern pplition does mny things nd is orgnized into mny ojets tht hndle eh tskF sn this hpterD we9ll tlk out speil r ojet in ymfonyP tht helps you instntiteD orgnize nd retrieve the mny ojets of your pplitionF his ojetD lled servie ontinerD will llow you to stndrdize nd entrlize the wy ojets re onstruted in your pplitionF he ontiner mkes your life esierD is super fstD nd emphsizes n rhiteture tht promotes reusle nd deoupled odeF end sine ll ore ymfonyP lsses use the ontinerD you9ll lern how to extendD on(gure nd use ny ojet in ymfonyPF sn lrge prtD the servie ontiner is the iggest ontriutor to the speed nd extensiility of ymfonyPF SFISF ervie gontiner PWQ

ymfony houmenttionD PFH pinllyD on(guring nd using the servie ontiner is esyF fy the end of this hpterD you9ll e omfortle reting your own ojets vi the ontiner nd ustomizing ojets from ny thirdEprty undleF ou9ll egin writing ode tht is more reusleD testle nd deoupledD simply euse the servie ontiner mkes writing good ode so esyF
5.15.1 What is a Service?

ut simplyD ervie is ny r ojet tht performs some sort of glol tskF st9s purposefullyEgeneri nme used in omputer siene to desrie n ojet tht9s reted for spei( purpose @eFgF delivering emilsAF ih servie is used throughout your pplition whenever you need the spei( funtionlity it providesF ou don9t hve to do nything speil to mke servieX simply write r lss with some ode tht omplishes spei( tskF gongrtultionsD you9ve just reted servie3 X es ruleD r ojet is servie if it is used glolly in your pplitionF e single wiler servie is used glolly to send emil messges wheres the mny wessge ojets tht it delivers re not serviesF imilrlyD rodut ojet is not servieD ut n ojet tht persists rodut ojets to dtse is servieF o wht9s the ig del thenc he dvntge of thinking out servies is tht you egin to think out seprting eh piee of funtionlity in your pplition into series of serviesF ine eh servie does just one joD you n esily ess eh servie nd use its funtionlity wherever you need itF ih servie n lso e more esily tested nd on(gured sine it9s seprted from the other funtionlity in your pplitionF his ide is lled servieEoriented rhiteture nd is not unique to ymfonyP or even rF truturing your pplition round set of independent servie lsses is wellEknown nd trusted ojetEoriented estEprtieF hese skills re key to eing good developer in lmost ny lngugeF
5.15.2 What is a Service Container?

e ervie gontiner @or dependeny injetion ontinerA is simply r ojet tht mnges the instntition of servies @iFeF ojetsAF por exmpleD suppose we hve simple r lss tht delivers emil messgesF ithout servie ontinerD we must mnully rete the ojet whenever we need itX

use Acme\HelloBundle\Mailer; $mailer = new Mailer('sendmail'); $mailer->send('ryan@foobar.net', ... );


his is esy enoughF he imginry wiler lss llows us to on(gure the method used to deliver the emil messges @eFgF sendmilD smtpD etAF fut wht if we wnted to use the PWR SF

ymfony houmenttionD PFH miler servie somewhere elsec e ertinly don9t wnt to repet the miler on(gurtion every time we need to use the wiler ojetF ht if we needed to hnge the trnsport from sendmil to smtp everywhere in the pplitionc e9d need to hunt down every ple we rete wiler servie nd hnge itF
5.15.3 Creating/Conguring Services in the Container

e etter nswer is to let the servie ontiner rete the wiler ojet for youF sn order for this to workD we must teh the ontiner how to rete the wiler servieF his is done vi on(gurtionD whih n e spei(ed in ewvD wv or rX

ewv

# app/cong/cong.yml services: my_mailer: class: Acme\HelloBundle\Mailer arguments: [sendmail]


wv

<!-- app/cong/cong.xml --> <services> <service id="my_mailer" class="Acme\HelloBundle\Mailer"> <argument>sendmail</argument> </service> </services>
r

// app/cong/cong.php use Symfony\Component\DependencyInjection\Denition; $container->setDenition('my_mailer', new Denition( 'Acme\HelloBundle\Mailer', array('sendmail') ));


X hen ymfonyP initilizesD it uilds the servie ontiner using the pplition on(gurtion @ppGon(gGon(gFyml y defultAF he ext (le tht9s loded is ditted y the eppuernelXXregistergontinergon(gurtion@A methodD whih lods n environmentE spei( on(gurtion (le @eFgF on(gdevFyml for the dev environment or on(gprodFyml for prodAF en instne of the emerellofundlewiler ojet is now ville vi the servie ontinerF he ontiner is ville in ny trditionl ymfonyP ontroller where you n SFISF ervie gontiner PWS

ymfony houmenttionD PFH ess the servies of the ontiner vi the get@A shortut methodX

class HelloController extends Controller { // ... public function sendEmailAction() { // ... $mailer = $this->get('my_mailer'); $mailer->send('ryan@foobar.net', ... ); }

hen we sk for the mymiler servie from the ontinerD the ontiner onstruts the ojet nd returns itF his is nother mjor dvntge of using the servie ontinerF xmelyD servie is never onstruted until it9s neededF sf you de(ne servie nd never use it on requestD the servie is never retedF his sves memory nd inreses the speed of your pplitionF his lso mens tht there9s very little or no performne hit for de(ning lots of serviesF ervies tht re never used re never onstrutedF es n dded onusD the wiler servie is only reted one nd the sme instne is returned eh time you sk for the servieF his is lmost lwys the ehvior you9ll need @it9s more )exile nd powerfulAD ut we9ll lern lter how you n on(gure servie tht hs multiple instnesF
5.15.4 Service Parameters

he retion of new servies @iFeF ojetsA vi the ontiner is pretty strightforwrdF rmeters mke de(ning servies more orgnized nd )exileX

ewv

# app/cong/cong.yml parameters: my_mailer.class: Acme\HelloBundle\Mailer my_mailer.transport: sendmail services: my_mailer: class: %my_mailer.class% arguments: [%my_mailer.transport%]
wv

<!-- app/cong/cong.xml --> <parameters>


PWT SF

ymfony houmenttionD PFH

<parameter key="my_mailer.class">Acme\HelloBundle\Mailer</parameter> <parameter key="my_mailer.transport">sendmail</parameter> </parameters> <services> <service id="my_mailer" class="%my_mailer.class%"> <argument>%my_mailer.transport%</argument> </service> </services>
r

// app/cong/cong.php use Symfony\Component\DependencyInjection\Denition; $container->setParameter('my_mailer.class', 'Acme\HelloBundle\Mailer'); $container->setParameter('my_mailer.transport', 'sendmail'); $container->setDenition('my_mailer', new Denition( '%my_mailer.class%', array('%my_mailer.transport%') ));
he end result is extly the sme s efore E the di'erene is only in how we de(ned the servieF fy surrounding the mymilerFlss nd mymilerFtrnsport strings in perent @7A signsD the ontiner knows to look for prmeters with those nmesF hen the ontiner is uiltD it looks up the vlue of eh prmeter nd uses it in the servie de(nitionF he purpose of prmeters is to feed informtion into serviesF yf ourse there ws nothing wrong with de(ning the servie without using ny prmetersF rmetersD howeverD hve severl dvntgesX

seprtion nd orgniztion of ll servie options under single prmeters keyY prmeter vlues n e used in multiple servie de(nitionsY when reting servie in undle @we9ll show this shortlyAD using prmeters llows the servie to e esily ustomized in your pplitionF
he hoie of using or not using prmeters is up to youF righEqulity thirdEprty undles will lwys use prmeters s they mke the servie stored in the ontiner more on(gurleF por the servies in your pplitionD howeverD you my not need the )exiility of prmetersF
5.15.5 Importing other Container Conguration Resources

X sn this setionD we9ll refer to servie on(gurtion (les s resouresF his is to highlight tht ft thtD while most on(gurtion resoures will e (les @eFgF ewvD wvD SFISF ervie gontiner PWU

ymfony houmenttionD PFH rAD ymfonyP is so )exile tht on(gurtion ould e loded from nywhere @eFgF dtse or even vi n externl we servieAF he servie ontiner is uilt using single on(gurtion resoure @ppGon(gGon(gFyml y defultAF ell other servie on(gurtion @inluding the ore ymfonyP nd thirdEprty undle on(gurtionA must e imported from inside this (le in one wy or notherF his gives you solute )exiility over the servies in your pplitionF ixternl servie on(gurtion n e imported in two di'erent wysF pirstD we9ll tlk out the method tht you9ll use most ommonly in your pplitionX the imports diretiveF sn the following setionD we9ll introdue the seond methodD whih is the )exile nd preferred method for importing servie on(gurtion from thirdEprty undlesF smporting gon(gurtion with imports o frD we9ve pled our mymiler servie ontiner de(nition diretly in the pplition on(gurtion (le @eFgF ppGon(gGon(gFymlAF yf ourseD sine the wiler lss itself lives inside the emerellofundleD it mkes more sense to put the mymiler ontiner de(nition inside the undle s wellF pirstD move the mymiler ontiner de(nition into new ontiner resoure (le inside emerellofundleF sf the esoures or esouresGon(g diretories don9t existD rete themF

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: my_mailer.class: Acme\HelloBundle\Mailer my_mailer.transport: sendmail services: my_mailer: class: %my_mailer.class% arguments: [%my_mailer.transport%]
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <parameter key="my_mailer.class">Acme\HelloBundle\Mailer</parameter> <parameter key="my_mailer.transport">sendmail</parameter> </parameters> <services> <service id="my_mailer" class="%my_mailer.class%"> <argument>%my_mailer.transport%</argument>

PWV

SF

ymfony houmenttionD PFH

</service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; $container->setParameter('my_mailer.class', 'Acme\HelloBundle\Mailer'); $container->setParameter('my_mailer.transport', 'sendmail'); $container->setDenition('my_mailer', new Denition( '%my_mailer.class%', array('%my_mailer.transport%') ));
he de(nition itself hsn9t hngedD only its lotionF yf ourse the servie ontiner doesn9t know out the new resoure (leF portuntelyD we n esily import the resoure (le using the imports key in the pplition on(gurtionF

ewv

# app/cong/cong.yml imports: hello_bundle: resource: @AcmeHelloBundle/Resources/cong/services.yml


wv

<!-- app/cong/cong.xml --> <imports> <import resource="@AcmeHelloBundle/Resources/cong/services.xml"/> </imports>


r

// app/cong/cong.php $this->import('@AcmeHelloBundle/Resources/cong/services.php');
he imports diretive llows your pplition to inlude servie ontiner on(gurtion resoures from ny other lotion @most ommonly from undlesAF he resoure lotionD for (lesD is the solute pth to the resoure (leF he speil demerello syntx resolves the diretory pth of the emerellofundle undleF his helps you speify the pth to the resoure without worrying lter if you move the emerellofundle to di'erent diretoryF

SFISF ervie gontiner

PWW

ymfony houmenttionD PFH smporting gon(gurtion vi gontiner ixtensions hen developing in ymfonyPD you9ll most ommonly use the imports diretive to import ontiner on(gurtion from the undles you9ve reted spei(lly for your pplitionF hirdEprty undle ontiner on(gurtionD inluding ymfonyP ore serviesD re usully loded using nother method tht9s more )exile nd esy to on(gure in your pplitionF rere9s how it worksF snternllyD eh undle de(nes its servies very muh like we9ve seen so frF xmelyD undle uses one or more on(gurtion resoure (les @usully wvA to speify the prmeters nd servies for tht undleF roweverD insted of importing eh of these resoures diretly from your pplition on(gurtion using the imports diretiveD you n simply invoke servie ontiner extension inside the undle tht does the work for youF e servie ontiner extension is r lss reted y the undle uthor to omplish two thingsX

import ll servie ontiner resoures needed to on(gure the servies for the undleY provide semntiD strightforwrd on(gurtion so tht the undle n e on(gured without interting with the )t prmeters of the undle9s servie ontiner on(gurtionF
sn other wordsD servie ontiner extension on(gures the servies for undle on your ehlfF end s we9ll see in momentD the extension provides sensileD highElevel interfe for on(guring the undleF ke the prmeworkfundle E the ore ymfonyP frmework undle E s n exmpleF he presene of the following ode in your pplition on(gurtion invokes the servie ontiner extension inside the prmeworkfundleX

ewv

# app/cong/cong.yml framework: secret: xxxxxxxxxx charset: UTF-8 form: true csrf_protection: true router: { resource: "%kernel.root_dir%/cong/routing.yml" } # ...
wv

<!-- app/cong/cong.xml --> <framework:cong charset="UTF-8" secret="xxxxxxxxxx"> <framework:form /> <framework:csrf-protection /> <framework:router resource="%kernel.root_dir%/cong/routing.xml" /> <!-- ... --> </framework>
QHH SF

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('framework', array( 'secret' => 'xxxxxxxxxx', 'charset' => 'UTF-8', 'form' => array(), 'csrf-protection' => array(), 'router' => array('resource' => '%kernel.root_dir%/cong/routing.php'), // ... ));
hen the on(gurtion is prsedD the ontiner looks for n extension tht n hndle the frmework on(gurtion diretiveF he extension in questionD whih lives in the prmeworkfundleD is invoked nd the servie on(gurtion for the prmeworkfundle is lodedF sf you remove the frmework key from your pplition on(gurtion (le entirelyD the ore ymfonyP servies won9t e lodedF he point is tht you9re in ontrolX the ymfonyP frmework doesn9t ontin ny mgi or perform ny tions tht you don9t hve ontrol overF yf ourse you n do muh more thn simply tivte the servie ontiner extension of the prmeworkfundleF ih extension llows you to esily ustomize the undleD without worrying out how the internl servies re de(nedF sn this seD the extension llows you to ustomize the hrsetD errorhndlerD srfprotetionD router on(gurtion nd muh moreF snternllyD the prmeworkfundle uses the options spei(ed here to de(ne nd on(gure the servies spei( to itF he undle tkes re of reting ll the neessry prmeters nd servies for the servie ontinerD while still llowing muh of the on(gurtion to e esily ustomizedF es n dded onusD most servie ontiner extensions re lso smrt enough to perform vlidtion E notifying you of options tht re missing or the wrong dt typeF hen instlling or on(guring undleD see the undle9s doumenttion for how the servies for the undle should e instlled nd on(guredF he options ville for the ore undles n e found inside the eferene quideF X xtivelyD the servie ontiner only reognizes the prmetersD serviesD nd imports diretivesF eny other diretives re hndled y servie ontiner extensionF

5.15.6 Referencing (Injecting) Services

o frD our originl mymiler servie is simpleX it tkes just one rgument in its onstrutorD whih is esily on(gurleF es you9ll seeD the rel power of the ontiner is relized when you need to rete servie tht depends on one or more other servies in the ontinerF

SFISF ervie gontiner

QHI

ymfony houmenttionD PFH vet9s strt with n exmpleF uppose we hve new servieD xewsletterwngerD tht helps to mnge the preprtion nd delivery of n emil messge to olletion of ddressesF yf ourse the mymiler servie is lredy relly good t delivering emil messgesD so we9ll use it inside xewsletterwnger to hndle the tul delivery of the messgesF his pretend lss might look something like thisX

namespace Acme\HelloBundle\Newsletter; use Acme\HelloBundle\Mailer; class NewsletterManager { protected $mailer; public function __construct(Mailer $mailer) { $this->mailer = $mailer; } } // ...

ithout using the servie ontinerD we n rete new xewsletterwnger firly esily from inside ontrollerX

public function sendNewsletterAction() { $mailer = $this->get('my_mailer'); $newsletter = new Acme\HelloBundle\Newsletter\NewsletterManager($mailer); // ... }


his pproh is (neD ut wht if we deide lter tht the xewsletterwnger lss needs seond or third onstrutor rgumentc ht if we deide to reftor our ode nd renme the lssc sn oth sesD you9d need to (nd every ple where the xewsletterwnger is instntited nd modify itF yf ourseD the servie ontiner gives us muh more ppeling optionX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager services: my_mailer: # ...


QHP SF

ymfony houmenttionD PFH

newsletter_manager: class: %newsletter_manager.class% arguments: [@my_mailer]


wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</par </parameters> <services> <service id="my_mailer" ... > <!-- ... --> </service> <service id="newsletter_manager" class="%newsletter_manager.class%"> <argument type="service" id="my_mailer"/> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setDenition('my_mailer', ... ); $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%', array(new Reference('my_mailer')) ));
sn ewvD the speil dmymiler syntx tells the ontiner to look for servie nmed mymiler nd to pss tht ojet into the onstrutor of xewsletterwngerF sn this seD howeverD the spei(ed servie mymiler must existF sf it does notD n exeption will e thrownF ou n mrk your dependenies s optionl E this will e disussed in the next setionF sing referenes is very powerful tool tht llows you to rete independent servie lsses with wellEde(ned dependeniesF sn this exmpleD the newslettermnger servie needs the mymiler servie in order to funtionF hen you de(ne this dependeny in the servie ontinerD the ontiner tkes re of ll the work of instntiting the ojetsF

SFISF ervie gontiner

QHQ

ymfony houmenttionD PFH yptionl hependeniesX etter snjetion snjeting dependenies into the onstrutor in this mnner is n exellent wy of ensuring tht the dependeny is ville to useF sf you hve optionl dependenies for lssD then setter injetion my e etter optionF his mens injeting the dependeny using method ll rther thn through the onstrutorF he lss would look like thisX

namespace Acme\HelloBundle\Newsletter; use Acme\HelloBundle\Mailer; class NewsletterManager { protected $mailer; public function setMailer(Mailer $mailer) { $this->mailer = $mailer; } } // ...

snjeting the dependeny y the setter method just needs hnge of syntxX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager services: my_mailer: # ... newsletter_manager: class: %newsletter_manager.class% calls: - [ setMailer, [ @my_mailer ] ]
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</par </parameters>

QHR

SF

ymfony houmenttionD PFH

<services> <service id="my_mailer" ... > <!-- ... --> </service> <service id="newsletter_manager" class="%newsletter_manager.class%"> <call method="setMailer"> <argument type="service" id="my_mailer" /> </call> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setDenition('my_mailer', ... ); $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%' ))->addMethodCall('setMailer', array( new Reference('my_mailer') ));
X he pprohes presented in this setion re lled onstrutor injetion nd setter injetionF he ymfonyP servie ontiner lso supports property injetionF

5.15.7 Making References Optional

ometimesD one of your servies my hve n optionl dependenyD mening tht the dependeny is not required for your servie to work properlyF sn the exmple oveD the mymiler servie must existD otherwise n exeption will e thrownF fy modifying the newslettermnger servie de(nitionD you n mke this referene optionlF he ontiner will then injet it if it exists nd do nothing if it doesn9tX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... services:


SFISF ervie gontiner QHS

ymfony houmenttionD PFH

newsletter_manager: class: %newsletter_manager.class% arguments: [@?my_mailer]


wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <services> <service id="my_mailer" ... > <!-- ... --> </service> <service id="newsletter_manager" class="%newsletter_manager.class%"> <argument type="service" id="my_mailer" on-invalid="ignore" /> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerInterface;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setDenition('my_mailer', ... ); $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%', array(new Reference('my_mailer', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)) ));
sn ewvD the speil dc syntx tells the servie ontiner tht the dependeny is optionlF yf ourseD the xewsletterwnger must lso e written to llow for n optionl dependenyX

public function __construct(Mailer $mailer = null) { // ... }

5.15.8 Core Symfony and Third-Party Bundle Services

ine ymfonyP nd ll thirdEprty undles on(gure nd retrieve their servies vi the ontinerD you n esily ess them or even use them in your own serviesF o keep things simpleD ymfonyP y defult does not require tht ontrollers e de(ned s serviesF QHT SF

ymfony houmenttionD PFH purthermore ymfonyP injets the entire servie ontiner into your ontrollerF por exmpleD to hndle the storge of informtion on user9s sessionD ymfonyP provides session servieD whih you n ess inside stndrd ontroller s followsX

public function indexAction($bar) { $session = $this->get('session'); $session->set('foo', $bar); } // ...

sn ymfonyPD you9ll onstntly use servies provided y the ymfony ore or other thirdE prty undles to perform tsks suh s rendering templtes @templtingAD sending emils @milerAD or essing informtion on the request @requestAF e n tke this step further y using these servies inside servies tht you9ve reted for your pplitionF vet9s modify the xewsletterwnger to use the rel ymfonyP miler servie @insted of the pretend mymilerAF vet9s lso pss the templting engine servie to the xewsletterwnger so tht it n generte the emil ontent vi templteX

namespace Acme\HelloBundle\Newsletter; use Symfony\Component\Templating\EngineInterface; class NewsletterManager { protected $mailer; protected $templating; public function __construct(\Swift_Mailer $mailer, EngineInterface $templating) { $this->mailer = $mailer; $this->templating = $templating; } } // ...

gon(guring the servie ontiner is esyX

ewv

services: newsletter_manager: class: %newsletter_manager.class% arguments: [@mailer, @templating]


SFISF ervie gontiner QHU

ymfony houmenttionD PFH

wv

<service id="newsletter_manager" class="%newsletter_manager.class%"> <argument type="service" id="mailer"/> <argument type="service" id="templating"/> </service>
r

$container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%', array( new Reference('mailer'), new Reference('templating') ) ));
he newslettermnger servie now hs ess to the ore miler nd templting serviesF his is ommon wy to rete servies spei( to your pplition tht leverge the power of di'erent servies within the frmeworkF X fe sure tht swiftmiler entry ppers in your pplition on(gurtionF es we mentioned in smporting gon(gurtion vi gontiner ixtensionsD the swiftmiler key invokes the servie extension from the wiftmilerfundleD whih registers the miler servieF

5.15.9 Advanced Container Conguration

es we9ve seenD de(ning servies inside the ontiner is esyD generlly involving servie on(gurtion key nd few prmetersF roweverD the ontiner hs severl other tools ville tht help to tg servies for speil funtionlityD rete more omplex serviesD nd perform opertions fter the ontiner is uiltF wrking ervies s puli G privte hen de(ning serviesD you9ll usully wnt to e le to ess these de(nitions within your pplition odeF hese servies re lled puliF por exmpleD the dotrine servie registered with the ontiner when using the hotrinefundle is puli servie s you n ess it viX

$doctrine = $container->get('doctrine');
roweverD there re useEses when you don9t wnt servie to e puliF his is ommon when servie is only de(ned euse it ould e used s n rgument for nother servieF

QHV

SF

ymfony houmenttionD PFH X sf you use privte servie s n rgument to more thn one other servieD this will result in two di'erent instnes eing used s the instntition of the privte servie is done inline @eFgF new rivtepoofr@AAF imply sidX e servie will e privte when you do not wnt to ess it diretly from your odeF rere is n exmpleX

ewv

services: foo: class: Acme\HelloBundle\Foo public: false


wv

<service id="foo" class="Acme\HelloBundle\Foo" public="false" />


r

$denition = new Denition('Acme\HelloBundle\Foo'); $denition->setPublic(false); $container->setDenition('foo', $denition);


xow tht the servie is privteD you nnot llX

$container->get('foo');
roweverD if servie hs een mrked s privteD you n still lis it @see elowA to ess this servie @vi the lisAF X ervies re y defult puliF

elising hen using ore or third prty undles within your pplitionD you my wnt to use shortuts to ess some serviesF ou n do so y lising them ndD furthermoreD you n even lis nonEpuli serviesF

ewv

services: foo: class: Acme\HelloBundle\Foo

SFISF ervie gontiner

QHW

ymfony houmenttionD PFH

bar: alias: foo


wv

<service id="foo" class="Acme\HelloBundle\Foo"/> <service id="bar" alias="foo" />


r

$denition = new Denition('Acme\HelloBundle\Foo'); $container->setDenition('foo', $denition); $containerBuilder->setAlias('bar', 'foo');


his mens tht when using the ontiner diretlyD you n ess the foo servie y sking for the r servie like thisX

$container->get('bar'); // Would return the foo service


equiring (les here might e use ses when you need to inlude nother (le just efore the servie itself gets lodedF o do soD you n use the (le diretiveF

ewv

services: foo: class: Acme\HelloBundle\Foo\Bar le: %kernel.root_dir%/src/path/to/le/foo.php


wv

<service id="foo" class="Acme\HelloBundle\Foo\Bar"> <le>%kernel.root_dir%/src/path/to/le/foo.php</le> </service>


r

$denition = new Denition('Acme\HelloBundle\Foo\Bar'); $denition->setFile('%kernel.root_dir%/src/path/to/le/foo.php'); $container->setDenition('foo', $denition);


xotie tht symfony will internlly ll the r funtion requireone whih mens tht your (le will e inluded only one per requestF

QIH

SF

ymfony houmenttionD PFH gs @tgsA sn the sme wy tht log post on the e might e tgged with things suh s ymfony or rD servies on(gured in your ontiner n lso e tggedF sn the servie ontinerD tg implies tht the servie is ment to e used for spei( purposeF ke the following exmpleX

ewv

services: foo.twig.extension: class: Acme\HelloBundle\Extension\FooExtension tags: - { name: twig.extension }


wv

<service id="foo.twig.extension" class="Acme\HelloBundle\Extension\FooExtension"> <tag name="twig.extension" /> </service>


r

$denition = new Denition('Acme\HelloBundle\Extension\FooExtension'); $denition->addTag('twig.extension'); $container->setDenition('foo.twig.extension', $denition);


he twigFextension tg is speil tg tht the wigfundle uses during on(gurtionF fy giving the servie this twigFextension tgD the undle knows tht the fooFtwigFextension servie should e registered s wig extension with wigF sn other wordsD wig (nds ll servies tgged with twigFextension nd utomtilly registers them s extensionsF gsD thenD re wy to tell ymfonyP or other thirdEprty undles tht your servie should e registered or used in some speil wy y the undleF he following is list of tgs ville with the ore ymfonyP undlesF ih of these hs di'erent e'et on your servie nd mny tgs require dditionl rguments @eyond just the nme prmeterAF

ssetiF(lter ssetiFtempltingFphp dtolletor formF(eldftoryFguesser kernelFhewrmer kernelFeventlistener monologFlogger


SFISF ervie gontiner QII

ymfony houmenttionD PFH

routingFloder seurityFlistenerFftory seurityFvoter templtingFhelper twigFextension trnsltionFloder vlidtorFonstrintvlidtor


5.15.10 Learn more from the Cookbook

row to se ptory to grete ervies row to wnge gommon hependenies with rent ervies row to de(ne gontrollers s ervies

5.16 Performance

ymfonyP is fstD right out of the oxF yf ourseD if you relly need speedD there re mny wys tht you n mke ymfony even fsterF sn this hpterD you9ll explore mny of the most ommon nd powerful wys to mke your ymfony pplition even fsterF
5.16.1 Use a Byte Code Cache (e.g. APC)

yne the est @nd esiestA things tht you should do to improve your performne is to use yte ode heF he ide of yte ode he is to remove the need to onstntly reompile the r soure odeF here re numer of yte ode hes villeD some of whih re open soureF he most widely used yte ode he is proly eg sing yte ode he relly hs no downsideD nd ymfonyP hs een rhiteted to perform relly well in this type of environmentF purther yptimiztions fyte ode hes usully monitor the soure (les for hngesF his ensures tht if the soure of (le hngesD the yte ode is reompiled utomtillyF his is relly onvenientD ut oviously dds overhedF

QIP

SF

ymfony houmenttionD PFH por this resonD some yte ode hes o'er n option to disle these heksF yviouslyD when disling these heksD it will e up to the server dmin to ensure tht the he is lered whenever ny soure (les hngeF ytherwiseD the updtes you9ve mde won9t e seenF por exmpleD to disle these heks in egD simply dd pFsttaH to your phpFini on(gurtionF
5.16.2 Use an Autoloader that caches (e.g. ApcUniversalClassLoader)

fy defultD the ymfonyP stndrd edition uses the niverslglssvoder in the utoloderFphp (leF his utoloder is esy to useD s it will utomtilly (nd ny new lsses tht you9ve pled in the registered diretoriesF nfortuntelyD this omes t ostD s the loder itertes over ll on(gured nmespes to (nd prtiulr (leD mking (leexists lls until it (nlly (nds the (le it9s looking forF he simplest solution is to he the lotion of eh lss fter it9s loted the (rst timeF ymfony omes with lss E epniverslglssvoder E loder tht extends the niverslglssvoder nd stores the lss lotions in egF o use this lss loderD simply dpt your utoloderFphp s followsX

// app/autoload.php require __DIR__.'/../vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; use Symfony\Component\ClassLoader\ApcUniversalClassLoader; $loader = new ApcUniversalClassLoader('some caching unique prex'); // ...
X hen using the eg utoloderD if you dd new lssesD they will e found utomtilly nd everything will work the sme s efore @iFeF no reson to ler the heAF roweverD if you hnge the lotion of prtiulr nmespe or pre(xD you9ll need to )ush your eg heF ytherwiseD the utoloder will still e looking t the old lotion for ll lsses inside tht nmespeF

5.16.3 Use Bootstrap Files

o ensure optiml )exiility nd ode reuseD ymfonyP pplitions leverge vriety of lsses nd Qrd prty omponentsF fut loding ll of these lsses from seprte (les on eh request n result in some overhedF o redue this overhedD the ymfonyP tndrd idition provides sript to generte soElled ootstrp (leD onsisting of multiple lsses de(nitions in single (leF fy inluding this (le @whih ontins opy of mny of the ore

SFITF erformne

QIQ

ymfony houmenttionD PFH lssesAD ymfony no longer needs to inlude ny of the soure (les ontining those lssesF his will redue dis sy quite itF sf you9re using the ymfonyP tndrd iditionD then you9re proly lredy using the ootstrp (leF o e sureD open your front ontroller @usully ppFphpA nd hek to mke sure tht the following line existsX

require_once __DIR__.'/../app/bootstrap.php.cache';
xote tht there re two disdvntges when using ootstrp (leX

the (le needs to e regenerted whenever ny of the originl soures hnge @iFeF when you updte the ymfonyP soure or vendor lirriesAY when deuggingD one will need to ple rek points inside the ootstrp (leF
sf you9re using ymfonyP tndrd iditionD the ootstrp (le is utomtilly reuilt fter updting the vendor lirries vi the php inGvendors instll ommndF footstrp piles nd fyte gode ghes iven when using yte ode heD performne will improve when using ootstrp (le sine there will e less (les to monitor for hngesF yf ourse if this feture is disled in the yte ode he @eFgF pFsttaH in egAD there is no longer reson to use ootstrp (leF

5.17 Internals

vooks like you wnt to understnd how ymfonyP works nd how to extend itF ht mkes me very hppy3 his setion is n inEdepth explntion of the ymfonyP internlsF X ou need to red this setion only if you wnt to understnd how ymfonyP works ehind the seneD or if you wnt to extend ymfonyPF

5.17.1 Overview

he ymfonyP ode is mde of severl independent lyersF ih lyer is uilt on top of the previous oneF X eutoloding is not mnged y the frmework diretlyY it9s done independently with the help of the ymfonygomponentglssvoderniverslglssvoder lss nd the srGutolodFphp (leF ed the dedited hpter for more informtionF QIR SF

ymfony houmenttionD PFH rttppoundtion gomponent he deepest level is the XnmespeXymfonygomponentrttppoundtion omponentF rttppoundtion provides the min ojets needed to del with rF st is n yjetE yriented strtion of some ntive r funtions nd vrilesX

he ymfonygomponentrttppoundtionequest lss strts the min r glol vriles like 6qiD 6yD 6gyyusiD 6psviD nd 6iiY he ymfonygomponentrttppoundtionesponse lss strts some r funtions like heder@AD setookie@AD nd ehoY he ymfonygomponentrttppoundtionession lss ymfonygomponentrttppoundtionessiontorgeessiontorgesnterfe interfe strt session mngement sessionB@A funtionsF
rttpuernel gomponent yn top of rttppoundtion is the XnmespeXymfonygomponentrttpuernel omponentF rttpuernel hndles the dynmi prt of rY it is thin wrpper on top of the equest nd esponse lsses to stndrdize the wy requests re hndledF st lso provides extension points nd tools tht mkes it the idel strting point to rete e frmework without too muh overhedF st lso optionlly dds on(gurility nd extensiilityD thnks to the hependeny snjetion omponent nd powerful plugin system @undlesAF FX ed more out the rttpuernel omponentF ed more out hependeny snjetion nd fundlesF prmeworkfundle fundle he XnmespeXymfonyfundleprmeworkfundle undle is the undle tht ties the min omponents nd lirries together to mke lightweight nd fst wg frmeworkF st omes with sensile defult on(gurtion nd onventions to ese the lerning urveF
5.17.2 Kernel

nd

he ymfonygomponentrttpuernelrttpuernel lss is the entrl lss of ymfonyP nd is responsile for hndling lient requestsF sts min gol is to onvert ymfonygomponentrttppoundtionequest ojet to ymfonygomponentrttppoundtionesponse ojetF ivery ymfonyP uernel implements ymfonygomponentrttpuernelrttpuernelsnterfeX SFIUF snternls QIS

ymfony houmenttionD PFH

function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)


gontrollers o onvert equest to esponseD the uernel relies on gontrollerF e gontroller n e ny vlid r llleF he uernel delegtes the seletion of wht gontroller should e exeuted to n implementtion of ymfonygomponentrttpuernelgontrollergontrolleresolversnterfeX

public function getController(Request $request); public function getArguments(Request $request, $controller);

he XmethodXymfonygomponentrttpuernelgontrollergontrolleresolversnterfeXXgetgontroller method returns the gontroller @ r llleA ssoited with the given equestF he defult implementtion @ymfonygomponentrttpuernelgontrollergontrolleresolverA looks for ontroller request ttriute tht represents the ontroller nme @ lssXXmethod stringD like fundleflogfundleostgontrollerXindexetionAF

X he defult implementtion uses the ymfonyfundleprmeworkfundleiventvisteneroutervis to de(ne the ontroller equest ttriute @see kernelFrequest iventAF

he XmethodXymfonygomponentrttpuernelgontrollergontrolleresolversnterfeXXgetergument method returns n rry of rguments to pss to the gontroller llleF he defult implementtion utomtilly resolves the method rgumentsD sed on the equest ttriutesF wthing gontroller method rguments from equest ttriutes por eh method rgumentD ymfonyP tries to get the vlue of equest ttriute with the sme nmeF sf it is not de(nedD the rgument defult vlue is used if de(nedX

// Symfony2 will look for an 'id' attribute (mandatory) // and an 'admin' one (optional) public function showAction($id, $admin = true) { // ... }

QIT

SF

ymfony houmenttionD PFH rndling equests he hndle@A method tkes equest nd lwys returns esponseF o onvert the equestD hndle@A relies on the esolver nd n ordered hin of ivent noti(tions @see the next setion for more informtion out eh iventAX IF fefore doing nything elseD the kernelFrequest event is noti(ed ! if one of the listeners returns esponseD it jumps to step V diretlyY PF he esolver is lled to determine the gontroller to exeuteY QF visteners of the kernelFontroller event n now mnipulte the gontroller llle the wy they wnt @hnge itD wrp itD FFFAY RF he uernel heks tht the gontroller is tully vlid r llleY SF he esolver is lled to determine the rguments to pss to the gontrollerY TF he uernel lls the gontrollerY UF sf the gontroller does not return esponseD listeners of the kernelFview event n onvert the gontroller return vlue to esponseY VF visteners of the kernelFresponse event n mnipulte the esponse @ontent nd hedersAY WF he esponse is returnedF sf n ixeption is thrown during proessingD the kernelFexeption is noti(ed nd listeners re given hne to onvert the ixeption to esponseF sf tht worksD the kernelFresponse event is noti(edY if notD the ixeption is reEthrownF sf you don9t wnt ixeptions to e ught @for emedded requests for instneAD disle the kernelFexeption event y pssing flse s the third rgument to the hndle@A methodF snternl equests et ny time during the hndling of request @the mster9 oneAD suErequest n e hndledF ou n pss the request type to the hndle@A method @its seond rgumentAX

rttpuernelsnterfeXXweiiiY rttpuernelsnterfeXXfiiF
he type is pssed to ll events nd listeners n t ordingly @some proessing must only our on the mster requestAF

SFIUF snternls

QIU

ymfony houmenttionD PFH ivents ih event thrown y the uernel is ymfonygomponentrttpuerneliventuerneliventF his mens hs ess to the sme si informtionX sulss of tht eh event

getequestype@A E returns the type of the request @rttpuernelsnterfeXXweiii or rttpuernelsnterfeXXfiiAY getuernel@A E returns the uernel hndling the requestY getequest@A E returns the urrent equest eing hndledF

getRequestType()
he getequestype@A method llows listeners to know the type of the requestF por instneD if listener must only e tive for mster requestsD dd the following ode t the eginning of your listener methodX

use Symfony\Component\HttpKernel\HttpKernelInterface; if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { // return immediately return; }


X sf you re not yet fmilir with the ymfonyP ivent hisptherD red the ivents setion (rstF

kernel.request Event
ivent glssX ymfonygomponentrttpuerneliventqetesponseivent he gol of this event is to either return esponse ojet immeditely or setup vriles so tht gontroller n e lled fter the eventF eny listener n return esponse ojet vi the setesponse@A method on the eventF sn this seD ll other listeners won9t e lledF his event is used y prmeworkfundle to populte the ontroller equest ttriuteD vi the ymfonyfundleprmeworkfundleiventvisteneroutervistenerF equestvistener uses ymfonygomponentoutingoutersnterfe ojet to mth the equest nd determine the gontroller nme @stored in the ontroller equest ttriuteAF

QIV

SF

ymfony houmenttionD PFH

kernel.controller Event
ivent glssX ymfonygomponentrttpuerneliventpiltergontrollerivent his event is not used y prmeworkfundleD ut n e n entry point used to modify the ontroller tht should e exeutedX

use Symfony\Component\HttpKernel\Event\FilterControllerEvent; public function onKernelController(FilterControllerEvent $event) { $controller = $event->getController(); // ... // the controller can be changed to any PHP callable $event->setController($controller);

kernel.view Event
ivent glssX ymfonygomponentrttpuerneliventqetesponseporgontrolleresultivent his event is not used y prmeworkfundleD ut it n e used to implement view suE systemF his event is lled only if the gontroller does not return esponse ojetF he purpose of the event is to llow some other return vlue to e onverted into esponseF he vlue returned y the gontroller is essile vi the getgontrolleresult methodX

use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; use Symfony\Component\HttpFoundation\Response; public function onKernelView(GetResponseForControllerResultEvent $event) { $val = $event->getReturnValue(); $response = new Response(); // some how customize the Response from the return value } $event->setResponse($response);

kernel.response Event
ivent glssX ymfonygomponentrttpuerneliventpilteresponseivent he purpose of this event is to llow other systems to modify or reple the esponse ojet fter its retionX SFIUF snternls QIW

ymfony houmenttionD PFH

public function onKernelResponse(FilterResponseEvent $event) { $response = $event->getResponse(); // .. modify the response object }
he prmeworkfundle registers severl listenersX

ymfonygomponentrttpuerneliventvistenerro(lervistenerX ollets dt for the urrent requestY ymfonyfundleero(lerfundleiventvistenereheugoolrvistenerX injets the e heug oolrY ymfonygomponentrttpuerneliventvisteneresponsevistenerX esponse gontentEype sed on the request formtY
(xes the

ymfonygomponentrttpuerneliventvistenerisivistenerX dds urrogteE gontrol r heder when the esponse needs to e prsed for is tgsF

kernel.exception Event
ivent glssX ymfonygomponentrttpuerneliventqetesponseporixeptionivent prmeworkfundle registers n ymfonygomponentrttpuerneliventvistenerixeptionvistener tht forwrds the equest to given gontroller @the vlue of the exeptionlistenerFontroller prmeter ! must e in the lssXXmethod nottionAF e listener on this event n rete nd set esponse ojetD rete nd set new ixeption ojetD or do nothingX

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Response; public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); $response = new Response(); // setup the Response object based on the caught exception $event->setResponse($response); // you can alternatively set a new Exception // $exception = new \Exception('Some special exception'); // $event->setException($exception);

QPH

SF

ymfony houmenttionD PFH


5.17.3 The Event Dispatcher

yjeted yriented ode hs gone long wy to ensuring ode extensiilityF fy reting lsses tht hve well de(ned responsiilitiesD your ode eomes more )exile nd developer n extend them with sulsses to modify their ehviorsF fut if he wnts to shre his hnges with other developers who hve lso mde their own sulssesD ode inheritne is mootF gonsider the relEworld exmple where you wnt to provide plugin system for your projetF e plugin should e le to dd methodsD or do something efore or fter method is exeutedD without interfering with other pluginsF his is not n esy prolem to solve with single inheritneD nd multiple inheritne @were it possile with rA hs its own drwksF he ymfonyP ivent hispther implements the yserver pttern in simple nd e'etive wy to mke ll these things possile nd to mke your projets truly extensileF ke simple exmple from the ymfonyP rttpuernel omponentF yne esponse ojet hs een retedD it my e useful to llow other elements in the system to modify it @eFgF dd some he hedersA efore it9s tully usedF o mke this possileD the ymfonyP kernel throws n event E kernelFresponseF rere9s how it workX

e listener @r ojetA tells entrl dispther ojet tht it wnts to listen to the kernelFresponse eventY et some pointD the ymfonyP kernel tells the dispther ojet to dispth the kernelFresponse eventD pssing with it n ivent ojet tht hs ess to the esponse ojetY he dispther noti(es @iFeF lls method onA ll listeners of the kernelFresponse eventD llowing eh of them to mke modi(tions to the esponse ojetF
ivents hen n event is dispthedD it9s identi(ed y unique nme @eFgF kernelFresponseAD whih ny numer of listeners might e listening toF en ymfonygomponentiventhisptherivent instne is lso reted nd pssed to ll of the listenersF es you9ll see lterD the ivent ojet itself often ontins dt out the event eing dispthedF

Naming Conventions
he unique event nme n e ny stringD ut optionlly follows few simple nming onventionsX

use only lowerse lettersD numersD dots @FAD nd undersores @AY pre(x nmes with nmespe followed y dot @eFgF kernelFAY

SFIUF snternls

QPI

ymfony houmenttionD PFH

end nmes with ver tht indites wht tion is eing tken @eFgF requestAF
rere re some exmples of good event nmesX

kernelFresponse formFpresetdt

Event Names and Event Objects


hen the dispther noti(es listenersD it psses n tul ivent ojet to those listenersF he se ivent lss is very simpleX it ontins method for stopping event propgtionD ut not muh elseF yften timesD dt out spei( event needs to e pssed long with the ivent ojet so tht the listeners hve needed informtionF sn the se of the kernelFresponse eventD the ivent ojet tht9s reted nd pssed to eh listener is tully of type ymfonygomponentrttpuerneliventpilteresponseiventD sulss of the se ivent ojetF his lss ontins methods suh s getesponse nd setesponseD llowing listeners to get or even reple the esponse ojetF he morl of the story is thisX when reting listener to n eventD the ivent ojet tht9s pssed to the listener my e speil sulss tht hs dditionl methods for retrieving informtion from nd responding to the eventF he hispther he dispther is the entrl ojet of the event dispther systemF sn generlD single dispther is retedD whih mintins registry of listenersF hen n event is dispthed vi the disptherD it noti(es ll listeners registered with tht eventF

use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher();


gonneting visteners o tke dvntge of n existing eventD you need to onnet listener to the dispther so tht it n e noti(ed when the event is dispthedF e ll to the dispther ddvistener@A method ssoites ny vlid r llle to n eventX

$listener = new AcmeListener(); $dispatcher->addListener('foo.action', array($listener, 'onFooAction'));


he ddvistener@A method tkes up to three rgumentsX QPP SF

ymfony houmenttionD PFH

he event nme @stringA tht this listener wnts to listen toY e r llle tht will e noti(ed when n event is thrown tht it listens toY en optionl priority integer @higher equls more importntA tht determines when listener is triggered versus other listeners @defults to HAF sf two listeners hve the sme priorityD they re exeuted in the order tht they were dded to the disptherF
X e r llle is r vrile tht n e used y the lluserfun@A funtion nd returns true when pssed to the isllle@A funtionF st n e glosure instneD string representing funtionD or n rry representing n ojet method or lss methodF o frD you9ve seen how r ojets n e registered s listenersF ou n lso register r glosures s event listenersX

use Symfony\Component\EventDispatcher\Event; $dispatcher->addListener('foo.action', function (Event $event) { // will be executed when the foo.action event is dispatched });
yne listener is registered with the disptherD it wits until the event is noti(edF sn the ove exmpleD when the fooFtion event is dispthedD the dispther lls the emevistenerXXonpooetion method nd psses the ivent ojet s the single rgumentX

use Symfony\Component\EventDispatcher\Event; class AcmeListener { // ... public function onFooAction(Event $event) { // do something }

X sf you use the ymfonyP wg frmeworkD listeners n e registered vi your on(gurtionF es n dded onusD the listener ojets re instntited only when neededF sn mny sesD speil ivent sulss tht9s spei( to the given event is pssed to the listenerF his gives the listener ess to speil informtion out the eventF ghek the doumenttion or implementtion of eh event to determine the ext ymfonygomponentiventhisptherivent instne

SFIUF snternls

QPQ

ymfony houmenttionD PFH tht9s eing pssedF por exmpleD the kernelFevent event psses n instne of ymfonygomponentrttpuerneliventpilteresponseiventX

use Symfony\Component\HttpKernel\Event\FilterResponseEvent public function onKernelResponse(FilterResponseEvent $event) { $response = $event->getResponse(); $request = $event->getRequest(); } // ...

greting nd hispthing n ivent sn ddition to registering listeners with existing eventsD you n rete nd throw your own eventsF his is useful when reting thirdEprty lirries nd lso when you wnt to keep di'erent omponents of your own system )exile nd deoupledF

The Static Events Class


uppose you wnt to rete new ivent E storeForder E tht is dispthed eh time n order is reted inside your pplitionF o keep things orgnizedD strt y reting toreivents lss inside your pplition tht serves to de(ne nd doument your eventX

namespace Acme\StoreBundle; nal class StoreEvents { /** * The store.order event is thrown each time an order is created * in the system. * * The event listener receives an Acme\StoreBundle\Event\FilterOrderEvent * instance. * * @var string */ const onStoreOrder = 'store.order'; }
xotie tht this lss doesn9t tully do nythingF he purpose of the toreivents lss is just to e lotion where informtion out ommon events n e entrlizedF xotie lso tht speil pilteryrderivent lss will e pssed to eh listener of this eventF

QPR

SF

ymfony houmenttionD PFH

Creating an Event object


vterD when you dispth this new eventD you9ll rete n ivent instne nd pss it to the disptherF he dispther then psses this sme instne to eh of the listeners of the eventF sf you don9t need to pss ny informtion to your listenersD you n use the defult ymfonygomponentiventhisptherivent lssF wost of the timeD howeverD you will need to pss informtion out the event to eh listenerF o omplish thisD you9ll rete new lss tht extends ymfonygomponentiventhisptheriventF sn this exmpleD eh listener will need ess to some pretend yrder ojetF grete n ivent lss tht mkes this possileX

namespace Acme\StoreBundle\Event; use Symfony\Component\EventDispatcher\Event; use Acme\StoreBundle\Order; class FilterOrderEvent extends Event { protected $order; public function __construct(Order $order) { $this->order = $order; } public function getOrder() { return $this->order; }

ih listener now hs ess to the yrder ojet vi the getyrder methodF

Dispatch the Event


he XmethodXymfonygomponentiventhisptheriventhisptherXXdispth method noti(es ll listeners of the given eventF st tkes two rgumentsX the nme of the event to dispth nd the ivent instne to pss to eh listener of tht eventX

use Acme\StoreBundle\StoreEvents; use Acme\StoreBundle\Order; use Acme\StoreBundle\Event\FilterOrderEvent; // the order is somehow created or retrieved $order = new Order();
SFIUF snternls QPS

ymfony houmenttionD PFH

// ... // create the FilterOrderEvent and dispatch it $event = new FilterOrderEvent($order); $dispatcher->dispatch(StoreEvents::onStoreOrder, $event);
xotie tht the speil pilteryrderivent ojet is reted nd pssed to the dispth methodF xowD ny listener to the storeForder event will reeive the pilteryrderivent nd hve ess to the yrder ojet vi the getyrder methodX

// some listener class that's been registered for onStoreOrder use Acme\StoreBundle\Event\FilterOrderEvent; public function onStoreOrder(FilterOrderEvent $event) { $order = $event->getOrder(); // do something to or with the order }
ssing long the ivent hispther yjet sf you hve look t the iventhispther lssD you will notie tht the lss does not t s ingleton @there is no getsnstne@A stti methodAF ht is intentionlD s you might wnt to hve severl onurrent event dispthers in single r requestF fut it lso mens tht you need wy to pss the dispther to the ojets tht need to onnet or notify eventsF he est prtie is to injet the event dispther ojet into your ojetsD k dependeny injetionF ou n use onstrutor injetionX

class Foo { protected $dispatcher = null; public function __construct(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; }

yr setter injetionX

class Foo { protected $dispatcher = null;

QPT

SF

ymfony houmenttionD PFH

public function setEventDispatcher(EventDispatcher $dispatcher) { $this->dispatcher = $dispatcher; }

ghoosing etween the two is relly mtter of tsteF wny tend to prefer the onstrutor injetion s the ojets re fully initilized t onstrution timeF fut when you hve long list of dependeniesD using setter injetion n e the wy to goD espeilly for optionl dependeniesF X sf you use dependeny injetion like we did in the two exmples oveD you n then use the ymfonyP hependeny snjetion omponent to elegntly mnge these ojetsF

sing ivent usriers he most ommon wy to listen to n event is to register n event listener with the disptherF his listener n listen to one or more events nd is noti(ed eh time those events re dispthedF enother wy to listen to events is vi n event susrierF en event susrier is r lss tht9s le to tell the dispther extly whih events it should susrie toF st implements the ymfonygomponentiventhisptheriventusriersnterfe interfeD whih requires single stti method lled getusriediventsF ke the following exmple of susrier tht susries to the kernelFresponse nd storeForder eventsX

namespace Acme\StoreBundle\Event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; class StoreSubscriber implements EventSubscriberInterface { static public function getSubscribedEvents() { return array( 'kernel.response' => 'onKernelResponse', 'store.order' => 'onStoreOrder', ); } public function onKernelResponse(FilterResponseEvent $event) { // ... }
SFIUF snternls QPU

ymfony houmenttionD PFH

public function onStoreOrder(FilterOrderEvent $event) { // ... }

his is very similr to listener lssD exept tht the lss itself n tell the dispther whih events it should listen toF o register susrier with the disptherD use the XmethodXymfonygomponentiventhisptheriventhisptherXXddusrier methodX

use Acme\StoreBundle\Event\StoreSubscriber; $subscriber = new StoreSubscriber(); $dispatcher->addSubscriber($subscriber);


he dispther will utomtilly register the susrier for eh event returned y the getusriedivents methodF his method returns n rry indexed y event nmes nd whose vlues re either the method nme to ll or n rry omposed of the method nme to ll nd priorityF topping ivent plowGropgtion sn some sesD it my mke sense for listener to prevent ny other listeners from eing lledF sn other wordsD the listener needs to e le to tell the dispther to stop ll propgtion of the event to future listeners @iFeF to not notify ny more listenersAF his n e omplished from inside listener vi the XmethodXymfonygomponentiventhisptheriventXXstopropgtion methodX

use Acme\StoreBundle\Event\FilterOrderEvent; public function onStoreOrder(FilterOrderEvent $event) { // ... } $event->stopPropagation();

xowD ny listeners to storeForder tht hve not yet een lled will not e lledF
5.17.4 Proler

hen enledD the ymfonyP pro(ler ollets useful informtion out eh request mde to your pplition nd store them for lter nlysisF se the pro(ler in the development QPV SF

ymfony houmenttionD PFH environment to help you to deug your ode nd enhne performneY use it in the prodution environment to explore prolems fter the ftF ou rrely hve to del with the pro(ler diretly s ymfonyP provides visulizer tools like the e heug oolr nd the e ro(lerF sf you use the ymfonyP tndrd iditionD the pro(lerD the we deug toolrD nd the we pro(ler re ll lredy on(gured with sensile settingsF X he pro(ler ollets informtion for ll requests @simple requestsD rediretsD exeptionsD ejx requestsD is requestsY nd for ll r methods nd ll formtsAF st mens tht for single vD you n hve severl ssoited pro(ling dt @one per externl requestGresponse pirAF

isulizing ro(ling ht

Using the Web Debug Toolbar


sn the development environmentD the we deug toolr is ville t the ottom of ll pgesF st displys good summry of the pro(ling dt tht gives you instnt ess to lot of useful informtion when something does not work s expetedF sf the summry provided y the e heug oolr is not enoughD lik on the token link @ string mde of IQ rndom hrtersA to ess the e ro(lerF X sf the token is not likleD it mens tht the pro(ler routes re not registered @see elow for on(gurtion informtionAF

Analyzing Proling data with the Web Proler


he e ro(ler is visuliztion tool for pro(ling dt tht you n use in development to deug your ode nd enhne performneY ut it n lso e used to explore prolems tht our in produtionF st exposes ll informtion olleted y the pro(ler in we interfeF

Accessing the Proling information


ou don9t need to use the defult visulizer to ess the pro(ling informtionF fut how n you retrieve pro(ling informtion for spei( request fter the ftc hen the pro(ler stores dt out equestD it lso ssoites token with itY this token is ville in the EheugEoken r heder of the esponseX

SFIUF snternls

QPW

ymfony houmenttionD PFH

$prole = $container->get('proler')->loadProleFromResponse($response); $prole = $container->get('proler')->loadProle($token);


X hen the pro(ler is enled ut not the we deug toolrD or when you wnt to get the token for n ejx requestD use tool like pireug to get the vlue of the EheugEoken r hederF se the (nd@A method to ess tokens sed on some riteriX

// get the latest 10 tokens $tokens = $container->get('proler')->nd('', '', 10); // get the latest 10 tokens for all URL containing /admin/ $tokens = $container->get('proler')->nd('', '/admin/', 10); // get the latest 10 tokens for local requests $tokens = $container->get('proler')->nd('127.0.0.1', '', 10);
sf you wnt to mnipulte pro(ling dt on di'erent mhine thn the one where the informtion were genertedD use the export@A nd import@A methodsX

// on the production machine $prole = $container->get('proler')->loadProle($token); $data = $proler->export($prole); // on the development machine $proler->import($data); Conguration
he defult ymfonyP on(gurtion omes with sensile settings for the pro(lerD the we deug toolrD nd the we pro(lerF rere is for instne the on(gurtion for the development environmentX

ewv

# load the proler framework: proler: { only_exceptions: false } # enable the web proler web_proler: toolbar: true

QQH

SF

ymfony houmenttionD PFH

intercept_redirects: true verbose: true


wv

<!-- xmlns:webproler="http://symfony.com/schema/dic/webproler" --> <!-- xsi:schemaLocation="http://symfony.com/schema/dic/webproler http://symfony.com/schema/dic/we <!-- load the proler --> <framework:cong> <framework:proler only-exceptions="false" /> </framework:cong> <!-- enable the web proler --> <webproler:cong toolbar="true" intercept-redirects="true" verbose="true" />
r

// load the proler $container->loadFromExtension('framework', array( 'proler' => array('only-exceptions' => false), )); // enable the web proler $container->loadFromExtension('web_proler', array( 'toolbar' => true, 'intercept-redirects' => true, 'verbose' => true, ));
hen onlyEexeptions is set to trueD the pro(ler only ollets dt when n exeption is thrown y the pplitionF hen intereptEredirets is set to trueD the we pro(ler interepts the redirets nd gives you the opportunity to look t the olleted dt efore following the rediretF hen verose is set to trueD the e heug oolr displys lot of informtionF etting verose to flse hides some seondry informtion to mke the toolr shorterF sf you enle the we pro(lerD you lso need to mount the pro(ler routesX

ewv

_proler: resource: @WebProlerBundle/Resources/cong/routing/proler.xml


SFIUF snternls QQI

ymfony houmenttionD PFH

prex: /_proler
wv

<import resource="@WebProlerBundle/Resources/cong/routing/proler.xml" prex="/_proler" />


r

$collection->addCollection($loader->import("@WebProlerBundle/Resources/cong/routing/proler.xml")
es the pro(ler dds some overhedD you might wnt to enle it only under ertin irumstnes in the prodution environmentF he onlyEexeptions settings limits pro(ling to SHH pgesD ut wht if you wnt to get informtion when the lient s omes from spei( ddressD or for limited portion of the wesitec ou n use request mtherX

ewv

# enables the proler only for request coming for the 192.168.0.0 network framework: proler: matcher: { ip: 192.168.0.0/24 } # enables the proler only for the /admin URLs framework: proler: matcher: { path: "^/admin/" } # combine rules framework: proler: matcher: { ip: 192.168.0.0/24, path: "^/admin/" } # use a custom matcher instance dened in the "custom_matcher" service framework: proler: matcher: { service: custom_matcher }
wv

<!-- enables the proler only for request coming for the 192.168.0.0 network --> <framework:cong> <framework:proler> <framework:matcher ip="192.168.0.0/24" /> </framework:proler> </framework:cong> <!-- enables the proler only for the /admin URLs --> <framework:cong>
QQP SF

ymfony houmenttionD PFH

<framework:proler> <framework:matcher path="^/admin/" /> </framework:proler> </framework:cong> <!-- combine rules --> <framework:cong> <framework:proler> <framework:matcher ip="192.168.0.0/24" path="^/admin/" /> </framework:proler> </framework:cong> <!-- use a custom matcher instance dened in the "custom_matcher" service --> <framework:cong> <framework:proler> <framework:matcher service="custom_matcher" /> </framework:proler> </framework:cong>
r

// enables the proler only for request coming for the 192.168.0.0 network $container->loadFromExtension('framework', array( 'proler' => array( 'matcher' => array('ip' => '192.168.0.0/24'), ), )); // enables the proler only for the /admin URLs $container->loadFromExtension('framework', array( 'proler' => array( 'matcher' => array('path' => '^/admin/'), ), )); // combine rules $container->loadFromExtension('framework', array( 'proler' => array( 'matcher' => array('ip' => '192.168.0.0/24', 'path' => '^/admin/'), ), )); # use a custom matcher instance dened in the "custom_matcher" service $container->loadFromExtension('framework', array( 'proler' => array( 'matcher' => array('service' => 'custom_matcher'), ),
SFIUF snternls QQQ

ymfony houmenttionD PFH

));

5.17.5 Learn more from the Cookbook

row to use the ro(ler in puntionl est row to rete ustom ht golletor row to extend glss without using snheritne row to ustomize wethod fehvior without using snheritne

5.18 API Symfony2

es puli ymfonyP @ AD X

Y Y @ A Y D F
F es F he stle es is sed on whitelistD tgged with dpiF hereforeD everything not tgged expliitly is not prt of the stle esF X esF es of ymfony PFHD the following omponents hve puli tgged esX

frowseruit glssvoder gonsole gsseletor hependenysnjetion homgrwler iventhispther


QQR SF

ymfony houmenttionD PFH

pinder rttppoundtion rttpuernel vole roess outing emplting rnsltion lidtor ml ymfonyP r ymfonyP versus plt r snstlling nd gon(guring ymfony ymfonyP gontroller outing greting nd using empltes hotrine @A eurity r ghe rnsltions ervie gontiner erformne snternls es ymfonyP ymfonyP r ymfonyP versus plt r
SFIVF es ymfonyP QQS

ymfony houmenttionD PFH

snstlling nd gon(guring ymfony ymfonyP gontroller outing greting nd using empltes hotrine @A eurity r ghe rnsltions ervie gontiner erformne snternls es ymfonyP

QQT

SF

III

QQU

6.1 How to Create and store a Symfony2 Project in git

X hough this entry is spei(lly out gitD the sme generi priniples will pply if you9re storing your projet in uversionF yne you9ve red through ymfonyP nd eome fmilir with using ymfonyD you9ll noEdout e redy to strt your own projetF sn this ookook rtileD you9ll lern the est wy to strt new ymfonyP projet tht9s stored using the git soure ontrol mngement systemF
6.1.1 Initial Project Setup

o get strtedD you9ll need to downlod ymfony nd initilize your lol git repositoryX IF hownlod the ymfonyP tndrd idition without vendorsF PF nzipGuntr the distriutionF st will rete folder lled ymfony with your new projet strutureD on(g (lesD etF enme it to whtever you likeF QF grete new (le lled Fgitignore t the root of your new projet @eFgF next to the deps (leA nd pste the following into itF piles mthing these ptterns will e ignored y gitX

/web/bundles/ /app/bootstrap* /app/cache/* /app/logs/* /vendor/ /app/cong/parameters.ini


QQW

ymfony houmenttionD PFH

RF gopy ppGon(gGprmetersFini to ppGon(gGprmetersFiniFdistF he prmetersFini (le is ignored y git @see oveA so tht mhineEspei( settings like dtse psswords ren9t ommittedF fy reting the prmetersFiniFdist (leD new developers n quikly lone the projetD opy this (le to prmetersFiniD ustomize itD nd strt developingF SF snitilize your git repositoryX

$ git init
TF edd ll of the initil (les to gitX

$ git add .
UF grete n initil ommit with your strted projetX

$ git commit -m "Initial commit"


VF pinllyD downlod ll of the thirdEprty vendor lirriesX

$ php bin/vendors install


et this pointD you hve fullyEfuntionl ymfonyP projet tht9s orretly ommitted to gitF ou n immeditely egin developmentD ommitting the new hnges to your git repositoryF ou n ontinue to follow long with the ymfonyP hpter to lern more out how to on(gure nd develop inside your pplitionF X he ymfonyP tndrd idition omes with some exmple funtionlityF o remove the smple odeD follow the instrutions on the tndrd idition edmeF

6.1.2 Managing Vendor Libraries with bin/vendors and deps

ivery ymfony projet uses lrge group of thirdEprty vendor lirriesF fy defultD these lirries re downloded y running the php inGvendors instll sriptF his sript reds from the deps (leD nd downlods the given lirries into the vendorG diretoryF st lso reds depsFlok (leD pinning eh lirry listed there to the ext git ommit hshF sn this setupD the vendors lirries ren9t prt of your git repositoryD not even s sumodulesF snstedD we rely on the deps nd depsFlok (les nd the inGvendors sript to mnge everythingF hose (les re prt of your repositoryD so the neessry versions of eh thirdE prty lirry re versionEontrolled in gitD nd you n use the vendors sript to ring your projet up to dteF

QRH

TF

ymfony houmenttionD PFH henever developer lones projetD heGshe should run the php inGvendors instll sript to ensure tht ll of the needed vendor lirries re downlodedF pgrding ymfony ine ymfony is just group of thirdEprty lirries nd thirdEprty lirries re entirely ontrolled through deps nd depsFlokD upgrding ymfony mens simply upgrding eh of these (les to mth their stte in the ltest ymfony tndrd iditionF yf ourseD if you9ve dded new entries to deps or depsFlokD e sure to reple only the originl prts @iFeF e sure not to lso delete ny of your ustom entriesAF X here is lso php inGvendors updte ommndD ut this hs nothing to do with upgrding your projet nd you will normlly not need to use itF his ommnd is used to freeze the versions of ll of your vendor lirries y reding their urrent stte nd reording it into the depsFlok (leF

endors nd umodules snsted of using the depsD inGvendors system for mnging your vendor lirriesD you my insted hoose to use ntive git sumodulesF here is nothing wrong with this pprohD though the deps system is the o0il wy to solve this prolem nd git sumodules n e di0ult to work with t timesF
6.1.3 Storing your Project on a Remote Server

ou now hve fullyEfuntionl ymfonyP projet stored in gitF roweverD in most sesD you9ll lso wnt to store your projet on remote server oth for kup purposesD nd so tht other developers n ollorte on the projetF he esiest wy to store your projet on remote server is vi qitruF uli repositories re freeD however you will need to py monthly fee to host privte repositoriesF elterntivelyD you n store your git repository on ny server y reting reones repository nd then pushing to itF yne lirry tht helps mnge this is qitoliteF

6.2

E ymfonyPD E uernel D wigfundleXixeptionXshow F D

TFPF

QRI

ymfony houmenttionD PFH wigfundleD D F D E X IF @ AY PF wigfundleXXixeptionXshow D @F exeptionontroller in the wig refereneAY X D F kernelFexeptionD F F kernelFexeption iventF wigfundleF E D D F F overidingE undleEtempltesF D ED E D X ppGesouresGwigfundleGviewsGixeptionGerrorFhtmlFtwigX

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>An Error Occurred: {{ status_text }}</title> </head> <body> <h1>Oops! An Error Occurred</h1> <h2>The server returned a "{{ status_code }} {{ status_text }}".</h2> </body> </html>
X wig9D F wig E D D ymfonyPF por more informtion out wig see greting nd using empltesF rwv D ymfony D tyx @errorFjsonFtwigAD wvD @errorFxmlFtwigAD tvsript @errorFjsFtwigAF F D E QRP TF

ymfony houmenttionD PFH ppGesouresGwigfundleGviewsGixeptionF D F


6.2.1 404

E rF D ppGesouresGwigfundleGviewsGixeptionGerrorRHRFhtmlFtwig RHR @ AF D D ymfony E X

D @ errorRHRFjsonFtwigAY D @ errorFjsonFtwigAY D rwv @ errorFhtmlFtwigAF


X esouresGviewsGixeptionD wigfundleF ymfonyPD wigkfundle vendorGsymfonyGsrGymfonyGfundleGwigfundleF D D E wigfundle ppGesouresGwigfundleGviewsGixeption F

X ED E E exeptionFhtmlFtwig rwv E exeptionFjsonFtwig tyxF

6.3 How to dene Controllers as Services

sn the ookD you9ve lerned how esily ontroller n e used when it extends the se ymfonyfundleprmeworkfundlegontrollergontroller lssF hile this works (neD ontrollers n lso e spei(ed s serviesF

TFQF row to de(ne gontrollers s ervies

QRQ

ymfony houmenttionD PFH o refer to ontroller tht9s de(ned s servieD use the single olon @XA nottionF por exmpleD suppose we9ve de(ned servie lled myontroller nd we wnt to forwrd to method lled indexetion@A inside the servieX

$this->forward('my_controller:indexAction', array('foo' => $bar));


ou need to use the sme nottion when de(ning the route ontroller vlueX

my_controller: pattern: / defaults: { _controller: my_controller:indexAction }


o use ontroller in this wyD it must e de(ned in the servie ontiner on(gurtionF por more informtionD see the ervie gontiner hpterF hen using ontroller de(ned s servieD it will most likely not extend the se gontroller lssF snsted of relying on its shortut methodsD you9ll intert diretly with the servies tht you needF portuntelyD this is usully pretty esy nd the se gontroller lss itself is gret soure on how to perform mny ommon tsksF X peifying ontroller s servie tkes little it more workF he primry dvntge is tht the entire ontroller or ny servies pssed to the ontroller n e modi(ed vi the servie ontiner on(gurtionF his is espeilly useful when developing n openE soure undle or ny undle tht will e used in mny di'erent projetsF oD even if you don9t speify your ontrollers s serviesD you9ll likely see this done in some openEsoure ymfonyP undlesF

6.4 How to force routes to always use HTTPS

ometimesD you wnt to seure some routes nd e sure tht they re lwys essed vi the r protoolF he outing omponent llows you to enfore the r sheme vi the sheme requirementX

ewv

secure: pattern: /secure defaults: { _controller: AcmeDemoBundle:Main:secure } requirements: _scheme: https


wv

<?xml version="1.0" encoding="UTF-8" ?>

QRR

TF

ymfony houmenttionD PFH

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="secure" pattern="/secure"> <default key="_controller">AcmeDemoBundle:Main:secure</default> <requirement key="_scheme">https</requirement> </route> </routes>
r

use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('secure', new Route('/secure', array( '_controller' => 'AcmeDemoBundle:Main:secure', ), array( '_scheme' => 'https', ))); return $collection;
he ove on(gurtion fores the seure route to lwys use rF hen generting the seure vD nd if the urrent sheme is rD ymfony will utomtilly generte n solute v with r s the shemeX

# If the current scheme is HTTPS {{ path('secure') }} # generates /secure # If the current scheme is HTTP {{ path('secure') }} # generates https://example.com/secure
he requirement is lso enfored for inoming requestsF sf you try to ess the Gseure pth with rD you will utomtilly e redireted to the sme vD ut with the r shemeF he ove exmple uses https for the shemeD ut you n lso fore v to lwys use httpF X he eurity omponent provides nother wy to enfore the r sheme vi the requireshnnel settingF his lterntive method is etter suited to seure n re of your wesite @ll vs under GdminA or when you wnt to seure vs de(ned in third prty undleF TFRF row to fore routes to lwys use r QRS

ymfony houmenttionD PFH

6.5 How to allow a / character in a route parameter

ometimesD you need to ompose vs with prmeters tht n ontin slsh GF por exmpleD tke the lssi GhelloG{nme} routeF fy defultD GhelloGpien will mth this route ut not GhelloGpienGurisF his is euse ymfony uses this hrter s seprtor etween route prtsF his guide overs how you n modify route so tht GhelloGpienGuris mthes the GhelloG{nme} routeD where {nme} equls pienGurisF
6.5.1 Congure the Route

fy defultD the symfony routing omponents requires tht the prmeters mth the following regex ptternX GCF his mens tht ll hrters re llowed exept GF ou must expliitly llow G to e prt of your prmeter y speifying more permissive regex ptternF

ewv

_hello: pattern: /hello/{name} defaults: { _controller: AcmeDemoBundle:Demo:hello } requirements: name: ".+"


wv

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing <route id="_hello" pattern="/hello/{name}"> <default key="_controller">AcmeDemoBundle:Demo:hello</default> <requirement key="name">.+</requirement> </route> </routes>
r

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


QRT TF

ymfony houmenttionD PFH

$collection = new RouteCollection(); $collection->add('_hello', new Route('/hello/{name}', array( '_controller' => 'AcmeDemoBundle:Demo:hello', ), array( 'name' => '.+', ))); return $collection;
ennottions

use Sensio\Bundle\FrameworkExtraBundle\Conguration\Route; class DemoController { /** * @Route("/hello/{name}", name="_hello", requirements={"name" = ".+"}) */ public function helloAction($name) { // ... } }
ht9s it3 xowD the {nme} prmeter n ontin the G hrterF

6.6 How to Use Assetic for Asset Management

esseti is powerful sset mngement lirry whih is pkged with the ymfonyP tndrd idition nd n e esily used in ymfonyP diretly from wig or r templtesF esseti omines two mjor idesX ssets nd (ltersF he ssets re (les suh s gD tvript nd imges (lesF he (lters re things tht n e pplied to these (les efore they re served to the rowserF his llows seprtion etween the sset (les stored in the pplition nd the (les tully presented to the userF ithout essetiD you just serve the (les tht re stored in the pplition diretlyX

wig

<script src="{{ asset('js/script.js') }}" type="text/javascript" />


r

<script src="<?php echo $view['assets']->getUrl('js/script.js') ?>" type="text/javascript" />


TFTF row to se esseti for esset wngement QRU

ymfony houmenttionD PFH fut with essetiD you n mnipulte these ssets however you wnt @or lod them from nywhereA efore serving themF hese mens you nX

winify nd omine ll of your g nd t (les un ll @or just someA of your g or t (les through some sort of ompilerD suh s viD e or go'eeript un imge optimiztions on your imges
6.6.1 Assets

sing esseti provides mny dvntges over diretly serving the (lesF he (les do not need to e stored where they re served from nd n e drwn from vrious soures suh s from within undleX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/*' %} <script type="text/javascript" src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/*')) as $url): ?> <script type="text/javascript" src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>
sn this exmpleD ll of the (les in the esouresGpuliGjsG diretory of the emepoofundle will e loded nd served from di'erent lotionF he tul rendered tg might simply look likeX `sript sraGjsGdIPQFjsb`Gsriptb ou n lso omine severl (les into oneF his helps to redue the numer of r requests whih is good for front end performneD s most rowsers will only proess limited numer t time slowing down pge lod timesF st lso llows you to mintin the (les more esily y splitting them into mngele prtsF his n lso help with reEusility s you n esily split projet spei( (les from those whih n e used in other pplitions ut still serve them s single (leX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/*' '@AcmeBarBundle/Resources/public/js/form.js' '@AcmeBarBundle/Resources/public/js/calendar.js' %}


QRV TF

ymfony houmenttionD PFH

<script src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/*', '@AcmeBarBundle/Resources/public/js/form.js', '@AcmeBarBundle/Resources/public/js/calendar.js')) as $url): ?> <script src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>
his does not only pply to your own (les you n lso use esseti to omine third prty ssetsD suh s juery with your own into single (leX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/thirdparty/jquery.js' '@AcmeFooBundle/Resources/public/js/*' %} <script src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/thirdparty/jquery.js', '@AcmeFooBundle/Resources/public/js/*')) as $url): ?> <script src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>

6.6.2 Filters

edditionlly to this esseti n pply (lters to the ssets efore they re servedF his inludes tsks suh s ompressing the output for smller (le sizes whih is nother vlule front end optimistionF yther (lters inlude ompiling tvript (le from go'eeript (les nd e to gF wny of the (lters do not do the work diretly ut use other lirries to do itD this so you will often hve to instll tht softwre s wellF he gret dvntge of using esseti to invoke these lirries is tht insted of hving to run them mnully when you hve worked on the (lesD esseti will tke re of this for you nd remove this step ltogether from your development nd deployment proessesF o use (lter you must speify it in the esseti on(gurtion s they re not enled y defultF por exmple to use the tvript s gompressor the following on(g needs to e ddedX TFTF row to se esseti for esset wngement QRW

ymfony houmenttionD PFH

ewv

# app/cong/cong.yml assetic: lters: yui_js: jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar"


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="yui_js" jar="%kernel.root_dir%/Resources/java/yuicompressor.jar" /> </assetic:cong>


r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'yui_js' => array( 'jar' => '%kernel.root_dir%/Resources/java/yuicompressor.jar', ), ), ));
ou n then speify using the (lter in the templteX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/*' lter='yui_js' %} <script src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/*'), array('yui_js')) as $url): ?> <script src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>
e more detil guide to on(guring nd using esseti (lters s well s detils of esseti9s deug mode n e found in row to winify tvripts nd tylesheets with s gompressorF

QSH

TF

ymfony houmenttionD PFH


6.6.3 Controlling the URL used

sf you wish to you n ontrol the vs whih esseti produesF his is done from the templte nd is reltive to the puli doument rootX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/*' output='js/combined.js' %} <script src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/*'), array(), array('output' => 'js/combined.js') ) as $url): ?> <script src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>
X ymfony lso ontins method for he ustingD where the (nl v generted y esseti in the prod environment ontins query prmeter tht n e inremented vi on(gurtion on eh deploymentF por more informtionD see the ssetsversion on(gurtion optionF

6.6.4 Caching the output

he proess of reting the (les served up n e quite slow espeilly when using some of the (lters whih invoke third prty softwre to the tul workF iven when working in the development environment the slow down in the pge lods if this ws to e done eh time would quikly get frustrtingF portuntely in the dev environment esseti hes the output so this will not hppenD rther thn hving to ler the he mnully thoughD it monitors for hnges to the ssets nd regenertes the (les s neededF his mens you n work on the sset (les nd see the results on pge lod ut without hving to su'er ontinul slow pge lodsF por produtionD where you will not e mking hnges to the sset (lesD performne n e inresed y voiding the step of heking for hngesF esseti llows you to go further thn this nd void touhing ymfonyP nd even r t ll when serving the (lesF his is done y dumping ll of the output (les using onsole ommndF hese n then e served diretly y the we server s stti (lesD inresing performne nd llowing the we server to del with hing hedersF he onsole ommnd to dump the (les isX TFTF row to se esseti for esset wngement QSI

ymfony houmenttionD PFH

php app/console assetic:dump


X yne you hve dumped the output you will need to run the onsole ommnd gin to see ny new hngesF sf you run it on your development server you will need to remove the (les in order to strt letting esseti proess the ssets on the )y ginF

6.7 How

to

Minify

JavaScripts

and

Stylesheets

with

YUI

Compressor

hoo3 provides n exellent utility for minifying tvripts nd stylesheets so they trvel over the wire fsterD the s gompressorF hnks to essetiD you n tke dvntge of this tool very esilyF
6.7.1 Download the YUI Compressor JAR

he s gompressor is written in tv nd distriuted s teF hownlod the te from the hoo3 site nd sve it to ppGesouresGjvGyuiompressorFjrF
6.7.2 Congure the YUI Filters

xow you need to on(gure two esseti (lters in your pplitionD one for minifying tvripts with the s gompressor nd one for minifying stylesheetsX

ewv

# app/cong/cong.yml assetic: lters: yui_css: jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar" yui_js: jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar"


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="yui_css" jar="%kernel.root_dir%/Resources/java/yuicompressor.jar" />


QSP TF

ymfony houmenttionD PFH

<assetic:lter name="yui_js" jar="%kernel.root_dir%/Resources/java/yuicompressor.jar" /> </assetic:cong>


r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'yui_css' => array( 'jar' => '%kernel.root_dir%/Resources/java/yuicompressor.jar', ), 'yui_js' => array( 'jar' => '%kernel.root_dir%/Resources/java/yuicompressor.jar', ), ), ));
ou now hve ess to two new esseti (lters in your pplitionX yuiss nd yuijsF hese will use the s gompressor to minify stylesheets nd tvriptsD respetivelyF
6.7.3 Minify your Assets

ou hve s gompressor on(gured nowD ut nothing is going to hppen until you pply one of these (lters to n ssetF ine your ssets re prt of the view lyerD this work is done in your templtesX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/*' lter='yui_js' %} <script src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/*'), array('yui_js')) as $url): ?> <script src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>
X he ove exmple ssumes tht you hve undle lled emepoofundle nd your tvript (les re in the esouresGpuliGjs diretory under your undleF his isn9t importnt however E you n inlude your tvsript (les no mtter where they reF

TFUF row to winify tvripts nd tylesheets with s gompressor

QSQ

ymfony houmenttionD PFH ith the ddition of the yuijs (lter to the sset tgs oveD you should now see mini(ed tvripts oming over the wire muh fsterF he sme proess n e repeted to minify your stylesheetsF

wig

{% stylesheets '@AcmeFooBundle/Resources/public/css/*' lter='yui_css' %} <link rel="stylesheet" type="text/css" media="screen" href="{{ asset_url }}" /> {% endstylesheets %}
r

<?php foreach ($view['assetic']->stylesheets( array('@AcmeFooBundle/Resources/public/css/*'), array('yui_css')) as $url): ?> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $view->escape($url) ?>" /> <?php endforeach; ?>

6.7.4 Disable Minication in Debug Mode

wini(ed tvripts nd tylesheets re very di0ult to redD let lone deugF feuse of thisD esseti lets you disle ertin (lter when your pplition is in deug modeF ou n do this e pre(xing the (lter nme in your templte with question mrkX cF his tells esseti to only pply this (lter when deug mode is o'F

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/*' lter='?yui_js' %} <script src="{{ asset_url }}"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/*'), array('?yui_js')) as $url): ?> <script src="<?php echo $view->escape($url) ?>"></script> <?php endforeach; ?>

6.8 How

to

Use

Assetic

For

Image

Optimization

with

Twig

Functions

emongst its mny (ltersD esseti hs four (lters whih n e used for onEtheE)y imge optimiztionF his llows you to get the ene(ts of smller (le sizes without hving to QSR TF

ymfony houmenttionD PFH use n imge editor to proess eh imgeF he results re hed nd n e dumped for prodution so there is no performne hit for your end usersF
6.8.1 Using Jpegoptim

tpegoptim is utility for optimizing tiq (lesF o use it with essetiD dd the following to the esseti on(gX

ewv

# app/cong/cong.yml assetic: lters: jpegoptim: bin: path/to/jpegoptim


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="jpegoptim" bin="path/to/jpegoptim" /> </assetic:cong>


r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'jpegoptim' => array( 'bin' => 'path/to/jpegoptim', ), ), ));
X xotie tht to use jpegoptimD you must hve it lredy instlled on your systemF he in option points to the lotion of the ompiled inryF st n now e used from templteX

wig

{% image '@AcmeFooBundle/Resources/public/images/example.jpg' lter='jpegoptim' output='/images/example.jpg' %}


TFVF row to se esseti por smge yptimiztion with wig puntions QSS

ymfony houmenttionD PFH

<img src="{{ asset_url }}" alt="Example"/> {% endimage %}


r

<?php foreach ($view['assetic']->images( array('@AcmeFooBundle/Resources/public/images/example.jpg'), array('jpegoptim')) as $url): ?> <img src="<?php echo $view->escape($url) ?>" alt="Example"/> <?php endforeach; ?>
emoving ll isp ht fy defultD running this (lter only removes some of the met informtion stored in the (leF eny isp dt nd omments re not removedD ut you n remove these y using the stripll optionX

ewv

# app/cong/cong.yml assetic: lters: jpegoptim: bin: path/to/jpegoptim strip_all: true


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="jpegoptim" bin="path/to/jpegoptim" strip_all="true" /> </assetic:cong>
r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'jpegoptim' => array( 'bin' => 'path/to/jpegoptim', 'strip_all' => 'true', ), ), ));
QST TF

ymfony houmenttionD PFH vowering wximum ulity he qulity level of the tiq is not 'eted y defultF ou n gin further (le size redutions y setting the mx qulity setting lower thn the urrent level of the imgesF his will of ourse e t the expense of imge qulityX

ewv

# app/cong/cong.yml assetic: lters: jpegoptim: bin: path/to/jpegoptim max: 70


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="jpegoptim" bin="path/to/jpegoptim" max="70" /> </assetic:cong>
r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'jpegoptim' => array( 'bin' => 'path/to/jpegoptim', 'max' => '70', ), ), ));

6.8.2 Shorter syntax: Twig Function

sf you9re using wigD it9s possile to hieve ll of this with shorter syntx y enling nd using speil wig funtionF trt y dding the following on(gX

ewv

# app/cong/cong.yml assetic: lters:


TFVF row to se esseti por smge yptimiztion with wig puntions QSU

ymfony houmenttionD PFH

jpegoptim: bin: path/to/jpegoptim twig: functions: jpegoptim: ~


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="jpegoptim" bin="path/to/jpegoptim" /> <assetic:twig> <assetic:twig_function name="jpegoptim" /> </assetic:twig> </assetic:cong>
r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'jpegoptim' => array( 'bin' => 'path/to/jpegoptim', ), ), 'twig' => array( 'functions' => array('jpegoptim'), ), ), ));
he wig templte n now e hnged to the followingX

<img src="{{ jpegoptim('@AcmeFooBundle/Resources/public/images/example.jpg') }}" alt="Example"/>


ou n speify the output diretory in the on(g in the following wyX

ewv

# app/cong/cong.yml assetic: lters: jpegoptim: bin: path/to/jpegoptim


QSV TF

ymfony houmenttionD PFH

twig: functions: jpegoptim: { output: images/*.jpg }


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="jpegoptim" bin="path/to/jpegoptim" /> <assetic:twig> <assetic:twig_function name="jpegoptim" output="images/*.jpg" /> </assetic:twig> </assetic:cong>
r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'jpegoptim' => array( 'bin' => 'path/to/jpegoptim', ), ), 'twig' => array( 'functions' => array( 'jpegoptim' => array( output => 'images/*.jpg' ), ), ), ));

6.9 How to Apply an Assetic Filter to a Specic File Extension

esseti (lters n e pplied to individul (lesD groups of (les or evenD s you9ll see hereD (les tht hve spei( extensionF o show you how to hndle eh optionD let9s suppose tht you wnt to use esseti9s go'eeript (lterD whih ompiles go'eeript (les into tvsriptF he min on(gurtion is just the pths to o'ee nd nodeF hese defult respetively to GusrGinGo'ee nd GusrGinGnodeX

ewv
TFWF row to epply n esseti pilter to pei( pile ixtension QSW

ymfony houmenttionD PFH

# app/cong/cong.yml assetic: lters: coee: bin: /usr/bin/coee node: /usr/bin/node


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="coee" bin="/usr/bin/coee" node="/usr/bin/node" /> </assetic:cong>
r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'coee' => array( 'bin' => '/usr/bin/coee', 'node' => '/usr/bin/node', ), ), ));

6.9.1 Filter a Single File

ou n now serve up single go'eeript (le s tvript from within your templtesX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/example.coee' lter='coee' %} <script src="{{ asset_url }} type="text/javascript"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/example.coee'), array('coee')) as $url): ?>


QTH TF

ymfony houmenttionD PFH

<script src="<?php echo $view->escape($url) ?>" type="text/javascript"></script> <?php endforeach; ?>


his is ll tht9s needed to ompile this go'eeript (le nd server it s the ompiled tvriptF
6.9.2 Filter Multiple Files

ou n lso omine multiple go'eeript (les into single output (leX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/example.coee' '@AcmeFooBundle/Resources/public/js/another.coee' lter='coee' %} <script src="{{ asset_url }} type="text/javascript"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/example.coee', '@AcmeFooBundle/Resources/public/js/another.coee'), array('coee')) as $url): ?> <script src="<?php echo $view->escape($url) ?>" type="text/javascript"></script> <?php endforeach; ?>
foth the (les will now e served up s single (le ompiled into regulr tvriptF
6.9.3 Filtering based on a File Extension

yne of the gret dvntges of using esseti is reduing the numer of sset (les to lower r requestsF sn order to mke full use of thisD it would e good to omine ll your tvript nd go'eeript (les together sine they will ultimtely ll e served s tvriptF nfortuntely just dding the tvript (les to the (les to e omined s ove will not work s the regulr tvript (les will not survive the go'eeript ompiltionF his prolem n e voided y using the pplyto option in the on(gD whih llows you to speify tht (lter should lwys e pplied to prtiulr (le extensionsF sn this se you n speify tht the go'ee (lter is pplied to ll Fo'ee (lesX

ewv

# app/cong/cong.yml assetic:
TFWF row to epply n esseti pilter to pei( pile ixtension QTI

ymfony houmenttionD PFH

lters: coee: bin: /usr/bin/coee node: /usr/bin/node apply_to: "\.coee$"


wv

<!-- app/cong/cong.xml --> <assetic:cong> <assetic:lter name="coee" bin="/usr/bin/coee" node="/usr/bin/node" apply_to="\.coee$" /> </assetic:cong>
r

// app/cong/cong.php $container->loadFromExtension('assetic', array( 'lters' => array( 'coee' => array( 'bin' => '/usr/bin/coee', 'node' => '/usr/bin/node', 'apply_to' => '\.coee$', ), ), ));
ith thisD you no longer need to speify the o'ee (lter in the templteF ou n lso list regulr tvript (lesD ll of whih will e omined nd rendered s single tvript (le @with only the Fo'ee (les eing run through the go'eeript (lterAX

wig

{% javascripts '@AcmeFooBundle/Resources/public/js/example.coee' '@AcmeFooBundle/Resources/public/js/another.coee' '@AcmeFooBundle/Resources/public/js/regular.js' %} <script src="{{ asset_url }} type="text/javascript"></script> {% endjavascripts %}


r

<?php foreach ($view['assetic']->javascripts( array('@AcmeFooBundle/Resources/public/js/example.coee', '@AcmeFooBundle/Resources/public/js/another.coee',


QTP TF

ymfony houmenttionD PFH

'@AcmeFooBundle/Resources/public/js/regular.js'), as $url): ?> <script src="<?php echo $view->escape($url) ?>" type="text/javascript"></script> <?php endforeach; ?>

6.10 How to handle File Uploads with Doctrine

rndling (le uplods with hotrine entities is no di'erent thn hndling ny other (le uplodF sn other wordsD you9re free to move the (le in your ontroller fter hndling form sumissionF por exmples of how to do thisD see the (le type referene pgeF sf you hoose toD you n lso integrte the (le uplod into your entity lifeyle @iFeF retionD updte nd removlAF sn this seD s your entity is retedD updtedD nd removed from hotrineD the (le uploding nd removl proessing will tke ple utomtilly @without needing to do nything in your ontrollerAY o mke this workD you9ll need to tke re of numer of detilsD whih will e overed in this ookook entryF
6.10.1 Basic Setup

pirstD rete simple hotrine intity lss to work withX

// src/Acme/DemoBundle/Entity/Document.php namespace Acme\DemoBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\Entity */ class Document { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ public $id; /** * @ORM\Column(type="string", length=255) * @Assert\NotBlank
TFIHF row to hndle pile plods with hotrine QTQ

ymfony houmenttionD PFH

*/ public $name; /** * @ORM\Column(type="string", length=255, nullable=true) */ public $path; public function getAbsolutePath() { return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path; } public function getWebPath() { return null === $this->path ? null : $this->getUploadDir().'/'.$this->path; } protected function getUploadRootDir() { // the absolute directory path where uploaded documents should be saved return __DIR__.'/../../../../web/'.$this->getUploadDir(); } protected function getUploadDir() { // get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view. return 'uploads/documents'; }

he houment entity hs nme nd it is ssoited with (leF he pth property stores the reltive pth to the (le nd is persisted to the dtseF he getesoluteth@A is onveniene method tht returns the solute pth to the (le while the geteth@A is onveniene method tht returns the we pthD whih n e used in templte to link to the uploded (leF X sf you hve not done so lredyD you should proly red the (le type doumenttion (rst to understnd how the si uplod proess worksF

X sf you9re using nnottions to speify your nnottion rules @s shown in this exmpleAD e sure tht you9ve enled vlidtion y nnottion @see vlidtion on(gurtionAF o hndle the tul (le uplod in the formD use virtul (le (eldF por exmpleD if you9re QTR TF

ymfony houmenttionD PFH uilding your form diretly in ontrollerD it might look like thisX

public function uploadAction() { // ... $form = $this->createFormBuilder($document) ->add('name') ->add('le') ->getForm() ; } // ...

xextD rete this property on your houment lss nd dd some vlidtion rulesX

// src/Acme/DemoBundle/Entity/Document.php // ... class Document { /** * @Assert\File(maxSize="6000000") */ public $le; } // ...

X es you re using the pile onstrintD ymfonyP will utomtilly guess tht the form (eld is (le uplod inputF ht9s why you did not hve to set it expliitly when reting the form ove @Ebdd@9(le9AAF he following ontroller shows you how to hndle the entire proessX

use Acme\DemoBundle\Entity\Document; use Sensio\Bundle\FrameworkExtraBundle\Conguration\Template; // ... /** * @Template() */ public function uploadAction() { $document = new Document(); $form = $this->createFormBuilder($document)
TFIHF row to hndle pile plods with hotrine QTS

ymfony houmenttionD PFH

->add('name') ->add('le') ->getForm()

if ($this->getRequest()->getMethod() === 'POST') { $form->bindRequest($this->getRequest()); if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $em->persist($document); $em->ush(); } $this->redirect($this->generateUrl('...'));

} }

return array('form' => $form->createView());

X hen writing the templteD don9t forget to set the entype ttriuteX

<h1>Upload File</h1> <form action="#" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" value="Upload Document" /> </form>
he previous ontroller will utomtilly persist the houment entity with the sumitted nmeD ut it will do nothing out the (le nd the pth property will e lnkF en esy wy to hndle the (le uplod is to move it just efore the entity is persisted nd then set the pth property ordinglyF trt y lling new uplod@A method on the houment lssD whih you9ll rete in moment to hndle the (le uplodX

if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $document->upload(); $em->persist($document); $em->ush(); $this->redirect('...');


QTT TF

ymfony houmenttionD PFH

}
he uplod@A method will tke dvntge of the ymfonygomponentrttppoundtionpileplodedpile ojetD whih is wht9s returned fter (le (eld is sumittedX

public function upload() { // the le property can be empty if the eld is not required if (null === $this->le) { return; } // we use the original le name here but you should // sanitize it at least to avoid any security issues // move takes the target directory and then the target lename to move to $this->le->move($this->getUploadRootDir(), $this->le->getClientOriginalName()); // set the path property to the lename where you'ved saved the le $this->setPath($this->le->getClientOriginalName()); // clean up the le property as you won't need it anymore $this->le = null;

6.10.2 Using Lifecycle Callbacks

iven if this implementtion worksD it su'ers from mjor )wX ht if there is prolem when the entity is persistedc he (le would hve lredy moved to its (nl lotion even though the entity9s pth property didn9t persist orretlyF o void these issuesD you should hnge the implementtion so tht the dtse opertion nd the moving of the (le eome tomiX if there is prolem persisting the entity or if the (le nnot e movedD then nothing should hppenF o do thisD you need to move the (le right s hotrine persists the entity to the dtseF his n e omplished y hooking into n entity lifeyle llkX

/** * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class Document { }

TFIHF row to hndle pile plods with hotrine

QTU

ymfony houmenttionD PFH xextD reftor the houment lss to tke dvntge of these llksX

use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class Document { /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->le) { // do whatever you want to generate a unique name $this->setPath(uniqid().'.'.$this->le->guessExtension()); } } /** * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload() { if (null === $this->le) { return; } // you must throw an exception here if the le cannot be moved // so that the entity is not persisted to the database // which the UploadedFile move() method does automatically $this->le->move($this->getUploadRootDir(), $this->path); } unset($this->le);

/** * @ORM\PostRemove() */ public function removeUpload() { if ($le = $this->getAbsolutePath()) { unlink($le); }


QTV TF

ymfony houmenttionD PFH

he lss now does everything you needX it genertes unique (lenme efore persistingD moves the (le fter persistingD nd removes the (le if the entity is ever deletedF X he dywreersist@A nd dywostersist@A event llks re triggered efore nd fter the entity is persisted to the dtseF yn the other hndD the dywrepdte@A nd dywostpdte@A event llks re lled when the entity is updtedF X he repdte nd ostpdte llks re only triggered if there is hnge in one of the entity9s (eld tht re persistedF his mens thtD y defultD if you modify only the 6(le propertyD these events will not e triggeredD s the property itself is not diretly persisted vi hotrineF yne solution would e to use n updted (eld tht9s persisted to hotrineD nd to modify it mnully when hnging the (leF

6.10.3 Using the id as the lename

sf you wnt to use the id s the nme of the (leD the implementtion is slightly di'erent s you need to sve the extension under the pth propertyD insted of the tul (lenmeX

use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class Document { /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->le) { $this->setPath($this->le->guessExtension()); } } /** * @ORM\PostPersist()
TFIHF row to hndle pile plods with hotrine QTW

ymfony houmenttionD PFH

* @ORM\PostUpdate() */ public function upload() { if (null === $this->le) { return; } // you must throw an exception here if the le cannot be moved // so that the entity is not persisted to the database // which the UploadedFile move() method does $this->le->move($this->getUploadRootDir(), $this->id.'.'.$this->le->guessExtension()); } unset($this->le);

/** * @ORM\PostRemove() */ public function removeUpload() { if ($le = $this->getAbsolutePath()) { unlink($le); } } public function getAbsolutePath() { return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->id.'.'.$this->path; }

6.11 Doctrine

Extensions:

Timestampable:

Sluggable,

Translatable, etc.

hotrineP is very )exileD nd the ommunity hs lredy reted series of useful hotrine extensions to help you with tsks ommon entityErelted tsksF yne undle in prtiulr E the hotrineixtensionsfundle E provides integrtion with n extensions lirry tht o'ers luggleD rnsltleD imestmpleD voggleD nd ree ehviorsF ee the undle for more detilsF

QUH

TF

ymfony houmenttionD PFH

6.12 Registering Event Listeners and Subscribers

hotrine pkges rih event system tht (res events when lmost nything hppens inside the systemF por youD this mens tht you n rete ritrry servies nd tell hotrine to notify those ojets whenever ertin tion @eFgF preveA hppens within hotrineF his ould e usefulD for exmpleD to rete n independent serh index whenever n ojet in your dtse is svedF hotrine de(nes two types of ojets tht n listen to hotrine eventsX listeners nd susriersF foth re very similrD ut listeners re it more strightforwrdF por moreD see he ivent ystem on hotrine9s wesiteF
6.12.1 Conguring the Listener/Subscriber

o register servie to t s n event listener or susrier you just hve to tg it with the pproprite nmeF hepending on your useEseD you n hook listener into every hfev onnetion nd yw entity mnger or just into one spei( hfev onnetion nd ll the entity mngers tht use this onnetionF

ewv

doctrine: dbal: default_connection: default connections: default: driver: pdo_sqlite memory: true services: my.listener: class: Acme\SearchBundle\Listener\SearchIndexer tags: - { name: doctrine.event_listener, event: postSave } my.listener2: class: Acme\SearchBundle\Listener\SearchIndexer2 tags: - { name: doctrine.event_listener, event: postSave, connection: default } my.subscriber: class: Acme\SearchBundle\Listener\SearchIndexerSubsriber tags: - { name: doctrine.event_subscriber, connection: default }
wv

TFIPF egistering ivent visteners nd usriers

QUI

ymfony houmenttionD PFH

<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:doctrine="http://symfony.com/schema/dic/doctrine"> <doctrine:cong> <doctrine:dbal default-connection="default"> <doctrine:connection driver="pdo_sqlite" memory="true" /> </doctrine:dbal> </doctrine:cong> <services> <service id="my.listener" class="Acme\SearchBundle\Listener\SearchIndexer"> <tag name="doctrine.event_listener" event="postSave" /> </service> <service id="my.listener2" class="Acme\SearchBundle\Listener\SearchIndexer2"> <tag name="doctrine.event_listener" event="postSave" connection="default" /> </service> <service id="my.subscriber" class="Acme\SearchBundle\Listener\SearchIndexerSubsriber"> <tag name="doctrine.event_subscriber" connection="default" /> </service> </services> </container>

6.12.2 Creating the Listener Class

sn the previous exmpleD servie myFlistener ws on(gured s hotrine listener on the event postveF ht lss ehind tht servie must hve postve methodD whih will e lled when the event is thrownX

// src/Acme/SearchBundle/Listener/SearchIndexer.php namespace Acme\SearchBundle\Listener; use Doctrine\ORM\Event\LifecycleEventArgs; use Acme\StoreBundle\Entity\Product; class SearchIndexer { public function postSave(LifecycleEventArgs $args) { $entity = $args->getEntity(); $entityManager = $args->getEntityManager(); // perhaps you only want to act on some "Product" entity if ($entity instanceof Product) { // do something with the Product
QUP TF

ymfony houmenttionD PFH

sn eh eventD you hve ess to vifeyleiventergs ojetD whih gives you ess to oth the entity ojet of the event nd the entity mnger itselfF yne importnt thing to notie is tht listener will e listening for ll entities in your pplitionF oD if you9re interested in only hndling spei( type of entity @eFgF rodut entity ut not flogost entityAD you should hek for the lss nme of the entity in your method @s shown oveAF

6.13 How to generate Entities from an Existing Database

hen strting work on rnd new projet tht uses dtseD two di'erent situtions omes nturllyF sn most sesD the dtse model is designed nd uilt from srthF ometimesD howeverD you9ll strt with n existing nd proly unhngele dtse modelF portuntelyD hotrine omes with unh of tools to help generte model lsses from your existing dtseF X es the hotrine tools doumenttion sysD reverse engineering is oneEtime proess to get strted on projetF hotrine is le to onvert pproximtely UHEVH7 of the neessry mpping informtion sed on (eldsD indexes nd foreign key onstrintsF hotrine n9t disover inverse ssoitionsD inheritne typesD entities with foreign keys s primry keys or semntil opertions on ssoitions suh s sde or lifeyle eventsF ome dditionl work on the generted entities will e neessry fterwrds to design eh to (t your domin model spei(itiesF his tutoril ssumes you9re using simple log pplition with the following two tlesX logpost nd logommentF e omment reord is linked to post reord thnks to foreign key onstrintF

CREATE TABLE `blog_post` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `title` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `content` longtext COLLATE utf8_unicode_ci NOT NULL, `created_at` datetime NOT NULL, PRIMARY KEY (`id`), ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE `blog_comment` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `post_id` bigint(20) NOT NULL,
TFIQF row to generte intities from n ixisting htse QUQ

ymfony houmenttionD PFH

`author` varchar(20) COLLATE utf8_unicode_ci NOT NULL, `content` longtext COLLATE utf8_unicode_ci NOT NULL, `created_at` datetime NOT NULL, PRIMARY KEY (`id`), KEY `blog_comment_post_id_idx` (`post_id`), CONSTRAINT `blog_post_id` FOREIGN KEY (`post_id`) REFERENCES `blog_post` (`id`) ON DELETE CA ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
fefore diving into the reipeD e sure your dtse onnetion prmeters re orretly setup in the ppGon(gGprmetersFini (le @or wherever your dtse on(gurtion is keptA nd tht you hve initilized undle tht will host your future entity lssF sn this tutorilD we will ssume tht n emeflogfundle exists nd is loted under the srGemeGflogfundle folderF he (rst step towrds uilding entity lsses from n existing dtse is to sk hotrine to introspet the dtse nd generte the orresponding metdt (lesF wetdt (les desrie the entity lss to generte sed on tles (eldsF

php app/console doctrine:mapping:convert xml ./src/Acme/BlogBundle/Resources/cong/doctrine/metadata/orm


his ommnd line tool sks hotrine to introspet the dtse nd generte the wv metdt (les under the srGemeGflogfundleGesouresGon(gGdotrineGmetdtGorm folder of your undleF X st9s lso possile to generte metdt lss in ewv formt y hnging the (rst rgument to ymlF he generted flogostFdmFxml metdt (le looks s followsX

<?xml version="1.0" encoding="utf-8"?> <doctrine-mapping> <entity name="BlogPost" table="blog_post"> <change-tracking-policy>DEFERRED_IMPLICIT</change-tracking-policy> <id name="id" type="bigint" column="id"> <generator strategy="IDENTITY"/> </id> <eld name="title" type="string" column="title" length="100"/> <eld name="content" type="text" column="content"/> <eld name="isPublished" type="boolean" column="is_published"/> <eld name="createdAt" type="datetime" column="created_at"/> <eld name="updatedAt" type="datetime" column="updated_at"/> <eld name="slug" type="string" column="slug" length="255"/> <lifecycle-callbacks/> </entity> </doctrine-mapping>
yne the metdt (les re genertedD you n sk hotrine to import the shem nd uild QUR TF

ymfony houmenttionD PFH relted entity lsses y exeuting the following two ommndsF

php app/console doctrine:mapping:import AcmeBlogBundle annotation php app/console doctrine:generate:entities AcmeBlogBundle


he (rst ommnd genertes entity lsses with n nnottions mppingD ut you n of ourse hnge the nnottion rgument to xml or ymlF he newly reted floggomment entity lss looks s followX

<?php // src/Acme/BlogBundle/Entity/BlogComment.php namespace Acme\BlogBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Acme\BlogBundle\Entity\BlogComment * * @ORM\Table(name="blog_comment") * @ORM\Entity */ class BlogComment { /** * @var bigint $id * * @ORM\Column(name="id", type="bigint", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var string $author * * @ORM\Column(name="author", type="string", length=100, nullable=false) */ private $author; /** * @var text $content * * @ORM\Column(name="content", type="text", nullable=false) */ private $content; /**
TFIQF row to generte intities from n ixisting htse QUS

ymfony houmenttionD PFH

* @var datetime $createdAt * * @ORM\Column(name="created_at", type="datetime", nullable=false) */ private $createdAt; /** * @var BlogPost * * @ORM\ManyToOne(targetEntity="BlogPost") * @ORM\JoinColumn(name="post_id", referencedColumnName="id") */ private $post;

es you n seeD hotrine onverts ll tle (elds to pure privte nd nnotted lss propertiesF he most impressive thing is tht it lso disovered the reltionship with the flogost entity lss sed on the foreign key onstrintF gonsequentlyD you n (nd privte 6post property mpped with flogost entity in the floggomment entity lssF he lst ommnd generted ll getters nd setters for your two flogost nd floggomment entity lss propertiesF he generted entities re now redy to e usedF rve fun3

6.14 How to use Doctrine's DBAL Layer

X his rtile is out hotrine hfev9s lyerF ypillyD you9ll work with the higher level hotrine yw lyerD whih simply uses the hfev ehind the senes to tully ommunite with the dtseF o red more out the hotrine ywD see  hotrine @AF he hotrine htse estrtion vyer @hfevA is n strtion lyer tht sits on top of hy nd o'ers n intuitive nd )exile es for ommuniting with the most populr reltionl dtsesF sn other wordsD the hfev lirry mkes it esy to exeute queries nd perform other dtse tionsF X ed the o0il hotrine hfev houmenttion to lern ll the detils nd pilities of hotrine9s hfev lirryF o get strtedD on(gure the dtse onnetion prmetersX

ewv

QUT

TF

ymfony houmenttionD PFH

# app/cong/cong.yml doctrine: dbal: driver: pdo_mysql dbname: Symfony2 user: root password: null charset: UTF8
wv

// app/cong/cong.xml <doctrine:cong> <doctrine:dbal name="default" dbname="Symfony2" user="root" password="null" driver="pdo_mysql" /> </doctrine:cong>
r

// app/cong/cong.php $container->loadFromExtension('doctrine', array( 'dbal' => array( 'driver' => 'pdo_mysql', 'dbname' => 'Symfony2', 'user' => 'root', 'password' => null, ), ));
por full hfev on(gurtion optionsD see hotrine hfev gon(gurtionF ou n then ess the hotrine hfev onnetion y essing the dtseonnetion servieX

class UserController extends Controller { public function indexAction() { $conn = $this->get('database_connection'); $users = $conn->fetchAll('SELECT * FROM users'); } // ...

TFIRF row to use hotrine9s hfev vyer

QUU

ymfony houmenttionD PFH

6.14.1 Registering Custom Mapping Types

ou n register ustom mpping types through ymfony9s on(gurtionF hey will e dded to ll on(gured onnetionsF por more informtion on ustom mpping typesD red hotrine9s gustom wpping ypes setion of their doumenttionF

ewv

# app/cong/cong.yml doctrine: dbal: types: custom_rst: Acme\HelloBundle\Type\CustomFirst custom_second: Acme\HelloBundle\Type\CustomSecond


wv

<!-- app/cong/cong.xml --> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doct <doctrine:cong> <doctrine:dbal> <doctrine:dbal default-connection="default"> <doctrine:connection> <doctrine:mapping-type name="enum">string</doctrine:mapping-type> </doctrine:connection> </doctrine:dbal> </doctrine:cong> </container>
r

// app/cong/cong.php $container->loadFromExtension('doctrine', array( 'dbal' => array( 'connections' => array( 'default' => array( 'mapping_types' => array( 'enum' => 'string', ),
QUV TF

ymfony houmenttionD PFH

));

),

),

),

6.14.2 Registering Custom Mapping Types in the SchemaTool

he hemool is used to inspet the dtse to ompre the shemF o hieve this tskD it needs to know whih mpping type needs to e used for eh dtse typesF egistering new ones n e done through the on(gurtionF vet9s mp the ixw type @not suppoorted y hfev y defultA to the string mpping typeX

ewv

# app/cong/cong.yml doctrine: dbal: connection: default: // Other connections parameters mapping_types: enum: string
wv

<!-- app/cong/cong.xml --> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doct <doctrine:cong> <doctrine:dbal> <doctrine:type name="custom_rst" class="Acme\HelloBundle\Type\CustomFirst" /> <doctrine:type name="custom_second" class="Acme\HelloBundle\Type\CustomSecond" /> </doctrine:dbal> </doctrine:cong> </container>
r

// app/cong/cong.php $container->loadFromExtension('doctrine', array( 'dbal' => array(


TFIRF row to use hotrine9s hfev vyer QUW

ymfony houmenttionD PFH

));

),

'types' => array( 'custom_rst' => 'Acme\HelloBundle\Type\CustomFirst', 'custom_second' => 'Acme\HelloBundle\Type\CustomSecond', ),

6.15 How to work with Multiple Entity Managers

ou n use multiple entity mngers in ymfonyP pplitionF his is neessry if you re using di'erent dtses or even vendors with entirely di'erent sets of entitiesF sn other wordsD one entity mnger tht onnets to one dtse will hndle some entities while nother entity mnger tht onnets to nother dtse might hndle the restF X sing multiple entity mngers is pretty esyD ut more dvned nd not usully requiredF fe sure you tully need multiple entity mngers efore dding in this lyer of omplexityF he following on(gurtion ode shows how you n on(gure two entity mngersX

ewv

doctrine: orm: default_entity_manager: default entity_managers: default: connection: default mappings: AcmeDemoBundle: ~ AcmeStoreBundle: ~ customer: connection: customer mappings: AcmeCustomerBundle: ~
sn this seD you9ve de(ned two entity mngers nd lled them defult nd ustomerF he defult entity mnger mnges entities in the emehemofundle nd emetorefundleD while the ustomer entity mnger mnges entities in the emegustomerfundleF hen working with multiple entity mngersD you should e expliit out whih entity mnger you wntF sf you do omit the entity mnger9s nme when sking for itD the defult entity mnger @iFeF defultA is returnedX

QVH

TF

ymfony houmenttionD PFH

class UserController extends Controller { public function indexAction() { // both return the "default" em $em = $this->get('doctrine')->getEntityManager(); $em = $this->get('doctrine')->getEntityManager('default'); } $customerEm = $this->get('doctrine')->getEntityManager('customer');

ou n now use hotrine just s you did efore E using the defult entity mnger to persist nd feth entities tht it mnges nd the ustomer entity mnger to persist nd feth its entitiesF

6.16 Registering Custom DQL Functions

hotrine llows you to speify ustom hv funtionsF por more informtion on this topiD red hotrine9s ookook rtile hv ser he(ned puntionsF sn ymfonyD you n register your ustom hv funtions s followsX

ewv

# app/cong/cong.yml doctrine: orm: # ... entity_managers: default: # ... dql: string_functions: test_string: Acme\HelloBundle\DQL\StringFunction second_string: Acme\HelloBundle\DQL\SecondStringFunction numeric_functions: test_numeric: Acme\HelloBundle\DQL\NumericFunction datetime_functions: test_datetime: Acme\HelloBundle\DQL\DatetimeFunction
wv

<!-- app/cong/cong.xml --> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"


TFITF egistering gustom hv puntions QVI

ymfony houmenttionD PFH

xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doct

<doctrine:cong> <doctrine:orm> <!-- ... --> <doctrine:entity-manager name="default"> <!-- ... --> <doctrine:dql> <doctrine:string-function name="test_string>Acme\HelloBundle\DQL\StringFunction</d <doctrine:string-function name="second_string>Acme\HelloBundle\DQL\SecondStringFun <doctrine:numeric-function name="test_numeric>Acme\HelloBundle\DQL\NumericFuncti <doctrine:datetime-function name="test_datetime>Acme\HelloBundle\DQL\DatetimeFun </doctrine:dql> </doctrine:entity-manager> </doctrine:orm> </doctrine:cong> </container>
r

// app/cong/cong.php $container->loadFromExtension('doctrine', array( 'orm' => array( // ... 'entity_managers' => array( 'default' => array( // ... 'dql' => array( 'string_functions' => array( 'test_string' => 'Acme\HelloBundle\DQL\StringFunction', 'second_string' => 'Acme\HelloBundle\DQL\SecondStringFunction', ), 'numeric_functions' => array( 'test_numeric' => 'Acme\HelloBundle\DQL\NumericFunction', ), 'datetime_functions' => array( 'test_datetime' => 'Acme\HelloBundle\DQL\DatetimeFunction', ), ), ), ), ), ));

QVP

TF

ymfony houmenttionD PFH

6.17 How to customize Form Rendering

ymfony gives you wide vriety of wys to ustomize how form is renderedF sn this guideD you9ll lern how to ustomize every possile prt of your form with s little e'ort s possile whether you use wig or r s your templting engineF
6.17.1 Form Rendering Basics

ell tht the lelD error nd rwv widget of form (eld n esily e rendered y using the formrow wig funtion or the row r helper methodX

wig

{{ form_row(form.age) }}
r

<?php echo $view['form']->row($form['age']) }} ?>


ou n lso render eh of the three prts of the (eld individullyX

wig

<div> {{ form_label(form.age) }} {{ form_errors(form.age) }} {{ form_widget(form.age) }} </div>


r

<div> <?php echo $view['form']->label($form['age']) }} ?> <?php echo $view['form']->errors($form['age']) }} ?> <?php echo $view['form']->widget($form['age']) }} ?> </div>
sn oth sesD the form lelD errors nd rwv widget re rendered y using set of mrkup tht ships stndrd with ymfonyF por exmpleD oth of the ove templtes would renderX

<div> <label for="form_age">Age</label> <ul> <li>This eld is required</li> </ul> <input type="number" id="form_age" name="form[age]" /> </div>
TFIUF row to ustomize porm endering QVQ

ymfony houmenttionD PFH o quikly prototype nd test formD you n render the entire form with just one lineX

wig

{{ form_widget(form) }}
r

<?php echo $view['form']->widget($form) }} ?>


he reminder of this reipe will explin how every prt of the form9s mrkup n e modi(ed t severl di'erent levelsF por more informtion out form rendering in generlD see F
6.17.2 What are Form Themes?

ymfony uses form frgments E smll piee of templte tht renders just one prt of form E to render every prt of form E E (eld lelsD errorsD input text (eldsD selet tgsD et he frgments re de(ned s loks in wig nd s templte (les in rF e theme is nothing more thn set of frgments tht you wnt to use when rendering formF sn other wordsD if you wnt to ustomize one portion of how form is renderedD you9ll import theme whih ontins ustomiztion of the pproprite form frgmentsF ymfony omes with defult theme @formdivlyoutFhtmlFtwig in wig nd prmeworkfundleXporm in rA tht de(nes eh nd every frgment needed to render every prt of formF sn the next setion you will lern how to ustomize theme y overriding some or ll of its frgmentsF por exmpleD when the widget of integer type (eld is renderedD n input numer (eld is generted

wig

{{ form_widget(form.age) }}
r

<?php echo $view['form']->widget($form['age']) ?>


rendersX

<input type="number" id="form_age" name="form[age]" required="required" value="33" />


snternllyD ymfony uses the integerwidget frgment to render the (eldF his is euse the (eld type is integer nd you9re rendering its widget @s opposed to its lel or errorsAF

QVR

TF

ymfony houmenttionD PFH sn wig tht would defult to the lok integerwidget from the formdivlyoutFhtmlFtwig templteF sn r it would rther e the integerwidgetFhtmlFphp prmeworkfundleGesouresGviewsGporm folderF (le loted in

he defult implementtion of the integerwidget frgment looks like thisX

wig

{% block integer_widget %} {% set type = type|default('number') %} {{ block('eld_widget') }} {% endblock integer_widget %}


r

<!-- integer_widget.html.php -->

<?php echo $view['form']->renderBlock('eld_widget', array('type' => isset($type) ? $type : "number")) ?


es you n seeD this frgment itself renders nother frgment E (eldwidgetX

wig

{% block eld_widget %} {% set type = type|default('text') %} <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" /> {% endblock eld_widget %}
r

<!-- FrameworkBundle/Resources/views/Form/eld_widget.html.php --> <input type="<?php echo isset($type) ? $view->escape($type) : "text" ?>" value="<?php echo $view->escape($value) ?>" <?php echo $view['form']->renderBlock('attributes') ?> />
he point isD the frgments ditte the rwv output of eh prt of formF o ustomize the form outputD you just need to identify nd override the orret frgmentF e set of these form frgment ustomiztions is known s form themeF hen rendering formD you n hoose whih form theme@sA you wnt to pplyF sn wig theme is single templte (le nd the frgments re the loks de(ned in this (leF sn r theme is folder nd the the frgments re individul templte (les in this folderF

TFIUF row to ustomize porm endering

QVS

ymfony houmenttionD PFH

unowing whih lok to ustomize sn this exmpleD the ustomized frgment nme is integerwidget euse you wnt to override the rwv widget for ll integer (eld typesF sf you need to ustomize textre (eldsD you would ustomize textrewidgetF es you n seeD the frgment nme is omintion of the (eld type nd whih prt of the (eld is eing rendered @eFgF widgetD lelD errorsD rowAF es suhD to ustomize how errors re rendered for just input text (eldsD you should ustomize the texterrors frgmentF wore ommonlyD howeverD you9ll wnt to ustomize how errors re displyed ross ll (eldsF ou n do this y ustomizing the (elderrors frgmentF his tkes dvntge of (eld type inheritneF pei(llyD sine the text type extends from the (eld typeD the form omponent will (rst look for the typeEspei( frgment @eFgF texterrorsA efore flling k to its prent frgment nme if it doesn9t exist @eFgF (elderrorsAF por more informtion on this topiD see porm prgment xmingF

6.17.3 Form Theming

o see the power of form themingD suppose you wnt to wrp every input numer (eld with div tgF he key to doing this is to ustomize the integerwidget frgmentF
6.17.4 Form Theming in Twig

hen ustomizing the form (eld lok in wigD you hve two options on where the ustomized form lok n liveX wethod snside the sme templte s the form snside seprte templte ros uik nd esy gn e reused y mny templtes gons gn9t e reused in other templtes equires n extr templte to e reted

foth methods hve the sme e'et ut re etter in di'erent situtionsF wethod IX snside the sme emplte s the porm he esiest wy to ustomize the integerwidget lok is to ustomize it diretly in the templte tht9s tully rendering the formF

{% extends '::base.html.twig' %} {% form_theme form _self %}


QVT TF

ymfony houmenttionD PFH

{% block integer_widget %} <div class="integer_widget"> {% set type = type|default('number') %} {{ block('eld_widget') }} </div> {% endblock %} {% block content %} {# render the form #} {{ form_row(form.age) }} {% endblock %}
fy using the speil {7 formtheme form self 7} tgD wig looks inside the sme templte for ny overridden form loksF essuming the formFge (eld is n integer type (eldD when its widget is renderedD the ustomized integerwidget lok will e usedF he disdvntge of this method is tht the ustomized form lok n9t e reused when rendering other forms in other templtesF sn other wordsD this method is most useful when mking form ustomiztions tht re spei( to single form in your pplitionF sf you wnt to reuse form ustomiztion ross severl @or llA forms in your pplitionD red on to the next setionF wethod PX snside eprte emplte ou n lso hoose to put the ustomized integerwidget form lok in seprte templte entirelyF he ode nd endEresult re the smeD ut you n now reEuse the form ustomiztion ross mny templtesX

{# src/Acme/DemoBundle/Resources/views/Form/elds.html.twig #} {% block integer_widget %} <div class="integer_widget"> {% set type = type|default('number') %} {{ block('eld_widget') }} </div> {% endblock %}
xow tht you9ve reted the ustomized form lokD you need to tell ymfony to use itF snside the templte where you9re tully rendering your formD tell ymfony to use the templte vi the formtheme tgX

{% form_theme form 'AcmeDemoBundle:Form:elds.html.twig' %} {{ form_widget(form.age) }}

TFIUF row to ustomize porm endering

QVU

ymfony houmenttionD PFH hen the formFge widget is renderedD ymfony will use the integerwidget lok from the new templte nd the input tg will e wrpped in the div element spei(ed in the ustomized lokF
6.17.5 Form Theming in PHP

hen using r s templting engineD the only method to ustomize frgment is to rete new templte (le E this is similr to the seond method used y wigF he templte (le must e nmed fter the frgmentF ou must rete integerwidgetFhtmlFphp (le in order to ustomize the integerwidget frgmentF

<!-- src/Acme/DemoBundle/Resources/views/Form/integer_widget.html.php --> <div class="integer_widget"> <?php echo $view['form']->renderBlock('eld_widget', array('type' => isset($type) ? $type : "number")) ?> </div>
xow tht you9ve reted the ustomized form templteD you need to tell ymfony to use itF snside the templte where you9re tully rendering your formD tell ymfony to use the theme vi the setheme helper methodX

<?php $view['form']->setTheme($form, array('AcmeDemoBundle:Form')) ;?> <?php $view['form']->widget($form['age']) ?>


hen the formFge widget is renderedD ymfony will use the ustomized integerwidgetFhtmlFphp templte nd the input tg will e wrpped in the div elementF
6.17.6 Referencing Base Form Blocks (Twig specic)

o frD to override prtiulr form lokD the est method is to opy the defult lok from formdivlyoutFhtmlFtwigD pste it into di'erent templteD nd the ustomize itF sn mny sesD you n void doing this y referening the se lok when ustomizing itF his is esy to doD ut vries slightly depending on if your form lok ustomiztions re in the sme templte s the form or seprte templteF eferening floks from inside the sme emplte s the porm smport the loks y dding use tg in the templte where you9re rendering the formX

{% use 'form_div_layout.html.twig' with integer_widget as base_integer_widget %}

QVV

TF

ymfony houmenttionD PFH xowD when the loks from formdivlyoutFhtmlFtwig re importedD the integerwidget lok is lled seintegerwidgetF his mens tht when you rede(ne the integerwidget lokD you n referene the defult mrkup vi seintegerwidgetX

{% block integer_widget %} <div class="integer_widget"> {{ block('base_integer_widget') }} </div> {% endblock %}


eferening fse floks from n ixternl emplte sf your form ustomiztions live inside n externl templteD you n referene the se lok y using the prent@A wig funtionX

{# src/Acme/DemoBundle/Resources/views/Form/elds.html.twig #} {% extends 'form_div_layout.html.twig' %} {% block integer_widget %} <div class="integer_widget"> {{ parent() }} </div> {% endblock %}
X st is not possile to referene the se lok when using r s the templting engineF ou hve to mnully opy the ontent from the se lok to your new templte (leF

6.17.7 Making Application-wide Customizations

sf you9d like ertin form ustomiztion to e glol to your pplitionD you n omplish this y mking the form ustomiztions in n externl templte nd then importing it inside your pplition on(gurtionX wig fy using the following on(gurtionD ny ustomized form loks inside the emehemofundleXpormX(eldsFhtmlFtwig templte will e used glolly when form is renderedF

ewv
TFIUF row to ustomize porm endering QVW

ymfony houmenttionD PFH

# app/cong/cong.yml twig: form: resources: - 'AcmeDemoBundle:Form:elds.html.twig' # ...


wv

<!-- app/cong/cong.xml --> <twig:cong ...> <twig:form> <resource>AcmeDemoBundle:Form:elds.html.twig</resource> </twig:form> <!-- ... --> </twig:cong>
r

// app/cong/cong.php $container->loadFromExtension('twig', array( 'form' => array('resources' => array( 'AcmeDemoBundle:Form:elds.html.twig', )) // ... ));
fy defultD wig uses div lyout when rendering formsF ome peopleD howeverD my prefer to render forms in tle lyoutF se the formtlelyoutFhtmlFtwig resoure to use suh lyoutX

ewv

# app/cong/cong.yml twig: form: resources: ['form_table_layout.html.twig'] # ...


wv

<!-- app/cong/cong.xml --> <twig:cong ...>


QWH TF

ymfony houmenttionD PFH

<twig:form> <resource>form_table_layout.html.twig</resource> </twig:form> <!-- ... --> </twig:cong>


r

// app/cong/cong.php $container->loadFromExtension('twig', array( 'form' => array('resources' => array( 'form_table_layout.html.twig', )) // ... ));
sf you only wnt to mke the hnge in one templteD dd the following line to your templte (le rther thn dding the templte s resoureX

{% form_theme form 'form_table_layout.html.twig' %}


xote tht the form vrile in the ove ode is the form view vrile tht you pssed to your templteF r fy using the following on(gurtionD ny ustomized form frgments inside the srGemeGhemofundleGesouresGviewsGporm folder will e used glolly when form is renderedF

ewv

# app/cong/cong.yml framework: templating: form: resources: - 'AcmeDemoBundle:Form' # ...


wv

<!-- app/cong/cong.xml --> <framework:cong ...>


TFIUF row to ustomize porm endering QWI

ymfony houmenttionD PFH

<framework:templating> <framework:form> <resource>AcmeDemoBundle:Form</resource> </framework:form> </framework:templating> <!-- ... --> </framework:cong>


r

// app/cong/cong.php // PHP $container->loadFromExtension('framework', array( 'templating' => array('form' => array('resources' => array( 'AcmeDemoBundle:Form', ))) // ... ));
fy defultD the r engine uses div lyout when rendering formsF ome peopleD howeverD my prefer to render forms in tle lyoutF se the prmeworkfundleXpormle resoure to use suh lyoutX

ewv

# app/cong/cong.yml framework: templating: form: resources: - 'FrameworkBundle:FormTable'


wv

<!-- app/cong/cong.xml --> <framework:cong ...> <framework:templating> <framework:form> <resource>FrameworkBundle:FormTable</resource> </framework:form> </framework:templating> <!-- ... --> </framework:cong>

QWP

TF

ymfony houmenttionD PFH

// app/cong/cong.php $container->loadFromExtension('framework', array( 'templating' => array('form' => array('resources' => array( 'FrameworkBundle:FormTable', ))) // ... ));
sf you only wnt to mke the hnge in one templteD dd the following line to your templte (le rther thn dding the templte s resoureX

<?php $view['form']->setTheme($form, array('FrameworkBundle:FormTable')); ?>


xote tht the 6form vrile in the ove ode is the form view vrile tht you pssed to your templteF
6.17.8 How to customize an Individual eld

o frD you9ve seen the di'erent wys you n ustomize the widget output of ll text (eld typesF ou n lso ustomize individul (eldsF por exmpleD suppose you hve two text (elds E (rstnme nd lstnme E ut you only wnt to ustomize one of the (eldsF his n e omplished y ustomizing frgment whose nme is omintion of the (eld id ttriute nd whih prt of the (eld is eing ustomizedF por exmpleX

wig

{% form_theme form _self %} {% block _product_name_widget %} <div class="text_widget"> {{ block('eld_widget') }} </div> {% endblock %} {{ form_widget(form.name) }}
r

<!-- Main template --> <?php echo $view['form']->setTheme($form, array('AcmeDemoBundle:Form')); ?> <?php echo $view['form']->widget($form['name']); ?>
TFIUF row to ustomize porm endering QWQ

ymfony houmenttionD PFH

<!-- src/Acme/DemoBundle/Resources/views/Form/_product_name_widget.html.php --> <div class="text_widget"> echo $view['form']->renderBlock('eld_widget') ?> </div>


rereD the produtnmewidget frgment de(nes the templte to use for the (eld whose id is produtnme @nd nme is produtnmeAF X he produt portion of the (eld is the form nmeD whih my e set mnully or generted utomtilly sed on your form type nme @eFgF rodutype equtes to produtAF sf you9re not sure wht your form nme isD just view the soure of your generted formF ou n lso override the mrkup for n entire (eld row using the sme methodX

wig

{% form_theme form _self %} {% block _product_name_row %} <div class="name_row"> {{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }} </div> {% endblock %}
r

<!-- _product_name_row.html.php --> <div class="name_row"> <?php echo $view['form']->label($form) ?> <?php echo $view['form']->errors($form) ?> <?php echo $view['form']->widget($form) ?> </div>

6.17.9 Other Common Customizations

o frD this reipe hs shown you severl di'erent wys to ustomize single piee of how form is renderedF he key is to ustomize spei( frgment tht orresponds to the portion of the form you wnt to ontrol @see nming form loksAF

QWR

TF

ymfony houmenttionD PFH sn the next setionsD you9ll see how you n mke severl ommon form ustomiztionsF o pply these ustomiztionsD use one of the methods desried in the porm heming setionF gustomizing irror yutput X he form omponent only hndles how the vlidtion errors re renderedD nd not the tul vlidtion error messgesF he error messges themselves re determined y the vlidtion onstrints you pply to your ojetsF por more informtionD see the hpter on vlidtionF here re mny di'erent wys to ustomize how errors re rendered when form is sumitted with errorsF he error messges for (eld re rendered when you use the formerrors helperX

wig

{{ form_errors(form.age) }}
r

<?php echo $view['form']->errors($form['age']); ?>


fy defultD the errors re rendered inside n unordered listX

<ul> <li>This eld is required</li> </ul>


o override how errors re rendered for ll (eldsD simply opyD pste nd ustomize the (elderrors frgmentF

wig

{% block eld_errors %} {% spaceless %} {% if errors|length > 0 %} <ul class="error_list"> {% for error in errors %} <li>{{ error.messageTemplate|trans(error.messageParameters, 'validators') }}</li> {% endfor %} </ul> {% endif %} {% endspaceless %} {% endblock eld_errors %}
r

TFIUF row to ustomize porm endering

QWS

ymfony houmenttionD PFH

<!-- elds_errors.html.php --> <?php if ($errors): ?> <ul class="error_list"> <?php foreach ($errors as $error): ?> <li><?php echo $view['translator']->trans( $error->getMessageTemplate(), $error->getMessageParameters(), 'validators' ) ?></li> <?php endforeach; ?> </ul> <?php endif ?>
X ee porm heming for how to pply this ustomiztionF ou n lso ustomize the error output for just one spei( (eld typeF por exmpleD ertin errors tht re more glol to your form @iFeF not spei( to just one (eldA re rendered seprtelyD usully t the top of your formX

wig

{{ form_errors(form) }}
r

<?php echo $view['form']->render($form); ?>


o ustomize only the mrkup used for these errorsD follow the sme diretions s oveD ut now ll the lok formerrors @wigA G the (le formerrorsFhtmlFphp @rAF xowD when errors for the form type re renderedD your ustomized frgment will e used insted of the defult (elderrorsF gustomizing the porm ow hen you n mnge itD the esiest wy to render form (eld is vi the formrow funtionD whih renders the lelD errors nd rwv widget of (eldF o ustomize the mrkup used for rendering ll form (eld rowsD override the (eldrow frgmentF por exmpleD suppose you wnt to dd lss to the div element round eh rowX

wig

{% block eld_row %} <div class="form_row"> {{ form_label(form) }} {{ form_errors(form) }}


QWT TF

ymfony houmenttionD PFH

{{ form_widget(form) }} </div> {% endblock eld_row %}


r

<!-- eld_row.html.php --> <div class="form_row"> <?php echo $view['form']->label($form) ?> <?php echo $view['form']->errors($form) ?> <?php echo $view['form']->widget($form) ?> </div>
X ee porm heming for how to pply this ustomiztionF

edding equired esterisk to pield vels sf you wnt to denote ll of your required (elds with required sterisk @BAD you n do this y ustomizing the (eldlel frgmentF sn wigD if you9re mking the form ustomiztion inside the sme templte s your formD modify the use tg nd dd the followingX

{% use 'form_div_layout.html.twig' with eld_label as base_eld_label %} {% block eld_label %} {{ block('base_eld_label') }} {% if required %} <span class="required" title="This eld is required">*</span> {% endif %} {% endblock %}
sn wigD if you9re mking the form ustomiztion inside seprte templteD use the followingX

{% extends 'form_div_layout.html.twig' %} {% block eld_label %} {{ parent() }} {% if required %} <span class="required" title="This eld is required">*</span>

TFIUF row to ustomize porm endering

QWU

ymfony houmenttionD PFH

{% endif %} {% endblock %}
hen using r s templting engine you hve to opy the ontent from the originl templteX

<!-- eld_label.html.php -->

<!-- original content --> <label for="<?php echo $view->escape($id) ?>" <?php foreach($attr as $k => $v) { printf('%s="%s" ', $view-> <!-- customization --> <?php if ($required) : ?> <span class="required" title="This eld is required">*</span> <?php endif ?>
X ee porm heming for how to pply this ustomiztionF

edding help messges ou n lso ustomize your form widgets to hve n optionl help messgeF sn wigD sf you9re mking the form ustomiztion inside the sme templte s your formD modify the use tg nd dd the followingX

{% use 'form_div_layout.html.twig' with eld_widget as base_eld_widget %} {% block eld_widget %} {{ block('base_eld_widget') }} {% if help is dened %} <span class="help">{{ help }}</span> {% endif %} {% endblock %}
sn twigD sf you9re mking the form ustomiztion inside seprte templteD use the followingX

{% extends 'form_div_layout.html.twig' %} {% block eld_widget %} {{ parent() }} {% if help is dened %} <span class="help">{{ help }}</span>

QWV

TF

ymfony houmenttionD PFH

{% endif %} {% endblock %}
hen using r s templting engine you hve to opy the ontent from the originl templteX

<!-- eld_widget.html.php --> <!-- Original content --> <input type="<?php echo isset($type) ? $view->escape($type) : "text" ?>" value="<?php echo $view->escape($value) ?>" <?php echo $view['form']->renderBlock('attributes') ?> /> <!-- Customization --> <?php if (isset($help)) : ?> <span class="help"><?php echo $view->escape($help) ?></span> <?php endif ?>
o render help messge elow (eldD pss in help vrileX

wig

{{ form_widget(form.title, { 'help': 'foobar' }) }}


r

<?php echo $view['form']->widget($form['title'], array('help' => 'foobar')) ?>


X ee porm heming for how to pply this ustomiztionF

6.18 How to Create a Custom Form Field Type

his rtile hs not een written yetD ut will soonF sf you9re interested in writing this entryD see gontriuting to the houmenttionF

6.19 How to create a Custom Validation Constraint

ou n rete ustom onstrint y extending the se onstrint lssD ymfonygomponentlidtorgonstrintF yptions for your onstrint re represented s

TFIVF row to grete gustom porm pield ype

QWW

ymfony houmenttionD PFH puli properties on the onstrint lssF por exmpleD the rl onstrint inludes the messge nd protools propertiesX

namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation */ class Url extends Constraint { public $message = 'This value is not a valid URL'; public $protocols = array('http', 'https', 'ftp', 'ftps'); }
X he dennottion nnottion is neessry for this new onstrint in order to mke it ville for use in lsses vi nnottionsF es you n seeD onstrint lss is firly minimlF he tul vlidtion is performed y nother onstrint vlidtor lssF he onstrint vlidtor lss is spei(ed y the onstrint9s vlidtedfy@A methodD whih inludes some simple defult logiX

// in the base Symfony\Component\Validator\Constraint class public function validatedBy() { return get_class($this).'Validator'; }


sn other wordsD if you rete ustom gonstrint @eFgF wygonstrintAD ymfonyP will utomtilly look for nother lssD wygonstrintlidtor when tully performing the vlidtionF he vlidtor lss is lso simpleD nd only hs one required methodX islidF ke the xotflnklidtor s n exmpleX

class NotBlankValidator extends ConstraintValidator { public function isValid($value, Constraint $constraint) { if (null === $value || '' === $value) { $this->setMessage($constraint->message); } return false;

return true;
RHH TF

ymfony houmenttionD PFH

6.19.1 Constraint Validators with Dependencies

sf your onstrint vlidtor hs dependeniesD suh s dtse onnetionD it will need to e on(gured s servie in the dependeny injetion ontinerF his servie must inlude the vlidtorFonstrintvlidtor tg nd n lis ttriuteX

ewv

services: validator.unique.your_validator_name: class: Fully\Qualied\Validator\Class\Name tags: - { name: validator.constraint_validator, alias: alias_name }


wv

<service id="validator.unique.your_validator_name" class="Fully\Qualied\Validator\Class\Name"> <argument type="service" id="doctrine.orm.default_entity_manager" /> <tag name="validator.constraint_validator" alias="alias_name" /> </service>
r

$container ->register('validator.unique.your_validator_name', 'Fully\Qualied\Validator\Class\Name') ->addTag('validator.constraint_validator', array('alias' => 'alias_name')) ;


our onstrint lss my now use this lis to referene the pproprite vlidtorX

public function validatedBy() { return 'alias_name'; }

6.20 How to Master and Create new Environments

ivery pplition is the omintion of ode nd set of on(gurtion tht dittes how tht ode should funtionF he on(gurtion my de(ne the dtse eing usedD whether or not something should e hedD or how verose logging should eF sn ymfonyPD the ide of environments is the ide tht the sme odese n e run using multiple di'erent TFPHF row to wster nd grete new invironments RHI

ymfony houmenttionD PFH on(gurtionsF por exmpleD the dev environment should use on(gurtion tht mkes development esy nd friendlyD while the prod environment should use set of on(gurtion optimized for speedF
6.20.1 Dierent Environments, Dierent Conguration Files

e typil ymfonyP pplition egins with three environmentsX devD prodD nd testF es disussedD eh environment simply represents wy to exeute the sme odese with di'erent on(gurtionF st should e no surprise then tht eh environment lods its own individul on(gurtion (leF sf you9re using the ewv on(gurtion formtD the following (les re usedX

for the dev environmentX ppGon(gGon(gdevFyml for the prod environmentX ppGon(gGon(gprodFyml for the test environmentX ppGon(gGon(gtestFyml
his works vi simple stndrd tht9s used y defult inside the eppuernel lssX

// app/AppKernel.php // ... class AppKernel extends Kernel { // ... public function registerContainerConguration(LoaderInterface $loader) { $loader->load(__DIR__.'/cong/cong_'.$this->getEnvironment().'.yml'); }

es you n seeD when ymfonyP is lodedD it uses the given environment to determine whih on(gurtion (le to lodF his omplishes the gol of multiple environments in n elegntD powerful nd trnsprent wyF yf ourseD in relityD eh environment di'ers only somewht from othersF qenerllyD ll environments will shre lrge se of ommon on(gurtionF ypening the dev on(gurtion (leD you n see how this is omplished esily nd trnsprentlyX

ewv

imports: - { resource: cong.yml } # ...


wv
RHP TF

ymfony houmenttionD PFH

<imports> <import resource="cong.xml" /> </imports> <!-- ... -->


r

$loader->import('cong.php'); // ...
o shre ommon on(gurtionD eh environment9s on(gurtion (le simply (rst imports from entrl on(gurtion (le @on(gFymlAF he reminder of the (le n then devite from the defult on(gurtion y overriding individul prmetersF por exmpleD y defultD the wepro(ler toolr is disledF roweverD in the dev environmentD the toolr is tivted y modifying the defult vlue in the dev on(gurtion (leX

ewv

# app/cong/cong_dev.yml imports: - { resource: cong.yml } web_proler: toolbar: true # ...


wv

<!-- app/cong/cong_dev.xml --> <imports> <import resource="cong.xml" /> </imports> <webproler:cong toolbar="true" # ... />
r

// app/cong/cong_dev.php $loader->import('cong.php'); $container->loadFromExtension('web_proler', array( 'toolbar' => true, // ..


TFPHF row to wster nd grete new invironments RHQ

ymfony houmenttionD PFH

));

6.20.2 Executing an Application in Dierent Environments

o exeute the pplition in eh environmentD lod up the pplition using either the ppFphp @for the prod environmentA or the ppdevFphp @for the dev environmentA front ontrollerX

http://localhost/app.php -> *prod* environment http://localhost/app_dev.php -> *dev* environment


X he given vs ssume tht your we server is on(gured to use the weG diretory of the pplition s its rootF ed more in snstlling ymfonyPF sf you open up one of these (lesD you9ll quikly see tht the environment used y eh is expliitly setX
1 2 3 4 5 6 7 8 9

<?php require_once __DIR__.'/../app/bootstrap_cache.php'; require_once __DIR__.'/../app/AppCache.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppCache(new AppKernel('prod', false)); $kernel->handle(Request::createFromGlobals())->send();
es you n seeD the prod key spei(es tht this environment will run in the prod environmentF e ymfonyP pplition n e exeuted in ny environment y using this ode nd hnging the environment stringF X he test environment is used when writing funtionl tests nd is not essile in the rowser diretly vi front ontrollerF sn other wordsD unlike the other environmentsD there is no pptestFphp front ontroller (leF

RHR

TF

ymfony houmenttionD PFH heug wode smportntD ut unrelted to the topi of environments is the flse key on line V of the front ontroller oveF his spei(es whether or not the pplition should run in deug modeF egrdless of the environmentD ymfonyP pplition n e run with deug mode set to true or flseF his 'ets mny things in the pplitionD suh s whether or not errors should e displyed or if he (les re dynmilly reuilt on eh requestF hough not requirementD deug mode is generlly set to true for the dev nd test environments nd flse for the prod environmentF snternllyD the vlue of the deug mode eomes the kernelFdeug prmeter used inside the servie ontinerF sf you look inside the pplition on(gurtion (leD you9ll see the prmeter usedD for exmpleD to turn logging on or o' when using the hotrine hfevX ewv

doctrine: dbal: logging: %kernel.debug% # ...


wv

<doctrine:dbal logging="%kernel.debug%" ... />


r

$container->loadFromExtension('doctrine', array( 'dbal' => array( 'logging' => '%kernel.debug%', // ... ), // ... ));

6.20.3 Creating a New Environment

fy defultD ymfonyP pplition hs three environments tht hndle most sesF yf ourseD sine n environment is nothing more thn string tht orresponds to set of on(gurtionD reting new environment is quite esyF upposeD for exmpleD tht efore deploymentD you need to enhmrk your pplitionF yne wy to enhmrk the pplition is to use nerEprodution settingsD ut with ymfonyP9s wepro(ler enledF his llows ymfonyP to reord informtion out your pplition while enhmrkingF he est wy to omplish this is vi new environment lledD for exmpleD enhmrkF trt y reting new on(gurtion (leX

ewv
TFPHF row to wster nd grete new invironments RHS

ymfony houmenttionD PFH

# app/cong/cong_benchmark.yml imports: - { resource: cong_prod.yml } framework: proler: { only_exceptions: false }


wv

<!-- app/cong/cong_benchmark.xml --> <imports> <import resource="cong_prod.xml" /> </imports> <framework:cong> <framework:proler only-exceptions="false" /> </framework:cong>
r

// app/cong/cong_benchmark.php $loader->import('cong_prod.php') $container->loadFromExtension('framework', array( 'proler' => array('only-exceptions' => false), ));
end with this simple dditionD the pplition now supports new environment lled enhmrkF his new on(gurtion (le imports the on(gurtion from the prod environment nd modi(es itF his gurntees tht the new environment is identil to the prod environmentD exept for ny hnges expliitly mde hereF feuse you9ll wnt this environment to e essile vi rowserD you should lso rete front ontroller for itF gopy the weGppFphp (le to weGppenhmrkFphp nd edit the environment to e enhmrkX

<?php require_once __DIR__.'/../app/bootstrap.php'; require_once __DIR__.'/../app/AppKernel.php'; use Symfony\Component\HttpFoundation\Request;

RHT

TF

ymfony houmenttionD PFH

$kernel = new AppKernel('benchmark', false); $kernel->handle(Request::createFromGlobals())->send();


he new environment is now essile viX

http://localhost/app_benchmark.php
X ome environmentsD like the dev environmentD re never ment to e essed on ny deployed server y the generl puliF his is euse ertin environmentsD for deugging purposesD my give too muh informtion out the pplition or underlying infrstrutureF o e sure these environments ren9t essileD the front ontroller is usully proteted from externl s ddresses vi the following ode t the top of the ontrollerX

if (!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'))) { die('You are not allowed to access this le. Check '.basename(__FILE__).' for more information.'); }

6.20.4 Environments and the Cache Directory

ymfonyP tkes dvntge of hing in mny wysX the pplition on(gurtionD routing on(gurtionD wig templtes nd more re hed to r ojets stored in (les on the (lesystemF fy defultD these hed (les re lrgely stored in the ppGhe diretoryF roweverD eh environment hes its own set of (lesX

app/cache/dev - cache directory for the *dev* environment app/cache/prod - cache directory for the *prod* environment
ometimesD when deuggingD it my e helpful to inspet hed (le to understnd how something is workingF hen doing soD rememer to look in the diretory of the environment you9re using @most ommonly dev while developing nd deuggingAF hile it n vryD the ppGheGdev diretory inludes the followingX

pphevheugrojetgontinerFphp E the hed servie ontiner tht represents the hed pplition on(gurtionY ppdevrlqenertorFphp E the r lss generted from the routing on(gurtion nd used when generting vsY ppdevrlwtherFphp E the r lss used for route mthing E look here to see the ompiled regulr expression logi used to mth inoming vs to di'erent routesY twigG E this diretory ontins ll the hed wig templtesF

TFPHF row to wster nd grete new invironments

RHU

ymfony houmenttionD PFH


6.20.5 Going Further

ed the rtile on row to et ixternl rmeters in the ervie gontinerF

6.21 How to Set External Parameters in the Service Container

sn the hpter row to wster nd grete new invironmentsD you lerned how to mnge your pplition on(gurtionF et timesD it my ene(t your pplition to store ertin redentils outside of your projet odeF htse on(gurtion is one suh exmpleF he )exiility of the symfony servie ontiner llows you to esily do thisF
6.21.1 Environment Variables

ymfony will gr ny environment vrile pre(xed with wpyx nd set it s prmeter in the servie ontinerF houle undersores re repled with periodD s period is not vlid hrter in n environment vrile nmeF por exmpleD if you9re using epheD environment vriles n e set using the following irtulrost on(gurtionX

<VirtualHost *:80> ServerName Symfony2 DocumentRoot "/path/to/symfony_2_app/web" DirectoryIndex index.php index.html SetEnv SYMFONY__DATABASE__USER user SetEnv SYMFONY__DATABASE__PASSWORD secret <Directory "/path/to/my_symfony_2_app/web"> AllowOverride All Allow from All </Directory> </VirtualHost>
X he exmple ove is for n ephe on(gurtionD using the etinv diretiveF roweverD this will work for ny we server whih supports the setting of environment vrilesF xow tht you hve delred n environment vrileD it will e present in the r 6ii glol vrileF ymfony then utomtilly sets ll 6ii vriles pre(xed with wpyx s prmeters in the servie ontinerF ou n now referene these prmeters wherever you need themF

RHV

TF

ymfony houmenttionD PFH

ewv

doctrine: dbal: driver pdo_mysql dbname: symfony2_project user: %database.user% password: %database.password%
wv

<!-- xmlns:doctrine="http://symfony.com/schema/dic/doctrine" --> <!-- xsi:schemaLocation="http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctr <doctrine:cong> <doctrine:dbal driver="pdo_mysql" dbname="symfony2_projet" user="%database.user%" password="%database.password%" /> </doctrine:cong>
r

$container->loadFromExtension('doctrine', array('dbal' => array( 'driver' => 'pdo_mysql', 'dbname' => 'symfony2_project', 'user' => '%database.user%', 'password' => '%database.password%', ));

6.21.2 Constants

he ontiner lso hs support for setting r onstnts s prmetersF o tke dvntge of this fetureD mp the nme of your onstnt to prmeter keyD nd de(ne the type s onstntF

<?xml version="1.0" encoding="UTF-8"?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >

<parameters> <parameter key="global.constant.value" type="constant">GLOBAL_CONSTANT</parameter> <parameter key="my_class.constant.value" type="constant">My_Class::CONSTANT_NAME</pa


TFPIF row to et ixternl rmeters in the ervie gontiner RHW

ymfony houmenttionD PFH

</parameters> </container>
X his only works for wv on(gurtionF sf you9re not using wvD simply import n wv (le to tke dvntge of this funtionlityX

// app/cong/cong.yml imports: - { resource: parameters.xml }

6.21.3 Miscellaneous Conguration

he imports diretive n e used to pull in prmeters stored elsewhereF smporting r (le gives you the )exiility to dd whtever is needed in the ontinerF he following imports (le nmed prmetersFphpF

ewv

# app/cong/cong.yml imports: - { resource: parameters.php }


wv

<!-- app/cong/cong.xml --> <imports> <import resource="parameters.php" /> </imports>


r

// app/cong/cong.php $loader->import('parameters.php');
X e resoure (le n e one of mny typesF rD wvD ewvD sxsD nd losure resoures re ll supported y the imports diretiveF sn prmetersFphpD tell the servie ontiner the prmeters tht you wish to setF his is useful when importnt on(gurtion is in nonstndrd formtF he exmple elow inludes hrupl dtse9s on(gurtion in the symfony servie ontinerF

// app/cong/parameters.php

RIH

TF

ymfony houmenttionD PFH

include_once('/path/to/drupal/sites/all/default/settings.php'); $container->setParameter('drupal.database.url', $db_url);

6.22 How to Use a Factory to Create Services

ymfonyP9s ervie gontiner provides powerful wy of ontrolling the retion of ojetsD llowing you to speify rguments pssed to the onstrutor s well s lling methods nd setting prmetersF ometimesD howeverD this will not provide you with everything you need to onstrut your ojetsF por this situtionD you n use ftory to rete the ojet nd tell the servie ontiner to ll method on the ftory rther thn diretly instntiting the ojetF uppose you hve ftory tht on(gures nd returns new xewsletterwnger ojetX

namespace Acme\HelloBundle\Newletter; class NewsletterFactory { public function get() { $newsletterManager = new NewsletterManager(); // ... } return $newsletterManager;

o mke the xewsletterwnger ojet ville s servieD you n on(gure the servie ontiner to use the xewsletterptory ftory lssX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager newsletter_factory.class: Acme\HelloBundle\Newsletter\NewsletterFactory services: newsletter_manager: class: %newsletter_manager.class% factory_class: %newsletter_factory.class% factory_method: get
wv
TFPPF row to se ptory to grete ervies RII

ymfony houmenttionD PFH

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</par <parameter key="newsletter_factory.class">Acme\HelloBundle\Newsletter\NewsletterFactory</param </parameters> <services> <service id="newsletter_manager" class="%newsletter_manager.class%" factory-class="%newsletter_factory.class%" factory-method="get" /> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setParameter('newsletter_factory.class', 'Acme\HelloBundle\Newsletter\NewsletterFactory'); $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%' ))->setFactoryClass( '%newsletter_factory.class%' )->setFactoryMethod( 'get' );
hen you speify the lss to use for the ftory @vi ftorylssA the method will e lled sttillyF sf the ftory itself should e instntited nd the resulting ojet9s method lled @s in this exmpleAD on(gure the ftory itself s servieX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager newsletter_factory.class: Acme\HelloBundle\Newsletter\NewsletterFactory services: newsletter_factory: class: %newsletter_factory.class% newsletter_manager: class: %newsletter_manager.class%
RIP TF

ymfony houmenttionD PFH

factory_service: newsletter_factory factory_method: get


wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</par <parameter key="newsletter_factory.class">Acme\HelloBundle\Newsletter\NewsletterFactory</param </parameters> <services> <service id="newsletter_factory" class="%newsletter_factory.class%"/> <service id="newsletter_manager" class="%newsletter_manager.class%" factory-service="newsletter_factory" factory-method="get" /> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setParameter('newsletter_factory.class', 'Acme\HelloBundle\Newsletter\NewsletterFactory'); $container->setDenition('newsletter_factory', new Denition( '%newsletter_factory.class%' )) $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%' ))->setFactoryService( 'newsletter_factory' )->setFactoryMethod( 'get' );
X he ftory servie is spei(ed y its id nme nd not referene to the servie itselfF oD you do not need to use the d syntxF

TFPPF row to se ptory to grete ervies

RIQ

ymfony houmenttionD PFH


6.22.1 Passing Arguments to the Factory Method

sf you need to pss rguments to the ftory methodD you n use the rguments options inside the servie ontinerF por exmpleD suppose the get method in the previous exmple tkes the templting servie s n rgumentX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager newsletter_factory.class: Acme\HelloBundle\Newsletter\NewsletterFactory services: newsletter_factory: class: %newsletter_factory.class% newsletter_manager: class: %newsletter_manager.class% factory_service: newsletter_factory factory_method: get arguments: @templating
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</par <parameter key="newsletter_factory.class">Acme\HelloBundle\Newsletter\NewsletterFactory</param </parameters> <services> <service id="newsletter_factory" class="%newsletter_factory.class%"/> <service id="newsletter_manager" class="%newsletter_manager.class%" factory-service="newsletter_factory" factory-method="get" > <argument type="service" id="templating" /> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition;

RIR

TF

ymfony houmenttionD PFH

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setParameter('newsletter_factory.class', 'Acme\HelloBundle\Newsletter\NewsletterFactory'); $container->setDenition('newsletter_factory', new Denition( '%newsletter_factory.class%' )) $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%', array(new Reference('templating')) ))->setFactoryService( 'newsletter_factory' )->setFactoryMethod( 'get' );

6.23 How to Manage Common Dependencies with Parent Services

es you dd more funtionlity to your pplitionD you my well strt to hve relted lsses tht shre some of the sme dependeniesF por exmple you my hve xewsletter wnger whih uses setter injetion to set its dependeniesX

namespace Acme\HelloBundle\Mail; use Acme\HelloBundle\Mailer; use Acme\HelloBundle\EmailFormatter; class NewsletterManager { protected $mailer; protected $emailFormatter; public function setMailer(Mailer $mailer) { $this->mailer = $mailer; } public function setEmailFormatter(EmailFormatter $emailFormatter) { $this->emailFormatter = $emailFormatter; } // ...

nd lso qreeting grd lss whih shres the sme dependeniesX TFPQF row to wnge gommon hependenies with rent ervies RIS

ymfony houmenttionD PFH

namespace Acme\HelloBundle\Mail; use Acme\HelloBundle\Mailer; use Acme\HelloBundle\EmailFormatter; class GreetingCardManager { protected $mailer; protected $emailFormatter; public function setMailer(Mailer $mailer) { $this->mailer = $mailer; } public function setEmailFormatter(EmailFormatter $emailFormatter) { $this->emailFormatter = $emailFormatter; } // ...

he servie on(g for these lsses would look something like thisX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Mail\NewsletterManager greeting_card_manager.class: Acme\HelloBundle\Mail\GreetingCardManager services: my_mailer: # ... my_email_formatter: # ... newsletter_manager: class: %newsletter_manager.class% calls: - [ setMailer, [ @my_mailer ] ] - [ setEmailFormatter, [ @my_email_formatter] ] greeting_card_manager: class: %greeting_card_manager.class% calls: - [ setMailer, [ @my_mailer ] ] - [ setEmailFormatter, [ @my_email_formatter] ]
RIT TF

ymfony houmenttionD PFH

wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Mail\NewsletterManager</paramete <parameter key="greeting_card_manager.class">Acme\HelloBundle\Mail\GreetingCardManager</pa </parameters> <services> <service id="my_mailer" ... > <!-- ... --> </service> <service id="my_email_formatter" ... > <!-- ... --> </service> <service id="newsletter_manager" class="%newsletter_manager.class%"> <call method="setMailer"> <argument type="service" id="my_mailer" /> </call> <call method="setEmailFormatter"> <argument type="service" id="my_email_formatter" /> </call> </service> <service id="greeting_card_manager" class="%greeting_card_manager.class%"> <call method="setMailer"> <argument type="service" id="my_mailer" /> </call> <call method="setEmailFormatter"> <argument type="service" id="my_email_formatter" /> </call> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Mail\NewsletterManager'); $container->setParameter('greeting_card_manager.class', 'Acme\HelloBundle\Mail\GreetingCardManager $container->setDenition('my_mailer', ... ); $container->setDenition('my_email_formatter', ... ); $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%'
TFPQF row to wnge gommon hependenies with rent ervies RIU

ymfony houmenttionD PFH

))->addMethodCall('setMailer', array( new Reference('my_mailer') ))->addMethodCall('setEmailFormatter', array( new Reference('my_email_formatter') )); $container->setDenition('greeting_card_manager', new Denition( '%greeting_card_manager.class%' ))->addMethodCall('setMailer', array( new Reference('my_mailer') ))->addMethodCall('setEmailFormatter', array( new Reference('my_email_formatter') ));
here is lot of repetition in oth the lsses nd the on(gurtionF his mens tht if you hngedD for exmpleD the wiler of imilpormtter lsses to e injeted vi the onstrutorD you would need to updte the on(g in two plesF vikewise if you needed to mke hnges to the setter methods you would need to do this in oth lssesF he typil wy to del with the ommon methods of these relted lsses would e to extrt them to super lssX

namespace Acme\HelloBundle\Mail; use Acme\HelloBundle\Mailer; use Acme\HelloBundle\EmailFormatter; abstract class MailManager { protected $mailer; protected $emailFormatter; public function setMailer(Mailer $mailer) { $this->mailer = $mailer; } public function setEmailFormatter(EmailFormatter $emailFormatter) { $this->emailFormatter = $emailFormatter; } // ...

he xewsletterwnger nd qreetinggrdwnger n then extend this super lssX

namespace Acme\HelloBundle\Mail; class NewsletterManager extends MailManager {


RIV TF

ymfony houmenttionD PFH

// ...

ndX

namespace Acme\HelloBundle\Mail; class GreetingCardManager extends MailManager { // ... }


sn similr fshionD the ymfonyP servie ontiner lso supports extending servies in the on(gurtion so you n lso redue the repetition y speifying prent for servieF

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Mail\NewsletterManager greeting_card_manager.class: Acme\HelloBundle\Mail\GreetingCardManager mail_manager.class: Acme\HelloBundle\Mail\MailManager services: my_mailer: # ... my_email_formatter: # ... mail_manager: class: %mail_manager.class% abstract: true calls: - [ setMailer, [ @my_mailer ] ] - [ setEmailFormatter, [ @my_email_formatter] ] newsletter_manager: class: %newsletter_manager.class% parent: mail_manager greeting_card_manager: class: %greeting_card_manager.class% parent: mail_manager
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... -->


TFPQF row to wnge gommon hependenies with rent ervies RIW

ymfony houmenttionD PFH

<parameter key="newsletter_manager.class">Acme\HelloBundle\Mail\NewsletterManager</paramete <parameter key="greeting_card_manager.class">Acme\HelloBundle\Mail\GreetingCardManager</pa <parameter key="mail_manager.class">Acme\HelloBundle\Mail\MailManager</parameter> </parameters>

<services> <service id="my_mailer" ... > <!-- ... --> </service> <service id="my_email_formatter" ... > <!-- ... --> </service> <service id="mail_manager" class="%mail_manager.class%" abstract="true"> <call method="setMailer"> <argument type="service" id="my_mailer" /> </call> <call method="setEmailFormatter"> <argument type="service" id="my_email_formatter" /> </call> </service> <service id="newsletter_manager" class="%newsletter_manager.class%" parent="mail_manager"/> <service id="greeting_card_manager" class="%greeting_card_manager.class%" parent="mail_manag </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Mail\NewsletterManager'); $container->setParameter('greeting_card_manager.class', 'Acme\HelloBundle\Mail\GreetingCardManager $container->setParameter('mail_manager.class', 'Acme\HelloBundle\Mail\MailManager'); $container->setDenition('my_mailer', ... ); $container->setDenition('my_email_formatter', ... ); $container->setDenition('mail_manager', new Denition( '%mail_manager.class%' ))->SetAbstract( true )->addMethodCall('setMailer', array( new Reference('my_mailer') ))->addMethodCall('setEmailFormatter', array( new Reference('my_email_formatter') )); $container->setDenition('newsletter_manager', new DenitionDecorator(
RPH TF

ymfony houmenttionD PFH

'mail_manager' ))->setClass( '%newsletter_manager.class%' ); $container->setDenition('greeting_card_manager', new DenitionDecorator( 'mail_manager' ))->setClass( '%greeting_card_manager.class%' );


sn this ontextD hving prent servie implies tht the rguments nd method lls of the prent servie should e used for the hild serviesF pei(llyD the setter methods de(ned for the prent servie will e lled when the hild servies re instntitedF X sf you remove the prent on(g keyD the servies will still e instntited nd they will still of ourse extend the wilwnger lssF he di'erene is tht omitting the prent on(g key will men tht the lls de(ned on the milmnger servie will not e exeuted when the hild servies re instntitedF he prent lss is strt s it should not e diretly instntitedF etting it to strt in the on(g (le s hs een done ove will men tht it n only e used s prent servie nd nnot e used diretly s servie to injet nd will e removed t ompile timeF sn other wordsD it exists merely s templte tht other servies n useF
6.23.1 Overriding Parent Dependencies

here my e times where you wnt to override wht lss is pssed in for dependeny of one hild servie onlyF portuntelyD y dding the method ll on(g for the hild servieD the dependenies set y the prent lss will e overriddenF o if you needed to pss di'erent dependeny just to the xewsletterwnger lssD the on(g would look like thisX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Mail\NewsletterManager greeting_card_manager.class: Acme\HelloBundle\Mail\GreetingCardManager mail_manager.class: Acme\HelloBundle\Mail\MailManager services: my_mailer: # ... my_alternative_mailer: # ... my_email_formatter:
TFPQF row to wnge gommon hependenies with rent ervies RPI

ymfony houmenttionD PFH

# ... mail_manager: class: %mail_manager.class% abstract: true calls: - [ setMailer, [ @my_mailer ] ] - [ setEmailFormatter, [ @my_email_formatter] ] newsletter_manager: class: %newsletter_manager.class% parent: mail_manager calls: - [ setMailer, [ @my_alternative_mailer ] ] greeting_card_manager: class: %greeting_card_manager.class% parent: mail_manager
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Mail\NewsletterManager</paramete <parameter key="greeting_card_manager.class">Acme\HelloBundle\Mail\GreetingCardManager</pa <parameter key="mail_manager.class">Acme\HelloBundle\Mail\MailManager</parameter> </parameters> <services> <service id="my_mailer" ... > <!-- ... --> </service> <service id="my_alternative_mailer" ... > <!-- ... --> </service> <service id="my_email_formatter" ... > <!-- ... --> </service> <service id="mail_manager" class="%mail_manager.class%" abstract="true"> <call method="setMailer"> <argument type="service" id="my_mailer" /> </call> <call method="setEmailFormatter"> <argument type="service" id="my_email_formatter" /> </call> </service> <service id="newsletter_manager" class="%newsletter_manager.class%" parent="mail_manager">
RPP TF

ymfony houmenttionD PFH

<call method="setMailer"> <argument type="service" id="my_alternative_mailer" /> </call> </service> <service id="greeting_card_manager" class="%greeting_card_manager.class%" parent="mail_manag </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

// ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Mail\NewsletterManager'); $container->setParameter('greeting_card_manager.class', 'Acme\HelloBundle\Mail\GreetingCardManager $container->setParameter('mail_manager.class', 'Acme\HelloBundle\Mail\MailManager'); $container->setDenition('my_mailer', ... ); $container->setDenition('my_alternative_mailer', ... ); $container->setDenition('my_email_formatter', ... ); $container->setDenition('mail_manager', new Denition( '%mail_manager.class%' ))->SetAbstract( true )->addMethodCall('setMailer', array( new Reference('my_mailer') ))->addMethodCall('setEmailFormatter', array( new Reference('my_email_formatter') )); $container->setDenition('newsletter_manager', new DenitionDecorator( 'mail_manager' ))->setClass( '%newsletter_manager.class%' )->addMethodCall('setMailer', array( new Reference('my_alternative_mailer') )); $container->setDenition('newsletter_manager', new DenitionDecorator( 'mail_manager' ))->setClass( '%greeting_card_manager.class%' );
he qreetinggrdwnger will reeive the sme dependenies s eforeD ut the xewsletterwnger will e pssed the mylterntivemiler insted of the mymiler servieF

TFPQF row to wnge gommon hependenies with rent ervies

RPQ

ymfony houmenttionD PFH


6.23.2 Collections of Dependencies

st should e noted tht the overridden setter method in the previous exmple is tully lled twie E one per the prent de(nition nd one per the hild de(nitionF sn the previous exmpleD tht ws (neD sine the seond setwiler ll reples miler ojet set y the (rst llF sn some sesD howeverD this n e prolemF por exmpleD if the overridden method ll involves dding something to olletionD then two ojets will e dded to tht olletionF he following shows suh seD if the prent lss looks like thisX

namespace Acme\HelloBundle\Mail; use Acme\HelloBundle\Mailer; use Acme\HelloBundle\EmailFormatter; abstract class MailManager { protected $lters; public function setFilter($lter) { $this->lters[] = $lter; } // ...

sf you hd the following on(gX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... newsletter_manager.class: Acme\HelloBundle\Mail\NewsletterManager mail_manager.class: Acme\HelloBundle\Mail\MailManager services: my_lter: # ... another_lter: # ... mail_manager: class: %mail_manager.class% abstract: true calls: - [ setFilter, [ @my_lter ] ] newsletter_manager:
RPR TF

ymfony houmenttionD PFH

class: %newsletter_manager.class% parent: mail_manager calls: - [ setFilter, [ @another_lter ] ]


wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="newsletter_manager.class">Acme\HelloBundle\Mail\NewsletterManager</paramete <parameter key="mail_manager.class">Acme\HelloBundle\Mail\MailManager</parameter> </parameters> <services> <service id="my_lter" ... > <!-- ... --> </service> <service id="another_lter" ... > <!-- ... --> </service> <service id="mail_manager" class="%mail_manager.class%" abstract="true"> <call method="setFilter"> <argument type="service" id="my_lter" /> </call> </service> <service id="newsletter_manager" class="%newsletter_manager.class%" parent="mail_manager"> <call method="setFilter"> <argument type="service" id="another_lter" /> </call> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference; // ... $container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Mail\NewsletterManager'); $container->setParameter('mail_manager.class', 'Acme\HelloBundle\Mail\MailManager'); $container->setDenition('my_lter', ... ); $container->setDenition('another_lter', ... ); $container->setDenition('mail_manager', new Denition( '%mail_manager.class%'
TFPQF row to wnge gommon hependenies with rent ervies RPS

ymfony houmenttionD PFH

))->SetAbstract( true )->addMethodCall('setFilter', array( new Reference('my_lter') )); $container->setDenition('newsletter_manager', new DenitionDecorator( 'mail_manager' ))->setClass( '%newsletter_manager.class%' )->addMethodCall('setFilter', array( new Reference('another_lter') ));
sn this exmpleD the setpilter of the newslettermnger servie will e lled twieD resulting in the 6(lters rry ontining oth my(lter nd nother(lter ojetsF his is gret if you just wnt to dd dditionl (lters to the sulssesF sf you wnt to reple the (lters pssed to the sulssD removing the prent setting from the on(g will prevent the se lss from lling to setpilterF

6.24 How to work with Scopes

his entry is ll out sopesD somewht dvned topi relted to the ervie gontinerF sf you9ve ever gotten n error mentioning sopes when reting serviesD or need to rete servie tht depends on the request servieD then this entry is for youF
6.24.1 Understanding Scopes

he sope of servie ontrols how long n instne of servie is used y the ontinerF the hependeny snjetion omponent provides two generi sopesX

ontiner @the defult oneAX he sme instne is used eh time you request it from this ontinerF prototypeX e new instne is reted eh time you request the servieF
he prmeworkfundle lso de(nes third sopeX requestF his sopes is tied to the requestD mening new instne is reted for eh surequest nd is unville outside the request @for instne in the gvsAF opes dd onstrint on the dependenies of servieX servie nnot depend on servies from nrrower sopeF por exmpleD if you rete generi myfoo servieD ut try to injet the request omponentD you9ll reeive ymfonygomponenthependenysnjetionixeptionopeideningsnjetionixeption when ompiling the ontinerF ed the sider elow for more detilsF RPT TF

ymfony houmenttionD PFH

opes nd hependenies smgine you9ve on(gured mymiler servieF ou hven9t on(gured the sope of the servieD so it defults to ontinerF sn other wordsD everytime you sk the ontiner for the mymiler servieD you get the sme ojet kF his is usully how you wnt your servies to workF smgineD howeverD tht you need the request servie in your mymiler servieD mye euse you9re reding the v of the urrent requestF oD you dd it s onstrutor rgumentF vet9s look t why this presents prolemX hen requesting mymilerD n instne of mymiler @let9s ll it wilereA is reted nd the request servie is @let9s ll it equeste is pssed to itAF vife is good3 ou9ve now mde surequest in ymfonyD whih is fny wy of sying tht you9ve lledD for exmpleD the {7 render FFF 7} wig funtionD whih exeutes nother ontrollerF snternllyD the old request servie @equesteA is tully repled y new request instne @equestfAF his hppens in the kgroundD nd it9s totlly normlF sn your emedded ontrollerD you one gin sk for the mymiler servieF ine your servie is in the ontiner sopeD the sme instne @wilereA is just reEusedF fut here9s the prolemX the wilere instne still ontins the old equeste ojetD whih is now not the orret request ojet to hve @equestf is now the urrent request servieAF his is sutleD ut the misEmth ould use mjor prolemsD whih is why it9s not llowedF oD tht9s the reson why sopes existsD nd how they n use prolemsF ueep reding to (nd out the ommon solutionsF

X e servie n of ourse depend on servie from wider sope without ny issueF

6.24.2 Setting the Scope in the Denition

he sope of servie is de(ned in the de(nition of the servieX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml services: greeting_card_manager: class: Acme\HelloBundle\Mail\GreetingCardManager scope: request


wv
TFPRF row to work with opes RPU

ymfony houmenttionD PFH

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <services> <service id="greeting_card_manager" class="Acme\HelloBundle\Mail\GreetingCardManager" scope= </services>


r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; $container->setDenition( 'greeting_card_manager', new Denition('Acme\HelloBundle\Mail\GreetingCardManager') )->setScope('request');


sf you don9t speify the sopeD it defults to ontinerD whih is wht you wnt most of the timeF nless your servie depends on nother servie tht9s soped to nrrower sope @most ommonlyD the request servieAD you proly don9t need to set the sopeF
6.24.3 Using a Service from a narrower Scope

sf your servie depends on soped servieD the est solution is to put it in the sme sope @or nrrower oneAF sullyD this mens putting your new servie in the request servieF fut this is not lwys possile @for instneD twig extension must e in the ontiner sope s the wig environment needs it s dependenyAF sn these sesD you should pss the entire ontiner into your servie nd retrieve your dependeny from the ontiner eh time we need it to e sure you hve the right instneX

namespace Acme\HelloBundle\Mail; use Symfony\Component\DependencyInjection\ContainerInterface; class Mailer { protected $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function sendEmail() { $request = $this->container->get('request'); // Do something using the request here
RPV TF

ymfony houmenttionD PFH

}
X ke re not to store the request in property of the ojet for future ll of the servie s it would e the sme issue desried in the (rst setion @exept tht symfony nnot detet tht you re wrongAF

he servie on(g for this lss would look something like thisX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... my_mailer.class: Acme\HelloBundle\Mail\Mailer services: my_mailer: class: %my_mailer.class% arguments: - "@service_container" # scope: container can be omitted as it is the default
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="my_mailer.class">Acme\HelloBundle\Mail\Mailer</parameter> </parameters> <services> <service id="my_mailer" class="%my_mailer.class%"> <argument type="service" id="service_container" /> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference; // ... $container->setParameter('my_mailer.class', 'Acme\HelloBundle\Mail\Mailer'); $container->setDenition('my_mailer', new Denition( '%my_mailer.class%',
TFPRF row to work with opes RPW

ymfony houmenttionD PFH

));

array(new Reference('service_container'))

X snjeting the whole ontiner into servie is generlly not good ide @only injet wht you needAF sn some rre sesD like when working with wig extensionsD its neessry to due shortoming in wig itselfF

6.25 How

to

use

PdoSessionStorage

to

store

Sessions

in

the

Database

he defult session storge of ymfonyP writes the session informtion to (le@sAF wost medium to lrge wesites use dtse to store the session vlues insted of (lesD euse dtses re esier to use nd sle in multiEweserver environmentF ymfonyP hs uiltEin solution for dtse session storge lled ymfonygomponentrttppoundtionessiontorgedoessiontorgeF o use itD you just need to hnge some prmeters in on(gFyml @or the on(gurtion formt of your hoieAX

ewv

# app/cong/cong.yml framework: session: # ... storage_id: session.storage.pdo parameters: pdo.db_options: db_table: session db_id_col: session_id db_data_col: session_value db_time_col: session_time services: pdo: class: PDO arguments: dsn: "mysql:dbname=mydatabase" user: myuser password: mypassword session.storage.pdo:
RQH TF

ymfony houmenttionD PFH

class: Symfony\Component\HttpFoundation\SessionStorage\PdoSessionStorage arguments: [@pdo, %session.storage.options%, %pdo.db_options%]


wv

<!-- app/cong/cong.xml --> <framework:cong> <framework:session storage-id="session.storage.pdo" default-locale="en" lifetime="3600" auto-start="t </framework:cong> <parameters> <parameter key="pdo.db_options" type="collection"> <parameter key="db_table">session</parameter> <parameter key="db_id_col">session_id</parameter> <parameter key="db_data_col">session_value</parameter> <parameter key="db_time_col">session_time</parameter> </parameter> </parameters> <services> <service id="pdo" class="PDO"> <argument>mysql:dbname=mydatabase</argument> <argument>myuser</argument> <argument>mypassword</argument> </service>

<service id="session.storage.pdo" class="Symfony\Component\HttpFoundation\SessionStorage\PdoSes <argument type="service" id="pdo" /> <argument>%session.storage.options%</argument> <argument>%pdo.db_options%</argument> </service> </services>
r

// app/cong/cong.yml use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference; $container->loadFromExtension('framework', array( // ... 'session' => array( // ... 'storage_id' => 'session.storage.pdo', ), ));

TFPSF row to use doessiontorge to store essions in the htse

RQI

ymfony houmenttionD PFH

$container->setParameter('pdo.db_options', array( 'db_table' => 'session', 'db_id_col' => 'session_id', 'db_data_col' => 'session_value', 'db_time_col' => 'session_time', )); $pdoDenition = new Denition('PDO', array( 'mysql:dbname=mydatabase', 'myuser', 'mypassword', )); $container->setDenition('pdo', $pdoDenition);

$storageDenition = new Denition('Symfony\Component\HttpFoundation\SessionStorage\PdoSessionStor new Reference('pdo'), '%session.storage.options%', '%pdo.db_options%', )); $container->setDenition('session.storage.pdo', $storageDenition);
dtleX he nme of the session tle in your dtse didolX he nme of the id olumn in your session tle @egre@PSSA or lrgerA ddtolX he nme of the vlue olumn in your session tle @i or gvyfA dtimeolX he nme of the time olumn in your session tle @sxiqiA
6.25.1 Sharing your Database Connection Information

ith the given on(gurtionD the dtse onnetion settings re de(ned for the session storge onnetion onlyF his is yu when you use seprte dtse for the session dtF fut if you9d like to store the session dt in the sme dtse s the rest of your projet9s dtD you n use the onnetion settings from the prmeterFini y referening the dtseE relted prmeters de(ned thereX

ewv

pdo: class: PDO arguments: - "mysql:dbname=%database_name%" - %database_user% - %database_password%

RQP

TF

ymfony houmenttionD PFH

wv

<service id="pdo" class="PDO"> <argument>mysql:dbname=%database_name%</argument> <argument>%database_user%</argument> <argument>%database_password%</argument> </service>


wv

$pdoDenition = new Denition('PDO', array( 'mysql:dbname=%database_name%', '%database_user%', '%database_password%', ));

6.25.2 Example MySQL Statement

he vEttement for reting the needed htseEle ould look like the following @wyvAX

CREATE TABLE `session` ( `session_id` varchar(255) NOT NULL, `session_value` text NOT NULL, `session_time` int(11) NOT NULL, PRIMARY KEY (`session_id`), UNIQUE KEY `session_id_idx` (`session_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

6.26 Bundle Structure and Best Practices

e undle is diretory tht hs wellEde(ned struture nd n host nything from lsses to ontrollers nd we resouresF iven if undles re very )exileD you should follow some est prties if you wnt to distriute themF
6.26.1 Bundle Name

e undle is lso r nmespeF he nmespe must follow the tehnil interoperility stndrds for r SFQ nmespes nd lss nmesX it strts with vendor segmentD followed y zero or more tegory segmentsD nd it ends with the nmespe short nmeD whih must end with fundle su0xF

TFPTF fundle truture nd fest rties

RQQ

ymfony houmenttionD PFH e nmespe eomes undle s soon s you dd undle lss to itF he undle lss nme must follow these simple rulesX

se only lphnumeri hrters nd undersoresY se gmelgsed nmeY se desriptive nd short nme @no more thn P wordsAY re(x the nme with the ontention of the vendor @nd optionlly the tegory nmespesAY u0x the nme with fundleF
rere re some vlid undle nmespes nd lss nmesX xmespe emefundleflogfundle emefundleoilflogfundle emeflogfundle fundle glss xme emeflogfundle emeoilflogfundle emeflogfundle

fy onventionD the getxme@A method of the undle lss should return the lss nmeF X sf you shre your undle pulilyD you must use the undle lss nme s the nme of the repository @emeflogfundle nd not flogfundle for instneAF

X ymfonyP ore fundles do not pre(x the with ymfony nd lwys dd fundle sunmespeY ymfonyfundleprmeworkfundleprmeworkfundleF

fundle lss for exmpleX

ih undle hs n lisD whih is the lowerEsed short version of the undle nme using undersores @mehello for emerellofundleD or mesoillog for emeoilflogfundle for instneAF his lis is used to enfore uniqueness within undle @see elow for some usge exmplesAF
6.26.2 Directory Structure

he si diretory struture of rellofundle undle must red s followsX

XXX/... HelloBundle/ HelloBundle.php Controller/ Resources/ meta/ LICENSE


RQR TF

ymfony houmenttionD PFH

cong/ doc/ index.rst translations/ views/ public/ Tests/


he diretory@iesA re)ets the nmespe struture of the undleF he following (les re mndtoryX

rellofundleFphpY esouresGmetGvsgixiX he full liense for the odeY esouresGdoGindexFrstX he root (le for the fundle doumenttionF
X hese onventions ensure tht utomted tools n rely on this defult struture to workF he depth of suEdiretories should e kept to the miniml for most used lsses nd (les @P levels t mximumAF wore levels n e de(ned for nonEstrtegiD lessEused (lesF he undle diretory is redEonlyF sf you need to write temporry (lesD store them under the heG or logG diretory of the host pplitionF ools n generte (les in the undle diretory strutureD ut only if the generted (les re going to e prt of the repositoryF he following lsses nd (les hve spei( emplementsX ype gommnds gontrollers ervie gontiner ixtensions ivent visteners gon(gurtion e esoures rnsltion (les empltes nit nd puntionl ests hiretory gommndG gontrollerG hependenysnjetionG iventvistenerG esouresGon(gG esouresGpuliG esouresGtrnsltionsG esouresGviewsG estsG

6.26.3 Classes

he undle diretory struture is used s the nmespe hierrhyF por instneD rellogontroller ontroller is stored in fundleGrellofundleGgontrollerGrellogontrollerFphp nd the fully quli(ed lss nme is fundlerellofundlegontrollerrellogontrollerF TFPTF fundle truture nd fest rties RQS

ymfony houmenttionD PFH ell lsses nd (les must follow the ymfonyP oding stndrdsF ome lsses should e seen s fdes nd should e s short s possileD like gommndsD relpersD vistenersD nd gontrollersF glsses tht onnet to the ivent hispther should e su0xed with vistenerF ixeptions lsses should e stored in n ixeption suEnmespeF
6.26.4 Vendors

e undle must not emed thirdEprty r lirriesF st should rely on the stndrd ymfonyP utoloding instedF e undle should not emed thirdEprty lirries written in tvriptD gD or ny other lngugeF
6.26.5 Tests

e undle should ome with test suite written with rnit nd stored under the estsG diretoryF ests should follow the following priniplesX

he test suite must e exeutle with simple phpunit ommnd run from smple pplitionY he funtionl tests should only e used to test the response output nd some pro(ling informtion if you hve someY he ode overge should t lest overs WS7 of the ode seF
X e test suite must not ontin ellestsFphp sriptsD ut must rely on the existene of phpunitFxmlFdist (leF

6.26.6 Documentation

ell lsses nd funtions must ome with full rhoF ixtensive doumenttion should lso e provided in the retruturedext formtD under the esouresGdoG diretoryY the esouresGdoGindexFrst (le is the only mndtory (le nd must e the entry point for the doumenttionF

RQT

TF

ymfony houmenttionD PFH


6.26.7 Controllers

es est prtieD ontrollers in undle tht9s ment to e distriuted to others must not extend the ymfonyfundleprmeworkfundlegontrollergontroller se lssF hey n implement ymfonygomponenthependenysnjetiongontinerewresnterfe or extend ymfonygomponenthependenysnjetiongontinerewre instedF X sf you hve look t ymfonyfundleprmeworkfundlegontrollergontroller methodsD you will see tht they re only nie shortuts to ese the lerning urveF

6.26.8 Routing

sf the undle provides routesD they must e pre(xed with the undle lisF por n emeflogfundle for instneD ll routes must e pre(xed with melogF
6.26.9 Templates

sf undle provides templtesD they must use wigF e undle must not provide min lyoutD exept if it provides full working pplitionF
6.26.10 Translation Files

sf undle provides messge trnsltionsD they must e de(ned in the vspp formtY the domin should e nmed fter the undle nme @undleFhelloAF e undle must not override existing messges from nother undleF
6.26.11 Conguration

o provide more )exiilityD undle n provide on(gurle settings y using the ymfonyP uiltEin mehnismsF por simple on(gurtion settingsD rely on the defult prmeters entry of the ymfonyP on(gurtionF ymfonyP prmeters re simple keyGvlue pirsY vlue eing ny vlid r vlueF ih prmeter nme should strt with the undle lisD though this is just estEprtie suggestionF he rest of the prmeter nme will use period @FA to seprte di'erent prts @eFgF mehelloFemilFfromAF he end user n provide vlues in ny on(gurtion (leX

ewv

TFPTF fundle truture nd fest rties

RQU

ymfony houmenttionD PFH

# app/cong/cong.yml parameters: acme_hello.email.from: fabien@example.com


wv

<!-- app/cong/cong.xml --> <parameters> <parameter key="acme_hello.email.from">fabien@example.com</parameter> </parameters>


r

// app/cong/cong.php $container->setParameter('acme_hello.email.from', 'fabien@example.com');


sxs

[parameters] acme_hello.email.from = fabien@example.com


etrieve the on(gurtion prmeters in your ode from the ontinerX

$container->getParameter('acme_hello.email.from');
iven if this mehnism is simple enoughD you re highly enourged to use the semnti on(gurtion desried in the ookookF X sf you re de(ning serviesD they should lso e pre(xed with the undle lisF

6.26.12 Learn more from the Cookbook

row to expose emnti gon(gurtion for fundle

6.27 How to use Bundle Inheritance to Override parts of a Bundle

his rtile hs not een written yetD ut will soonF sf you9re interested in writing this entryD see gontriuting to the houmenttionF his topi is ment to show how you n mke one undle extend nother nd use this to override di'erent spets of tht undleF

RQV

TF

ymfony houmenttionD PFH

6.28 How to expose a Semantic Conguration for a Bundle

sf you open your pplition on(gurtion (le @usully ppGon(gGon(gFymlAD you9ll see numer of di'erent on(gurtion nmespesD suh s frmeworkD twigD nd dotrineF ih of these on(gures spei( undleD llowing you to on(gure things t high level nd then let the undle mke ll the lowElevelD omplex hnges tht resultF por exmpleD the following tells the prmeworkfundle to enle the form integrtionD whih involves the de(ning of quite few servies s well s integrtion of other relted omponentsX

ewv

framework: # ... form:


wv

true

<framework:cong> <framework:form /> </framework:cong>


r

$container->loadFromExtension('framework', array( // ... 'form' => true, // ... ));


hen you rete undleD you hve two hoies on how to hndle on(gurtionX IF xorml ervie gon(gurtion @esyAX ou n speify your servies in on(gurtion (le @eFgF serviesFymlA tht lives in your undle nd then import it from your min pplition on(gurtionF his is relly esyD quik nd totlly e'etiveF sf you mke use of prmetersD then you still hve the )exiility to ustomize your undle from your pplition on(gurtionF ee smporting gon(gurtion with imports for more detilsF PF ixposing emnti gon(gurtion @dvnedAX his is the wy on(gurtion is done with the ore undles @s desried oveAF he si ide is thtD insted of hving the user override individul prmetersD you let the user on(gure just fewD spei(lly reted optionsF es the undle developerD you then prse through tht on(gurtion nd lod servies inside n ixtension lssF ith this methodD you won9t need to

TFPVF row to expose emnti gon(gurtion for fundle

RQW

ymfony houmenttionD PFH import ny on(gurtion resoures from your min pplition on(gurtionX the ixtension lss n hndle ll of thisF he seond option E whih you9ll lern out in this rtile E is muh more )exileD ut lso requires more time to setupF sf you9re wondering whih method you should useD it9s proly good ide to strt with method 5ID nd then hnge to 5P lter if you need toF he seond method hs severl spei( dvntgesX

wuh more powerful thn simply de(ning prmetersX spei( option vlue might trigger the retion of mny servie de(nitionsY eility to hve on(gurtion hierrhy mrt merging when severl on(gurtion (les @eFgF on(gdevFyml nd on(gFymlA override eh other9s on(gurtionY gon(gurtion vlidtion @if you use gon(gurtion glssAY shi utoEompletion when you rete n h nd developers use wvF
yverriding undle prmeters sf fundle provides n ixtension lssD then you should generlly not override ny servie ontiner prmeters from tht undleF he ide is tht if n ixtension lss is presentD every setting tht should e on(gurle should e present in the on(gurtion mde ville y tht lssF sn other words the extension lss de(nes ll the pulily supported on(gurtion settings for whih kwrd omptiility will e mintinedF

6.28.1 Creating an Extension Class

sf you do hoose to expose semnti on(gurtion for your undleD you9ll (rst need to rete new ixtension lssD whih will hndle the proessF his lss should live in the hependenysnjetion diretory of your undle nd its nme should e onstruted y repling the fundle post(x of the fundle lss nme with ixtensionF por exmpleD the ixtension lss of emerellofundle would e lled emerelloixtensionX

// Acme/HelloBundle/DependencyInjection/HelloExtension.php use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; class AcmeHelloExtension extends Extension { public function load(array $congs, ContainerBuilder $container) { // where all of the heavy logic is done }
RRH TF

ymfony houmenttionD PFH

public function getXsdValidationBasePath() { return __DIR__.'/../Resources/cong/'; } public function getNamespace() { return 'http://www.example.com/symfony/schema/'; }

X he getsdlidtionfseth nd getxmespe methods re only required if the undle provides optionl h9s for the on(gurtionF he presene of the previous lss mens tht you n now de(ne n mehello on(gurtion nmespe in ny on(gurtion (leF he nmespe mehello is onstruted from the extension9s lss nme y removing the word ixtension nd then lowersing nd undersoring the rest of the nmeF sn other wordsD emerelloixtension eomes mehelloF ou n egin speifying on(gurtion under this nmespe immeditelyX

ewv

# app/cong/cong.yml acme_hello: ~
wv

<!-- app/cong/cong.xml --> <?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:acme_hello="http://www.example.com/symfony/schema/" xsi:schemaLocation="http://www.example.com/symfony/schema/ http://www.example.com/symfony/s <acme_hello:cong /> ... </container>
r

// app/cong/cong.php $container->loadFromExtension('acme_hello', array());

TFPVF row to expose emnti gon(gurtion for fundle

RRI

ymfony houmenttionD PFH X sf you follow the nming onventions lid out oveD then the lod@A method of your extension ode is lwys lled s long s your undle is registered in the uernelF sn other wordsD even if the user does not provide ny on(gurtion @iFeF the mehello entry doesn9t even pperAD the lod@A method will e lled nd pssed n empty 6on(gs rryF ou n still provide some sensile defults for your undle if you wntF

6.28.2 Parsing the $congs Array

henever user inludes the mehello nmespe in on(gurtion (leD the on(gurtion under it it is dded to n rry of on(gurtions nd pssed to the lod@A method of your extension @ymfonyP utomtilly onverts wv nd ewv to n rryAF ke the following on(gurtionX

ewv

# app/cong/cong.yml acme_hello: foo: fooValue bar: barValue


wv

<!-- app/cong/cong.xml --> <?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:acme_hello="http://www.example.com/symfony/schema/" xsi:schemaLocation="http://www.example.com/symfony/schema/ http://www.example.com/symfony/s <acme_hello:cong foo="fooValue"> <acme_hello:bar>barValue</acme_hello:bar> </acme_hello:cong> </container>
r

// app/cong/cong.php $container->loadFromExtension('acme_hello', array( 'foo' => 'fooValue', 'bar' => 'barValue', ));
he rry pssed to your lod@A method will look like thisX

RRP

TF

ymfony houmenttionD PFH

array( array( 'foo' => 'fooValue', 'bar' => 'barValue', ) )


xotie tht this is n rry of rrysD not just single )t rry of the on(gurtion vluesF his is intentionlF por exmpleD if mehello ppers in nother on(gurtion (le E sy on(gdevFyml E with di'erent vlues eneth itD then the inoming rry might look like thisX

array( array( 'foo' => 'fooValue', 'bar' => 'barValue', ), array( 'foo' => 'fooDevValue', 'baz' => 'newCongEntry', ), )
he order of the two rrys depends on whih one is set (rstF st9s your joD thenD to deide how these on(gurtions should e merged togetherF ou mightD for exmpleD hve lter vlues override previous vlues or somehow merge them togetherF vterD in the gon(gurtion glss setionD you9ll lern of truly roust wy to hndle thisF fut for nowD you might just merge them mnullyX

public function load(array $congs, ContainerBuilder $container) { $cong = array(); foreach ($congs as $subCong) { $cong = array_merge($cong, $subCong); } } // now use the at $cong array
X wke sure the ove merging tehnique mkes sense for your undleF his is just n exmpleD nd you should e reful to not use it lindlyF

TFPVF row to expose emnti gon(gurtion for fundle

RRQ

ymfony houmenttionD PFH


6.28.3 Using the load() Method

ithin lod@AD the 6ontiner vrile refers to ontiner tht only knows out this nmespe on(gurtion @iFeF it doesn9t ontin servie informtion loded from other undlesAF he gol of the lod@A method is to mnipulte the ontinerD dding nd on(guring ny methods or servies needed y your undleF voding ixternl gon(gurtion esoures yne ommon thing to do is to lod n externl on(gurtion (le tht my ontin the ulk of the servies needed y your undleF por exmpleD suppose you hve serviesFxml (le tht holds muh of your undle9s servie on(gurtionX

use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\Cong\FileLocator; public function load(array $congs, ContainerBuilder $container) { // prepare your $cong variable $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/cong')); $loader->load('services.xml');

ou might even do this onditionllyD sed on one of the on(gurtion vluesF por exmpleD suppose you only wnt to lod set of servies if n enled option is pssed nd set to trueX

public function load(array $congs, ContainerBuilder $container) { // prepare your $cong variable $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/cong')); if (isset($cong['enabled']) && $cong['enabled']) { $loader->load('services.xml'); }

gon(guring ervies nd etting rmeters yne you9ve loded some servie on(gurtionD you my need to modify the on(gurtion sed on some of the input vluesF por exmpleD suppose you hve servie who9s (rst rgument is some string type tht it will use internllyF ou9d like this to e esily on(gured y the undle userD so in your servie on(gurtion (le @eFgF serviesFxmlAD you

RRR

TF

ymfony houmenttionD PFH de(ne this servie nd use lnk prmeter E mehelloFmyservietype E s its (rst rgumentX

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/servi <parameters> <parameter key="acme_hello.my_service_type" /> </parameters> <services> <service id="acme_hello.my_service" class="Acme\HelloBundle\MyService"> <argument>%acme_hello.my_service_type%</argument> </service> </services> </container>
fut why would you de(ne n empty prmeter nd then pss it to your serviec he nswer is tht you9ll set this prmeter in your extension lssD sed on the inoming on(gurtion vluesF upposeD for exmpleD tht you wnt to llow the user to de(ne this type option under key lled mytypeF edd the following to the lod@A method to do thisX

public function load(array $congs, ContainerBuilder $container) { // prepare your $cong variable $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/cong')); $loader->load('services.xml'); if (!isset($cong['my_type'])) { throw new \InvalidArgumentException('The "my_type" option must be set'); } } $container->setParameter('acme_hello.my_service_type', $cong['my_type']);

xowD the user n e'etively on(gure the servie y speifying the mytype on(gurtion vlueX

ewv

# app/cong/cong.yml acme_hello: my_type: foo # ...


wv
TFPVF row to expose emnti gon(gurtion for fundle RRS

ymfony houmenttionD PFH

<!-- app/cong/cong.xml --> <?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:acme_hello="http://www.example.com/symfony/schema/" xsi:schemaLocation="http://www.example.com/symfony/schema/ http://www.example.com/symfony/s <acme_hello:cong my_type="foo"> <!-- ... --> </acme_hello:cong> </container>
r

// app/cong/cong.php $container->loadFromExtension('acme_hello', array( 'my_type' => 'foo', // ... ));


qlol rmeters hen you9re on(guring the ontinerD e wre tht you hve the following glol prmeters ville to useX

kernelFnme kernelFenvironment kernelFdeug kernelFrootdir kernelFhedir kernelFlogsdir kernelFundledirs kernelFundles kernelFhrset


X ell prmeter nd servie nmes strting with re reserved for the frmeworkD nd new ones must not e de(ned y undlesF

RRT

TF

ymfony houmenttionD PFH


6.28.4 Validation and Merging with a Conguration Class

o frD you9ve done the merging of your on(gurtion rrys y hnd nd re heking for the presene of on(g vlues mnully using the isset@A r funtionF en optionl gon(gurtion system is lso ville whih n help with mergingD vlidtionD defult vluesD nd formt normliztionF X pormt normliztion refers to the ft tht ertin formts E lrgely wv E result in slightly di'erent on(gurtion rrys nd tht these rrys need to e normlized to mth everything elseF o tke dvntge of this systemD you9ll rete gon(gurtion lss nd uild tree tht de(nes your on(gurtion in tht lssX

// src/Acme/HelloBundle/DependencyExtension/Conguration.php namespace Acme\HelloBundle\DependencyInjection; use Symfony\Component\Cong\Denition\Builder\TreeBuilder; use Symfony\Component\Cong\Denition\CongurationInterface; class Conguration implements CongurationInterface { public function getCongTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('acme_hello'); $rootNode ->children() ->scalarNode('my_type')->defaultValue('bar')->end() ->end() ; } return $treeBuilder;

his is very simple exmpleD ut you n now use this lss in your lod@A method to merge your on(gurtion nd fore vlidtionF sf ny options other thn mytype re pssedD the user will e noti(ed with n exeption tht n unsupported option ws pssedX

use Symfony\Component\Cong\Denition\Processor; // ... public function load(array $congs, ContainerBuilder $container) { $processor = new Processor();
TFPVF row to expose emnti gon(gurtion for fundle RRU

ymfony houmenttionD PFH

$conguration = new Conguration(); $cong = $processor->processConguration($conguration, $congs); } // ...

he proessgon(gurtion@A method uses the on(gurtion tree you9ve de(ned in the gon(gurtion lss nd uses it to vlidteD normlize nd merge ll of the on(gurtion rrys togetherF he gon(gurtion lss n e muh more omplited thn shown hereD supporting rry nodesD prototype nodesD dvned vlidtionD wvEspei( normliztion nd dvned mergingF he est wy to see this in tion is to hekout out some of the ore gon(gurtion lssesD suh s the one from the prmeworkfundle gon(gurtion or the wigfundle gon(gurtionF
6.28.5 Extension Conventions

hen reting n extensionD follow these simple onventionsX

he extension must e stored in the hependenysnjetion suEnmespeY he extension must e nmed fter the undle nme nd su0xed with ixtension @emerelloixtension for emerellofundleAY he extension should provide n h shemF
sf you follow these simple onventionsD your extensions will e registered utomtilly y ymfonyPF sf notD override the fundle XmethodXymfonygomponentrttpuernelfundlefundleXXuild method in your undleX

use Acme\HelloBundle\DependencyInjection\UnconventionalExtensionClass; class AcmeHelloBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); // register extensions that do not follow the conventions manually $container->registerExtension(new UnconventionalExtensionClass());

sn this seD the extension lss must lso implement getelis@A method nd return unique lis nmed fter the undle @eFgF mehelloAF his is required euse the lss RRV TF

ymfony houmenttionD PFH nme doesn9t follow the stndrds y ending in ixtensionF edditionllyD the lod@A method of your extension will only e lled if the user spei(es the mehello lis in t lest one on(gurtion (leF yne ginD this is euse the ixtension lss doesn9t follow the stndrds set out oveD so nothing hppens utomtillyF

6.29

E F D wiftmilerfundleD E wiftmiler F X X

public function registerBundles() { $bundles = array( // ... new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), ); } // ...

6.29.1

wiftmilerD F E trnsportX

ewv

# app/cong/cong.yml swiftmailer: transport: smtp encryption: ssl auth_mode: login host: smtp.gmail.com username: your_username password: your_password
wv

TFPWF

RRW

ymfony houmenttionD PFH

<!-- app/cong/cong.xml -->

<!-xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer" http://symfony.com/schema/dic/swiftmailer http://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xs --> <swiftmailer:cong transport="smtp" encryption="ssl" auth-mode="login" host="smtp.gmail.com" username="your_username" password="your_password" />
r

// app/cong/cong.php $container->loadFromExtension('swiftmailer', array( 'transport' => "smtp", 'encryption' => "ssl", 'auth_mode' => "login", 'host' => "smtp.gmail.com", 'username' => "your_username", 'password' => "your_password", ));
wiftmiler D E F X

trnsport @smtpD milD sendmilD gmilA usernme pssword host port enryption @tlsD sslA uthmode @plinD loginD rmEmdSA spool
! type @ D (le E A ! pth @ A RSH TF

ymfony houmenttionD PFH

deliveryddress @ A disledelivery @ true A


6.29.2

wiftmiler D D wiftwessge F  milerF D X

public function indexAction($name) { $message = \Swift_Message::newInstance() ->setSubject('Hello Email') ->setFrom('send@example.com') ->setTo('recipient@example.com') ->setBody($this->renderView('HelloBundle:Hello:email.txt.twig', array('name' => $name))) ; $this->get('mailer')->send($message); } return $this->render(...);

D enderiew@AF 6messge D D D rwv D F D wiftmiler E F X D ymfonyPX

qmil row to ork with imils huring hevelopment row to pool imil

6.30 Gmail

D w E D qmil F wiftmiler F

TFQHF qmil

RSI

ymfony houmenttionD PFH X qmil D F D trnsport gmil usernme pssword qoogleX

ewv

# app/cong/cong_dev.yml swiftmailer: transport: gmail username: your_gmail_username password: your_gmail_password


wv

<!-- app/cong/cong_dev.xml -->

<!-xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer" http://symfony.com/schema/dic/swiftmailer http://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xs --> <swiftmailer:cong transport="gmail" username="your_gmail_username" password="your_gmail_password" />


r

// app/cong/cong_dev.php $container->loadFromExtension('swiftmailer', array( 'transport' => "gmail", 'username' => "your_gmail_username", 'password' => "your_gmail_password", ));
3 X gmil D smtp enryptionD uthmode host qmilF

RSP

TF

ymfony houmenttionD PFH

6.31 How to Work with Emails During Development

hen you re reting n pplition whih sends emilsD you will often not wnt to tully send the emils to the spei(ed reipient while developmentF sf you re using the wiftmilerfundle with ymfonyPD you n esily hieve this through on(gurtion settings without hving to mke ny hnges to your pplition9s ode t llF here re two min hoies when it omes to hndling emils during developmentX @A disling the sending of emils ltogether or @A sending ll the emils to spei(ed ddressF
6.31.1 Disabling Sending

ou n disle sending emils y setting the disledelivery option to trueF his is the defult in the test environment in the tndrd distriutionF sf you do this in the test spei( on(g then emils will not e sent when you run testsD ut will ontinue to e sent in the prod nd dev environmentsX

ewv

# app/cong/cong_test.yml swiftmailer: disable_delivery: true


wv

<!-- app/cong/cong_test.xml -->

<!-xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer" http://symfony.com/schema/dic/swiftmailer http://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xs --> <swiftmailer:cong disable-delivery="true" />


r

// app/cong/cong_test.php $container->loadFromExtension('swiftmailer', array( 'disable_delivery' => "true", ));


sf you9d lso like to disle deliver in the dev environmentD simply dd this on(gurtion to the on(gdevFyml (leF

TFQIF row to ork with imils huring hevelopment

RSQ

ymfony houmenttionD PFH


6.31.2 Sending to a Specied Address

ou n lso hoose to hve ll emils sent to spei( ddressD insted of the ddress tully spei(ed when sending the messgeF his n e done vi the deliveryddress optionX

ewv

# app/cong/cong_dev.yml swiftmailer: delivery_address: dev@example.com


wv

<!-- app/cong/cong_dev.xml -->

<!-xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer" http://symfony.com/schema/dic/swiftmailer http://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xs --> <swiftmailer:cong delivery-address="dev@example.com" />


r

// app/cong/cong_dev.php $container->loadFromExtension('swiftmailer', array( 'delivery_address' => "dev@example.com", ));


xowD suppose you9re sending n emil to reipientdexmpleFomF

public function indexAction($name) { $message = \Swift_Message::newInstance() ->setSubject('Hello Email') ->setFrom('send@example.com') ->setTo('recipient@example.com') ->setBody($this->renderView('HelloBundle:Hello:email.txt.twig', array('name' => $name))) ; $this->get('mailer')->send($message); } return $this->render(...);

sn the dev environmentD the emil will insted e sent to devdexmpleFomF wiftmiler will dd n extr heder to the emilD EwiftEo ontining the repled ddressD so you will still e le to see who it would hve een sent toF RSR TF

ymfony houmenttionD PFH

X sn ddition to the to ddressesD this will lso stop the emil eing sent to ny gg nd fgg ddresses set for itF wiftmiler will dd dditionl heders to the emil with the overridden ddresses in themF hese re EwiftEg nd EwiftEf for the gg nd fgg ddresses respetivelyF

6.31.3 Viewing from the Web Debug Toolbar

ou n view ny emils sent y pge when you re in the dev environment using the e heug oolrF he emil ion in the toolr will show how mny emils were sentF sf you lik itD report showing the detils of the emils will openF sf you9re sending n emil nd then redireting immeditely fterD you9ll need to set the intereptredirets option to true in the on(gdevFyml (le so tht you n see the emil in the we deug toolr efore eing rediretedF

6.32 How to Spool Email

hen you re using the wiftmilerfundle to send n emil from ymfonyP pplitionD it will defult to sending the emil immeditelyF ou myD howeverD wnt to void the performne hit of the ommunition etween wiftmiler nd the emil trnsportD whih ould use the user to wit for the next pge to lod while the emil is sendingF his n e voided y hoosing to spool the emils insted of sending them diretlyF his mens tht wiftmiler does not ttempt to send the emil ut insted sves the messge to somewhere suh s (leF enother proess n then red from the spool nd tke re of sending the emils in the spoolF gurrently only spooling to (le is supported y wiftmilerF sn order to use the spoolD use the following on(gurtionX

ewv

# app/cong/cong.yml swiftmailer: # ... spool: type: le path: /path/to/spool


wv

<!-- app/cong/cong.xml --> <!-xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer"


TFQPF row to pool imil RSS

ymfony houmenttionD PFH

http://symfony.com/schema/dic/swiftmailer http://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xs --> <swiftmailer:cong> <swiftmailer:spool type="le" path="/path/to/spool" /> </swiftmailer:cong>


r

// app/cong/cong.php $container->loadFromExtension('swiftmailer', array( // ... 'spool' => array( 'type' => 'le', 'path' => '/path/to/spool', ) ));
X sf you wnt to store the spool somewhere with your projet diretoryD rememer tht you n use the 7kernelFrootdir7 prmeter to referene the projet9s rootX

path: %kernel.root_dir%/spool
xowD when your pp sends n emilD it will not tully e sent ut insted dded to the spoolF ending the messges from the spool is done seprtelyF here is onsole ommnd to send the messges in the spoolX

php app/console swiftmailer:spool:send


st hs n option to limit the numer of messges to e sentX

php app/console swiftmailer:spool:send --message-limit=10


ou n lso set the time limit in seondsX

php app/console swiftmailer:spool:send --time-limit=10


yf ourse you will not wnt to run this mnully in relityF snstedD the onsole ommnd should e triggered y ron jo or sheduled tsk nd run t regulr intervlF

RST

TF

ymfony houmenttionD PFH

6.33 How to simulate HTTP Authentication in a Functional Test

sf your pplition needs r uthentitionD pss the usernme nd pssword s server vriles to reteglient@AX

$client = static::createClient(array(), array( 'PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pa$$word', ));
ou n lso override it on per request sisX

$client->request('DELETE', '/post/12', array(), array( 'PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pa$$word', ));

6.34 How to test the Interaction of several Clients

sf you need to simulte n intertion etween di'erent glients @think of ht for instneAD rete severl glientsX

$harry = static::createClient(); $sally = static::createClient(); $harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages'); $this->assertEquals(201, $harry->getResponse()->getStatusCode()); $this->assertRegExp('/Hello/', $sally->getResponse()->getContent());
his works exept when your ode mintins glol stte or if it depends on thirdEprty lirries tht hs some kind of glol stteF sn suh seD you n insulte your lientsX

$harry = static::createClient(); $sally = static::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());
TFQQF row to simulte r euthentition in puntionl est RSU

ymfony houmenttionD PFH snsulted lients trnsprently exeute their requests in dedited nd len r proessD thus voiding ny sideEe'etsF X es n insulted lient is slowerD you n keep one lient in the min proessD nd insulte the other onesF

6.35 How to use the Proler in a Functional Test

st9s highly reommended tht funtionl test only tests the esponseF fut if you write funtionl tests tht monitor your prodution serversD you might wnt to write tests on the pro(ling dt s it gives you gret wy to hek vrious things nd enfore some metrisF he ymfonyP ro(ler gthers lot of dt for eh requestF se this dt to hek the numer of dtse llsD the time spent in the frmeworkD FFF fut efore writing ssertionsD lwys hek tht the pro(ler is indeed ville @it is enled y defult in the test environmentAX

class HelloControllerTest extends WebTestCase { public function testIndex() { $client = static::createClient(); $crawler = $client->request('GET', '/hello/Fabien'); // Write some assertions about the Response // ... // Check that the proler is enabled if ($prole = $client->getProle()) { // check the number of requests $this->assertTrue($prole->getCollector('db')->getQueryCount() < 10); // check the time spent in the framework $this->assertTrue( $prole->getCollector('timer')->getTime() < 0.5);

sf test fils euse of pro(ling dt @too mny hf queries for instneAD you might wnt to use the e ro(ler to nlyze the request fter the tests (nishF st9s esy to hieve if you emed the token in the error messgeX

$this->assertTrue( $prole->get('db')->getQueryCount() < 30,


RSV TF

ymfony houmenttionD PFH

);

sprintf('Checks that query count is less than 30 (token %s)', $prole->getToken())

X he pro(ler store n e di'erent depending on the environment @espeilly if you use the vite storeD whih is the defult on(gured oneAF

X he pro(ler informtion is ville even if you insulte the lient or if you use n r lyer for your testsF

X ed the es for uiltEin dt olletors to lern more out their interfesF

6.36 How to test Doctrine Repositories

nit testing hotrine repositories in ymfony projet is not strightforwrd tskF sndeedD to lod repository you need to lod your entitiesD n entity mngerD nd some other stu' like onnetionF o test your repositoryD you hve two di'erent optionsX IF puntionl testX his inludes using rel dtse onnetion with rel dtse ojetsF st9s esy to setup nd n test nythingD ut is slower to exeuteF ee puntionl estingF PF nit testX nit testing is fster to run nd more preise in how you testF st does require little it more setupD whih is overed in this doumentF st n lso only test methods thtD for exmpleD uild queriesD not methods tht tully exeute themF
6.36.1 Unit Testing

es ymfony nd hotrine shre the sme testing frmeworkD it9s quite esy to implement unit tests in your ymfony projetF he yw omes with its own set of tools to ese the unit testing nd moking of everything you needD suh s onnetionD n entity mngerD etF fy using the testing omponents provided y hotrine E long with some si setup E you n leverge hotrine9s tools to unit test your repositoriesF ueep in mind tht if you wnt to test the tul exeution of your queriesD you9ll need funtionl test @see puntionl estingAF nit testing is only possile when testing method tht uilds queryF

TFQTF row to test hotrine epositories

RSW

ymfony houmenttionD PFH etup pirstD you need to dd the hotrineests nmespe to your utoloderX

// app/autoload.php $loader->registerNamespaces(array( //... 'Doctrine\\Tests' => __DIR__.'/../vendor/doctrine/tests', ));


xextD you will need to setup n entity mnger in eh test so tht hotrine will e le to lod your entities nd repositories for youF es hotrine is not le y defult to lod nnottion metdt from your entitiesD you9ll need to on(gure the nnottion reder to e le to prse nd lod the entitiesX

// src/Acme/ProductBundle/Tests/Entity/ProductRepositoryTest.php namespace Acme\ProductBundle\Tests\Entity; use Doctrine\Tests\OrmTestCase; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\ORM\Mapping\Driver\DriverChain; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; class ProductRepositoryTest extends OrmTestCase { private $_em; protected function setUp() { $reader = new AnnotationReader(); $reader->setIgnoreNotImportedAnnotations(true); $reader->setEnableParsePhpImports(true); $metadataDriver = new AnnotationDriver( $reader, // provide the namespace of the entities you want to tests 'Acme\\ProductBundle\\Entity' ); $this->_em = $this->_getTestEntityManager(); $this->_em->getConguration() ->setMetadataDriverImpl($metadataDriver); // allows you to use the AcmeProductBundle:Product syntax $this->_em->getConguration()->setEntityNamespaces(array( 'AcmeProductBundle' => 'Acme\\ProductBundle\\Entity'
RTH TF

ymfony houmenttionD PFH

));

sf you look t the odeD you n notieX

ou extend from hotrineestsyrmestgseD whih provide useful methods for unit testingY ou need to setup the ennottioneder to e le to prse nd lod the entitiesY ou rete the entity mnger y lling getestintitywngerD whih returns moked entity mnger with moked onnetionF
ht9s it3 ou9re redy to write units tests for your hotrine repositoriesF riting your nit est ememer tht hotrine repository methods n only e tested if they re uilding nd returning query @ut not tully exeuting queryAF ke the following exmpleX

// src/Acme/StoreBundle/Entity/ProductRepository namespace Acme\StoreBundle\Entity; use Doctrine\ORM\EntityRepository; class ProductRepository extends EntityRepository { public function createSearchByNameQueryBuilder($name) { return $this->createQueryBuilder('p') ->where('p.name LIKE :name', $name) } }
sn this exmpleD the method is returning ueryfuilder instneF ou n test the result of this method in vriety of wysX

class ProductRepositoryTest extends \Doctrine\Tests\OrmTestCase { /* ... */ public function testCreateSearchByNameQueryBuilder() { $queryBuilder = $this->_em->getRepository('AcmeProductBundle:Product') ->createSearchByNameQueryBuilder('foo'); $this->assertEquals('p.name LIKE :name', (string) $queryBuilder->getDqlPart('where'));
TFQTF row to test hotrine epositories RTI

ymfony houmenttionD PFH

$this->assertEquals(array('name' => 'foo'), $queryBuilder->getParameters());

sn this testD you disset the ueryfuilder ojetD looking tht eh prt is s you9d expetF sf you were dding other things to the query uilderD you might hek the dql prtsX seletD fromD joinD setD groupfyD hvingD or orderfyF sf you only hve rw uery ojet or prefer to test the tul queryD you n test the hv query string diretlyX

public function testCreateSearchByNameQueryBuilder() { $queryBuilder = $this->_em->getRepository('AcmeProductBundle:Product') ->createSearchByNameQueryBuilder('foo'); $query = $queryBuilder->getQuery(); // test DQL $this->assertEquals( 'SELECT p FROM Acme\ProductBundle\Entity\Product p WHERE p.name LIKE :name', $query->getDql() );

6.36.2 Functional Testing

sf you need to tully exeute queryD you will need to oot the kernel to get vlid onnetionF sn this seD you9ll extend the eestgseD whih mkes ll of this quite esyX

// src/Acme/ProductBundle/Tests/Entity/ProductRepositoryFunctionalTest.php namespace Acme\ProductBundle\Tests\Entity; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class ProductRepositoryFunctionalTest extends WebTestCase { /** * @var \Doctrine\ORM\EntityManager */ private $_em; public function setUp() { $kernel = static::createKernel(); $kernel->boot();
RTP TF

ymfony houmenttionD PFH

$this->_em = $kernel->getContainer() ->get('doctrine.orm.entity_manager');

public function testProductByCategoryName() { $results = $this->_em->getRepository('AcmeProductBundle:Product') ->searchProductsByNameQuery('foo') ->getResult(); } $this->assertEquals(count($results), 1);

6.37 How to add Remember Me Login Functionality

yne user is uthentitedD their redentils re typilly stored in the sessionF his mens tht when the session ends they will e logged out nd hve to provide their login detils gin next time they wish to ess the pplitionF ou n llow users to hoose to sty logged in for longer thn the session lsts using ookie with the rememerme (rewll optionF he (rewll needs to hve seret key on(guredD whih is used to enrypt the ookie9s ontentF st lso hs severl options with defult vlues whih re shown hereX

ewv

# app/cong/security.yml rewalls: main: remember_me: key: aSecretKey lifetime: 3600 path: / domain: ~ # Defaults to the current domain from $_SERVER
wv

<!-- app/cong/security.xml --> <cong> <rewall> <remember-me key="aSecretKey" lifetime="3600" path="/" domain="" <!-- Defaults to the current domain from $_SERVER --> />
TFQUF row to dd ememer we vogin puntionlity RTQ

ymfony houmenttionD PFH

</rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('remember_me' => array( 'key' => '/login_check', 'lifetime' => 3600, 'path' => '/', 'domain' => '', // Defaults to the current domain from $_SERVER )), ), ));
st9s good ide to provide the user with the option to use or not use the rememer me funtionlityD s it will not lwys e ppropriteF he usul wy of doing this is to dd hekox to the login formF fy giving the hekox the nme rememermeD the ookie will utomtilly e set when the hekox is heked nd the user suessfully logs inF oD your spei( login form might ultimtely look like thisX

wig

{# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #} {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('login_check') }}" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <input type="checkbox" id="remember_me" name="_remember_me" checked /> <label for="remember_me">Keep me logged in</label> <input type="submit" name="login" /> </form>
r

<?php // src/Acme/SecurityBundle/Resources/views/Security/login.html.php ?> <?php if ($error): ?> <div><?php echo $error->getMessage() ?></div>
RTR TF

ymfony houmenttionD PFH

<?php endif; ?> <form action="<?php echo $view['router']->generate('login_check') ?>" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="<?php echo $last_username ?>" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <input type="checkbox" id="remember_me" name="_remember_me" checked /> <label for="remember_me">Keep me logged in</label> <input type="submit" name="login" /> </form>
he user will then utomtilly e logged in on susequent visits while the ookie remins vlidF
6.37.1 Forcing the User to Re-authenticate before accessing certain Resources

hen the user returns to your siteD heGshe is uthentited utomtilly sed on the informtion stored in the rememer me ookieF his llows the user to ess proteted resoures s if the user hd tully uthentited upon visiting the siteF sn some sesD howeverD you my wnt to fore the user to tully reEuthentite efore essing ertin resouresF por exmpleD you might llow rememer me user to see si ount informtionD ut then require them to tully reEuthentite efore modifying tht informtionF he seurity omponent provides n esy wy to do thisF sn ddition to roles expliitly ssigned to themD users re utomtilly given one of the following roles depending on how they re uthentitedX

serixsgeihexyxwyv E utomtilly ssigned to user who is in (rewll proteted prt of the site ut who hs not tully logged inF his is only possile if nonymous ess hs een llowedF serixsgeihiwiwfiih E utomtilly ssigned to user who ws uthentited vi rememer me ookieF serixsgeihpvv E utomtilly ssigned to user tht hs provided their login detils during the urrent sessionF
ou n use these to ontrol ess eyond the expliitly ssigned rolesF

TFQUF row to dd ememer we vogin puntionlity

RTS

ymfony houmenttionD PFH X sf you hve the serixsgeihiwiwfiih roleD then you lso hve the serixsgeihexyxwyv roleF sf you hve the serixsgeihpvv roleD then you lso hve the other two rolesF sn other wordsD these roles represent three levels of inresing strength of uthentitionF ou n use these dditionl roles for (ner grined ontrol over ess to prts of siteF por exmpleD you my wnt you user to e le to view their ount t Gount when uthentited y ookie ut to hve to provide their login detils to e le to edit the ount detilsF ou n do this y seuring spei( ontroller tions using these rolesF he edit tion in the ontroller ould e seured using the servie ontextF sn the following exmpleD the tion serixsgeihpvv roleF is only llowed if the user hs the

use Symfony\Component\Security\Core\Exception\AccessDeniedException // ... public function editAction() { if (false === $this->get('security.context')->isGranted( 'IS_AUTHENTICATED_FULLY' )) { throw new AccessDeniedException(); } } // ...

ou n lso hoose to instll nd use the optionl tweurityixtrfundleD whih n seure your ontroller using nnottionsX

use JMS\SecurityExtraBundle\Annotation\Secure; /** * @Secure(roles="IS_AUTHENTICATED_FULLY") */ public function editAction($name) { // ... }


X sf you lso hd n ess ontrol in your seurity on(gurtion tht required the user to hve yvii role in order to ess ny of the ount reD then you9d hve the following situtionX

sf nonEuthentited @or nonymously uthentited userA tries to ess the ount reD the user will e sked to uthentiteF
RTT TF

ymfony houmenttionD PFH

yne the user hs entered his usernme nd psswordD ssuming the user reeives the yvii role per your on(gurtionD the user will hve the serixsgeihpvv role nd e le to ess ny pge in the ount setionD inluding the editetion ontrollerF sf the user9s session endsD when the user returns to the siteD he will e le to ess every ount pge E exept for the edit pge E without eing fored to reEuthentiteF roweverD when he tries to ess the editetion ontrollerD he will e fored to reE uthentiteD sine he is notD yetD fully uthentitedF
por more informtion on seuring servies or methods in this wyD see row to seure ny ervie or wethod in your epplitionF

6.38 How to implement your own Voter to blacklist IP Addresses

he ymfonyP seurity omponent provides severl lyers to uthentite usersF yne of the lyers is lled voterF e voter is dedited lss tht heks if the user hs the rights to e onneted to the pplitionF por instneD ymfonyP provides lyer tht heks if the user is fully uthentited or if it hs some expeted rolesF st is sometimes useful to rete ustom voter to hndle spei( se not hndled y the frmeworkF sn this setionD you9ll lern how to rete voter tht will llow you to lklist users y their sF
6.38.1 The Voter Interface

e ustom voter must implement ymfonygomponenteuritygoreeuthoriztionoterotersnterfeD whih requires the following three methodsX

interface VoterInterface { function supportsAttribute($attribute); function supportsClass($class); function vote(TokenInterface $token, $object, array $attributes); }
he supportsettriute@A method is used to hek if the voter supports the given user ttriute @iFeX roleD n lD etFAF he supportsglss@A method is used to hek if the voter supports the urrent user token lssF he vote@A method must implement the usiness logi tht veri(es whether or not the user is grnted essF his method must return one of the following vluesX TFQVF row to implement your own oter to lklist s eddresses RTU

ymfony houmenttionD PFH

otersnterfeXXeggiqexihX he user is llowed to ess the pplition otersnterfeXXeggiefesxX he voter nnot deide if the user is grnted or not otersnterfeXXeggihixsihX he user is not llowed to ess the pplition
sn this exmpleD we will hek if the user9s s ddress mthes ginst list of lklisted ddressesF sf the user9s s is lklistedD we will return otersnterfeXXeggihixsihD otherwise we will return otersnterfeXXeggiefesx s this voter9s purpose is only to deny essD not to grnt essF
6.38.2 Creating a Custom Voter

o lklist user sed on its sD we n use the request servie nd ompre the s ddress ginst set of lklisted s ddressesX

namespace Acme\DemoBundle\Security\Authorization\Voter; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; class ClientIpVoter implements VoterInterface { public function __construct(ContainerInterface $container, array $blacklistedIp = array()) { $this->container = $container; $this->blacklistedIp = $blacklistedIp; } public function supportsAttribute($attribute) { // we won't check against a user attribute, so we return true return true; } public function supportsClass($class) { // our voter supports all type of token classes, so we return true return true; } function vote(TokenInterface $token, $object, array $attributes) { $request = $this->container->get('request'); if (in_array($this->request->getClientIp(), $this->blacklistedIp)) {
RTV TF

ymfony houmenttionD PFH

} }

return VoterInterface::ACCESS_DENIED;

return VoterInterface::ACCESS_ABSTAIN;

ht9s it3 he voter is doneF he next step is to injet the voter into the seurity lyerF his n e done esily through the servie ontinerF
6.38.3 Declaring the Voter as a Service

o injet the voter into the seurity lyerD we must delre it s servieD nd tg it s seurityFvoterX

ewv

# src/Acme/AcmeBundle/Resources/cong/services.yml services: security.access.blacklist_voter: class: Acme\DemoBundle\Security\Authorization\Voter\ClientIpVoter arguments: [@service_container, [123.123.123.123, 171.171.171.171]] public: false tags: { name: security.voter }
wv

<!-- src/Acme/AcmeBundle/Resources/cong/services.xml --> <service id="security.access.blacklist_voter" class="Acme\DemoBundle\Security\Authorization\Voter\ClientIpVoter" public="false"> <argument type="service" id="service_container" strict="false" /> <argument type="collection"> <argument>123.123.123.123</argument> <argument>171.171.171.171</argument> </argument> <tag name="security.voter" /> </service>
r

// src/Acme/AcmeBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;


TFQVF row to implement your own oter to lklist s eddresses RTW

ymfony houmenttionD PFH

$denition = new Denition( 'Acme\DemoBundle\Security\Authorization\Voter\ClientIpVoter', array( new Reference('service_container'), array('123.123.123.123', '171.171.171.171'), ), ); $denition->addTag('security.voter'); $denition->setPublic(false); $container->setDenition('security.access.blacklist_voter', $denition);
X fe sure to import this on(gurtion (le from your min pplition on(gurtion (le @eFgF ppGon(gGon(gFymlAF por more informtion see smporting gon(gurtion with importsF o red more out de(ning servies in generlD see the ervie gontiner hpterF

6.38.4 Changing the Access Decision Strategy

sn order for the new voter to tke e'etD we need to hnge the defult ess deision strtegyD whihD y defultD grnts ess if ny voter grnts essF sn our seD we will hoose the unnimous strtegyF nlike the 0rmtive strtegy @the defultAD with the unnimous strtegyD if only one voter denies ess @eFgF the glientspoterAD ess is not grnted to the end userF o do thtD override the defult essdeisionmnger setion of your pplition on(gurtion (le with the following odeF

ewv

# app/cong/security.yml security: access_decision_manager: # Strategy can be: armative, unanimous or consensus strategy: unanimous
ht9s it3 xowD when deiding whether or not user should hve essD the new voter will deny ess to ny user in the list of lklisted ssF

6.39 Access Control Lists (ACLs)

sn omplex pplitionsD you will often fe the prolem tht ess deisions nnot only e sed on the person @okenA who is requesting essD ut lso involve domin ojet RUH TF

ymfony houmenttionD PFH tht ess is eing requested forF his is where the egv system omes inF smgine you re designing log system where your users n omment on your postsF xowD you wnt user to e le to edit his own ommentsD ut not those of other usersY esidesD you yourself wnt to e le to edit ll ommentsF sn this senrioD gomment would e our domin ojet tht you wnt to restrit ess toF ou ould tke severl pprohes to omplish this using ymfonyPD two si pprohes re @nonEexhustiveAX

infore seurity in your usiness methodsX fsillyD tht mens keeping referene inside eh gomment to ll users who hve essD nd then ompre these users to the provided okenF infore seurity with rolesX sn this pprohD you would dd role for eh gomment ojetD iFeF yvigywwixID yvigywwixPD etF
foth pprohes re perfetly vlidF roweverD they ouple your uthoriztion logi to your usiness ode whih mkes it less reusle elsewhereD nd lso inreses the di0ulty of unit testingF fesidesD you ould run into performne issues if mny users would hve ess to single domin ojetF portuntelyD there is etter wyD whih we will tlk out nowF
6.39.1 Bootstrapping

xowD efore we (nlly n get into tionD we need to do some ootstrppingF pirstD we need to on(gure the onnetion the egv system is supposed to useX

ewv

# app/cong/security.yml security: acl: connection: default


wv

<!-- app/cong/security.xml --> <acl> <connection>default</connection> </acl>


r

// app/cong/security.php $container->loadFromExtension('security', 'acl', array( 'connection' => 'default', ));

TFQWF eess gontrol vists @egvsA

RUI

ymfony houmenttionD PFH X he egv system requires t lest one hotrine hfev onnetion to e on(guredF roweverD tht does not men tht you hve to use hotrine for mpping your domin ojetsF ou n use whtever mpper you like for your ojetsD e it hotrine ywD wongo yhwD ropelD or rw vD the hoie is yoursF efter the onnetion is on(guredD we hve to import the dtse strutureF portuntelyD we hve tsk for thisF imply run the following ommndX

php app/console init:acl

6.39.2 Getting Started

goming k to our smll exmple from the eginningD let9s implement egv for itF greting n egvD nd dding n egi

use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; use Symfony\Component\Security\Acl\Permission\MaskBuilder; // ... // BlogController.php public function addCommentAction(Post $post) { $comment = new Comment(); // setup $form, and bind data // ... if ($form->isValid()) { $entityManager = $this->get('doctrine.orm.default_entity_manager'); $entityManager->persist($comment); $entityManager->ush(); // creating the ACL $aclProvider = $this->get('security.acl.provider'); $objectIdentity = ObjectIdentity::fromDomainObject($comment); $acl = $aclProvider->createAcl($objectIdentity); // retrieving the security identity of the currently logged-in user $securityContext = $this->get('security.context'); $user = $securityContext->getToken()->getUser(); $securityIdentity = UserSecurityIdentity::fromAccount($user);
RUP TF

ymfony houmenttionD PFH

// grant owner access $acl->insertObjectAce($securityIdentity, MaskBuilder::MASK_OWNER); $aclProvider->updateAcl($acl);

here re ouple of importnt implementtion deisions in this ode snippetF por nowD s only wnt to highlight twoX pirstD you my hve notied tht Ebreteel@A does not ept domin ojets diretlyD ut only implementtions of the yjetsdentitysnterfeF his dditionl step of indiretion llows you to work with egvs even when you hve no tul domin ojet instne t hndF his will e extremely helpful if you wnt to hek permissions for lrge numer of ojets without tully hydrting these ojetsF he other interesting prt is the Ebinsertyjetee@A llF sn our exmpleD we re grnting the user who is urrently logged in owner ess to the gommentF he wskfuilderXXweuyxi is preEde(ned integer itmskY don9t worry the msk uilder will strt wy most of the tehnil detilsD ut using this tehnique we n store mny di'erent permissions in one dtse row whih gives us onsiderle oost in performneF X he order in whih egis re heked is signi(ntF es generl ruleD you should ple more spei( entries t the eginningF

gheking eess

// BlogController.php public function editCommentAction(Comment $comment) { $securityContext = $this->get('security.context'); // check for edit access if (false === $securityContext->isGranted('EDIT', $comment)) { throw new AccessDeniedException(); } // retrieve actual comment object, and do your editing here // ...

sn this exmpleD we hek whether the user hs the ihs permissionF snternllyD ymfonyP mps the permission to severl integer itmsksD nd heks whether the user hs ny of TFQWF eess gontrol vists @egvsA RUQ

ymfony houmenttionD PFH themF X ou n de(ne up to QP se permissions @depending on your y r might vry etween QH to QPAF sn dditionD you n lso de(ne umultive permissionsF

6.39.3 Cumulative Permissions

sn our (rst exmple oveD we only grnted the user the yxi se permissionF hile this e'etively lso llows the user to perform ny opertion suh s viewD editD etF on the domin ojetD there re ses where we wnt to grnt these permissions expliitlyF he wskfuilder n e used for reting it msks esily y omining severl se permissionsX

$builder = new MaskBuilder(); $builder ->add('view') ->add('edit') ->add('delete') ->add('undelete') ; $mask = $builder->get(); // int(15)
his integer itmsk n then e used to grnt user the se permissions you dded oveX

$acl->insertObjectAce(new UserSecurityIdentity('johannes'), $mask);


he user is now llowed to viewD editD deleteD nd unEdelete ojetsF

6.40 Advanced ACL Concepts

he im of this hpter is to give more inEdepth view of the egv systemD nd lso explin some of the design deisions ehind itF
6.40.1 Design Concepts

ymfonyP9s ojet instne seurity pilities re sed on the onept of n eess gontrol vistF ivery domin ojet instne hs its own egvF he egv instne holds detiled list of eess gontrol intries @egisA whih re used to mke ess deisionsF ymfonyP9s egv system fouses on two min ojetivesX

providing wy to e0iently retrieve lrge mount of egvsGegis for your domin ojetsD nd to modify themY
RUR TF

ymfony houmenttionD PFH

providing wy to esily mke deisions of whether person is llowed to perform n tion on domin ojet or notF
es indited y the (rst pointD one of the min pilities of ymfonyP9s egv system is highEperformne wy of retrieving egvsGegisF his is extremely importnt sine eh egv might hve severl egisD nd inherit from nother egv in treeElike fshionF hereforeD we spei(lly do not leverge ny ywD ut the defult implementtion interts with your onnetion diretly using hotrine9s hfevF yjet sdentities he egv system is ompletely deoupled from your domin ojetsF hey don9t even hve to e stored in the sme dtseD or on the sme serverF sn order to hieve this deouplingD in the egv system your ojets re represented through ojet identity ojetsF iverytimeD you wnt to retrieve the egv for domin ojetD the egv system will (rst rete n ojet identity from your domin ojetD nd then pss this ojet identity to the egv provider for further proessingF eurity sdentities his is nlog to the ojet identityD ut represents userD or role in your pplitionF ih roleD or user hs its own seurity identityF
6.40.2 Database Table Structure

he defult implementtion uses (ve dtse tles s listed elowF he tles re ordered from lest rows to most rows in typil pplitionX

lseurityidentitiesX his tle reords ll seurity identities @shA whih hold egisF he defult implementtion ships with two seurity identitiesX oleeuritysdentityD nd sereuritysdentity llssesX his tle mps lss nmes to unique id whih n e referened from other tlesF lojetidentitiesX ih row in this tle represents single domin ojet instneF lojetidentitynestorsX his tle llows us to determine ll the nestors of n egv in very e0ient wyF lentriesX his tle ontins ll egisF his is typilly the tle with the most rowsF st n ontin tens of millions without signi(ntly impting performneF

TFRHF edvned egv gonepts

RUS

ymfony houmenttionD PFH


6.40.3 Scope of Access Control Entries

eess ontrol entries n hve di'erent sopes in whih they pplyF sn ymfonyPD we hve silly two di'erent sopesX

glssEopeX hese entries pply to ll ojets with the sme lssF yjetEopeX his ws the sope we solely used in the previous hpterD nd it only pplies to one spei( ojetF
ometimesD you will (nd the need to pply n egi only to spei( (eld of the ojetF vet9s sy you wnt the sh only to e viewle y n dministrtorD ut not y your ustomer servieF o solve this ommon prolemD we hve dded two more suEsopesX

glssEpieldEopeX hese entries pply to ll ojets with the sme lssD ut only to spei( (eld of the ojetsF yjetEpieldEopeX hese entries pply to spei( ojetD nd only to spei( (eld of tht ojetF
6.40.4 Pre-Authorization Decisions

por preEuthoriztion deisionsD tht is deisions efore ny methodD or seure tion is invokedD we rely on the proven eessheisionwnger servie tht is lso used for rehing uthoriztion deisions sed on rolesF tust like rolesD the egv system dds severl new ttriutes whih my e used to hek for di'erent permissionsF

RUT

TF

ymfony houmenttionD PFH fuiltEin ermission wp ettriute sntended wening si hether someone is llowed to view the domin ojetF snteger fitmsks siD ihsD yieyD weiD or yxi ihsD yieyD weiD or yxi hiviiD yieyD weiD or yxi xhiviiD yieyD weiD or yxi yieyD weiD or yxi weiD or yxi yxi

ihs hether someone is llowed to mke hnges to the domin ojetF hivii hether someone is llowed to delete the domin ojetF

xhivii hether someone is llowed to restore previously deleted domin ojetF yiey hether someone is llowed to perform ll of the ove tionsF wei hether someone is llowed to perform ll of the ove tionsD nd in ddition is llowed to grnt ny of the ove permissions to othersF yxi hether someone owns the domin ojetF en owner n perform ny of the ove tionsF ermission ettriutes vsF ermission fitmsks

ettriutes re used y the eessheisionwngerD just like roles re ttriutes used y the eessheisionwngerF yftenD these ttriutes represent in ft n ggregte of integer itmsksF snteger itmsks on the other hndD re used y the egv system internlly to e0iently store your users9 permissions in the dtseD nd perform ess heks using extremely fst itmsk opertionsF ixtensiility he ove permission mp is y no mens sttiD nd theoretilly ould e ompletely repled t willF roweverD it should over most prolems you enounterD nd for interoperility with other undlesD we enourge you to stik to the mening we hve envisged for themF

TFRHF edvned egv gonepts

RUU

ymfony houmenttionD PFH


6.40.5 Post Authorization Decisions

ost uthoriztion deisions re mde fter seure method hs een invokedD nd typilly involve the domin ojet whih is returned y suh methodF efter invotion providers lso llow to modifyD or (lter the domin ojet efore it is returnedF hue to urrent limittions of the r lngugeD there re no postEuthoriztion pilities uild into the ore eurity omponentF roweverD there is n experimentl tweurityixtrfundle whih dds these pilitiesF ee its doumenttion for further informtion on how this is omplishedF
6.40.6 Process for Reaching Authorization Decisions

he egv lss provides two methods for determining whether seurity identity hs the required itmsksD isqrnted nd ispieldqrntedF hen the egv reeives n uthoriztion request through one of these methodsD it delegtes this request to n implementtion of ermissionqrntingtrtegyF his llows you to reple the wy ess deisions re rehed without tully modifying the egv lss itselfF he ermissionqrntingtrtegy (rst heks ll your ojetEsope egis if none is pplileD the lssEsope egis will e hekedD if none is pplileD then the proess will e repeted with the egis of the prent egvF sf no prent egv existsD n exeption will e thrownF

6.41 How to force HTTPS or HTTP for Dierent URLs

ou n fore res of your site to use the r protool in the seurity on(gF his is done through the essontrol rules using the requireshnnel optionF por exmpleD if you wnt to fore ll vs strting with Gseure to use r then you ould use the following on(gX

ewv

access_control: - path: ^/secure roles: ROLE_ADMIN requires_channel: https


wv

<access-control> <rule path="^/secure" role="ROLE_ADMIN" requires_channel="https" /> </access-control>


r

RUV

TF

ymfony houmenttionD PFH

'access_control' => array( array('path' => '^/secure', 'role' => 'ROLE_ADMIN', 'requires_channel' => 'https' ), ),
he login form itself needs to llow nonymous ess otherwise users will e unle to uthentiteF o fore it to use r you n still use essontrol rules y using the serixsgeihexyxwyv roleX

ewv

access_control: - path: ^/login roles: IS_AUTHENTICATED_ANONYMOUSLY requires_channel: https


wv

<access-control> <rule path="^/login" role="IS_AUTHENTICATED_ANONYMOUSLY" requires_channel="https" /> </access-control>


r

'access_control' => array( array('path' => '^/login', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'requires_channel' => 'https' ), ),
st is lso possile to speify using r in the routing on(gurtion see row to fore routes to lwys use r for more detilsF

6.42 How to customize your Form Login

sing form login for uthentition is ommonD nd )exileD method for hndling uthentition in ymfonyPF retty muh every spet of the form login n e ustomizedF he fullD defult on(gurtion is shown in the next setionF

TFRPF row to ustomize your porm vogin

RUW

ymfony houmenttionD PFH


6.42.1 Form Login Conguration Reference

ewv

# app/cong/security.yml security: rewalls: main: form_login: # the user is redirected here when he/she needs to login login_path: /login # if true, forward the user to the login form instead of redirecting use_forward: false # submit the login form here check_path: /login_check # by default, the login form *must* be a POST, not a GET post_only: true # login success redirecting options (read further below) always_use_default_target_path: false default_target_path: / target_path_parameter: _target_path use_referer: false # login failure redirecting options (read further below) failure_path: null failure_forward: false # eld names for the username and password elds username_parameter: _username password_parameter: _password # csrf token options csrf_parameter: intention:
wv

_csrf_token authenticate

<!-- app/cong/security.xml --> <cong> <rewall> <form-login check_path="/login_check" login_path="/login" use_forward="false"


RVH TF

ymfony houmenttionD PFH

/> </rewall> </cong>


r

always_use_default_target_path="false" default_target_path="/" target_path_parameter="_target_path" use_referer="false" failure_path="null" failure_forward="false" username_parameter="_username" password_parameter="_password" csrf_parameter="_csrf_token" intention="authenticate" post_only="true"

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('form_login' => array( 'check_path' => '/login_check', 'login_path' => '/login', 'user_forward' => false, 'always_use_default_target_path' => false, 'default_target_path' => '/', 'target_path_parameter' => _target_path, 'use_referer' => false, 'failure_path' => null, 'failure_forward' => false, 'username_parameter' => '_username', 'password_parameter' => '_password', 'csrf_parameter' => '_csrf_token', 'intention' => 'authenticate', 'post_only' => true, )), ), ));

6.42.2 Redirecting after Success

ou n hnge where the login form redirets fter suessful login using the vrious on(g optionsF fy defult the form will rediret to the v the user requested @iFeF the v whih triggered the login form eing shownAF por exmpleD if the user requested httpXGGwwwFexmpleFomGdminGpostGIVGedit then fter heGshe will eventully e sent k TFRPF row to ustomize your porm vogin RVI

ymfony houmenttionD PFH to httpXGGwwwFexmpleFomGdminGpostGIVGedit fter suessfully logging inF his is done y storing the requested v in the sessionF sf no v is present in the session @perhps the user went diretly to the login pgeAD then the user is redireted to the defult pgeD whih is G @iFeF the homepgeA y defultF ou n hnge this ehvior in severl wysF X es mentionedD y defult the user is redireted k to the pge he originlly requestedF ometimesD this n use prolemsD like if kground ete request ppers to e the lst visited vD using the user to e redireted thereF por informtion on ontrolling this ehviorD see row to hnge the hefult rget th fehviorF

ghnging the hefult ge pirstD the defult pge n e set @iFeF the pge the user is redireted to if no previous pge ws stored in the sessionAF o set it to Gdmin use the following on(gX

ewv

# app/cong/security.yml security: rewalls: main: form_login: # ... default_target_path: /admin


wv

<!-- app/cong/security.xml --> <cong> <rewall> <form-login default_target_path="/admin" /> </rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('form_login' => array( // ... 'default_target_path' => '/admin', )),

RVP

TF

ymfony houmenttionD PFH

));

),

xowD when no v is set in the session users will e sent to GdminF elwys ediret to the hefult ge ou n mke it so tht users re lwys redireted to the defult pge regrdless of wht v they hd requested previously y setting the lwysusedefulttrgetpth option to trueX

ewv

# app/cong/security.yml security: rewalls: main: form_login: # ... always_use_default_target_path: true


wv

<!-- app/cong/security.xml --> <cong> <rewall> <form-login always_use_default_target_path="true" /> </rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('form_login' => array( // ... 'always_use_default_target_path' => true, )), ), ));

TFRPF row to ustomize your porm vogin

RVQ

ymfony houmenttionD PFH sing the eferring v sn se no previous v ws stored in the sessionD you my wish to try using the ripii instedD s this will often e the smeF ou n do this y setting usereferer to true @it defults to flseAX

ewv

# app/cong/security.yml security: rewalls: main: form_login: # ... use_referer:


wv

true

<!-- app/cong/security.xml --> <cong> <rewall> <form-login use_referer="true" /> </rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('form_login' => array( // ... 'use_referer' => true, )), ), ));
gontrol the ediret v from inside the porm ou n lso override where the user is redireted to vi the form itself y inluding hidden (eld with the nme trgetpthF por exmpleD to rediret to the v de(ned y some ount routeD use the followingX

wig

RVR

TF

ymfony houmenttionD PFH

{# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #} {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('login_check') }}" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <input type="hidden" name="_target_path" value="account" /> <input type="submit" name="login" /> </form>
r

<?php // src/Acme/SecurityBundle/Resources/views/Security/login.html.php ?> <?php if ($error): ?> <div><?php echo $error->getMessage() ?></div> <?php endif; ?> <form action="<?php echo $view['router']->generate('login_check') ?>" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="<?php echo $last_username ?>" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <input type="hidden" name="_target_path" value="account" /> <input type="submit" name="login" /> </form>
xowD the user will e redireted to the vlue of the hidden form (eldF he vlue ttriute n e reltive pthD solute vD or route nmeF ou n even hnge the nme of the hidden form (eld y hnging the trgetpthprmeter option to nother vlueF

ewv

# app/cong/security.yml security: rewalls: main: form_login: target_path_parameter: redirect_url


TFRPF row to ustomize your porm vogin RVS

ymfony houmenttionD PFH

wv

<!-- app/cong/security.xml --> <cong> <rewall> <form-login target_path_parameter="redirect_url" /> </rewall> </cong>
r

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('form_login' => array( 'target_path_parameter' => redirect_url, )), ), ));
edireting on vogin pilure sn ddition to rediret the user fter suessful loginD you n lso set the v tht the user should e redireted to fter filed login @eFgF n invlid usernme or pssword ws sumittedAF fy defultD the user is redireted k to the login form itselfF ou n set this to di'erent v with the following on(gX

ewv

# app/cong/security.yml security: rewalls: main: form_login: # ... failure_path: /login_failure


wv

<!-- app/cong/security.xml --> <cong> <rewall> <form-login


RVT TF

ymfony houmenttionD PFH

/> </rewall> </cong>


r

failure_path="login_failure"

// app/cong/security.php $container->loadFromExtension('security', array( 'rewalls' => array( 'main' => array('form_login' => array( // ... 'failure_path' => login_failure, )), ), ));

6.43 How to secure any Service or Method in your Application

sn the seurity hpterD you n see how to seure ontroller y requesting the seurityFontext servie from the ervie gontiner nd heking the urrent user9s roleX

use Symfony\Component\Security\Core\Exception\AccessDeniedException // ... public function helloAction($name) { if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); } } // ...

ou n lso seure ny servie in similr wy y injeting the seurityFontext servie into itF por generl introdution to injeting dependenies into servies see the ervie gontiner hpter of the ookF por exmpleD suppose you hve xewsletterwnger lss tht sends out emils nd you wnt to restrit its use to only users who hve some yvixiviiehwsx roleF fefore you dd seurityD the lss looks something like thisX

namespace Acme\HelloBundle\Newsletter; class NewsletterManager {


TFRQF row to seure ny ervie or wethod in your epplition RVU

ymfony houmenttionD PFH

public function sendNewsletter() { // where you actually do the work } } // ...

our gol is to hek the user9s role when the sendxewsletter@A method is lledF he (rst step towrds this is to injet the seurityFontext servie into the ojetF ine it won9t mke sense not to perform the seurity hekD this is n idel ndidte for onstrutor injetionD whih gurntees tht the seurity ontext ojet will e ville inside the xewsletterwnger lssX

namespace Acme\HelloBundle\Newsletter; use Symfony\Component\Security\Core\SecurityContextInterface; class NewsletterManager { protected $securityContext; public function __construct(SecurityContextInterface $securityContext) { $this->securityContext = $securityContext; } } // ...

hen in your servie on(gurtionD you n injet the servieX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: newsletter_manager.class: Acme\HelloBundle\Newsletter\NewsletterManager services: newsletter_manager: class: %newsletter_manager.class% arguments: [@security.context]
wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters>


RVV TF

ymfony houmenttionD PFH

<parameter key="newsletter_manager.class">Acme\HelloBundle\Newsletter\NewsletterManager</par </parameters> <services> <service id="newsletter_manager" class="%newsletter_manager.class%"> <argument type="service" id="security.context"/> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

$container->setParameter('newsletter_manager.class', 'Acme\HelloBundle\Newsletter\NewsletterManager' $container->setDenition('newsletter_manager', new Denition( '%newsletter_manager.class%', array(new Reference('security.context')) ));


he injeted servie n then e used to perform the seurity hek when the sendxewsletter@A method is lledX

namespace Acme\HelloBundle\Newsletter; use Symfony\Component\Security\Core\Exception\AccessDeniedException use Symfony\Component\Security\Core\SecurityContextInterface; // ... class NewsletterManager { protected $securityContext; public function __construct(SecurityContextInterface $securityContext) { $this->securityContext = $securityContext; } public function sendNewsletter() { if (false === $this->securityContext->isGranted('ROLE_NEWSLETTER_ADMIN')) { throw new AccessDeniedException(); } //-TFRQF row to seure ny ervie or wethod in your epplition RVW

ymfony houmenttionD PFH

} } // ...

sf the urrent user does not hve the yvixiviiehwsxD they will e prompted to log inF
6.43.1 Securing Methods Using Annotations

ou n lso seure method lls in ny servie with nnottions y using the optionl tweurityixtrfundle undleF his undle is inluded in the ymfonyP tndrd histriutionF o enle the nnottions funtionlityD tg the servie you wnt to seure with the seurityFseureservie tg @you n lso utomtilly enle this funtionlity for ll serviesD see the sider elowAX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml # ... services: newsletter_manager: # ... tags: - { name: security.secure_service }


wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <!-- ... --> <services> <service id="newsletter_manager" class="%newsletter_manager.class%"> <!-- ... --> <tag name="security.secure_service" /> </service> </services>
r

// src/Acme/HelloBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference;

RWH

TF

ymfony houmenttionD PFH

$denition = new Denition( '%newsletter_manager.class%', array(new Reference('security.context')) )); $denition->addTag('security.secure_service'); $container->setDenition('newsletter_manager', $denition);
ou n then hieve the sme results s ove using n nnottionX

namespace Acme\HelloBundle\Newsletter; use JMS\SecurityExtraBundle\Annotation\Secure; // ... class NewsletterManager { /** * @Secure(roles="ROLE_NEWSLETTER_ADMIN") */ public function sendNewsletter() { //-} } // ...

X he nnottions work euse proxy lss is reted for your lss whih performs the seurity heksF his mens thtD whilst you n use nnottions on puli nd proteted methodsD you nnot use them with privte methods or methods mrked (nlF he tweurityixtrfundle lso llows you to seure the prmeters nd return vlues of methodsF por more informtionD see the tweurityixtrfundle doumenttionF

TFRQF row to seure ny ervie or wethod in your epplition

RWI

ymfony houmenttionD PFH etivting the ennottions puntionlity for ll ervies hen seuring the method of servie @s shown oveAD you n either tg eh servie individullyD or tivte the funtionlity for ll servies t oneF o do soD set the seurellservies on(gurtion option to trueX ewv

# app/cong/cong.yml jms_security_extra: # ... secure_all_services: true


wv

<!-- app/cong/cong.xml --> <srv:container xmlns="http://symfony.com/schema/dic/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:srv="http://symfony.com/schema/dic/services" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/service <jms_security_extra secure_controllers="true" secure_all_services="true" /> </srv:container>
r

// app/cong/cong.php $container->loadFromExtension('jms_security_extra', array( // ... 'secure_all_services' => true, ));


he disdvntge of this method is thtD if tivtedD the initil pge lod my e very slow depending on how mny servies you hve de(nedF

6.44 How to load Security Users from the Database (the entity Provider)

his rtile hs not een written yetD ut will soonF sf you9re interested in writing this entryD see gontriuting to the houmenttionF his topi is ment to e full working exmple of how to use the entity user provider with the seurity omponentF st should show how to rete the ser lssD implement the methodsD mppingD et E everything you9ll need to get fullyEfuntionlity entity user provider workingF

RWP

TF

ymfony houmenttionD PFH

6.45 How to create a custom User Provider

his rtile hs not een written yetD ut will soonF sf you9re interested in writing this entryD see gontriuting to the houmenttionF his topi is ment to show how ustom user provider n e retedF yne potentil exmple E though etter exmple is welomed E is to show how ustom ser lss n e reted nd then populted vi ustom user provider tht lods users y mking n es servie ll out to some externl siteF

6.46 How to create a custom Authentication Provider

sf you hve red the hpter on eurityD you understnd the distintion ymfonyP mkes etween uthentition nd uthoriztion in the implementtion of seurityF his hpter disusses the ore lsses involved in the uthentition proessD nd how to implement ustom uthentition providerF feuse uthentition nd uthoriztion re seprte oneptsD this extension will e userEprovider gnostiD nd will funtion with your pplition9s user providersD my they e sed in memoryD dtseD or wherever else you hoose to store themF
6.46.1 Meet WSSE

he following hpter demonstrtes how to rete ustom uthentition provider for i uthentitionF he seurity protool for i provides severl seurity ene(tsX IF sernme G ssword enryption PF fe gurding ginst reply ttks QF xo we server on(gurtion required i is very useful for the seuring of we serviesD my they e ye or iF here is plenty of gret doumenttion on iD ut this rtile will fous not on the seurity protoolD ut rther the mnner in whih ustom protool n e dded to your ymfonyP pplitionF he sis of i is tht request heder is heked for enrypted redentilsD veri(ed using timestmp nd noneD nd uthentited for the requested user using pssword digestF X i lso supports pplition key vlidtionD whih is useful for we serviesD ut is outside the sope of this hpterF

TFRSF row to rete ustom ser rovider

RWQ

ymfony houmenttionD PFH


6.46.2 The Token

he role of the token in the ymfonyP seurity ontext is n importnt oneF e token represents the user uthentition dt present in the requestF yne request is uthentitedD the token retins the user9s dtD nd delivers this dt ross the seurity ontextF pirstD we will rete our token lssF his will llow the pssing of ll relevnt informtion to our uthentition providerF

// src/Acme/DemoBundle/Security/Authentication/Token/WsseUserToken.php namespace Acme\DemoBundle\Security\Authentication\Token; use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; class WsseUserToken extends AbstractToken { public $created; public $digest; public $nonce; public function getCredentials() { return ''; }

X he sseseroken lss extends the seurity omponent9s ymfonygomponenteuritygoreeuthentitionokenestrtoken lssD whih provides si token funtionlityF smplement the ymfonygomponenteuritygoreeuthentitionokenokensnterfe on ny lss to use s tokenF

6.46.3 The Listener

xextD you need listener to listen on the seurity ontextF he listener is responsile for (elding requests to the (rewll nd lling the uthentition providerF e listener must e n instne of ymfonygomponenteurityrttppirewllvistenersnterfeF e seurity listener should hndle the ymfonygomponentrttpuerneliventqetesponseivent eventD nd set n uthentited token in the seurity ontext if suessfulF

// src/Acme/DemoBundle/Security/Firewall/WsseListener.php namespace Acme\DemoBundle\Security\Firewall; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent;


RWR TF

ymfony houmenttionD PFH

use Symfony\Component\Security\Http\Firewall\ListenerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Acme\DemoBundle\Security\Authentication\Token\WsseUserToken; class WsseListener implements ListenerInterface { protected $securityContext; protected $authenticationManager;

public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $aut { $this->securityContext = $securityContext; $this->authenticationManager = $authenticationManager; } public function handle(GetResponseEvent $event) { $request = $event->getRequest(); if (!$request->headers->has('x-wsse')) { return; }

$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Crea if (preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) { $token = new WsseUserToken(); $token->setUser($matches[1]); $token->digest = $matches[2]; $token->nonce = $matches[3]; $token->created = $matches[4]; try { $returnValue = $this->authenticationManager->authenticate($token); if ($returnValue instanceof TokenInterface) { return $this->securityContext->setToken($returnValue); } else if ($returnValue instanceof Response) { return $event->setResponse($returnValue); } } catch (AuthenticationException $e) { // you might log something here }
TFRTF row to rete ustom euthentition rovider RWS

ymfony houmenttionD PFH

} $response = new Response(); $response->setStatusCode(403); $event->setResponse($response);

his listener heks the request for the expeted Ei hederD mthes the vlue returned for the expeted i informtionD retes token using tht informtionD nd psses the token on to the uthentition mngerF sf the proper informtion is not providedD or the uthentition mnger throws n ymfonygomponenteuritygoreixeptioneuthentitionixeptionD RHQ esponse is returnedF

X e lss not used oveD the ymfonygomponenteurityrttppirewllestrteuthenti lssD is very useful se lss whih provides ommonly needed funtionlity for seurity extensionsF his inludes mintining the token in the sessionD providing suess G filure hndlersD login form urlsD nd moreF es i does not require mintining uthentition sessions or login formsD it won9t e used for this exmpleF

6.46.4 The Authentication Provider

he uthentition provider will do the veri(tion of the sseserokenF xmelyD the provider will verify the greted heder vlue is vlid within (ve minutesD the xone heder vlue is unique within (ve minutesD nd the sswordhigest heder vlue mthes with the user9s psswordF

// src/Acme/DemoBundle/Security/Authentication/Provider/WsseProvider.php namespace Acme\DemoBundle\Security\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Acme\DemoBundle\Security\Authentication\Token\WsseUserToken; class WsseProvider implements AuthenticationProviderInterface { private $userProvider; private $cacheDir; public function __construct(UserProviderInterface $userProvider, $cacheDir)
RWT TF

ymfony houmenttionD PFH

{ }

$this->userProvider = $userProvider; $this->cacheDir = $cacheDir;

public function authenticate(TokenInterface $token) { $user = $this->userProvider->loadUserByUsername($token->getUsername());

if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword() $authenticatedToken = new WsseUserToken($user->getRoles()); $authenticatedToken->setUser($user); } } return $authenticatedToken;

throw new AuthenticationException('The WSSE authentication failed.');

protected function validateDigest($digest, $nonce, $created, $secret) { // Expire timestamp after 5 minutes if (time() - strtotime($created) > 300) { return false; }

// Validate nonce is unique within 5 minutes if (le_exists($this->cacheDir.'/'.$nonce) && le_get_contents($this->cacheDir.'/'.$nonce) + 300 >= tim throw new NonceExpiredException('Previously used nonce detected'); } le_put_contents($this->cacheDir.'/'.$nonce, time()); // Validate Secret $expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true)); } return $digest === $expected;

public function supports(TokenInterface $token) { return $token instanceof WsseUserToken; }

X he ymfonygomponenteuritygoreeuthentitionrovidereuthentitionrovider requires n uthentite method on the user tokenD nd supports methodD whih tells the TFRTF row to rete ustom euthentition rovider RWU

ymfony houmenttionD PFH uthentition mnger whether or not to use this provider for the given tokenF sn the se of multiple providersD the uthentition mnger will then move to the next provider in the listF

6.46.5 The Factory

ou hve reted ustom tokenD ustom listenerD nd ustom providerF xow you need to tie them ll togetherF row do you mke your provider ville to your seurity on(gurtionc he nswer is y using ftoryF e ftory is where you hook into the seurity omponentD telling it the nme of your provider nd ny on(gurtion options ville for itF pirstD you must rete lss whih implements ymfonyfundleeurityfundlehependenysnjetioneurityptoryeurityptorysnterfeF

// src/Acme/DemoBundle/DependencyInjection/Security/Factory/WsseFactory.php namespace Acme\DemoBundle\DependencyInjection\Security\Factory; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\DenitionDecorator; use Symfony\Component\Cong\Denition\Builder\NodeDenition; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; class WsseFactory implements SecurityFactoryInterface { public function create(ContainerBuilder $container, $id, $cong, $userProvider, $defaultEntryPoint) { $providerId = 'security.authentication.provider.wsse.'.$id; $container ->setDenition($providerId, new DenitionDecorator('wsse.security.authentication.provider')) ->replaceArgument(0, new Reference($userProvider)) ;

$listenerId = 'security.authentication.listener.wsse.'.$id; $listener = $container->setDenition($listenerId, new DenitionDecorator('wsse.security.authentication.liste } return array($providerId, $listenerId, $defaultEntryPoint);

public function getPosition() { return 'pre_auth'; } public function getKey() {


RWV TF

ymfony houmenttionD PFH

return 'wsse';

public function addConguration(NodeDenition $node) {}

he ymfonyfundleeurityfundlehependenysnjetioneurityptoryeurityptorysnterfe requires the following methodsX

rete methodD whih dds the listener nd uthentition provider to the hs ontiner for the pproprite seurity ontextY getosition methodD whih must e of type preuthD formD httpD nd rememerme nd de(nes the position t whih the provider is lledY getuey method whih de(nes the on(gurtion key used to referene the providerY ddgon(gurtion methodD whih is used to de(ne the on(gurtion options underneth the on(gurtion key in your seurity on(gurtionF etting on(gurtion options re explined lter in this hpterF

X e lss not used in this exmpleD ymfonyfundleeurityfundlehependenysnjetione is very useful se lss whih provides ommonly needed funtionlity for seurity ftoriesF st my e useful when de(ning n uthentition provider of di'erent typeF xow tht you hve reted ftory lssD the wsse key n e used s (rewll in your seurity on(gurtionF X ou my e wondering why do we need speil ftory lss to dd listeners nd providers to the dependeny injetion ontinercF his is very good questionF he reson is you n use your (rewll multiple timesD to seure multiple prts of your pplitionF feuse of thisD eh time your (rewll is usedD new servie is reted in the hs ontinerF he ftory is wht retes these new serviesF

6.46.6 Conguration

st9s time to see your uthentition provider in tionF ou will need to do few things in order to mke this workF he (rst thing is to dd the servies ove to the hs ontinerF our ftory lss ove mkes referene to servie ids tht do not exist yetX wsseFseurityFuthentitionFprovider nd wsseFseurityFuthentitionFlistenerF st9s time to de(ne those serviesF

ewv
TFRTF row to rete ustom euthentition rovider RWW

ymfony houmenttionD PFH

# src/Acme/DemoBundle/Resources/cong/services.yml services: wsse.security.authentication.provider: class: Acme\DemoBundle\Security\Authentication\Provider\WsseProvider arguments: ['', %kernel.cache_dir%/security/nonces] wsse.security.authentication.listener: class: Acme\DemoBundle\Security\Firewall\WsseListener arguments: [@security.context, @security.authentication.manager]
wv

<!-- src/Acme/DemoBundle/Resources/cong/services.xml --> <services> <service id="wsse.security.authentication.provider" class="Acme\DemoBundle\Security\Authentication\Provider\WsseProvider" public="false"> <argument /> <!-- User Provider --> <argument>%kernel.cache_dir%/security/nonces</argument> </service> <service id="wsse.security.authentication.listener" class="Acme\DemoBundle\Security\Firewall\WsseListener" public="false"> <argument type="service" id="security.context"/> <argument type="service" id="security.authentication.manager" /> </service> </services>
r

// src/Acme/DemoBundle/Resources/cong/services.php use Symfony\Component\DependencyInjection\Denition; use Symfony\Component\DependencyInjection\Reference; $container->setDenition('wsse.security.authentication.provider', new Denition( 'Acme\DemoBundle\Security\Authentication\Provider\WsseProvider', array('', '%kernel.cache_dir%/security/nonces') )); $container->setDenition('wsse.security.authentication.listener', new Denition( 'Acme\DemoBundle\Security\Firewall\WsseListener', array( new Reference('security.context'), new Reference('security.authentication.manager')) ));
xow tht your servies re de(nedD tell your seurity ontext out your ftoryF ptories must e inluded in n individul on(gurtion (leD t the time of this writingF ou need to SHH TF

ymfony houmenttionD PFH rete (le with your ftory servie in itD nd then use the ftories key in your on(gurtion to import itF

<!-- src/Acme/DemoBundle/Resources/cong/security_factories.xml --> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/servi <services> <service id="security.authentication.factory.wsse" class="Acme\DemoBundle\DependencyInjection\Security\Factory\WsseFactory" public="false"> <tag name="security.listener.factory" /> </service> </services> </container>
ewv

# app/cong/security.yml security: factories: - "%kernel.root_dir%/../src/Acme/DemoBundle/Resources/cong/security_factories.xml"


wv

<!-- app/cong/security.xml --> <cong> <factories> "%kernel.root_dir%/../src/Acme/DemoBundle/Resources/cong/security_factories.xml </factories> </cong>


r

// app/cong/security.php $container->loadFromExtension('security', array( 'factories' => array( "%kernel.root_dir%/../src/Acme/DemoBundle/Resources/cong/security_factories.xml" ), ));


ou re (nished3 ou n now de(ne prts of your pp s under i protetionF

security: rewalls: wsse_secured: pattern: /api/.* wsse: true


TFRTF row to rete ustom euthentition rovider SHI

ymfony houmenttionD PFH gongrtultions3 ou hve written your very own ustom seurity uthentition provider3
6.46.7 A Little Extra

row out mking your i uthentition provider it more exitingc he possiilities re endlessF hy don9t you strt y dding some spkle to tht shinec gon(gurtion ou n dd ustom options under the wsse key in your seurity on(gurtionF por instneD the time llowed efore expiring the greted heder itemD y defultD is S minutesF wke this on(gurleD so di'erent (rewlls n hve di'erent timeout lengthsF ou will (rst need to edit sseptory nd de(ne the new option in the ddgon(gurtion methodF

class WsseFactory implements SecurityFactoryInterface { # ... public function addConguration(NodeDenition $node) { $node ->children() ->scalarNode('lifetime')->defaultValue(300) ->end() ; }

xowD in the rete method of the ftoryD the 6on(g rgument will ontin lifetime9 keyD set to S minutes @QHH seondsA unless otherwise set in the on(gurtionF ss this rgument to your uthentition provider in order to put it to useF

class WsseFactory implements SecurityFactoryInterface { public function create(ContainerBuilder $container, $id, $cong, $userProvider, $defaultEntryPoint) { $providerId = 'security.authentication.provider.wsse.'.$id; $container ->setDenition($providerId, new DenitionDecorator('wsse.security.authentication.provider')) ->replaceArgument(0, new Reference($userProvider)) ->replaceArgument(2, $cong['lifetime']) ; // ...
SHP TF

ymfony houmenttionD PFH

} // ...

X ou9ll lso need to dd third rgument to the wsseFseurityFuthentitionFprovider servie on(gurtionD whih n e lnkD ut will e (lled in with the lifetime in the ftoryF he sserovider lss will lso now need to ept third onstrutor rgument E the lifetime E whih it should use insted of the hrdEoded QHH seondsF hese two steps re not shown hereF he lifetime of eh wsse request is now on(gurleD nd n e set to ny desirle vlue per (rewllF

security: rewalls: wsse_secured: pattern: /api/.* wsse: { lifetime: 30 }


he rest is up to you3 eny relevnt on(gurtion items n e de(ned in the ftory nd onsumed or pssed to the other lsses in the ontinerF

6.47 How to change the Default Target Path Behavior

fy defultD the seurity omponent retins the informtion of the lst request s in session vrile nmed seurityFtrgetpthF pon suessful loginD the user is redireted to this pthD s to help her ontinue from the lst known pge she visitedF yn some osionsD this is unexpetedF por exmple when the lst request s ws n r y ginst route whih is on(gured to llow only y methodD the user is redireted to this route only to get RHR errorF o get round this ehviorD you would simply need to extend the ixeptionvistener lss nd override the defult method nmed setrgetth@AF pirstD override the seurityFexeptionlistenerFlss prmeter in your on(gurtion (leF his n e done from your min on(gurtion (le @in ppGon(gA or from on(gurtion (le eing imported from undleX

ewv

# src/Acme/HelloBundle/Resources/cong/services.yml parameters: # ... security.exception_listener.class: Acme\HelloBundle\Security\Firewall\ExceptionListener


TFRUF row to hnge the hefult rget th fehvior SHQ

ymfony houmenttionD PFH

wv

<!-- src/Acme/HelloBundle/Resources/cong/services.xml --> <parameters> <!-- ... --> <parameter key="security.exception_listener.class">Acme\HelloBundle\Security\Firewall\ExceptionLis </parameters>
r

// src/Acme/HelloBundle/Resources/cong/services.php // ... $container->setParameter('security.exception_listener.class', 'Acme\HelloBundle\Security\Firewall\Except


xextD rete your own ixeptionvistenerX

// src/Acme/HelloBundle/Security/Firewall/ExceptionListener.php namespace Acme\HelloBundle\Security\Firewall; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\Firewall\ExceptionListener as BaseExceptionListener; class ExceptionListener extends BaseExceptionListener { protected function setTargetPath(Request $request) { // Do not save target path for XHR and non-GET requests // You can add any more logic here you want if ($request->isXmlHttpRequest() || 'GET' !== $request->getMethod()) { return; } } $request->getSession()->set('_security.target_path', $request->getUri());

edd s muh or few logi here s required for your senrio3

6.48 How to use Varnish to speedup my Website

feuse ymfonyP9s he uses the stndrd r he hedersD the ymfonyP everse roxy n esily e repled with ny other reverse proxyF rnish is powerfulD openEsoureD r elertor ple of serving hed ontent quikly nd inluding support for idge ide snludesF

SHR

TF

ymfony houmenttionD PFH


6.48.1 Conguration

es seen previouslyD ymfonyP is smrt enough to detet whether it tlks to reverse proxy tht understnds is or notF st works out of the ox when you use the ymfonyP reverse proxyD ut you need speil on(gurtion to mke it work with rnishF hnkfullyD ymfonyP relies on yet nother stndrd written y ekm @idge erhitetureAD so the % on(gurtion tips in this hpter n e useful even if you don9t use ymfonyPF X rnish only supports the sr ttriute for is tgs @onerror nd lt ttriutes re ignoredAF pirstD on(gure rnish so tht it dvertises its is support y dding urrogteEgpility heder to requests forwrded to the kend pplitionX

sub vcl_recv { set req.http.Surrogate-Capability = "abc=ESI/1.0"; }


henD optimize rnish so tht it only prses the esponse ontents when there is t lest one is tg y heking the urrogteEgontrol heder tht ymfonyP dds utomtillyX

sub vcl_fetch { if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; // for Varnish >= 3.0 set beresp.do_esi = true; // for Varnish < 3.0 // esi;

X gompression with is ws not supported in rnish until version QFH @red qs nd rnishAF sf you9re not using rnish QFHD put we server in front of rnish to perform the ompressionF

6.48.2 Cache Invalidation

ou should never need to invlidte hed dt euse invlidtion is lredy tken into ount ntively in the r he models @see ghe snvlidtionAF tillD rnish n e on(gured to ept speil r qi method tht will invlidte the he for given resoureX

TFRVF row to use rnish to speedup my esite

SHS

ymfony houmenttionD PFH

sub vcl_hit { if (req.request == "PURGE") { set obj.ttl = 0s; error 200 "Purged"; } } sub vcl_miss { if (req.request == "PURGE") { error 404 "Not purged"; } }
X ou must protet the qi r method somehow to void rndom people purging your hed dtF

6.49 How to use PHP instead of Twig for Templates

iven if ymfonyP defults to wig for its templte engineD you n still use plin r ode if you wntF foth templting engines re supported eqully in ymfonyPF ymfonyP dds some nie fetures on top of r to mke writing templtes with r more powerfulF
6.49.1 Rendering PHP Templates

sf you wnt to use the r templting engineD (rstD mke sure to enle it in your pplition on(gurtion (leX

ewv

# app/cong/cong.yml framework: # ... templating: { engines: ['twig', 'php'] }


wv

<!-- app/cong/cong.xml --> <framework:cong ... > <!-- ... --> <framework:templating ... > <framework:engine id="twig" /> <framework:engine id="php" />

SHT

TF

ymfony houmenttionD PFH

</framework:templating> </framework:cong>
r

$container->loadFromExtension('framework', array( // ... 'templating' => array( 'engines' => array('twig', 'php'), ), ));
ou n now render r templte insted of wig one simply y using the Fphp extension in the templte nme insted of FtwigF he ontroller elow renders the indexFhtmlFphp templteX

// src/Acme/HelloBundle/Controller/HelloController.php public function indexAction($name) { return $this->render('HelloBundle:Hello:index.html.php', array('name' => $name)); }

6.49.2 Decorating Templates

wore often thn notD templtes in projet shre ommon elementsD like the wellEknown heder nd footerF sn ymfonyPD we like to think out this prolem di'erentlyX templte n e deorted y nother oneF he indexFhtmlFphp templte is deorted y lyoutFhtmlFphpD thnks to the extend@A llX

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php --> <?php $view->extend('AcmeHelloBundle::layout.html.php') ?> Hello <?php echo $name ?>!
he rellofundleXXlyoutFhtmlFphp nottion sounds fmilirD doesn9t itc st is the sme nottion used to referene templteF he XX prt simply mens tht the ontroller element is emptyD so the orresponding (le is diretly stored under viewsGF xowD let9s hve look t the lyoutFhtmlFphp (leX

<!-- src/Acme/HelloBundle/Resources/views/layout.html.php --> <?php $view->extend('::base.html.php') ?> <h1>Hello Application</h1>

TFRWF row to use r insted of wig for empltes

SHU

ymfony houmenttionD PFH

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


he lyout is itself deorted y nother one @XXseFhtmlFphpAF ymfonyP supports multiple deortion levelsX lyout n itself e deorted y nother oneF hen the undle prt of the templte nme is emptyD views re looked for in the ppGesouresGviewsG diretoryF his diretory store glol views for your entire projetX

<!-- app/Resources/views/base.html.php --> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php $view['slots']->output('title', 'Hello Application') ?></title> </head> <body> <?php $view['slots']->output('_content') ?> </body> </html>
por oth lyoutsD the 6view9slots9Eboutput@9ontent9A expression is repled y the ontent of the hild templteD indexFhtmlFphp nd lyoutFhtmlFphp respetively @more on slots in the next setionAF es you n seeD ymfonyP provides methods on mysterious 6view ojetF sn templteD the 6view vrile is lwys ville nd refers to speil ojet tht provides unh of methods tht mkes the templte engine tikF
6.49.3 Working with Slots

e slot is snippet of odeD de(ned in templteD nd reusle in ny lyout deorting the templteF sn the indexFhtmlFphp templteD de(ne title slotX

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php --> <?php $view->extend('AcmeHelloBundle::layout.html.php') ?> <?php $view['slots']->set('title', 'Hello World Application') ?> Hello <?php echo $name ?>!
he se lyout lredy hs the ode to output the title in the hederX

<!-- app/Resources/views/layout.html.php --> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php $view['slots']->output('title', 'Hello Application') ?></title> </head>
SHV TF

ymfony houmenttionD PFH he output@A method inserts the ontent of slot nd optionlly tkes defult vlue if the slot is not de(nedF end ontent is just speil slot tht ontins the rendered hild templteF por lrge slotsD there is lso n extended syntxX

<?php $view['slots']->start('title') ?> Some large amount of HTML <?php $view['slots']->stop() ?>

6.49.4 Including other Templates

he est wy to shre snippet of templte ode is to de(ne templte tht n then e inluded into other templtesF grete helloFhtmlFphp templteX

<!-- src/Acme/HelloBundle/Resources/views/Hello/hello.html.php --> Hello <?php echo $name ?>!


end hnge the indexFhtmlFphp templte to inlude itX

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php --> <?php $view->extend('AcmeHelloBundle::layout.html.php') ?> <?php echo $view->render('AcmeHello:Hello:hello.html.php', array('name' => $name)) ?>
he render@A method evlutes nd returns the ontent of nother templte @this is the ext sme method s the one used in the ontrollerAF
6.49.5 Embedding other Controllers

end wht if you wnt to emed the result of nother ontroller in templtec ht9s very useful when working with ejxD or when the emedded templte needs some vrile not ville in the min templteF sf you rete fny tionD nd wnt to inlude it into the indexFhtmlFphp templteD simply use the following odeX

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php --> <?php echo $view['actions']->render('HelloBundle:Hello:fancy', array('name' => $name, 'color' => 'green')) ?>
rereD the rellofundleXrelloXfny string refers to the fny tion of the rello ontrollerX

// src/Acme/HelloBundle/Controller/HelloController.php

TFRWF row to use r insted of wig for empltes

SHW

ymfony houmenttionD PFH

class HelloController extends Controller { public function fancyAction($name, $color) { // create some object, based on the $color variable $object = ...; } } return $this->render('HelloBundle:Hello:fancy.html.php', array('name' => $name, 'object' => $object));

// ...

fut where is the 6view9tions9 rry element de(nedc vike 6view9slots9D it9s lled templte helperD nd the next setion tells you more out thoseF
6.49.6 Using Template Helpers

he ymfonyP templting system n e esily extended vi helpersF relpers re r ojets tht provide fetures useful in templte ontextF tions nd slots re two of the uiltEin ymfonyP helpersF greting vinks etween ges peking of we pplitionsD reting links etween pges is mustF snsted of hrdoding vs in templtesD the router helper knows how to generte vs sed on the routing on(gurtionF ht wyD ll your vs n e esily updted y hnging the on(gurtionX

<a href="<?php echo $view['router']->generate('hello', array('name' => 'Thomas')) ?>"> Greet Thomas! </a>
he generte@A method tkes the route nme nd n rry of prmeters s rgumentsF he route nme is the min key under whih routes re referened nd the prmeters re the vlues of the pleholders de(ned in the route ptternX

# src/Acme/HelloBundle/Resources/cong/routing.yml hello: # The route name pattern: /hello/{name} defaults: { _controller: AcmeHelloBundle:Hello:index }

SIH

TF

ymfony houmenttionD PFH sing essetsX imgesD tvriptsD nd stylesheets ht would the snternet e without imgesD tvriptsD nd stylesheetsc ymfonyP provides the ssets tg to del with them esilyX

<link href="<?php echo $view['assets']->getUrl('css/blog.css') ?>" rel="stylesheet" type="text/css" /> <img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" />
he ssets helper9s min purpose is to mke your pplition more portleF hnks to this helperD you n move the pplition root diretory nywhere under your we root diretory without hnging nything in your templte9s odeF
6.49.7 Output Escaping

hen using r templtesD espe vriles whenever they re displyed to the userX

<?php echo $view->escape($var) ?>


fy defultD the espe@A method ssumes tht the vrile is outputted within n rwv ontextF he seond rgument lets you hnge the ontextF por instneD to output something in tvript sriptD use the js ontextX

<?php echo $view->escape($var, 'js') ?>

6.50 How to autoload Classes

henever you use n unde(ned lssD r uses the utoloding mehnism to delegte the loding of (le de(ning the lssF ymfonyP provides universl utoloderD whih is le to lod lsses from (les tht implement one of the following onventionsX

he tehnil interoperility stndrds for r SFQ nmespes nd lss nmesY he ie nming onvention for lssesF
sf your lsses nd the thirdEprty lirries you use for your projet follow these stndrdsD the ymfonyP utoloder is the only utoloder you will ever needF
6.50.1 Usage

PFIX he usesnludeth method ws dded in ymfony PFIF egistering the ymfonygomponentglssvoderniverslglssvoder utoloder is strightforwrdX

TFSHF row to utolod glsses

SII

ymfony houmenttionD PFH

require_once '/path/to/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader(); // You can search the include_path as a last resort. $loader->useIncludePath(true); $loader->register();
por minor performne gins lss pths n e hed in memory using eg y registering the ymfonygomponentglssvoderepniverslglssvoderX

require_once '/path/to/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; require_once '/path/to/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; use Symfony\Component\ClassLoader\ApcUniversalClassLoader; $loader = new ApcUniversalClassLoader('apc.prex.'); $loader->register();
he utoloder is useful only if you dd some lirries to utolodF X he utoloder is utomtilly registered in ymfonyP pplition @see ppGutolodFphpAF sf the lsses to utolod use nmespesD use the XmethodXymfonygomponentglssvoderniverslglssvoderXXregisterxmespe or XmethodXymfonygomponentglssvoderniverslglssvoderXXregisterxmespes methodsX

$loader->registerNamespace('Symfony', __DIR__.'/vendor/symfony/src'); $loader->registerNamespaces(array( 'Symfony' => __DIR__.'/../vendor/symfony/src', 'Monolog' => __DIR__.'/../vendor/monolog/src', ));
por lsses tht follow the ie nming onventionD use the XmethodXymfonygomponentglssvoderniverslglssvoderXXregisterre(x or XmethodXymfonygomponentglssvoderniverslglssvoderXXregisterre(xes methodsX

$loader->registerPrex('Twig_', __DIR__.'/vendor/twig/lib');

SIP

TF

ymfony houmenttionD PFH

$loader->registerPrexes(array( 'Swift_' => __DIR__.'/vendor/swiftmailer/lib/classes', 'Twig_' => __DIR__.'/vendor/twig/lib', ));


X ome lirries lso require their root pth e registered in the r inlude pth @setinludepth@AAF glsses from suEnmespe or suEhierrhy of ie lsses n e looked for in lotion list to ese the vendoring of suEset of lsses for lrge projetsX

$loader->registerNamespaces(array( 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', 'Doctrine\\DBAL\\Migrations' => __DIR__.'/vendor/doctrine-migrations/lib', 'Doctrine\\DBAL' => __DIR__.'/vendor/doctrine-dbal/lib', 'Doctrine' => __DIR__.'/vendor/doctrine/lib', ));
sn this exmpleD if you try to use lss in the hotrinegommon nmespe or one of its hildrenD the utoloder will (rst look for the lss under the dotrineEommon diretoryD nd it will then fllk to the defult hotrine diretory @the lst one on(guredA if not foundD efore giving upF he order of the registrtions is signi(nt in this seF

6.51 How to locate Files

he XnmespeXymfonygomponentpinder omponent helps you to (nd (les nd diretories quikly nd esilyF


6.51.1 Usage

he ymfonygomponentpinderpinder lss (nds (les ndGor diretoriesX

use Symfony\Component\Finder\Finder; $nder = new Finder(); $nder->les()->in(__DIR__); foreach ($nder as $le) { print $le->getRealpath()."\n"; }
he 6(le is n instne of XphplssXplpilesnfoF TFSIF row to lote piles SIQ

ymfony houmenttionD PFH he ove ode prints the nmes of ll the (les in the urrent diretory reursivelyF he pinder lss uses )uent interfeD so ll methods return the pinder instneF X e pinder instne is r stertorF oD insted of iterting over the pinder with forehD you n lso onvert it to n rry with the XphpfuntionXitertortorry methodD or get the numer of items with XphpfuntionXitertorountF

6.51.2 Criteria

votion he lotion is the only mndtory riteriF st tells the (nder whih diretory to use for the serhX

$nder->in(__DIR__);
erh in severl lotions y hining lls to XmethodXymfonygomponentpinderpinderXXinX

$nder->les()->in(__DIR__)->in('/elsewhere');
ixlude diretories from mthing with the XmethodXymfonygomponentpinderpinderXXexlude methodX

$nder->in(__DIR__)->exclude('ruby');
es the pinder uses r itertorsD you n pss ny v with supported protoolX

$nder->in('ftp://example.com/pub/');
end it lso works with userEde(ned stremsX

use Symfony\Component\Finder\Finder; $s3 = new \Zend_Service_Amazon_S3($key, $secret); $s3->registerStreamWrapper("s3"); $nder = new Finder(); $nder->name('photos*')->size('< 100K')->date('since 1 hour ago'); foreach ($nder->in('s3://bucket-name') as $le) { // do something } print $le->getFilename()."\n";

X ed the trems doumenttion to lern how to rete your own stremsF SIR TF

ymfony houmenttionD PFH

piles or hiretories fy defultD the pinder returns (les nd diretoriesY the XmethodXymfonygomponentpinderpinderXX(les XmethodXymfonygomponentpinderpinderXXdiretories methods ontrol thtX ut nd

$nder->les(); $nder->directories();
sf you wnt to follow linksD use the followvinks@A methodX

$nder->les()->followLinks();
fy defultD the itertor ignores populr g (lesF his n e hnged with the ignoreg@A methodX

$nder->ignoreVCS(false);
orting ort the result y nme or y type @diretories (rstD then (lesAX

$nder->sortByName(); $nder->sortByType();
X xotie tht the sortB methods need to get ll mthing elements to do their josF por lrge itertorsD it is slowF ou n lso de(ne your own sorting lgorithm with sort@A methodX

$sort = function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }; $nder->sort($sort);

TFSIF row to lote piles

SIS

ymfony houmenttionD PFH pile xme estrit (les y nme with the XmethodXymfonygomponentpinderpinderXXnme methodX

$nder->les()->name('*.php');
he nme@A method epts glosD stringsD or regexesX

$nder->les()->name('/\.php$/');
he notxmes@A method exludes (les mthing ptternX

$nder->les()->notName('*.rb');
pile ize estrit (les y size with the XmethodXymfonygomponentpinderpinderXXsize methodX

$nder->les()->size('< 1.5K');
estrit y size rnge y hining llsX

$nder->les()->size('>= 1K')->size('<= 2K');


he omprison opertor n e ny of the followingX bD baD `D `a9D aa9F he trget vlue my use mgnitudes of kiloytes @kD kiAD megytes @mD miAD or gigytes @gD giAF hose su0xed with n i use the pproprite PBBn version in ordne with the sig stndrdF pile hte estrit (les y lst modi(ed dtes with the XmethodXymfonygomponentpinderpinderXXdte methodX

$nder->date('since yesterday');
he omprison opertor n e ny of the followingX bD baD `D `a9D aa9F ou n lso use sine or fter s n lis for bD nd until or efore s n lis for `F he trget vlue n e ny dte supported y the strtotime funtionF

SIT

TF

ymfony houmenttionD PFH hiretory hepth fy defultD the pinder reursively trverse diretoriesF estrit the depth of trversing with XmethodXymfonygomponentpinderpinderXXdepthX

$nder->depth('== 0'); $nder->depth('< 3');


gustom piltering o restrit the mthing (le with your XmethodXymfonygomponentpinderpinderXX(lterX own strtegyD use

$lter = function (\SplFileInfo $le) { if (strlen($le) > 10) { return false; } }; $nder->les()->lter($lter);
he (lter@A method tkes glosure s n rgumentF por eh mthing (leD it is lled with the (le s XphplssXplpilesnfo instneF he (le is exluded from the result set if the glosure returns flseF

6.52 How to create Console/Command-Line Commands

ymfonyP ships with gonsole omponentD whih llows you to rete ommndEline ommndsF our onsole ommnds n e used for ny reurring tskD suh s ronjosD importsD or other th josF
6.52.1 Creating a basic Command

o mke the onsole ommnds ville utomtilly with ymfonyPD rete gommnd diretory inside your undle nd rete php (le su0xed with gommndFphp for eh ommnd tht you wnt to provideF por exmpleD if you wnt to extend the emehemofundle @ville in the ymfony tndrd iditionA to greet us from the ommnd lineD rete qreetgommndFphp nd dd the following to itX

// src/Acme/DemoBundle/Command/GreetCommand.php namespace Acme\DemoBundle\Command;


TFSPF row to rete gonsoleGgommndEvine gommnds SIU

ymfony houmenttionD PFH

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class GreetCommand extends ContainerAwareCommand { protected function congure() { $this ->setName('demo:greet') ->setDescription('Greet someone') ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?') ->addOption('yell', null, InputOption::VALUE_NONE, 'If set, the task will yell in uppercase letters') ; } protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('name'); if ($name) { $text = 'Hello '.$name; } else { $text = 'Hello'; } if ($input->getOption('yell')) { $text = strtoupper($text); } } $output->writeln($text);

est the new onsole ommnd y running the following

app/console demo:greet Fabien


his will print the following to the ommnd lineX

Hello Fabien
ou n lso use the EEyell option to mke everything upperseX

app/console demo:greet Fabien --yell


his printsX SIV TF

ymfony houmenttionD PFH

HELLO FABIEN
goloring the yutput henever you output textD you n surround the text with tgs to olor its outputF por exmpleX

// green text $output->writeln('<info>foo</info>'); // yellow text $output->writeln('<comment>foo</comment>'); // black text on a cyan background $output->writeln('<question>foo</question>'); // white text on a red background $output->writeln('<error>foo</error>');

6.52.2 Using Command Arguments

he most interesting prt of the ommnds re the rguments nd options tht you n mke villeF erguments re the strings E seprted y spes E tht ome fter the ommnd nme itselfF hey re orderedD nd n e optionl or requiredF por exmpleD dd n optionl lstnme rgument to the ommnd nd mke the nme rgument requiredX

$this // ... ->addArgument('name', InputArgument::REQUIRED, 'Who do you want to greet?') ->addArgument('last_name', InputArgument::OPTIONAL, 'Your last name?') // ...
ou now hve ess to lstnme rgument in your ommndX

if ($lastName = $input->getArgument('last_name')) { $text .= ' '.$lastName; }


he ommnd n now e used in either of the following wysX

app/console demo:greet Fabien app/console demo:greet Fabien Potencier

TFSPF row to rete gonsoleGgommndEvine gommnds

SIW

ymfony houmenttionD PFH


6.52.3 Using Command Options

nlike rgumentsD options re not ordered @mening you n speify them in ny orderA nd re spei(ed with two dshes @eFgF EEyell E you n lso delre oneEletter shortut tht you n ll with single dsh like EyAF yptions re lwys optionlD nd n e setup to ept vlue @eFgF dirasrA or simply s oolen )g without vlue @eFgF yellAF X st is lso possile to mke n option optionlly ept vlue @so tht EEyell or yellaloud workAF yptions n lso e on(gured to ept n rry of vluesF por exmpleD dd new option to the ommnd tht n e used to speify how mny times in row the messge should e printedX

$this // ... ->addOption('iterations', null, InputOption::VALUE_REQUIRED, 'How many times should the message be p
xextD use this in the ommnd to print the messge multiple timesX

for ($i = 0; $i < $input->getOption('iterations'); $i++) { $output->writeln($text); }


xowD when you run the tskD you n optionlly speify EEitertions )gX

app/console demo:greet Fabien app/console demo:greet Fabien --iterations=5


he (rst exmple will only print oneD sine itertions is empty nd defults to I @the lst rgument of ddyptionAF he seond exmple will print (ve timesF ell tht options don9t re out their orderF oD either of the following will workX

app/console demo:greet Fabien --iterations=5 --yell app/console demo:greet Fabien --yell --iterations=5

6.52.4 Asking the User for Information

hen reting ommndsD you hve the ility to ollet more informtion from the user y sking himGher questionsF por exmpleD suppose you wnt to on(rm n tion efore tully exeuting itF edd the following to your ommndX

$dialog = $this->getHelperSet()->get('dialog'); if (!$dialog->askConrmation($output, '<question>Continue with this action?</question>', false)) {

SPH

TF

ymfony houmenttionD PFH

return;

sn this seD the user will e sked gontinue with this tionD nd unless they nswer with yD the tsk will stop runningF he third rgument to skgon(rmtion is the defult vlue to return if the user doesn9t enter ny inputF ou n lso sk questions with more thn simple yesGno nswerF por exmpleD if you needed to know the nme of somethingD you might do the followingX

$dialog = $this->getHelperSet()->get('dialog'); $name = $dialog->ask($output, 'Please enter the name of the widget', 'foo');

6.52.5 Testing Commands

ymfonyP provides severl tools to help you test your ommndsF he most useful one is the ymfonygomponentgonsoleestergommndester lssF st uses speil input nd output lsses to ese testing without rel onsoleX

use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Console\Application; class ListCommandTest extends \PHPUnit_Framework_TestCase { public function testExecute() { // mock the Kernel or create one depending on your needs $application = new Application($kernel); $command = $application->nd('demo:greet'); $commandTester = new CommandTester($command); $commandTester->execute(array('command' => $command->getFullName())); $this->assertRegExp('/.../', $commandTester->getDisplay()); } // ...

he XmethodXymfonygomponentgonsoleestergommndesterXXgethisply method returns wht would hve een displyed during norml ll from the onsoleF X ou n lso test whole onsole ymfonygomponentgonsoleesterepplitionesterF pplition y using

TFSPF row to rete gonsoleGgommndEvine gommnds

SPI

ymfony houmenttionD PFH


6.52.6 Getting Services from the Service Container

fy using ymfonyfundleprmeworkfundlegommndgontinerewregommnd s the se lss for the ommnd @insted of the more si ymfonygomponentgonsolegommndgommndAD you hve ess to the servie ontinerF sn other wordsD you hve ess to ny on(gured servieF por exmpleD you ould esily extend the tsk to e trnsltleX

protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('name'); $translator = $this->getContainer()->get('translator'); if ($name) { $output->writeln($translator->trans('Hello %name%!', array('%name%' => $name))); } else { $output->writeln($translator->trans('Hello!')); } }

6.52.7 Calling an existing Command

sf ommnd depends on nother one eing run efore itD insted of sking the user to rememer the order of exeutionD you n ll it diretly yourselfF his is lso useful if you wnt to rete met ommnd tht just runs unh of other ommnds @for instneD ll ommnds tht need to e run when the projet9s ode hs hnged on the prodution serversX lering the heD generting hotrineP proxiesD dumping esseti ssetsD FFFAF glling ommnd from nother one is strightforwrdX

protected function execute(InputInterface $input, OutputInterface $output) { $command = $this->getApplication()->nd('demo:greet'); $arguments = array( 'command' => 'demo:greet', 'name' => 'Fabien', '--yell' => true, ); $input = new ArrayInput($arguments); $returnCode = $command->run($input, $output); } // ...

pirstD you XmethodXymfonygomponentgonsolegommndgommndXX(nd the SPP TF

ymfony houmenttionD PFH ommnd you wnt to exeute y pssing the ommnd nmeF henD you need to rete new ymfonygomponentgonsolesnputerrysnput with the rguments nd options you wnt to pss to the ommndF iventullyD lling the run@A method tully exeutes the ommnd nd returns the returned ode from the ommnd @H if everything went (neD ny other integer otherwiseAF X wost of the timeD lling ommnd from ode tht is not exeuted on the ommnd line is not good ide for severl resonsF pirstD the ommnd9s output is optimized for the onsoleF fut more importntD you n think of ommnd s eing like ontrollerY it should use the model to do something nd disply feedk to the userF oD insted of lling ommnd from the eD reftor your ode nd move the logi to new lssF

6.53 How

to

optimize

your

development

Environment

for

debugging

hen you work on ymfony projet on your lol mhineD you should use the dev environment @ppdevFphp front ontrollerAF his environment on(gurtion is optimized for two min purposesX

qive the developer urte feedk whenever something goes wrong @we deug toolrD nie exeption pgesD pro(lerD FFFAY fe s similr s possile s the prodution environment to void prolems when deploying the projetF
6.53.1 Disabling the Bootstrap File and Class Caching

end to mke the prodution environment s fst s possileD ymfony retes ig r (les in your he ontining the ggregtion of r lsses your projet needs for every requestF roweverD this ehvior n onfuse your shi or your deuggerF his reipe shows you how you n twek this hing mehnism to mke it friendlier when you need to deug ode tht involves ymfony lssesF he ppdevFphp front ontroller reds s follows y defultX

// ... require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../app/AppKernel.php';

TFSQF row to optimize your development invironment for deugging

SPQ

ymfony houmenttionD PFH

use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('dev', true); $kernel->loadClassCache(); $kernel->handle(Request::createFromGlobals())->send();


o mke you deugger hppierD disle ll r lss hes y removing the ll to lodglssghe@A nd y repling the require sttements like elowX

// ...

// require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; require_once __DIR__.'/../app/autoload.php'; require_once __DIR__.'/../app/AppKernel.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('dev', true); // $kernel->loadClassCache(); $kernel->handle(Request::createFromGlobals())->send();
X sf you disle the r hesD don9t forget to revert fter your deugging sessionF ome shis do not like the ft tht some lsses re stored in di'erent lotionsF o void prolemsD you n either tell your shi to ignore the r he (lesD or you n hnge the extension used y ymfony for these (lesX

$kernel->loadClassCache('classes', '.php.cache');

6.54 Monolog

wonolog r SFQ ymfonyPF vogfook ythonF


6.54.1

D @A E @loggerAF @A @ AF

SPR

TF

ymfony houmenttionD PFH X D E F tremrndlerD @E ppGlogsGprodFlog prodution ppGlogsGdevFlog E AF wonolog D E prodution X pingersgrossedrndlerF D E @iy A F D X

$logger = $this->get('logger'); $logger->info('We just got the logger'); $logger->err('An error occurred');
F F

ewv

monolog: handlers: syslog: type: stream path: /var/log/symfony.log level: error main: type: ngerscrossed action_level: warning handler: le le: type: stream level: debug
wv

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:monolog="http://symfony.com/schema/dic/monolog" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services


TFSRF wonolog SPS

ymfony houmenttionD PFH

http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/mon <monolog:cong> <monolog:handler name="syslog" type="stream" path="/var/log/symfony.log" level="error" /> <monolog:handler name="main" type="ngerscrossed" action-level="warning" handler="le" /> <monolog:handler name="le" type="stream" level="debug" /> </monolog:cong> </container>
D F X (le D E prodution F

X wonologfundle E D F D FF E F

pormtter D E F wonolog E E wonologpormttervinepormtterD E F wonologpormtterpormttersnterfeF

ewv
SPT TF

ymfony houmenttionD PFH

services: my_formatter: class: Monolog\Formatter\JsonFormatter monolog: handlers: le: type: stream level: debug formatter: my_formatter
wv

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:monolog="http://symfony.com/schema/dic/monolog" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/mon <services> <service id="my_formatter" class="Monolog\Formatter\JsonFormatter" /> </services> <monolog:cong> <monolog:handler name="le" type="stream" level="debug" formatter="my_formatter" /> </monolog:cong> </container>

6.54.2

wonolog F E F E F roessors re on(gured using the monologFproessor hsg tgF ee the referene out itF edding essionGequest oken ometimes it is hrd to tell whih entries in the log elong to whih session ndGor requestF he following exmple will dd unique token for eh request using proessorF TFSRF wonolog SPU

ymfony houmenttionD PFH

namespace Acme\MyBundle; use Symfony\Component\HttpFoundation\Session; class SessionRequestProcessor { private $session; private $token; public function __construct(Session $session) { $this->session = $session; } public function processRecord(array $record) { if (null === $this->token) { try { $this->token = substr($this->session->getId(), 0, 8); } catch (\RuntimeException $e) { $this->token = '????????'; } $this->token .= '-' . substr(uniqid(), -8); } $record['extra']['token'] = $this->token; } return $record;

ewv

services: monolog.formatter.session_request: class: Monolog\Formatter\LineFormatter arguments: - "[%%datetime%%] [%%extra.token%%] %%channel%%.%%level_name%%: %%message%%\n" monolog.processor.session_request: class: Acme\MyBundle\SessionRequestProcessor arguments: [ @session ] tags: - { name: monolog.processor, method: processRecord } monolog: handlers: main:
SPV TF

ymfony houmenttionD PFH

type: stream path: %kernel.logs_dir%/%kernel.environment%.log level: debug formatter: monolog.formatter.session_request


X sf you use severl hndlersD you n lso register the proessor t the hndler level insted of glollyF

6.55 How to extend a Class without using Inheritance

o llow multiple lsses to dd methods to nother oneD you n de(ne the mgi ll@A method in the lss you wnt to e extended like thisX

class Foo { // ... public function __call($method, $arguments) { // create an event named 'foo.method_is_not_found' $event = new HandleUndenedMethodEvent($this, $method, $arguments); $this->dispatcher->dispatch($this, 'foo.method_is_not_found', $event); // no listener was able to process the event? The method does not exist if (!$event->isProcessed()) { throw new \Exception(sprintf('Call to undened method %s::%s.', get_class($this), $method)); } // return the listener returned value return $event->getReturnValue();

his uses speil rndlende(nedwethodivent tht should lso e retedF his is generi lss tht ould e reused eh time you need to use this pttern of lss extensionX

use Symfony\Component\EventDispatcher\Event; class HandleUndenedMethodEvent extends Event { protected $subject; protected $method; protected $arguments; protected $returnValue;
TFSSF row to extend glss without using snheritne SPW

ymfony houmenttionD PFH

protected $isProcessed = false; public function __construct($subject, $method, $arguments) { $this->subject = $subject; $this->method = $method; $this->arguments = $arguments; } public function getSubject() { return $this->subject; } public function getMethod() { return $this->method; } public function getArguments() { return $this->arguments; } /** * Sets the value to return and stops other listeners from being notied */ public function setReturnValue($val) { $this->returnValue = $val; $this->isProcessed = true; $this->stopPropagation(); } public function getReturnValue($val) { return $this->returnValue; } public function isProcessed() { return $this->isProcessed; }

xextD rete lss tht will listen to the fooFmethodisnotfound event nd dd the method r@AX SQH TF

ymfony houmenttionD PFH

class Bar { public function onFooMethodIsNotFound(HandleUndenedMethodEvent $event) { // we only want to respond to the calls to the 'bar' method if ('bar' != $event->getMethod()) { // allow another listener to take care of this unknown method return; } // the subject object (the foo instance) $foo = $event->getSubject(); // the bar method arguments $arguments = $event->getArguments(); // do something // ... // set the return value $event->setReturnValue($someValue);

pinllyD dd the new r method to the poo lss y register n instne of fr with the fooFmethodisnotfound eventX

$bar = new Bar(); $dispatcher->addListener('foo.method_is_not_found', $bar);

6.56 How

to

customize

Method

Behavior

without

using

Inheritance
6.56.1 Doing something before or after a Method Call

sf you wnt to do something just eforeD or just fter method is lledD you n dispth n event respetively t the eginning or t the end of the methodX

class Foo { // ... public function send($foo, $bar) {


TFSTF row to ustomize wethod fehvior without using snheritne SQI

ymfony houmenttionD PFH

// do something before the method $event = new FilterBeforeSendEvent($foo, $bar); $this->dispatcher->dispatch('foo.pre_send', $event); // get $foo and $bar from the event, they may have been modied $foo = $event->getFoo(); $bar = $event->getBar(); // the real method implementation is here // $ret = ...; // do something after the method $event = new FilterSendReturnValue($ret); $this->dispatcher->dispatch('foo.post_send', $event); } return $event->getReturnValue();

sn this exmpleD two events re thrownX fooFpresendD efore the method is exeutedD nd fooFpostsend fter the method is exeutedF ih uses ustom ivent lss to ommunite informtion to the listeners of the two eventsF hese event lsses would need to e reted y you nd should llowD in this exmpleD the vriles 6fooD 6r nd 6ret to e retrieved nd set y the listenersF por exmpleD ssuming the pilterendeturnlue hs seteturnlue methodD one listener might look like thisX

public function onFooPostSend(FilterSendReturnValue $event) { $ret = $event->getReturnValue(); // modify the original ``$ret`` value } $event->setReturnValue($ret);

6.57 How to register a new Request Format and Mime Type

ivery equest hs formt @eFgF htmlD jsonAD whih is used to determine wht type of ontent to return in the esponseF sn ftD the request formtD essile vi XmethodXymfonygomponentrttppoundtionequestXXgetequestpormtD is used to set the wswi type of the gontentEype heder on the esponse ojetF snternllyD ymfony ontins mp of the most ommon formts @eFgF htmlD jsonA nd their ssoited wswi types @eFgF textGhtmlD pplitionGjsonAF yf ourseD dditionl formtEwswi type entries n esily e ddedF his doument will show how you n dd the jsonp formt nd SQP TF

ymfony houmenttionD PFH orresponding wswi typeF


6.57.1 Create an kernel.request Listener

he key to de(ning new wswi type is to rete lss tht will listen to the kernelFrequest event dispthed y the ymfony kernelF he kernelFrequest event is dispthed erly in ymfony9s request hndling proess nd llows you to modify the request ojetF grete the following lssD repling the pth with pth to undle in your projetX

// src/Acme/DemoBundle/RequestListener.php namespace Acme\DemoBundle; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; class RequestListener { public function onKernelRequest(GetResponseEvent $event) { $event->getRequest()->setFormat('jsonp', 'application/javascript'); } }

6.57.2 Registering your Listener

es for ny other listenerD you need to dd it in one of your on(gurtion (le nd register it s listener y dding the kernelFeventlistener tgX

wv

<!-- app/cong/cong.xml --> <?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services <service id="acme.demobundle.listener.request" class="Acme\DemoBundle\RequestListener"> <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" /> </service> </container>
ewv

TFSUF row to register new equest pormt nd wime ype

SQQ

ymfony houmenttionD PFH

# app/cong/cong.yml services: acme.demobundle.listener.request: class: Acme\DemoBundle\RequestListener tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
r

# app/cong/cong.php $denition = new Denition('Acme\DemoBundle\RequestListener'); $denition->addTag('kernel.event_listener', array('event' => 'kernel.request', 'method' => 'onKernelRequ $container->setDenition('acme.demobundle.listener.request', $denition);
et this pointD the meFdemoundleFlistenerFrequest servie hs een on(gured nd will e noti(ed when the ymfony kernel dispthes the kernelFrequest eventF X ou n lso register the listener in on(gurtion extension lss @see smporting gon(gurtion vi gontiner ixtensions for more informtionAF

6.58 How to create a custom Data Collector

he ymfonyP ro(ler delegtes dt olleting to dt olletorsF ymfonyP omes undled with few of themD ut you n esily rete your ownF
6.58.1 Creating a Custom Data Collector

greting ustom dt olletor is s simple s implementing ymfonygomponentrttpuernelhtgolletorhtgolletorsnterfeX

the

interface DataCollectorInterface { /** * Collects data for the given Request and Response. * * @param Request $request A Request instance * @param Response $response A Response instance * @param \Exception $exception An Exception instance */ function collect(Request $request, Response $response, \Exception $exception = null); /** * Returns the name of the collector.
SQR TF

ymfony houmenttionD PFH

* * @return string The collector name */ function getName();

he getxme@A method must return unique nmeF his is used to ess the informtion lter on @see row to use the ro(ler in puntionl est for instneAF he ollet@A method is responsile for storing the dt it wnts to give ess to in lol propertiesF X es the pro(ler serilizes dt olletor instnesD you should not store ojets tht nnot e serilized @like hy ojetsAD or you need to provide your own serilize@A methodF

wost of the timeD it is onvenient to extend ymfonygomponentrttpuernelhtgolletorhtgolletor nd populte the 6thisEbdt property @it tkes re of serilizing the 6thisEbdt propertyAX

class MemoryDataCollector extends DataCollector { public function collect(Request $request, Response $response, \Exception $exception = null) { $this->data = array( 'memory' => memory_get_peak_usage(true), ); } public function getMemory() { return $this->data['memory']; } public function getName() { return 'memory'; }

6.58.2 Enabling Custom Data Collectors

o enle dt olletorD dd it s regulr servie in one of your on(gurtionD nd tg it with dtolletorX

ewv

TFSVF row to rete ustom ht golletor

SQS

ymfony houmenttionD PFH

services: data_collector.your_collector_name: class: Fully\Qualied\Collector\Class\Name tags: - { name: data_collector }


wv

<service id="data_collector.your_collector_name" class="Fully\Qualied\Collector\Class\Name"> <tag name="data_collector" /> </service>


r

$container ->register('data_collector.your_collector_name', 'Fully\Qualied\Collector\Class\Name') ->addTag('data_collector') ;

6.58.3 Adding Web Proler Templates

hen you wnt to disply the dt olleted y your ht golletor in the we deug toolr or the we pro(lerD rete wig templte following this skeletonX

{% extends 'WebProlerBundle:Proler:layout.html.twig' %} {% block toolbar %} {# the web debug toolbar content #} {% endblock %} {% block head %} {# if the web proler panel needs some specic JS or CSS les #} {% endblock %} {% block menu %} {# the menu content #} {% endblock %} {% block panel %} {# the panel content #} {% endblock %}
ih lok is optionlF he toolr lok is used for the we deug toolr nd menu nd pnel re used to dd pnel to the we pro(lerF ell loks hve ess to the olletor ojetF SQT TF

ymfony houmenttionD PFH X fuiltEin templtes use seTR enoded imge for the toolr @`img sra4sra4dtXimgeGpngYseTRDFFF4AF ou n esily lulte the seTR vlue for n imge with this little sriptX eho seTRenode@(legetontents@6ii9rgv9IAAYF o enle the templteD dd templte ttriute to the dtolletor tg in your on(gurtionF por exmpleD ssuming your templte is in some emeheugfundleX

ewv

services: data_collector.your_collector_name: class: Acme\DebugBundle\Collector\Class\Name tags: - { name: data_collector, template: "AcmeDebug:Collector:templatename", id: "your_collector_n
wv

<service id="data_collector.your_collector_name" class="Acme\DebugBundle\Collector\Class\Name"> <tag name="data_collector" template="AcmeDebug:Collector:templatename" id="your_collector_nam </service>


r

$container ->register('data_collector.your_collector_name', 'Acme\DebugBundle\Collector\Class\Name') ->addTag('data_collector', array('template' => 'AcmeDebugBundle:Collector:templatename', 'id' => 'y ;

6.59 How to Create a SOAP Web Service in a Symfony2 Controller

etting up ontroller to t s ye server is simple with ouple toolsF ou mustD of ourseD hve the r ye extension instlledF es the r ye extension n not urrently generte hvD you must either rete one from srth or use Qrd prty genertorF X here re severl ye server implementtions ville for use with rF end ye nd xuye re two exmplesF elthough we use the r ye extension in our exmplesD the generl ide should still e pplile to other implementtionsF ye works y exposing the methods of r ojet to n externl entity @iFeF the person using the ye servieAF o strtD rete lss E relloervie E whih represents the funtionlity tht you9ll expose in your ye servieF sn this seD the ye servie will llow the lient to ll method lled helloD whih hppens to send n emil ddressX TFSWF row to grete ye e ervie in ymfonyP gontroller SQU

ymfony houmenttionD PFH

namespace Acme\SoapBundle; class HelloService { private $mailer; public function __construct(\Swift_Mailer $mailer) { $this->mailer = $mailer; } public function hello($name) { $message = \Swift_Message::newInstance() ->setTo('me@example.com') ->setSubject('Hello Service') ->setBody($name . ' says hi!'); $this->mailer->send($message); return 'Hello, ' . $name;

} }

xextD you n trin ymfony to e le to rete n instne of this lssF ine the lss sends n eEmilD it9s een designed to ept wiftwiler instneF sing the ervie gontinerD we n on(gure ymfony to onstrut relloervie ojet properlyX

ewv

# app/cong/cong.yml services: hello_service: class: Acme\DemoBundle\Services\HelloService arguments: [mailer]


wv

<!-- app/cong/cong.xml --> <services> <service id="hello_service" class="Acme\DemoBundle\Services\HelloService"> <argument>mailer</argument> </service> </services>

SQV

TF

ymfony houmenttionD PFH felow is n exmple of ontroller tht is ple of hndling ye requestF sf indexetion@A is essile vi the route GsopD then the hv doument n e retrieved vi GsopcwsdlF

namespace Acme\SoapBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class HelloServiceController extends Controller { public function indexAction() { $server = new \SoapServer('/path/to/hello.wsdl'); $server->setObject($this->get('hello_service')); $response = new Response(); $response->headers->set('Content-Type', 'text/xml; charset=ISO-8859-1'); ob_start(); $server->handle(); $response->setContent(ob_get_clean()); } return $response;

ke note of the lls to ostrt@A nd ogetlen@AF hese methods ontrol output u'ering whih llows you to trp the ehoed output of 6serverEbhndle@AF his is neessry euse ymfony expets your ontroller to return esponse ojet with the output s its ontentF ou must lso rememer to set the gontentEype heder to textGxmlD s this is wht the lient will expetF oD you use ostrt@A to strt u'ering the hy nd use ogetlen@A to dump the ehoed output into the ontent of the esponse nd ler the output u'erF pinllyD you9re redy to return the esponseF felow is n exmple lling the servie using xuye lientF his exmple ssumes the indexetion in the ontroller ove is essile vi the route GsopX

$client = new \soapclient('http://example.com/app.php/soap?wsdl', true); $result = $client->call('hello', array('name' => 'Scott'));


en exmple hv is elowF

<?xml version="1.0" encoding="ISO-8859-1"?> <denitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"


TFSWF row to grete ye e ervie in ymfonyP gontroller SQW

ymfony houmenttionD PFH

xmlns:tns="urn:arnleadservicewsdl" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="urn:helloservicewsdl"> <types> <xsd:schema targetNamespace="urn:hellowsdl"> <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" /> <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" /> </xsd:schema> </types> <message name="helloRequest"> <part name="name" type="xsd:string" /> </message> <message name="helloResponse"> <part name="return" type="xsd:string" /> </message> <portType name="hellowsdlPortType"> <operation name="hello"> <documentation>Hello World</documentation> <input message="tns:helloRequest"/> <output message="tns:helloResponse"/> </operation> </portType> <binding name="hellowsdlBinding" type="tns:hellowsdlPortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="hello"> <soap:operation soapAction="urn:arnleadservicewsdl#hello" style="rpc"/> <input> <soap:body use="encoded" namespace="urn:hellowsdl" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="urn:hellowsdl" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="hellowsdl"> <port name="hellowsdlPort" binding="tns:hellowsdlBinding"> <soap:address location="http://example.com/app.php/soap" /> </port> </service> </denitions>

SRH

TF

ymfony houmenttionD PFH

6.60 Symfony2 symfony 1

he ymfonyP frmework emodies signi(nt evolution when ompred with the (rst version of the frmeworkF portuntelyD with the wg rhiteture t its oreD the skills used to mster symfonyI projet ontinue to e very relevnt when developing in ymfonyPF ureD ppFyml is goneD ut routingD ontrollers nd templtes ll reminF sn this hpterD we9ll wlk through the di'erenes etween symfonyI nd ymfonyPF es you9ll seeD mny tsks re tkled in slightly di'erent wyF ou9ll ome to ppreite these minor di'erenes s they promote stleD preditleD testle nd deoupled ode in your ymfonyP pplitionsF oD sit k nd relx s we tke you from then to nowF
6.60.1 Directory Structure

hen looking t ymfonyP projet E for exmpleD the ymfonyP tndrd E you9ll notie very di'erent diretory struture thn in symfonyIF he di'erenesD howeverD re somewht super(ilF he ppG hiretory sn symfonyID your projet hs one or more pplitionsD nd eh lives inside the ppsG diretory @eFgF ppsGfrontendAF fy defult in ymfonyPD you hve just one pplition represented y the ppG diretoryF vike in symfonyID the ppG diretory ontins on(gurtion spei( to tht pplitionF st lso ontins pplitionEspei( heD log nd templte diretories s well s uernel lss @eppuernelAD whih is the se ojet tht represents the pplitionF nlike symfonyID lmost no r ode lives in the ppG diretoryF his diretory is not ment to house modules or lirry (les s it did in symfonyIF snstedD it9s simply the home of on(gurtion nd other resoures @templtesD trnsltion (lesAF he srG hiretory ut simplyD your tul ode goes hereF sn ymfonyPD ll tul pplitionEode lives inside undle @roughly equivlent to symfonyI pluginA ndD y defultD eh undle lives inside the sr diretoryF sn tht wyD the sr diretory is it like the plugins diretory in symfonyID ut muh more )exileF edditionllyD while your undles will live in the srG diretoryD thirdE prty undles my live in the vendorGundlesG diretoryF o get etter piture of the srG diretoryD let9s (rst think of symfonyI pplitionF pirstD prt of your ode likely lives inside one or more pplitionsF wost ommonly these inlude modulesD ut ould lso inlude ny other r lsses you put in your pplitionF ou TFTHF ymfonyP symfony I SRI

ymfony houmenttionD PFH my hve lso reted shemFyml (le in the on(g diretory of your projet nd uilt severl model (lesF pinllyD to help with some ommon funtionlityD you9re using severl thirdEprty plugins tht live in the pluginsG diretoryF sn other wordsD the ode tht drives your pplition lives in mny di'erent plesF sn ymfonyPD life is muh simpler euse ll ymfonyP ode must live in undleF sn our pretend symfonyI projetD ll the ode ould e moved into one or more plugins @whih is very good prtieD in ftAF essuming tht ll modulesD r lssesD shemD routing on(gurtionD et were moved into pluginD the symfonyI pluginsG diretory would e very similr to the ymfonyP srG diretoryF ut simply ginD the srG diretory is where your odeD ssetsD templtes nd most nything else spei( to your projet will liveF he vendorG hiretory he vendorG diretory is silly equivlent to the liGvendorG diretory in symfonyID whih ws the onventionl diretory for ll vendor lirries nd undlesF fy defultD you9ll (nd the ymfonyP lirry (les in this diretoryD long with severl other dependent lirries suh s hotrinePD wig nd wiftmilerF Qrd prty ymfonyP undles usully live in the vendorGundlesGF he weG hiretory xot muh hs hnged in the weG diretoryF he most notiele di'erene is the sene of the ssGD jsG nd imgesG diretoriesF his is intentionlF vike with your r odeD ll ssets should lso live inside undleF ith the help of onsole ommndD the esouresGpuliG diretory of eh undle is opied or symolillyElinked to the weGundlesG diretoryF his llows you to keep ssets orgnized inside your undleD ut still mke them ville to the puliF o mke sure tht ll undles re villeD run the following ommndX

php app/console assets:install web


X his ommnd is the ymfonyP equivlent to the symfonyI pluginXpulishE ssets ommndF

6.60.2 Autoloading

yne of the dvntges of modern frmeworks is never needing to worry out requiring (lesF fy mking use of n utoloderD you n refer to ny lss in your projet nd trust tht it9s villeF eutoloding hs hnged in ymfonyP to e more universlD fsterD nd independent of needing to ler your heF SRP TF

ymfony houmenttionD PFH sn symfonyID utoloding ws done y serhing the entire projet for the presene of r lss (les nd hing this informtion in gint rryF ht rry told symfonyI extly whih (le ontined eh lssF sn the prodution environmentD this used you to need to ler the he when lsses were dded or movedF sn ymfonyPD new lss E niverslglssvoder E hndles this proessF he ide ehind the utoloder is simpleX the nme of your lss @inluding the nmespeA must mth up with the pth to the (le ontining tht lssF ke the prmeworkixtrfundle from the ymfonyP tndrd idition s n exmpleX

namespace Sensio\Bundle\FrameworkExtraBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; // ... class SensioFrameworkExtraBundle extends Bundle { // ...

he (le itself lives t vendorGundleGensioGfundleGprmeworkixtrfundleGensioprmeworkixtrfundl es you n seeD the lotion of the (le follows the nmespe of the lssF pei(llyD the nmespeD ensiofundleprmeworkixtrfundleD spells out the diretory tht the (le should live in @vendorGundleGensioGfundleGprmeworkixtrfundleAF his is euseD in the ppGutolodFphp (leD you9ll on(gure ymfony to look for the ensio nmespe in the vendorGundle diretoryX

// app/autoload.php // ... $loader->registerNamespaces(array( // ... 'Sensio' => __DIR__.'/../vendor/bundles', ));


sf the (le did not live t this ext lotionD you9d reeive glss 4ensiofundleprmeworkixtrfundleensioprmeworkixtrfundle4does not existF errorF sn ymfonyPD lss does not exist mens tht the suspet lss nmespe nd physil lotion do not mthF fsillyD ymfonyP is looking in one ext lotion for tht lssD ut tht lotion doesn9t exist @or ontins di'erent lssAF sn order for lss to e utolodedD you never need to ler your he in ymfonyPF es mentioned eforeD for the utoloder to workD it needs to know tht the ensio nmespe lives in the vendorGundles diretory nd thtD for exmpleD the hotrine nmespe lives in the vendorGdotrineGliG diretoryF his mpping is entirely ontrolled y you vi the ppGutolodFphp (leF sf you look t the rellogontroller from the ymfonyP tndrd idition you n see tht it lives in the emehemofundlegontroller nmespeF etD the eme nmespe is not TFTHF ymfonyP symfony I SRQ

ymfony houmenttionD PFH de(ned in the ppGutolodFphpF fy defult you do not need to expliitly on(gure the lotion of undles tht live in the srG diretoryF he niverslglssvoder is on(gured to fllk to the srG diretory using its registerxmespepllks methodX

// app/autoload.php // ... $loader->registerNamespaceFallbacks(array( __DIR__.'/../src', ));

6.60.3 Using the Console

sn symfonyID the onsole is in the root diretory of your projet nd is lled symfonyX

php symfony
sn ymfonyPD the onsole is now in the pp suEdiretory nd is lled onsoleX

php app/console

6.60.4 Applications

sn symfonyI projetD it is ommon to hve severl pplitionsX one for the frontend nd one for the kend for instneF sn ymfonyP projetD you only need to rete one pplition @ log pplitionD n intrnet pplitionD FFFAF wost of the timeD if you wnt to rete seond pplitionD you might insted rete nother projet nd shre some undles etween themF end if you need to seprte the frontend nd the kend fetures of some undlesD you n rete suEnmespes for ontrollersD suEdiretories for templtesD di'erent semnti on(gurtionsD seprte routing on(gurtionsD nd so onF yf ourseD there9s nothing wrong with hving multiple pplitions in your projetD tht9s entirely up to youF e seond pplition would men new diretoryD eFgF myppGD with the sme si setup s the ppG diretoryF X D F

SRR

TF

ymfony houmenttionD PFH


6.60.5 Bundles and Plugins

sn symfonyI projetD plugin ould ontin on(gurtionD modulesD r lirriesD ssets nd nything else relted to your projetF sn ymfonyPD the ide of plugin is repled y the undleF e undle is even more powerful thn plugin euse the ore ymfonyP frmework is rought in vi series of undlesF sn ymfonyPD undles re (rstElss itizens tht re so )exile tht even ore ode itself is undleF sn symfonyID plugin must e enled inside the rojetgon(gurtion lssX

// cong/ProjectConguration.class.php public function setup() { $this->enableAllPluginsExcept(array(/* some plugins here */)); }


sn ymfonyPD the undles re tivted inside the pplition kernelX

// app/AppKernel.php public function registerBundles() { $bundles = array( new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), // ... new Acme\DemoBundle\AcmeDemoBundle(), ); } return $bundles;

outing @routingFymlA nd gon(gurtion @on(gFymlA sn symfonyID the routingFyml nd ppFyml on(gurtion (les were utomtilly loded inside ny pluginF sn ymfonyPD routing nd pplition on(gurtion inside undle must e inluded mnullyF por exmpleD to inlude routing resoure from undle lled emehemofundleD you n do the followingX

# app/cong/routing.yml _hello: resource: "@AcmeDemoBundle/Resources/cong/routing.yml"


his will lod the routes found in the esouresGon(gGroutingFyml (le of the emehemofundleF he speil demehemofundle is shortut syntx thtD internllyD resolves to the full pth to tht undleF ou n use this sme strtegy to ring in on(gurtion from undleX TFTHF ymfonyP symfony I SRS

ymfony houmenttionD PFH

# app/cong/cong.yml imports: - { resource: "@AcmeDemoBundle/Resources/cong/cong.yml" }


sn ymfonyPD on(gurtion is it like ppFyml in symfonyID exept muh more systemtiF ith ppFymlD you ould simply rete ny keys you wntedF fy defultD these entries were meningless nd depended entirely on how you used them in your pplitionX

# some app.yml le from symfony1 all: email: from_address: foo.bar@example.com


sn ymfonyPD you n lso rete ritrry entries under the prmeters key of your on(gurtionX

parameters: email.from_address: foo.bar@example.com


ou n now ess this from ontrollerD for exmpleX

public function helloAction($name) { $fromAddress = $this->container->getParameter('email.from_address'); }


sn relityD the ymfonyP on(gurtion is muh more powerful nd is used primrily to on(gure ojets tht you n useF por more informtionD see the hpter titled ervie gontinerF

ork)ow
! row to grete nd store ymfonyP rojet in git

gontrollers
! ! row to de(ne gontrollers s ervies

outing
! row to fore routes to lwys use r ! row to llow G hrter in route prmeter

rndling tvript nd g essets


! row to se esseti for esset wngement ! row to winify tvripts nd tylesheets with s gompressor ! row to se esseti por smge yptimiztion with wig puntions SRT TF

ymfony houmenttionD PFH ! row to epply n esseti pilter to pei( pile ixtension

htse sntertion @hotrineA


! row to hndle pile plods with hotrine ! hotrine ixtensionsX imestmpleX luggleD rnsltleD etF ! egistering ivent visteners nd usriers ! row to use hotrine9s hfev vyer ! row to generte intities from n ixisting htse ! row to work with wultiple intity wngers ! egistering gustom hv puntions

porms nd lidtion
! row to ustomize porm endering ! row to grete gustom porm pield ype ! row to rete gustom lidtion gonstrint ! @dotrineA row to hndle pile plods with hotrine

gon(gurtion nd the ervie gontiner


! row to wster nd grete new invironments ! row to et ixternl rmeters in the ervie gontiner ! row to se ptory to grete ervies ! row to wnge gommon hependenies with rent ervies ! row to work with opes ! row to use doessiontorge to store essions in the htse

fundles
! fundle truture nd fest rties ! row to use fundle snheritne to yverride prts of fundle ! row to expose emnti gon(gurtion for fundle

imiling
! ! qmil ! row to ork with imils huring hevelopment ! row to pool imil TFTHF ymfonyP symfony I SRU

ymfony houmenttionD PFH

esting
! row to simulte r euthentition in puntionl est ! row to test the sntertion of severl glients ! row to use the ro(ler in puntionl est ! row to test hotrine epositories

eurity
! row to dd ememer we vogin puntionlity ! row to implement your own oter to lklist s eddresses ! eess gontrol vists @egvsA ! edvned egv gonepts ! row to fore r or r for hi'erent vs ! row to ustomize your porm vogin ! row to seure ny ervie or wethod in your epplition ! row to lod eurity sers from the htse @the entity roviderA ! row to rete ustom ser rovider ! row to rete ustom euthentition rovider ! row to hnge the hefult rget th fehvior

ghing
! row to use rnish to speedup my esite

emplting
! row to use r insted of wig for empltes

oolsD vogging nd snternls


! row to utolod glsses ! row to lote piles ! row to rete gonsoleGgommndEvine gommnds ! row to optimize your development invironment for deugging ! wonolog

e ervies
! row to grete ye e ervie in ymfonyP gontroller

ixtending ymfony
SRV TF

ymfony houmenttionD PFH ! row to extend glss without using snheritne ! row to ustomize wethod fehvior without using snheritne ! row to register new equest pormt nd wime ype ! row to rete ustom ht golletor

ymfonyP for symfonyI sers


! ymfonyP symfony I

ork)ow
! row to grete nd store ymfonyP rojet in git

gontrollers
! ! row to de(ne gontrollers s ervies

outing
! row to fore routes to lwys use r ! row to llow G hrter in route prmeter

rndling tvript nd g essets


! row to se esseti for esset wngement ! row to winify tvripts nd tylesheets with s gompressor ! row to se esseti por smge yptimiztion with wig puntions ! row to epply n esseti pilter to pei( pile ixtension

htse sntertion @hotrineA


! row to hndle pile plods with hotrine ! hotrine ixtensionsX imestmpleX luggleD rnsltleD etF ! egistering ivent visteners nd usriers ! row to use hotrine9s hfev vyer ! row to generte intities from n ixisting htse ! row to work with wultiple intity wngers ! egistering gustom hv puntions

porms nd lidtion
! row to ustomize porm endering ! row to grete gustom porm pield ype TFTHF ymfonyP symfony I SRW

ymfony houmenttionD PFH ! row to rete gustom lidtion gonstrint ! @dotrineA row to hndle pile plods with hotrine

gon(gurtion nd the ervie gontiner


! row to wster nd grete new invironments ! row to et ixternl rmeters in the ervie gontiner ! row to se ptory to grete ervies ! row to wnge gommon hependenies with rent ervies ! row to work with opes ! row to use doessiontorge to store essions in the htse

fundles
! fundle truture nd fest rties ! row to use fundle snheritne to yverride prts of fundle ! row to expose emnti gon(gurtion for fundle

imiling
! ! qmil ! row to ork with imils huring hevelopment ! row to pool imil

esting
! row to simulte r euthentition in puntionl est ! row to test the sntertion of severl glients ! row to use the ro(ler in puntionl est ! row to test hotrine epositories

eurity
! row to dd ememer we vogin puntionlity ! row to implement your own oter to lklist s eddresses ! eess gontrol vists @egvsA ! edvned egv gonepts ! row to fore r or r for hi'erent vs ! row to ustomize your porm vogin SSH TF

ymfony houmenttionD PFH ! row to seure ny ervie or wethod in your epplition ! row to lod eurity sers from the htse @the entity roviderA ! row to rete ustom ser rovider ! row to rete ustom euthentition rovider ! row to hnge the hefult rget th fehvior

ghing
! row to use rnish to speedup my esite

emplting
! row to use r insted of wig for empltes

oolsD vogging nd snternls


! row to utolod glsses ! row to lote piles ! row to rete gonsoleGgommndEvine gommnds ! row to optimize your development invironment for deugging ! wonolog

e ervies
! row to grete ye e ervie in ymfonyP gontroller

ixtending ymfony
! row to extend glss without using snheritne ! row to ustomize wethod fehvior without using snheritne ! row to register new equest pormt nd wime ype ! row to rete ustom ht golletor

ymfonyP for symfonyI sers


! ymfonyP symfony I

TFTHF ymfonyP symfony I

SSI

ymfony houmenttionD PFH

SSP

TF

IV

SSQ

ymfony houmenttionD PFH X

SSS

ymfony houmenttionD PFH

SST

Reference Documents

7.1 FrameworkBundle Conguration (framework)

his referene doument is work in progressF st should e urteD ut ll options re not yet fully overedF he prmeworkfundle ontins most of the se frmework funtionlity nd n e on(gured under the frmework key in your pplition on(gurtionF his inludes settings relted to sessionsD trnsltionD formsD vlidtionD routing nd moreF
7.1.1 Conguration

hrset seret ide test form


! enled

srfprotetion
! enled ! (eldnme

session
! lifetime

templting
SSU

ymfony houmenttionD PFH ! ssetsseurls ! ssetsversion ! ssetsversionformt hrset typeX string defultX pEV he hrter set tht9s used throughout the frmeworkF st eomes the servie ontiner prmeter nmed kernelFhrsetF seret typeX string required his is string tht should e unique to your pplitionF sn prtieD it9s used for generting the gp tokensD ut it ould e used in ny other ontext where hving unique string is usefulF st eomes the servie ontiner prmeter nmed kernelFseretF ide typeX string defultX null sf you9re using n shi like extwte or w imD then ymfony n turn ll of the (le pths in n exeption messge into linkD whih will open tht (le in your shiF sf you use extwte or w imD you n simply use one of the following uiltEin vluesX

textmte mvim
ou n lso speify ustom (le link stringF sf you do thisD ll perentge signs @7A must e douled to espe tht hrterF por exmpleD the full extwte string would look like thisX

framework: ide: "txmt://open?url=le://%%f&line=%%l"


yf ourseD sine every developer uses di'erent shiD it9s etter to set this on system levelF his n e done y setting the xdeugF(lelinkformt rFini vlue to the (le link stringF sf this on(gurtion vlue is setD then the ide option does not need to e spei(edF

SSV

UF eferene houments

ymfony houmenttionD PFH test typeX foolen sf this on(gurtion prmeter is presentD then the servies relted to testing your pplition re lodedF his setting should e present in your test environment @usully vi ppGon(gGon(gtestFymlAF por more informtionD see F form

csrf_protection
session

lifetime
typeX integer defultX VTRHH his determines the lifetime of the session E in seondsF templting

assets_base_urls
defultX { httpX D httpsX } his option llows you to de(ne se v9s to e used for ssets referened from http nd https pgesF e string vlue my e provided in lieu of singleEelement rryF sf multiple se v9s re providedD ymfonyP will selet one from the olletion eh time it genertes n sset9s pthF por your onvenieneD ssetsseurls n e set diretly with string or rry of stringsD whih will e utomtilly orgnized into olletions of se v9s for http nd https requestsF sf v strts with httpsXGG or is protoolEreltive @iFeF strts with GGA it will e dded to oth olletionsF v9s strting with httpXGG will only e dded to the http olletionF PFIF

assets_version
typeX string his option is used to ust the he on ssets y glolly dding query prmeter to ll rendered sset pths @eFgF GimgesGlogoFpngcvPAF his pplies only to ssets rendered vi the wig sset funtion @or r equivlentA s well s ssets rendered with essetiF UFIF prmeworkfundle gon(gurtion @frmeworkA SSW

ymfony houmenttionD PFH por exmpleD suppose you hve the followingX

wig

<img src="{{ asset('images/logo.png') }}" alt="Symfony!" />


r

<img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" alt="Symfony!" />


fy defultD this will render pth to your imge suh s GimgesGlogoFpngF xowD tivte the ssetsversion optionX

ewv

# app/cong/cong.yml framework: # ... templating: { engines: ['twig'], assets_version: v2 }


wv

<!-- app/cong/cong.xml --> <framework:templating assets-version="v2"> <framework:engine id="twig" /> </framework:templating>


r

// app/cong/cong.php $container->loadFromExtension('framework', array( // ... 'templating' => array( 'engines' => array('twig'), 'assets_version' => 'v2', ), ));
xowD the sme sset will e rendered s GimgesGlogoFpngcvP sf you use this fetureD you must mnully inrement the ssetsversion vlue efore eh deployment so tht the query prmeters hngeF ou n lso ontrol how the query string works vi the ssetsversionformt optionF

assets_version_format
typeX string defultX 77sc77s

STH

UF eferene houments

ymfony houmenttionD PFH his spei(es sprintf@A pttern tht will e used with the ssetsversion option to onstrut n sset9s pthF fy defultD the pttern dds the sset9s version s query stringF por exmpleD if ssetsversionformt is set to 77scversiona77s nd ssetsversion is set to SD the sset9s pth would e GimgesGlogoFpngcversionaSF X ell perentge signs @7A in the formt string must e douled to espe the hrterF ithout espingD vlues might indvertently e interpretted s ervie rmetersF

X ome ghx9s do not support heEusting vi query stringsD so injeting the version into the tul (le pth is neessryF hnkfullyD ssetsversionformt is not limited to produing versioned query stringsF he pttern reeives the sset9s originl pth nd version s its (rst nd seond prmetersD respetivelyF ine the sset9s pth is one prmeterD we nnot modify it inEple @eFgF GimgesGlogoEvSFpngAY howeverD we n pre(x the sset9s pth using pttern of versionE 77P6sG77I6sD whih would result in the pth versionESGimgesGlogoFpngF v rewrite rules ould then e used to disregrd the version pre(x efore serving the ssetF elterntivelyD you ould opy ssets to the pproprite version pth s prt of your deployment proess nd forgo ny v rewritingF he ltter option is useful if you would like older sset versions to remin essile t their originl vF

7.1.2 Full Default Conguration

ewv

framework: # general conguration charset: ~ secret: ~ # Required ide: ~ test: ~ # form conguration form: enabled: true csrf_protection: enabled: true eld_name: _token # esi conguration esi:
UFIF prmeworkfundle gon(gurtion @frmeworkA STI

ymfony houmenttionD PFH

enabled:

true

# proler conguration proler: only_exceptions: false only_master_requests: false dsn: sqlite:%kernel.cache_dir%/proler.db username: password: lifetime: 86400 matcher: ip: ~ path: ~ service: ~ # router conguration router: resource: ~ # Required type: ~ http_port: 80 https_port: 443 # session conguration session: auto_start: ~ default_locale: en storage_id: session.storage.native name: ~ lifetime: 86400 path: ~ domain: ~ secure: ~ httponly: ~ # templating conguration templating: assets_version: ~ assets_version_format: "%%s?%%s" assets_base_urls: http: [] ssl: [] cache: ~ engines: # Required form: resources: [FrameworkBundle:Form] # Example:
STP UF eferene houments

ymfony houmenttionD PFH

- twig loaders: packages:

[]

# Prototype name: version: ~ version_format: ~ base_urls: http: [] ssl: [] # translator conguration translator: enabled: true fallback: en # validation conguration validation: enabled: true cache: ~ enable_annotations: false # annotation conguration annotations: cache: le le_cache_dir: %kernel.cache_dir%/annotations debug: true

7.2 AsseticBundle Conguration Reference


7.2.1 Full Default Conguration

ewv

assetic: debug: true use_controller: true read_from: %kernel.root_dir%/../web write_to: %assetic.read_from% java: /usr/bin/java node: /usr/bin/node sass: /usr/bin/sass bundles:
UFPF essetifundle gon(gurtion eferene STQ

ymfony houmenttionD PFH

# Defaults (all currently registered bundles): - FrameworkBundle - SecurityBundle - TwigBundle - MonologBundle - SwiftmailerBundle - DoctrineBundle - AsseticBundle - ... assets: # Prototype name: inputs: lters: options: # Prototype name:

[]

[]

lters:

[]

# Prototype name: twig: functions: # Prototype name:

[]

[]

7.3 Conguration Reference

ewv

doctrine: dbal: default_connection: default connections: default: dbname: database host: localhost port: 1234 user: user password: secret
STR UF eferene houments

ymfony houmenttionD PFH

driver: pdo_mysql driver_class: MyNamespace\MyDriverImpl options: foo: bar path: %kernel.data_dir%/data.sqlite memory: true unix_socket: /tmp/mysql.sock wrapper_class: MyDoctrineDbalConnectionWrapper charset: UTF8 logging: %kernel.debug% platform_service: MyOwnDatabasePlatformService mapping_types: enum: string conn1: # ... types: custom: Acme\HelloBundle\MyCustomType orm: auto_generate_proxy_classes: false proxy_namespace: Proxies proxy_dir: %kernel.cache_dir%/doctrine/orm/Proxies default_entity_manager: default # The rst dened is used if not set entity_managers: default: # The name of a DBAL connection (the one marked as default is used if not set) connection: conn1 mappings: # Required AcmeHelloBundle: ~ class_metadata_factory_name: Doctrine\ORM\Mapping\ClassMetadataFactory # All cache drivers have to be array, apc, xcache or memcache metadata_cache_driver: array query_cache_driver: array result_cache_driver: type: memcache host: localhost port: 11211 instance_class: Memcache class: Doctrine\Common\Cache\MemcacheCache dql: string_functions: test_string: Acme\HelloBundle\DQL\StringFunction numeric_functions: test_numeric: Acme\HelloBundle\DQL\NumericFunction datetime_functions: test_datetime: Acme\HelloBundle\DQL\DatetimeFunction em2: # ...
UFQF gon(gurtion eferene STS

ymfony houmenttionD PFH

wv

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doct <doctrine:cong> <doctrine:dbal default-connection="default"> <doctrine:connection name="default" dbname="database" host="localhost" port="1234" user="user" password="secret" driver="pdo_mysql" driver-class="MyNamespace\MyDriverImpl" path="%kernel.data_dir%/data.sqlite" memory="true" unix-socket="/tmp/mysql.sock" wrapper-class="MyDoctrineDbalConnectionWrapper" charset="UTF8" logging="%kernel.debug%" platform-service="MyOwnDatabasePlatformService" > <doctrine:option key="foo">bar</doctrine:option> <doctrine:mapping-type name="enum">string</doctrine:mapping-type> </doctrine:connection> <doctrine:connection name="conn1" /> <doctrine:type name="custom">Acme\HelloBundle\MyCustomType</doctrine:type> </doctrine:dbal>

<doctrine:orm default-entity-manager="default" auto-generate-proxy-classes="false" proxy-namespac <doctrine:entity-manager name="default" query-cache-driver="array" result-cache-driver="array" <doctrine:metadata-cache-driver type="memcache" host="localhost" port="11211" instance-c <doctrine:mapping name="AcmeHelloBundle" /> <doctrine:dql> <doctrine:string-function name="test_string>Acme\HelloBundle\DQL\StringFunction</d <doctrine:numeric-function name="test_numeric>Acme\HelloBundle\DQL\NumericFuncti <doctrine:datetime-function name="test_datetime>Acme\HelloBundle\DQL\DatetimeFun </doctrine:dql> </doctrine:entity-manager> <doctrine:entity-manager name="em2" connection="conn2" metadata-cache-driver="apc"> <doctrine:mapping name="DoctrineExtensions" type="xml"
STT UF eferene houments

ymfony houmenttionD PFH

/> </doctrine:entity-manager> </doctrine:orm> </doctrine:cong> </container>

dir="%kernel.root_dir%/../src/vendor/DoctrineExtensions/lib/DoctrineExtensions/Entity" prex="DoctrineExtensions\Entity" alias="DExt"

7.3.1 Conguration Overview

his following on(gurtion exmple shows ll the on(gurtion defults tht the yw resolves toX

doctrine: orm: auto_mapping: true # the standard distribution overrides this to be true in debug, false otherwise auto_generate_proxy_classes: false proxy_namespace: Proxies proxy_dir: %kernel.cache_dir%/doctrine/orm/Proxies default_entity_manager: default metadata_cache_driver: array query_cache_driver: array result_cache_driver: array
here re lots of other on(gurtion options tht you n use to overwrite ertin lssesD ut those re for very dvned useEses onlyF ghing hrivers por the hing drivers you n speify the vlues rryD pD memhe or xheF he following exmple shows n overview of the hing on(gurtionsX

doctrine: orm: auto_mapping: true metadata_cache_driver: apc query_cache_driver: xcache result_cache_driver: type: memcache host: localhost port: 11211 instance_class: Memcache
UFQF gon(gurtion eferene STU

ymfony houmenttionD PFH wpping gon(gurtion ixpliit de(nition of ll the mpped entities is the only neessry on(gurtion for the yw nd there re severl on(gurtion options tht you n ontrolF he following on(gurtion options exist for mppingX

type yne of nnottionD xmlD ymlD php or sttiphpF his spei(es whih type of metdt type your mpping usesF dir th to the mpping or entity (les @depending on the driverAF sf this pth is reltive it is ssumed to e reltive to the undle rootF his only works if the nme of your mpping is undle nmeF sf you wnt to use this option to speify solute pths you should pre(x the pth with the kernel prmeters tht exist in the hsg @for exmple 7kernelFrootdir7AF pre(x e ommon nmespe pre(x tht ll entities of this mpping shreF his pre(x should never on)it with pre(xes of other de(ned mppings otherwise some of your entities nnot e found y hotrineF his option defults to the undle nmespe C intityD for exmple for n pplition undle lled emerellofundle pre(x would e emerellofundleintityF lis hotrine o'ers wy to lis entity nmespes to simplerD shorter nmes to e used in hv queries or for epository essF hen using undle the lis defults to the undle nmeF isundle his option is derived vlue from dir nd y defult is set to true if dir is reltive proved y (leexists@A hek tht returns flseF st is flse if the existene hek returns trueF sn this se n solute pth ws spei(ed nd the metdt (les re most likely in diretory outside of undleF
7.3.2 Doctrine DBAL Conguration

X hotrinefundle supports ll prmeters tht defult hotrine drivers eptD onverted to the wv or ewv nming stndrds tht ymfony enforesF ee the hotrine hfev doumenttion for more informtionF fesides defult hotrine optionsD there re some ymfonyErelted ones tht you n on(gureF he following lok shows ll possile on(gurtion keysX

ewv

doctrine: dbal: dbname: host: port:


STV

database localhost 1234


UF eferene houments

ymfony houmenttionD PFH

user: user password: secret driver: pdo_mysql driver_class: MyNamespace\MyDriverImpl options: foo: bar path: %kernel.data_dir%/data.sqlite memory: true unix_socket: /tmp/mysql.sock wrapper_class: MyDoctrineDbalConnectionWrapper charset: UTF8 logging: %kernel.debug% platform_service: MyOwnDatabasePlatformService mapping_types: enum: string types: custom: Acme\HelloBundle\MyCustomType
wv

<!-- xmlns:doctrine="http://symfony.com/schema/dic/doctrine" --> <!-- xsi:schemaLocation="http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctr <doctrine:cong> <doctrine:dbal name="default" dbname="database" host="localhost" port="1234" user="user" password="secret" driver="pdo_mysql" driver-class="MyNamespace\MyDriverImpl" path="%kernel.data_dir%/data.sqlite" memory="true" unix-socket="/tmp/mysql.sock" wrapper-class="MyDoctrineDbalConnectionWrapper" charset="UTF8" logging="%kernel.debug%" platform-service="MyOwnDatabasePlatformService" > <doctrine:option key="foo">bar</doctrine:option> <doctrine:mapping-type name="enum">string</doctrine:mapping-type> <doctrine:type name="custom">Acme\HelloBundle\MyCustomType</doctrine:type> </doctrine:dbal> </doctrine:cong>
sf you wnt to on(gure multiple onnetions in ewvD put them under the onnetions key UFQF gon(gurtion eferene STW

ymfony houmenttionD PFH nd give them unique nmeX

doctrine: dbal: default_connection: default connections: default: dbname: Symfony2 user: root password: null host: localhost customer: dbname: customer user: root password: null host: localhost
he dtseonnetion servie lwys refers to the defult onnetionD whih is the (rst one de(ned or the one on(gured vi the defultonnetion prmeterF ih onnetion is lso essile vi the dotrineFdlFnmeonnetion servie where nme if the nme of the onnetionF

7.4 Security Conguration Reference

he seurity system is one of the most powerful prts of ymfonyPD nd n lrgely e ontrolled vi its on(gurtionF
7.4.1 Full Default Conguration

he following is the full defult on(gurtion for the seurity systemF ih prt will e explined in the next setionF

ewv

# app/cong/security.yml security: access_denied_url: /foo/error403 always_authenticate_before_granting: false # strategy can be: none, migrate, invalidate session_xation_strategy: migrate access_decision_manager:
SUH UF eferene houments

ymfony houmenttionD PFH

strategy: armative allow_if_all_abstain: false allow_if_equal_granted_denied: true acl: connection: default # any name congured in doctrine.dbal section tables: class: acl_classes entry: acl_entries object_identity: acl_object_identities object_identity_ancestors: acl_object_identity_ancestors security_identity: acl_security_identities cache: id: service_id prex: sf2_acl_ voter: allow_if_object_identity_unavailable: true encoders: somename: class: Acme\DemoBundle\Entity\User Acme\DemoBundle\Entity\User: sha512 Acme\DemoBundle\Entity\User: plaintext Acme\DemoBundle\Entity\User: algorithm: sha512 encode_as_base64: true iterations: 5000 Acme\DemoBundle\Entity\User: id: my.custom.encoder.service.id providers: memory: name: memory users: foo: { password: foo, roles: ROLE_USER } bar: { password: bar, roles: [ROLE_USER, ROLE_ADMIN] } entity: entity: { class: SecurityBundle:User, property: username } factories: MyFactory: %kernel.root_dir%/../src/Acme/DemoBundle/Resources/cong/security_factories.xml rewalls: somename: pattern: .* request_matcher: some.service.id access_denied_url: /foo/error403
UFRF eurity gon(gurtion eferene SUI

ymfony houmenttionD PFH

access_denied_handler: some.service.id entry_point: some.service.id provider: name context: name stateless: false x509: provider: name http_basic: provider: name http_digest: provider: name form_login: check_path: /login_check login_path: /login use_forward: false always_use_default_target_path: false default_target_path: / target_path_parameter: _target_path use_referer: false failure_path: /foo failure_forward: false failure_handler: some.service.id success_handler: some.service.id username_parameter: _username password_parameter: _password csrf_parameter: _csrf_token csrf_page_id: form_login csrf_provider: my.csrf_provider.id post_only: true remember_me: false remember_me: token_provider: name key: someS3cretKey name: NameOfTheCookie lifetime: 3600 # in seconds path: /foo domain: somedomain.foo secure: true httponly: true always_remember_me: false remember_me_parameter: _remember_me logout: path: /logout target: / invalidate_session: false delete_cookies: a: { path: null, domain: null }
SUP UF eferene houments

ymfony houmenttionD PFH

b: { path: null, domain: null } handlers: [some.service.id, another.service.id] success_handler: some.service.id anonymous: ~ access_control: path: ^/foo host: mydomain.foo ip: 192.0.0.0/8 roles: [ROLE_A, ROLE_B] requires_channel: https role_hierarchy: ROLE_SUPERADMIN: ROLE_ADMIN ROLE_SUPERADMIN: 'ROLE_ADMIN, ROLE_USER' ROLE_SUPERADMIN: [ROLE_ADMIN, ROLE_USER] anything: { id: ROLE_SUPERADMIN, value: 'ROLE_USER, ROLE_ADMIN' } anything: { id: ROLE_SUPERADMIN, value: [ROLE_USER, ROLE_ADMIN] }

7.4.2 Form Login Conguration

hen using the formlogin uthentition listener eneth (rewllD there re severl ommon options for on(guring the form login experieneX he vogin porm nd roess

loginpth @typeX stringD defultX GloginA his is the v tht the user will e redireted to @unless useforwrd is set to trueA when heGshe tries to ess proteted resoure ut isn9t fully uthentitedF
his v must e essile y normlD unEuthentited userD else you my rete rediret loopF por detilsD see evoid gommon itfllsF

hekpth @typeX stringD defultX GloginhekA his is the v tht your login form must sumit toF he (rewll will interept ny requests @y requests onlyD e defultA to this v nd proess the sumitted login redentilsF
fe sure tht this v is overed y your min (rewll @iFeF don9t rete seprte (rewll just for hekpth vAF

useforwrd @typeX foolenD defultX flseA sf you9d like the user to e forwrded to the login form insted of eing rediretedD set this option to trueF usernmeprmeter @typeX stringD defultX usernmeA his is the (eld nme tht you should give to the usernme (eld of your login formF hen you sumit the form
UFRF eurity gon(gurtion eferene SUQ

ymfony houmenttionD PFH to hekpthD the seurity system will look for y prmeter with this nmeF

psswordprmeter @typeX stringD defultX psswordA his is the (eld nme tht you should give to the pssword (eld of your login formF hen you sumit the form to hekpthD the seurity system will look for y prmeter with this nmeF postonly @typeX foolenD defultX trueA fy defultD you must sumit your login form to the hekpth v s y requestF fy setting this option to trueD you n send qi request to the hekpth vF
edireting fter vogin

lwysusedefulttrgetpth @typeX foolenD defultX flseA defulttrgetpth @typeX stringD defultX GA trgetpthprmeter @typeX stringD defultX trgetpthA usereferer @typeX foolenD defultX flseA

7.5 SwiftmailerBundle Conguration


7.5.1 Full Default Conguration

ewv

swiftmailer: transport: smtp username: ~ password: ~ host: localhost port: false encryption: ~ auth_mode: ~ spool: type: le path: %kernel.cache_dir%/swiftmailer/spool sender_address: ~ antiood: threshold: 99 sleep: 0 delivery_address: ~ disable_delivery: ~ logging: true

SUR

UF eferene houments

ymfony houmenttionD PFH

7.6 TwigBundle Conguration Reference

ewv

twig: form: resources: # Default: - div_layout.html.twig # Example: - MyBundle::form.html.twig globals: # Examples: foo: pi: "@bar" 3.14

# Prototype key: id: ~ type: ~ value: ~ autoescape: ~ base_template_class: ~ # Example: Twig_Template cache: %kernel.cache_dir%/twig charset: %kernel.charset% debug: %kernel.debug% strict_variables: ~ auto_reload: ~ exception_controller: Symfony\Bundle\TwigBundle\Controller\ExceptionController::showAction
wv

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:twig="http://symfony.com/schema/dic/twig" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/doctrine/twig-1.0.

<twig:cong auto-reload="%kernel.debug%" autoescape="true" base-template-class="Twig_Template" <twig:form> <twig:resource>MyBundle::form.html.twig</twig:resource> </twig:form> <twig:global key="foo" id="bar" type="service" /> <twig:global key="pi">3.14</twig:global>
UFTF wigfundle gon(gurtion eferene SUS

ymfony houmenttionD PFH

</twig:cong> </container>
r

$container->loadFromExtension('twig', array( 'form' => array( 'resources' => array( 'MyBundle::form.html.twig', ) ), 'globals' => array( 'foo' => '@bar', 'pi' => 3.14, ), 'auto_reload' => '%kernel.debug%', 'autoescape' => true, 'base_template_class' => 'Twig_Template', 'cache' => '%kernel.cache_dir%/twig', 'charset' => '%kernel.charset%', 'debug' => '%kernel.debug%', 'strict_variables' => false, ));

7.6.1 Conguration

exeptionontroller typeX string defultX ymfonyfundlewigfundlegontrollerixeptiongontrollerXXshowetion his is the ontroller tht is tivted fter n exeption is thrown nywhere in your pplitionF he defult ontroller @ymfonyfundlewigfundlegontrollerixeptiongontrollerA is wht9s responsile for rendering spei( templtes under di'erent error onditions @see E AF wodifying this option is dvnedF sf you need to ustomize n error pge you should use the previous linkF sf you need to perform some ehvior on n exeptionD you should dd listener to the kernelFexeption event @see inling gustom vistenersAF

7.7 Conguration Reference

ewv

SUT

UF eferene houments

ymfony houmenttionD PFH

monolog: handlers: # Examples: syslog: type: path: level: bubble: formatter: main: type: action_level: buer_size: handler: custom: type: id:

stream /var/log/symfony.log ERROR false my_formatter ngerscrossed WARNING 30 custom service my_handler

# Prototype name: type: ~ # Required id: ~ priority: 0 level: DEBUG bubble: true path: %kernel.logs_dir%/%kernel.environment%.log ident: false facility: user max_les: 0 action_level: WARNING stop_buering: true buer_size: 0 handler: ~ members: [] from_email: ~ to_email: ~ subject: ~ email_prototype: id: ~ # Required (when the email_prototype is used) method: ~ formatter: ~
wv

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"


UFUF gon(gurtion eferene SUU

ymfony houmenttionD PFH

xmlns:monolog="http://symfony.com/schema/dic/monolog" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/mon <monolog:cong> <monolog:handler name="syslog" type="stream" path="/var/log/symfony.log" level="error" bubble="false" formatter="my_formatter" /> <monolog:handler name="main" type="ngerscrossed" action-level="warning" handler="custom" /> <monolog:handler name="custom" type="service" id="my_handler" /> </monolog:cong> </container>
X hen the pro(ler is enledD hndler is dded to store the logs9 messges in the pro(lerF he pro(ler uses the nme deug so it is reserved nd nnot e used in the on(gurtionF

7.8 WebProlerBundle Conguration


7.8.1 Full Default Conguration

ewv

web_proler: # display secondary information to make the toolbar shorter verbose: true # display the web debug toolbar at the bottom of pages with a summary of proler info
SUV UF eferene houments

ymfony houmenttionD PFH

toolbar:

false

# gives you the opportunity to look at the collected data before following the redirect intercept_redirects: false

7.9 Form Types Reference


7.9.1 birthday Field Type

e dte (eld tht speilizes in hndling irthdte dtF gn e rendered s single text oxD three text oxes @monthD dyD nd yerAD or three selet oxesF his type is essentilly the sme s the dte typeD ut with more pproprite defult for the yers optionF he yers option defults to IPH yers go to the urrent yerF nderlying ht ype endered s yptions snherited options n e hteimeD stringD timestmpD or rry @see the input optionA n e three selet oxes or I or Q text oxesD sed on the widget option

yers
widget input months dys formt pttern dttimezone usertimezone

rent type glss pield yptions

dte ymfonygomponentpormixtensiongoreypefirthd

years
typeX rry defultX IPH yers go to the urrent yer

UFWF porm ypes eferene

SUW

ymfony houmenttionD PFH vist of yers ville to the yer (eld typeF his option is only relevnt when the widget option is set to hoieF snherited options hese options inherit from the dte typeX

widget
typeX string defultX hoie he si wy in whih this (eld should e renderedF gn e one of the followingX

hoieX renders three selet inputsF he order of the selets is de(ned in the pttern optionF textX renders three (eld input of type text @monthD dyD yerAF singletextX renders single input of type textF ser9s input is vlidted sed on the formt optionF

input
typeX string defultX dtetime he formt of the input dt E iFeF the formt tht the dte is stored on your underlying ojetF lid vlues reX

string @eFgF PHIIEHTEHSA dtetime @ hteime ojetA rry @eFgF rry@9yer9 ab PHIID 9month9 ab HTD 9dy9 ab HSAA timestmp @eFgF IQHUPQPHHHA
he vlue tht omes k from the form will lso e normlized k into this formtF

months
typeX rry defultX I to IP vist of months ville to the month (eld typeF his option is only relevnt when the widget option is set to hoieF

SVH

UF eferene houments

ymfony houmenttionD PFH

days
typeX rry defultX I to QI vist of dys ville to the dy (eld typeF his option is only relevnt when the widget option is set to hoieX

'days' => range(1,31) format


typeX integer or string defultX sntlhtepormtterXXwihsw yption pssed to the sntlhtepormtter lssD used to trnsform user input into the proper formtF his is ritil when the widget option is set to singletextD nd will de(ne how to trnsform the inputF fy defultD the formt is determined sed on the urrent user loleY you n override it y pssing the formt s stringF

pattern
typeX string his option is only relevnt when the widget is set to hoieF he defult pttern is sed o' the formt optionD nd tries to mth the hrters wD dD nd y in the formt ptternF sf no mth is foundD the defult is the string {{ yer }}E{{ month }}E{{ dy }}F okens for this option inludeX

{{ yer }}X epled with the yer widget {{ month }}X epled with the month widget {{ dy }}X epled with the dy widget

data_timezone
typeX string defultX system defult timezone imezone tht the input dt is stored inF his must e one of the r supported timezones

user_timezone
typeX string defultX system defult timezone imezone for how the dt should e shown to the user @nd therefore lso the dt tht the user sumitsAF his must e one of the r supported timezones UFWF porm ypes eferene SVI

ymfony houmenttionD PFH


7.9.2 checkbox Field Type

gretes single input hekoxF his should lwys e used for (eld tht hs foolen vlueX if the ox is hekedD the (eld will e set to trueD if the ox is unhekedD the vlue will e set to flseF endered s yptions snherited options input text (eld

vlue
required lel redonly erroruling

rent type glss ixmple sge

(eld ymfonygomponentpormixtensiongoreypeghek

$builder->add('public', 'checkbox', array( 'label' => 'Show this entry publicly?', 'required' => false, ));
pield yptions

value
typeX mixed defultX I he vlue tht9s tully used s the vlue for the hekoxF his does not 'et the vlue tht9s set on your ojetF snherited options hese options inherit from the (eld typeX

required
typeX foolen defultX true

SVP

UF eferene houments

ymfony houmenttionD PFH sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.3 choice Field Type

e multiEpurpose (eld used to llow the user to hoose one or more optionsF st n e rendered s selet tgD rdio uttonsD or hekoxesF o use this (eldD you must speify either the hoielist or hoies optionF

UFWF porm ypes eferene

SVQ

ymfony houmenttionD PFH endered s yptions n e vrious tgs @see elowA

hoies hoielist multiple expnded preferredhoies emptyvlue required lel redonly erroruling

snherited options

rent type glss ixmple sge

form @if expndedAD (eld otherwise ymfonygomponentpormixtensiongoreypeghoie

he esiest wy to use this (eld is to speify the hoies diretly vi the hoies optionF he key of the rry eomes the vlue tht9s tully set on your underlying ojet @eFgF mAD while the vlue is wht the user sees on the form @eFgF wleAF

$builder->add('gender', 'choice', array( 'choices' => array('m' => 'Male', 'f' => 'Female'), 'required' => false, ));
fy setting multiple to trueD you n llow the user to hoose multiple vluesF he widget will e rendered s multiple selet tg or series of hekoxes depending on the expnded optionX

$builder->add('availability', 'choice', array( 'choices' => array( 'morning' => 'Morning', 'afternoon' => 'Afternoon', 'evening' => 'Evening', ), 'multiple' => true, ));
ou n lso use the hoielist optionD whih tkes n ojet tht n speify the hoies for your widgetF

SVR

UF eferene houments

ymfony houmenttionD PFH elet tgD ghekoxes or dio futtons his (eld my e rendered s one of severl di'erent rwv (eldsD depending on the expnded nd multiple optionsX element type selet tg selet tg @with multiple ttriuteA rdio uttons hekoxes pield yptions expnded flse flse true true multiple flse true flse true

choices
typeX rry defultX rry@A his is the most si wy to speify the hoies tht should e used y this (eldF he hoies option is n rryD where the rry key is the item vlue nd the rry vlue is the item9s lelX

$builder->add('gender', 'choice', array( 'choices' => array('m' => 'Male', 'f' => 'Female') )); choice_list
typeX ymfonygomponentpormixtensiongoreghoievistghoievistsnterfe his is one wy of speifying the options to e used for this (eldF he hoielist option must e n instne of the ghoievistsnterfeF por more dvned sesD ustom lss tht implements the interfe n e reted to supply the hoiesF

multiple
typeX foolen defultX flse sf trueD the user will e le to selet multiple options @s opposed to hoosing just one optionAF hepending on the vlue of the expnded optionD this will render either selet tg or hekoxes if true nd selet tg or rdio uttons if flseF he returned vlue will e n rryF

UFWF porm ypes eferene

SVS

ymfony houmenttionD PFH

expanded
typeX foolen defultX flse sf set to trueD rdio uttons or hekoxes will e rendered @depending on the multiple vlueAF sf flseD selet element will e renderedF

preferred_choices
typeX rry defultX rry@A sf this option is spei(edD then suEset of ll of the options will e moved to the top of the selet menuF he following would move the fz option to the topD with visul seprtor etween it nd the rest of the optionsX

$builder->add('foo_choices', 'choice', array( 'choices' => array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), 'preferred_choices' => array('baz'), ));
xote tht preferred hoies re only meningful when rendering s selet element @iFeF expnded is flseAF he preferred hoies nd norml hoies re seprted visully y set of dotted lines @iFeF EEEEEEEEEEEEEEEEEEEAF his n e ustomized when rendering the (eldX

wig

{{ form_widget(form.foo_choices, { 'separator': '=====' }) }}


r

<?php echo $view['form']->widget($form['foo_choices'], array('separator' => '=====')) ?> empty_value


typeX string or foolen his option determines whether or not speil empty option @eFgF ghoose n optionA will pper t the top of selet widgetF his option only pplies if oth the expnded nd multiple options re set to flseF

edd n empty vlue with ghoose n option s the textX

$builder->add('states', 'choice', array( 'empty_value' => 'Choose an option', ));


qurntee tht no empty vlue option is displyedX
SVT UF eferene houments

ymfony houmenttionD PFH

$builder->add('states', 'choice', array( 'empty_value' => false, ));


sf you leve the emptyvlue option unsetD then lnk @with no textA option will utomtilly e dded if nd only if the required option is flseX

// a blank (with no text) option will be added $builder->add('states', 'choice', array( 'required' => false, ));
snherited options hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

UFWF porm ypes eferene

SVU

ymfony houmenttionD PFH

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.4 collection Field Type

ee ymfonygomponentpormixtensiongoreypegolletionypeF
7.9.5 country Field Type

he ountry type is suset of the ghoieype tht displys ountries of the worldF es n dded onusD the ountry nmes re displyed in the lnguge of the userF he vlue for eh ountry is the twoEletter ountry odeF X he lole of your user is guessed using voleXXgethefult@A nlike the hoie typeD you don9t need to speify hoies or hoielist option s the (eld type utomtilly uses ll of the ountries of the worldF ou n speify either of these options mnullyD ut then you should just use the hoie type diretlyF endered s snherited options n e vrious tgs @see elet tgD ghekoxes or dio futtonsA

multiple expnded preferredhoies emptyvlue erroruling required lel redonly

rent type glss snherited options hese options inherit from the hoie typeX SVV

hoie ymfonygomponentpormixtensiongoreypegountr

UF eferene houments

ymfony houmenttionD PFH

multiple
typeX foolen defultX flse sf trueD the user will e le to selet multiple options @s opposed to hoosing just one optionAF hepending on the vlue of the expnded optionD this will render either selet tg or hekoxes if true nd selet tg or rdio uttons if flseF he returned vlue will e n rryF

expanded
typeX foolen defultX flse sf set to trueD rdio uttons or hekoxes will e rendered @depending on the multiple vlueAF sf flseD selet element will e renderedF

preferred_choices
typeX rry defultX rry@A sf this option is spei(edD then suEset of ll of the options will e moved to the top of the selet menuF he following would move the fz option to the topD with visul seprtor etween it nd the rest of the optionsX

$builder->add('foo_choices', 'choice', array( 'choices' => array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), 'preferred_choices' => array('baz'), ));
xote tht preferred hoies re only meningful when rendering s selet element @iFeF expnded is flseAF he preferred hoies nd norml hoies re seprted visully y set of dotted lines @iFeF EEEEEEEEEEEEEEEEEEEAF his n e ustomized when rendering the (eldX

wig

{{ form_widget(form.foo_choices, { 'separator': '=====' }) }}


r

<?php echo $view['form']->widget($form['foo_choices'], array('separator' => '=====')) ?> empty_value


typeX string or foolen

UFWF porm ypes eferene

SVW

ymfony houmenttionD PFH his option determines whether or not speil empty option @eFgF ghoose n optionA will pper t the top of selet widgetF his option only pplies if oth the expnded nd multiple options re set to flseF

edd n empty vlue with ghoose n option s the textX

$builder->add('states', 'choice', array( 'empty_value' => 'Choose an option', ));


qurntee tht no empty vlue option is displyedX

$builder->add('states', 'choice', array( 'empty_value' => false, ));


sf you leve the emptyvlue option unsetD then lnk @with no textA option will utomtilly e dded if nd only if the required option is flseX

// a blank (with no text) option will be added $builder->add('states', 'choice', array( 'required' => false, )); error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

SWH

UF eferene houments

ymfony houmenttionD PFH

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF
7.9.6 csrf Field Type

he srf type is hidden input (eld ontining gp tokenF endered s yptions input hidden (eld

srfprovider pgeid propertypth

rent type glss pield yptions

hidden ymfonygomponentpormixtensiongsrfypegsrfyp

csrf_provider
typeX ymfonygomponentpormgsrfrovidergsrfrovidersnterfe he gsrfrovidersnterfe ojet tht should generte the gp tokenF sf not setD this defults to the defult providerF

intention
typeX string en optionl unique identi(er used to generte the gp tokenF UFWF porm ypes eferene SWI

ymfony houmenttionD PFH

property_path
typeX ny defultX the (eld9s vlue pields disply property vlue of the form9s domin ojet y defultF hen the form is sumittedD the sumitted vlue is written k into the ojetF sf you wnt to override the property tht (eld reds from nd writes toD you n set the propertypth optionF sts defult vlue is the (eld9s nmeF
7.9.7 date Field Type

e (eld tht llows the user to modify dte informtion vi vriety of di'erent rwv elementsF he underlying dt used for this (eld type n e hteime ojetD stringD timestmp or n rryF es long s the input option is set orretlyD the (eld will tke re of ll of the detilsF he (eld n e rendered s single text oxD three text oxes @monthD dyD nd yerA or three selet oxes @see the widget optionAF nderlying ht ype endered s yptions n e hteimeD stringD timestmpD or rry @see the input optionA single text ox or three selet (elds

widget input emptyvlue yers months dys formt pttern dttimezone usertimezone

rent type glss fsi sge

(eld @if textAD form otherwise ymfonygomponentpormixtensiongoreypehte

his (eld type is highly on(gurleD ut esy to useF he most importnt options re input nd widgetF

SWP

UF eferene houments

ymfony houmenttionD PFH uppose tht you hve pulishedet (eld whose underlying dte is hteime ojetF he following on(gures the dte type for tht (eld s three di'erent hoie (eldsX

$builder->add('publishedAt', 'date', array( 'input' => 'datetime', 'widget' => 'choice', ));
he input option must e hnged to mth the type of the underlying dte dtF por exmpleD if the pulishedet (eld9s dt were unix timestmpD you9d need to set input to timestmpX

$builder->add('publishedAt', 'date', array( 'input' => 'timestamp', 'widget' => 'choice', ));
he (eld lso supports n rry nd string s vlid input option vluesF pield yptions

widget
typeX string defultX hoie he si wy in whih this (eld should e renderedF gn e one of the followingX

hoieX renders three selet inputsF he order of the selets is de(ned in the pttern optionF textX renders three (eld input of type text @monthD dyD yerAF singletextX renders single input of type textF ser9s input is vlidted sed on the formt optionF

input
typeX string defultX dtetime he formt of the input dt E iFeF the formt tht the dte is stored on your underlying ojetF lid vlues reX

string @eFgF PHIIEHTEHSA dtetime @ hteime ojetA rry @eFgF rry@9yer9 ab PHIID 9month9 ab HTD 9dy9 ab HSAA timestmp @eFgF IQHUPQPHHHA
UFWF porm ypes eferene SWQ

ymfony houmenttionD PFH he vlue tht omes k from the form will lso e normlized k into this formtF

empty_value
typeX string|rry sf your widget option is set to hoieD then this (eld will e represented s series of selet oxesF he emptyvlue option n e used to dd lnk entry to the top of eh selet oxX

$builder->add('dueDate', 'date', array( 'empty_value' => '', ));


elterntivelyD you n speify string to e displyed for the lnk vlueX

$builder->add('dueDate', 'date', array( 'empty_value' => array('year' => 'Year', 'month' => 'Month', 'day' => 'Day') )); years
typeX rry defultX (ve yers efore to (ve yers fter the urrent yer vist of yers ville to the yer (eld typeF his option is only relevnt when the widget option is set to hoieF

months
typeX rry defultX I to IP vist of months ville to the month (eld typeF his option is only relevnt when the widget option is set to hoieF

days
typeX rry defultX I to QI vist of dys ville to the dy (eld typeF his option is only relevnt when the widget option is set to hoieX

'days' => range(1,31)

SWR

UF eferene houments

ymfony houmenttionD PFH

format
typeX integer or string defultX sntlhtepormtterXXwihsw yption pssed to the sntlhtepormtter lssD used to trnsform user input into the proper formtF his is ritil when the widget option is set to singletextD nd will de(ne how to trnsform the inputF fy defultD the formt is determined sed on the urrent user loleY you n override it y pssing the formt s stringF

pattern
typeX string his option is only relevnt when the widget is set to hoieF he defult pttern is sed o' the formt optionD nd tries to mth the hrters wD dD nd y in the formt ptternF sf no mth is foundD the defult is the string {{ yer }}E{{ month }}E{{ dy }}F okens for this option inludeX

{{ yer }}X epled with the yer widget {{ month }}X epled with the month widget {{ dy }}X epled with the dy widget

data_timezone
typeX string defultX system defult timezone imezone tht the input dt is stored inF his must e one of the r supported timezones

user_timezone
typeX string defultX system defult timezone imezone for how the dt should e shown to the user @nd therefore lso the dt tht the user sumitsAF his must e one of the r supported timezones
7.9.8 datetime Field Type

his (eld type llows the user to modify dt tht represents spei( dte nd time @eFgF IWVREHTEHS IPXISXQHAF gn e rendered s text input or selet tgsF he underlying formt of the dt n e hteime ojetD stringD timestmp or n rryF

UFWF porm ypes eferene

SWS

ymfony houmenttionD PFH nderlying ht ype endered s yptions n e hteimeD stringD timestmpD or rry @see the input optionA single text ox or three selet (elds

dtewidget timewidget input dteformt yers months dys

rent type glss pield yptions

form ymfonygomponentpormixtensiongoreypehte

date_widget
typeX string defultX hoie he(nes the widget option for the dte type

time_widget
typeX string defultX hoie he(nes the widget option for the time type

input
typeX string defultX dtetime he formt of the input dt E iFeF the formt tht the dte is stored on your underlying ojetF lid vlues reX

string @eFgF PHIIEHTEHS IPXISXHHA dtetime @ hteime ojetA rry @eFgF rry@PHIID HTD HSD IPD ISD HAA timestmp @eFgF IQHUPUTIHHA
he vlue tht omes k from the form will lso e normlized k into this formtF

SWT

UF eferene houments

ymfony houmenttionD PFH

date_format
typeX integer or string defultX sntlhtepormtterXXwihsw he(nes the formt option tht will e pssed down to the dte (eldF

hours
typeX integer defultX I to PQ vist of hours ville to the hours (eld typeF his option is only relevnt when the widget option is set to hoieF

minutes
typeX integer defultX I to SW vist of minutes ville to the minutes (eld typeF his option is only relevnt when the widget option is set to hoieF

seconds
typeX integer defultX I to SW vist of seonds ville to the seonds (eld typeF his option is only relevnt when the widget option is set to hoieF

years
typeX rry defultX (ve yers efore to (ve yers fter the urrent yer vist of yers ville to the yer (eld typeF his option is only relevnt when the widget option is set to hoieF

months
typeX rry defultX I to IP vist of months ville to the month (eld typeF his option is only relevnt when the widget option is set to hoieF

UFWF porm ypes eferene

SWU

ymfony houmenttionD PFH

days
typeX rry defultX I to QI vist of dys ville to the dy (eld typeF his option is only relevnt when the widget option is set to hoieX

'days' => range(1,31) with_seconds


typeX foolen defultX flse hether or not to inlude seonds in the inputF his will result in n dditionl input to pture seondsF

data_timezone
typeX string defultX system defult timezone imezone tht the input dt is stored inF his must e one of the r supported timezones

user_timezone
typeX string defultX system defult timezone imezone for how the dt should e shown to the user @nd therefore lso the dt tht the user sumitsAF his must e one of the r supported timezones
7.9.9 email Field Type

he emil (eld is text (eld tht is rendered using the rwvS `input typea4emil4Gb tgF

SWV

UF eferene houments

ymfony houmenttionD PFH endered s snherited options input emil (eld @ text oxA

mxlength required lel trim redonly erroruling

rent type glss snherited yptions hese options inherit from the (eld typeX

(eld ymfonygomponentpormixtensiongoreypeimil

max_length
typeX integer his option is used to dd mxlength ttriuteD whih is used y some rowsers to limit the mount of text in (eldF

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }}

UFWF porm ypes eferene

SWW

ymfony houmenttionD PFH

trim
typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.10 entity Field Type

e speil hoie (eld tht9s designed to lod options from hotrine entityF por exmpleD if you hve gtegory entityD you ould use this (eld to disply selet (eld of llD or someD of the gtegory ojets from the dtseF

THH

UF eferene houments

ymfony houmenttionD PFH endered s yptions n e vrious tgs @see elet tgD ghekoxes or dio futtonsA

lss property queryuilder em required lel multiple expnded preferredhoies emptyvlue redonly erroruling

snherited options

rent type glss fsi sge

hoie ymfonyfridgehotrinepormypeintityype

he entity type hs just one required optionX the entity whih should e listed inside the hoie (eldX

$builder->add('users', 'entity', array( 'class' => 'AcmeHelloBundle:User', ));


sn this seD ll ser ojets will e loded from the dtse nd rendered s either selet tgD set or rdio uttons or series of hekoxes @this depends on the multiple nd expnded vluesAF

Using a Custom Query for the Entities


sf you need to speify ustom query to use when fething the entities @eFgF you only wnt to return some entitiesD or need to order themAD use the queryuilder optionF he esiest wy to use the option is s followsX

use Doctrine\ORM\EntityRepository; // ... $builder->add('users', 'entity', array( 'class' => 'AcmeHelloBundle:User',


UFWF porm ypes eferene THI

ymfony houmenttionD PFH

));

'query_builder' => function(EntityRepository $er) { return $er->createQueryBuilder('u') ->orderBy('u.username', 'ASC'); },

elet tgD ghekoxes or dio futtons his (eld my e rendered s one of severl di'erent rwv (eldsD depending on the expnded nd multiple optionsX element type selet tg selet tg @with multiple ttriuteA rdio uttons hekoxes pield yptions expnded flse flse true true multiple flse true flse true

class
typeX string required he lss of your entity @eFgF emetorefundleXgtegoryAF his n e fullyEquli(ed lss nme @eFgF emetorefundleintitygtegoryA or the short lis nme @s shown priorAF

property
typeX string his is the property tht should e used for displying the entities s text in the rwv elementF sf left lnkD the entity ojet will e st into string nd so must hve totring@A methodF

query_builder
typeX hotrineywueryfuilder or glosure sf spei(edD this is used to query the suset of options @nd their orderA tht should e used for the (eldF he vlue of this option n either e ueryfuilder ojet or glosureF sf using glosureD it should tke single rgumentD whih is the intityepository of the entityF

THP

UF eferene houments

ymfony houmenttionD PFH

em
typeX string defultX the defult entity mnger sf spei(edD the spei(ed entity mnger will e used to lod the hoies insted of the defult entity mngerF snherited options hese options inherit from the hoie typeX

multiple
typeX foolen defultX flse sf trueD the user will e le to selet multiple options @s opposed to hoosing just one optionAF hepending on the vlue of the expnded optionD this will render either selet tg or hekoxes if true nd selet tg or rdio uttons if flseF he returned vlue will e n rryF

expanded
typeX foolen defultX flse sf set to trueD rdio uttons or hekoxes will e rendered @depending on the multiple vlueAF sf flseD selet element will e renderedF

preferred_choices
typeX rry defultX rry@A sf this option is spei(edD then suEset of ll of the options will e moved to the top of the selet menuF he following would move the fz option to the topD with visul seprtor etween it nd the rest of the optionsX

$builder->add('foo_choices', 'choice', array( 'choices' => array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), 'preferred_choices' => array('baz'), ));
xote tht preferred hoies re only meningful when rendering s selet element @iFeF expnded is flseAF he preferred hoies nd norml hoies re seprted visully y set of dotted lines @iFeF EEEEEEEEEEEEEEEEEEEAF his n e ustomized when rendering the (eldX UFWF porm ypes eferene THQ

ymfony houmenttionD PFH

wig

{{ form_widget(form.foo_choices, { 'separator': '=====' }) }}


r

<?php echo $view['form']->widget($form['foo_choices'], array('separator' => '=====')) ?> empty_value


typeX string or foolen his option determines whether or not speil empty option @eFgF ghoose n optionA will pper t the top of selet widgetF his option only pplies if oth the expnded nd multiple options re set to flseF

edd n empty vlue with ghoose n option s the textX

$builder->add('states', 'choice', array( 'empty_value' => 'Choose an option', ));


qurntee tht no empty vlue option is displyedX

$builder->add('states', 'choice', array( 'empty_value' => false, ));


sf you leve the emptyvlue option unsetD then lnk @with no textA option will utomtilly e dded if nd only if the required option is flseX

// a blank (with no text) option will be added $builder->add('states', 'choice', array( 'required' => false, ));
hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF THR UF eferene houments

ymfony houmenttionD PFH

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.11 le Field Type

he (le type represents (le input in your formF endered s snherited options input (le (eld required lel redonly erroruling

rent type glss fsi sge vet9s sy you hve this form de(nitionX

form ymfonygomponentpormixtensiongoreypepiley

UFWF porm ypes eferene

THS

ymfony houmenttionD PFH

$builder->add('attachment', 'le');
X hon9t forget to dd the entype ttriute in the form tgX `form tiona454methoda4post4{{ formentype@formA }}bF hen the form is sumittedD the tthment (eld will e n instne of ymfonygomponentrttppoundtionpileplodedpileF st n e used to move the tthment (le to permnent lotionX

use Symfony\Component\HttpFoundation\File\UploadedFile; public function uploadAction() { // ... if ($form->isValid()) { $someNewFilename = ... $form['attachment']->getData()->move($dir, $someNewFilename); } } // ...

// ...

he move@A method tkes diretory nd (le nme s its rgumentsF ou might lulte the (lenme in one of the following wysX

// use the original le name $le->move($dir, $le->getClientOriginalName()); // compute a random name and try to guess the extension (more secure) $extension = $le->guessExtension(); if (!$extension) { // extension cannot be guessed $extension = 'bin'; } $le->move($dir, rand(1, 99999).'.'.$extension);
sing the originl nme vi getglientyriginlxme@A is not sfe s it ould hve een mnipulted y the endEuserF woreoverD it n ontin hrters tht re not llowed in (le nmesF ou should snitize the nme efore using it diretlyF ed the ookook for n exmple of how to mnge (le uplod ssoited with hotrine entityF

THT

UF eferene houments

ymfony houmenttionD PFH snherited options hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.12 The Abstract eld Type

he (eld form type is not n tul (eld type you useD ut rther funtions s the prent (eld type for mny other (eldsF UFWF porm ypes eferene THU

ymfony houmenttionD PFH he (eld type prede(nes ouple of optionsX dt typeX mixed defultX hefults to (eld of the underlying ojet @if there is oneA hen you rete formD eh (eld initilly displys the vlue of the orresponding property of the form9s domin ojet @if n ojet is ound to the formAF sf you wnt to override the initil vlue for the form or just nd individul (eldD you n set it in the dt optionX

$builder->add('token', 'hidden', array( 'data' => 'abcdef', ));


required typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

disled typeX foolenD defultX flse sf you don9t wnt user to modify the vlue of (eldD you n set the disled option to trueF eny sumitted vlue will e ignoredF

use Symfony\Component\Form\TextField $eld = new TextField('status', array( 'data' => 'Old data', 'disabled' => true, )); $eld->submit('New data'); // prints "Old data" echo $eld->getData();
trim typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

THV

UF eferene houments

ymfony houmenttionD PFH propertypth typeX ny defultX the (eld9s vlue pields disply property vlue of the form9s domin ojet y defultF hen the form is sumittedD the sumitted vlue is written k into the ojetF sf you wnt to override the property tht (eld reds from nd writes toD you n set the propertypth optionF sts defult vlue is the (eld9s nmeF
7.9.13 form Field Type

ee ymfonygomponentpormixtensiongoreypepormypeF
7.9.14 hidden Field Type

he hidden type represents hidden input (eldF endered s rent type glss input hidden (eld (eld ymfonygomponentpormixtensiongoreyperiddenype

7.9.15 integer Field Type

enders n input numer (eldF fsillyD this is text (eld tht9s good t hndling dt tht9s in n integer formF he input numer (eld looks like text oxD exept tht E if the user9s rowser supports rwvS E it will hve some extr frontend funtionlityF his (eld hs di'erent options on how to hndle input vlues tht ren9t integersF fy defultD ll nonEinteger vlues @eFgF TFUVA will round down @eFgF TAF endered s yptions input text (eld

roundingmode grouping
required lel redonly erroruling

snherited options

rent type glss

(eld ymfonygomponentpormixtensiongoreypesnteger

UFWF porm ypes eferene

THW

ymfony houmenttionD PFH pield yptions

rounding_mode
typeX integer defultX sntegerovolizedtringrnsformerXXyxhhyx fy defultD if the user enters nonEinteger numerD it will e rounded downF here re severl other rounding methodsD nd eh is onstnt on the ymfonygomponentpormixtensiongorehtrnsformersntegerovolizedtringrnsformerX

sntegerovolizedtringrnsformerXXyxhhyx ounding mode to round towrds zeroF sntegerovolizedtringrnsformerXXyxhpvyy ounding mode to round towrds negtive in(nityF sntegerovolizedtringrnsformerXXyxh ounding mode to round wy from zeroF sntegerovolizedtringrnsformerXXyxhgisvsxq ounding mode to round towrds positive in(nityF

grouping
typeX integer defultX flse he vlue set s the xumerpormtterXXqysxqih ttriute when using the r xumerpormtter lssF snherited options hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

TIH

UF eferene houments

ymfony houmenttionD PFH

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.16 language Field Type

he lnguge type is suset of the ghoieype tht llows the user to selet from lrge list of lngugesF es n dded onusD the lnguge nmes re displyed in the lnguge of the userF he vlue for eh lole is either the two letter syTQWEI lnguge ode @eFgF frAF X he lole of your user is guessed using voleXXgethefult@A nlike the hoie typeD you don9t need to speify hoies or hoielist option s the (eld type utomtilly uses lrge list of lngugesF ou n speify either of these options mnullyD ut then you should just use the hoie type diretlyF

UFWF porm ypes eferene

TII

ymfony houmenttionD PFH endered s snherited options n e vrious tgs @see elet tgD ghekoxes or dio futtonsA

multiple expnded preferredhoies emptyvlue erroruling required lel redonly

rent type glss snherited yptions hese options inherit from the hoie typeX

hoie ymfonygomponentpormixtensiongoreypevngu

multiple
typeX foolen defultX flse sf trueD the user will e le to selet multiple options @s opposed to hoosing just one optionAF hepending on the vlue of the expnded optionD this will render either selet tg or hekoxes if true nd selet tg or rdio uttons if flseF he returned vlue will e n rryF

expanded
typeX foolen defultX flse sf set to trueD rdio uttons or hekoxes will e rendered @depending on the multiple vlueAF sf flseD selet element will e renderedF

preferred_choices
typeX rry defultX rry@A sf this option is spei(edD then suEset of ll of the options will e moved to the top of the selet menuF he following would move the fz option to the topD with visul seprtor etween it nd the rest of the optionsX

TIP

UF eferene houments

ymfony houmenttionD PFH

$builder->add('foo_choices', 'choice', array( 'choices' => array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), 'preferred_choices' => array('baz'), ));
xote tht preferred hoies re only meningful when rendering s selet element @iFeF expnded is flseAF he preferred hoies nd norml hoies re seprted visully y set of dotted lines @iFeF EEEEEEEEEEEEEEEEEEEAF his n e ustomized when rendering the (eldX

wig

{{ form_widget(form.foo_choices, { 'separator': '=====' }) }}


r

<?php echo $view['form']->widget($form['foo_choices'], array('separator' => '=====')) ?> empty_value


typeX string or foolen his option determines whether or not speil empty option @eFgF ghoose n optionA will pper t the top of selet widgetF his option only pplies if oth the expnded nd multiple options re set to flseF

edd n empty vlue with ghoose n option s the textX

$builder->add('states', 'choice', array( 'empty_value' => 'Choose an option', ));


qurntee tht no empty vlue option is displyedX

$builder->add('states', 'choice', array( 'empty_value' => false, ));


sf you leve the emptyvlue option unsetD then lnk @with no textA option will utomtilly e dded if nd only if the required option is flseX

// a blank (with no text) option will be added $builder->add('states', 'choice', array( 'required' => false, ));

UFWF porm ypes eferene

TIQ

ymfony houmenttionD PFH

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF
7.9.17 locale Field Type

he lole type is suset of the ghoieype tht llows the user to selet from lrge list of loles @lngugeCountryAF es n dded onusD the lole nmes re displyed in the lnguge of the userF

TIR

UF eferene houments

ymfony houmenttionD PFH he vlue for eh lole is either the two letter syTQWEI lnguge ode @eFgF frAD or the lnguge ode followed y n undersore @AD then the syQITT ountry ode @eFgF frp for prenhGprneAF X he lole of your user is guessed using voleXXgethefult@A nlike the hoie typeD you don9t need to speify hoies or hoielist option s the (eld type utomtilly uses lrge list of lolesF ou n speify either of these options mnullyD ut then you should just use the hoie type diretlyF endered s snherited options n e vrious tgs @see elet tgD ghekoxes or dio futtonsA

multiple expnded preferredhoies emptyvlue erroruling required lel redonly

rent type glss snherited options hese options inherit from the hoie typeX

hoie ymfonygomponentpormixtensiongoreypevngu

multiple
typeX foolen defultX flse sf trueD the user will e le to selet multiple options @s opposed to hoosing just one optionAF hepending on the vlue of the expnded optionD this will render either selet tg or hekoxes if true nd selet tg or rdio uttons if flseF he returned vlue will e n rryF

expanded
typeX foolen defultX flse

UFWF porm ypes eferene

TIS

ymfony houmenttionD PFH sf set to trueD rdio uttons or hekoxes will e rendered @depending on the multiple vlueAF sf flseD selet element will e renderedF

preferred_choices
typeX rry defultX rry@A sf this option is spei(edD then suEset of ll of the options will e moved to the top of the selet menuF he following would move the fz option to the topD with visul seprtor etween it nd the rest of the optionsX

$builder->add('foo_choices', 'choice', array( 'choices' => array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), 'preferred_choices' => array('baz'), ));
xote tht preferred hoies re only meningful when rendering s selet element @iFeF expnded is flseAF he preferred hoies nd norml hoies re seprted visully y set of dotted lines @iFeF EEEEEEEEEEEEEEEEEEEAF his n e ustomized when rendering the (eldX

wig

{{ form_widget(form.foo_choices, { 'separator': '=====' }) }}


r

<?php echo $view['form']->widget($form['foo_choices'], array('separator' => '=====')) ?> empty_value


typeX string or foolen his option determines whether or not speil empty option @eFgF ghoose n optionA will pper t the top of selet widgetF his option only pplies if oth the expnded nd multiple options re set to flseF

edd n empty vlue with ghoose n option s the textX

$builder->add('states', 'choice', array( 'empty_value' => 'Choose an option', ));


qurntee tht no empty vlue option is displyedX

$builder->add('states', 'choice', array( 'empty_value' => false, ));


TIT UF eferene houments

ymfony houmenttionD PFH sf you leve the emptyvlue option unsetD then lnk @with no textA option will utomtilly e dded if nd only if the required option is flseX

// a blank (with no text) option will be added $builder->add('states', 'choice', array( 'required' => false, )); error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

UFWF porm ypes eferene

TIU

ymfony houmenttionD PFH


7.9.18 money Field Type

enders n input text (eld nd speilizes in hndling sumitted money dtF his (eld type llows you to speify urrenyD whose symol is rendered next to the text (eldF here re lso severl other options for ustomizing how the input nd output of the dt is hndledF endered s yptions input text (eld

urreny divisor preision grouping required lel redonly erroruling

snherited options

rent type glss pield yptions

(eld ymfonygomponentpormixtensiongoreypewoney

currency
typeX string defultX i pei(es the urreny tht the money is eing spei(ed inF his determines the urreny symol tht should e shown y the text oxF hepending on the urreny E the urreny symol my e shown efore or fter the input text (eldF his n lso e set to flse to hide the urreny symolF

divisor
typeX integer defultX I sfD for some resonD you need to divide your strting vlue y numer efore rendering it to the userD you n use the divisor optionF por exmpleX

$builder->add('price', 'money', array( 'divisor' => 100, ));

TIV

UF eferene houments

ymfony houmenttionD PFH sn this seD if the prie (eld is set to WWHHD then the vlue WW will tully e rendered to the userF hen the user sumits the vlue WWD it will e multiplied y IHH nd WWHH will ultimtely e set k on your ojetF

precision
typeX integer defultX P por some resonD if you need some preision other thn P deiml plesD you n modify this vlueF ou proly won9t need to do this unlessD for exmpleD you wnt to round to the nerest dollr @set the preision to HAF

grouping
typeX integer defultX flse he vlue set s the xumerpormtterXXqysxqih ttriute when using the r xumerpormtter lssF snherited yptions hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }}

UFWF porm ypes eferene

TIW

ymfony houmenttionD PFH

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.19 number Field Type

enders n input text (eld nd speilizes in hndling numer inputF his type o'ers di'erent options for the preisionD roundingD nd grouping tht you wnt to use for your numerF endered s yptions input text (eld

roundingmode preision grouping


required lel redonly erroruling

snherited options

rent type glss pield yptions

(eld ymfonygomponentpormixtensiongoreypexume

precision
typeX integer defultX voleEspei( @usully round QA his spei(es how mny deimls will e llowed until the (eld rounds the sumitted vlue @vi roundingmodeAF por exmpleD if preision is set to PD sumitted vlue of PHFIPQ will e rounded toD for exmpleD PHFIP @depending on your roundingmodeAF TPH UF eferene houments

ymfony houmenttionD PFH

rounding_mode
typeX integer defultX sntegerovolizedtringrnsformerXXyxhhyx sf sumitted numer needs to e rounded @sed on the preision optionAD you hve severl on(gurle options for tht roundingF ih option is onstnt on the ymfonygomponentpormixtensiongorehtrnsformersntegerovolizedtringrnsformerX

sntegerovolizedtringrnsformerXXyxhhyx ounding mode to round towrds zeroF sntegerovolizedtringrnsformerXXyxhpvyy ounding mode to round towrds negtive in(nityF sntegerovolizedtringrnsformerXXyxh ounding mode to round wy from zeroF sntegerovolizedtringrnsformerXXyxhgisvsxq ounding mode to round towrds positive in(nityF sntegerovolizedtringrnsformerXXyxhrevphyx ounding mode to round towrds nerest neighor unless oth neighors re equidistntD in whih se round downF sntegerovolizedtringrnsformerXXyxhrevpiix ounding mode to round towrds the nerest neighor unless oth neighors re equidistntD in whih seD round towrds the even neighorF sntegerovolizedtringrnsformerXXyxhrevp ounding mode to round towrds nerest neighor unless oth neighors re equidistntD in whih se round upF

grouping
typeX integer defultX flse he vlue set s the xumerpormtterXXqysxqih ttriute when using the r xumerpormtter lssF snherited yptions hese options inherit from the (eld typeX

required
typeX foolen defultX true UFWF porm ypes eferene TPI

ymfony houmenttionD PFH sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.20 password Field Type

he pssword (eld renders n input pssword text oxF

TPP

UF eferene houments

ymfony houmenttionD PFH endered s yptions snherited options input pssword (eld

lwysempty
mxlength required lel trim redonly erroruling

rent type glss pield yptions

text ymfonygomponentpormixtensiongoreypesswo

always_empty
typeX foolen defultX true sf set to trueD the (eld will lwys render lnkD even if the orresponding (eld hs vlueF hen set to flseD the pssword (eld will e rendered with the vlue ttriute set to its true vlueF ut simplyD if for some reson you wnt to render your pssword (eld with the pssword vlue lredy entered into the oxD set this to flseF snherited yptions hese options inherit from the (eld typeX

max_length
typeX integer his option is used to dd mxlength ttriuteD whih is used y some rowsers to limit the mount of text in (eldF

required
typeX foolen defultX true

UFWF porm ypes eferene

TPQ

ymfony houmenttionD PFH sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} trim


typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.21 percent Field Type

he perent type renders n input text (eld nd speilizes in hndling perentge dtF sf your perentge dt is stored s deiml @eFgF FWSAD you n use this (eld outEofEtheEoxF sf you store your dt s numer @eFgF WSAD you should set the type option to integerF TPR UF eferene houments

ymfony houmenttionD PFH his (eld dds perentge sign 7 fter the input oxF endered s yptions input text (eld

type preision
required lel redonly erroruling

snherited options

rent type glss yptions

(eld ymfonygomponentpormixtensiongoreypeeren

type
typeX string defultX frtionl his ontrols how your dt is stored on your ojetF por exmpleD perentge orresponding to SS7D might e stored s FSS or SS on your ojetF he two types hndle these two sesX

frtionl sf your dt is stored s deiml @eFgF FSSAD use this typeF he dt will e multiplied y IHH efore eing shown to the user @eFgF SSAF he sumitted dt will e divided y IHH on form sumit so tht the deiml vlue is stored @FSSAY integer sf your dt is stored s n integer @eFgF SSAD then use this optionF he rw vlue @SSA is shown to the user nd stored on your ojetF xote tht this only works for integer vluesF

precision
typeX integer defultX H fy defultD the input numers re re roundedF o llow for more deiml plesD use this optionF snherited yptions hese options inherit from the (eld typeX

UFWF porm ypes eferene

TPS

ymfony houmenttionD PFH

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.22 radio Field Type

gretes single rdio uttonF his should lwys e used for (eld tht hs foolen vlueX if the rdio utton is seletedD the (eld will e set to trueD if the utton is not seletedD the vlue will e set to flseF he rdio type isn9t usully used diretlyF wore ommonly it9s used internlly y other types suh s hoieF sf you wnt to hve foolen (eldD use hekoxF

TPT

UF eferene houments

ymfony houmenttionD PFH endered s yptions snherited options input text (eld

vlue
required lel redonly erroruling

rent type glss pield yptions

(eld ymfonygomponentpormixtensiongoreypedio

value
typeX mixed defultX I he vlue tht9s tully used s the vlue for the rdio uttonF his does not 'et the vlue tht9s set on your ojetF snherited yptions hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

UFWF porm ypes eferene

TPU

ymfony houmenttionD PFH

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.23 repeated Field Type

his is speil (eld groupD tht retes two identil (elds whose vlues must mth @or vlidtion error is thrownAF he most ommon use is when you need the user to repet his or her pssword or emil to verify uryF endered s yptions input text (eld y defultD ut see type option

type options (rstnme seondnme

snherited options

invlidmessge invlidmessgeprmeters erroruling

rent type glss ixmple sge

(eld ymfonygomponentpormixtensiongoreypeepet

TPV

UF eferene houments

ymfony houmenttionD PFH

$builder->add('password', 'repeated', array( 'type' => 'password', 'invalid_message' => 'The password elds must match.', 'options' => array('label' => 'Password'), ));
pon suessful form sumitD the vlue entered into oth of the pssword (elds eomes the dt of the pssword keyF sn other wordsD even though two (elds re tully renderedD the end dt from the form is just the single vlue @usully stringA tht you needF he most importnt option is typeD whih n e ny (eld type nd determines the tul type of the two underlying (eldsF he options option is pssed to eh of those individul (eldsD mening E in this exmple E ny option supported y the pssword type n e pssed in this rryF

Validation
yne of the key fetures of the repeted (eld is internl vlidtion @you don9t need to do nything to set this upA tht fores the two (elds to hve mthing vlueF sf the two (elds don9t mthD n error will e shown to the userF he invlidmessge is used to ustomize the error tht will e displyed when the two (elds do not mth eh otherF pield yptions

type
typeX string defultX text he two underlying (elds will e of this (eld typeF por exmpleD pssing type of pssword will render two pssword (eldsF

options
typeX rry defultX rry@A his options rry will e pssed to eh of the two underlying (eldsF sn other wordsD these re the options tht ustomize the individul (eld typesF por exmpleD if the type option is set to psswordD this rry might ontin the options lwysempty or required E oth options tht re supported y the pssword (eld typeF

UFWF porm ypes eferene

TPW

ymfony houmenttionD PFH

rst_name
typeX string defultX (rst his is the tul (eld nme to e used for the (rst (eldF his is mostly meninglessD howeverD s the tul dt entered into oth of the (elds will e ville under the key ssigned to the repeted (eld itself @eFgF psswordAF roweverD if you don9t speify lelD this (eld nme is used to guess the lel for youF

second_name
typeX string defultX seond he sme s (rstnmeD ut for the seond (eldF snherited options hese options inherit from the (eld typeX

invalid_message
typeX string defultX his vlue is not vlid his is the vlidtion error messge tht9s used when the dt entered is determined y internl vlidtion of (eld typeF his might hppenD for exmpleD if the user enters string into time (eld tht nnot e onverted into rel timeF por norml vlidtion messges @suh s when setting minimum length for (eldAD set the vlidtion messges with your vlidtion rules @refereneAF

invalid_message_parameters
typeX rry defultX rry@A hen setting the invlidmessge optionD you my need to inlude some vriles in the stringF his n e done y dding pleholders to tht option nd inluding the vriles in this optionX

$builder->add('some_eld', 'some_type', array( // ... 'invalid_message' => 'You entered an invalid value - it should include %num% letters', 'invalid_message_parameters' => array('%num%' => 6), ));

TQH

UF eferene houments

ymfony houmenttionD PFH

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.24 search Field Type

his renders n `input typea4serh4Gb (eldD whih is text ox with speil funtionlity supported y some rowsersF ed out the input serh (eld t hivesntorwvSForg endered s snherited options input serh (eld mxlength required lel trim redonly erroruling

rent type glss snherited yptions hese options inherit from the (eld typeX

text ymfonygomponentpormixtensiongoreypeerh

max_length
typeX integer his option is used to dd mxlength ttriuteD whih is used y some rowsers to limit the mount of text in (eldF

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF UFWF porm ypes eferene TQI

ymfony houmenttionD PFH his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} trim


typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.25 text Field Type

he text (eld represents the most si input text (eldF

TQP

UF eferene houments

ymfony houmenttionD PFH endered s snherited options input text (eld

mxlength required lel trim redonly erroruling

rent type glss snherited yptions hese options inherit from the (eld typeX

(eld ymfonygomponentpormixtensiongoreypeexty

max_length
typeX integer his option is used to dd mxlength ttriuteD whih is used y some rowsers to limit the mount of text in (eldF

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }}

UFWF porm ypes eferene

TQQ

ymfony houmenttionD PFH

trim
typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.26 textarea Field Type

enders textre rwv elementF endered s snherited options textre tg

mxlength required lel trim redonly erroruling

rent type glss snherited yptions hese options inherit from the (eld typeX

(eld ymfonygomponentpormixtensiongoreypeextr

TQR

UF eferene houments

ymfony houmenttionD PFH

max_length
typeX integer his option is used to dd mxlength ttriuteD whih is used y some rowsers to limit the mount of text in (eldF

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} trim


typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

UFWF porm ypes eferene

TQS

ymfony houmenttionD PFH

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF
7.9.27 time Field Type

e (eld to pture time inputF his n e rendered s text (eldD series of text (elds @eFgF hourD minuteD seondA or series of selet (eldsF he underlying dt n e stored s hteime ojetD stringD timestmp or n rryF nderlying ht ype endered s yptions n e hteimeD stringD timestmpD or rry @see the input optionA n e vrious tgs @see elowA

widget input withseonds hours minutes seonds dttimezone usertimezone

rent type glss fsi sge

form ymfonygomponentpormixtensiongoreypeime

his (eld type is highly on(gurleD ut esy to useF he most importnt options re input nd widgetF uppose tht you hve strtime (eld whose underlying time dt is hteime ojetF he following on(gures the time type for tht (eld s three di'erent hoie (eldsX

$builder->add('startTime', 'time', array( 'input' => 'datetime', 'widget' => 'choice', ));

TQT

UF eferene houments

ymfony houmenttionD PFH he input option must e hnged to mth the type of the underlying dte dtF por exmpleD if the strtime (eld9s dt were unix timestmpD you9d need to set input to timestmpX

$builder->add('startTime', 'time', array( 'input' => 'timestamp', 'widget' => 'choice', ));
he (eld lso supports n rry nd string s vlid input option vluesF pield yptions

widget
typeX string defultX hoie he si wy in whih this (eld should e renderedF gn e one of the followingX

hoieX renders two @or three if withseonds is trueA selet inputsF textX renders two or three text inputs @hourD minuteD seondAF singletextX renders single input of type textF ser9s input will e vlidted ginst the form hhXmm @or hhXmmXss if using seondsAF

input
typeX string defultX dtetime he formt of the input dt E iFeF the formt tht the dte is stored on your underlying ojetF lid vlues reX

string @eFgF IPXIUXPTA dtetime @ hteime ojetA rry @eFgF rry@9hour9 ab IPD 9minute9 ab IUD 9seond9 ab PTAA timestmp @eFgF IQHUPQPHHHA
he vlue tht omes k from the form will lso e normlized k into this formtF

with_seconds
typeX foolen defultX flse

UFWF porm ypes eferene

TQU

ymfony houmenttionD PFH hether or not to inlude seonds in the inputF his will result in n dditionl input to pture seondsF

hours
typeX integer defultX I to PQ vist of hours ville to the hours (eld typeF his option is only relevnt when the widget option is set to hoieF

minutes
typeX integer defultX I to SW vist of minutes ville to the minutes (eld typeF his option is only relevnt when the widget option is set to hoieF

seconds
typeX integer defultX I to SW vist of seonds ville to the seonds (eld typeF his option is only relevnt when the widget option is set to hoieF

data_timezone
typeX string defultX system defult timezone imezone tht the input dt is stored inF his must e one of the r supported timezones

user_timezone
typeX string defultX system defult timezone imezone for how the dt should e shown to the user @nd therefore lso the dt tht the user sumitsAF his must e one of the r supported timezones
7.9.28 timezone Field Type

he timezone type is suset of the ghoieype tht llows the user to selet from ll possile timezonesF

TQV

UF eferene houments

ymfony houmenttionD PFH he vlue for eh timezone is the full timezone nmeD suh s emeriGghigo or iuropeGsstnulF nlike the hoie typeD you don9t need to speify hoies or hoielist option s the (eld type utomtilly uses lrge list of lolesF ou n speify either of these options mnullyD ut then you should just use the hoie type diretlyF endered s snherited options n e vrious tgs @see elet tgD ghekoxes or dio futtonsA

multiple expnded preferredhoies emptyvlue erroruling required lel redonly

rent type glss snherited options hese options inherit from the hoie typeX

hoie ymfonygomponentpormixtensiongoreypeimezo

multiple
typeX foolen defultX flse sf trueD the user will e le to selet multiple options @s opposed to hoosing just one optionAF hepending on the vlue of the expnded optionD this will render either selet tg or hekoxes if true nd selet tg or rdio uttons if flseF he returned vlue will e n rryF

expanded
typeX foolen defultX flse sf set to trueD rdio uttons or hekoxes will e rendered @depending on the multiple vlueAF sf flseD selet element will e renderedF

UFWF porm ypes eferene

TQW

ymfony houmenttionD PFH

preferred_choices
typeX rry defultX rry@A sf this option is spei(edD then suEset of ll of the options will e moved to the top of the selet menuF he following would move the fz option to the topD with visul seprtor etween it nd the rest of the optionsX

$builder->add('foo_choices', 'choice', array( 'choices' => array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), 'preferred_choices' => array('baz'), ));
xote tht preferred hoies re only meningful when rendering s selet element @iFeF expnded is flseAF he preferred hoies nd norml hoies re seprted visully y set of dotted lines @iFeF EEEEEEEEEEEEEEEEEEEAF his n e ustomized when rendering the (eldX

wig

{{ form_widget(form.foo_choices, { 'separator': '=====' }) }}


r

<?php echo $view['form']->widget($form['foo_choices'], array('separator' => '=====')) ?> empty_value


typeX string or foolen his option determines whether or not speil empty option @eFgF ghoose n optionA will pper t the top of selet widgetF his option only pplies if oth the expnded nd multiple options re set to flseF

edd n empty vlue with ghoose n option s the textX

$builder->add('states', 'choice', array( 'empty_value' => 'Choose an option', ));


qurntee tht no empty vlue option is displyedX

$builder->add('states', 'choice', array( 'empty_value' => false, ));


sf you leve the emptyvlue option unsetD then lnk @with no textA option will utomtilly e dded if nd only if the required option is flseX

TRH

UF eferene houments

ymfony houmenttionD PFH

// a blank (with no text) option will be added $builder->add('states', 'choice', array( 'required' => false, ));
hese options inherit from the (eld typeX

required
typeX foolen defultX true sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} read_only


typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF

UFWF porm ypes eferene

TRI

ymfony houmenttionD PFH


7.9.29 url Field Type

he url (eld is text (eld tht prepends the sumitted vlue with given protool @eFgF httpXGGA if the sumitted vlue doesn9t lredy hve protoolF endered s yptions snherited options input url (eld

defultprotool
mxlength required lel trim redonly erroruling

rent type glss pield yptions

text ymfonygomponentpormixtensiongoreyperlyp

default_protocol
typeX string defultX http sf vlue is sumitted tht doesn9t egin with some protool @eFgF httpXGGD ftpXGGD etAD this protool will e prepended to the string when the dt is ound to the formF snherited yptions hese options inherit from the (eld typeX

max_length
typeX integer his option is used to dd mxlength ttriuteD whih is used y some rowsers to limit the mount of text in (eldF

required
typeX foolen defultX true TRP UF eferene houments

ymfony houmenttionD PFH sf trueD n rwvS required ttriute will e renderedF he orresponding lel will lso render with required lssF his is super(il nd independent from vlidtionF et estD if you let ymfony guess your (eld typeD then the vlue of this option will e guessed from your vlidtion informtionF

label
typeX string defultX he lel is guessed from the (eld nme ets the lel tht will e used when rendering the (eldF he lel n lso e diretly set inside the templteX

{{ render_label(form.name, 'Your name') }} trim


typeX foolen defultX true sf trueD the whitespe of the sumitted string vlue will e stripped vi the trim@A funtion when the dt is oundF his gurntees tht if vlue is sumitted with extr whitespeD it will e removed efore the vlue is merged k onto the underlying ojetF

read_only
typeX foolen defultX flse sf this option is trueD the (eld will e rendered with the disled ttriute so tht the (eld is not editleF

error_bubbling
typeX foolen defultX flse sf trueD ny errors for this (eld will e pssed to the prent (eld or formF por exmpleD if set to true on norml (eldD ny errors for tht (eld will e tthed to the min formD not to the spei( (eldF e form is omposed of (eldsD eh of whih re uilt with the help of (eld type @eFgF text typeD hoie typeD etAF ymfonyP omes stndrd with lrge list of (eld types tht n e used in your pplitionF

UFWF porm ypes eferene

TRQ

ymfony houmenttionD PFH


7.9.30 Supported Field Types

he following (eld types re ntively ville in ymfonyPX ext pields

text textre emil integer money numer pssword perent serh url
ghoie pields

hoie entity ountry lnguge lole timezone


hte nd ime pields

dte dtetime time irthdy

TRR

UF eferene houments

ymfony houmenttionD PFH yther pields

hekox (le rdio


pield qroups

olletion repeted
ridden pields

hidden srf
fse pields

(eld form

7.10 Twig Template Form Function Reference

his referene mnul overs ll the possile wig funtions ville for rendering formsF here re severl di'erent funtions villeD nd eh is responsile for rendering di'erent prt of form @eFgF lelsD errorsD widgetsD etAF
7.10.1 form_label(form.name, label, variables)

enders the lel for the given (eldF ou n optionlly pss the spei( lel you wnt to disply s the seond rgumentF

{{ form_label(form.name) }} {# The two following syntaxes are equivalent #} {{ form_label(form.name, 'Your Name', { 'attr': {'class': 'foo'} }) }} {{ form_label(form.name, null, { 'label': 'Your name', 'attr': {'class': 'foo'} }) }}

UFIHF wig emplte porm puntion eferene

TRS

ymfony houmenttionD PFH


7.10.2 form_errors(form.name)

enders ny errors for the given (eldF

{{ form_errors(form.name) }} {# render any "global" errors #} {{ form_errors(form) }}

7.10.3 form_widget(form.name, variables)

enders the rwv widget of given (eldF sf you pply this to n entire form or olletion of (eldsD eh underlying form row will e renderedF

{# render a widget, but add a "foo" class to it #} {{ form_widget(form.name, { 'attr': {'class': 'foo'} }) }}
he seond rgument to formwidget is n rry of vrilesF he most ommon vrile is ttrD whih is n rry of rwv ttriutes to pply to the rwv widgetF sn some sesD ertin types lso hve other templteErelted options tht n e pssedF hese re disussed on typeEyEtype sisF
7.10.4 form_row(form.name, variables)

enders the row of given (eldD whih is the omintion of the (eld9s lelD errors nd widgetF

{# render a eld row, but display a label with text "foo" #} {{ form_row(form.name, { 'label': 'foo' }) }}
he seond rgument to formrow is n rry of vrilesF he templtes provided in symfony only llow to override the lel s shown in the exmple oveF
7.10.5 form_rest(form, variables)

his renders ll (elds tht hve not yet een rendered for the given formF st9s good ide to lwys hve this somewhere inside your form s it9ll render hidden (elds for you nd mke ny (elds you forgot to render more ovious @sine it9ll render the (eld for youAF

{{ form_rest(form) }}

TRT

UF eferene houments

ymfony houmenttionD PFH


7.10.6 form_enctype(form)

sf the form ontins t lest one (le uplod (eldD this will render the required entypea4multiprtGformEdt4 form ttriuteF st9s lwys good ide to inlude this in your form tgX

<form action="{{ path('form_submit') }}" method="post" {{ form_enctype(form) }}>

7.11 Validation Constraints Reference


7.11.1 NotBlank

lidtes tht vlue is not lnkD de(ned s not equl to lnk string nd lso not equl to nullF o fore tht vlue is simply not equl to nullD see the xotxull onstrintF epplies to yptions glss lidtor fsi sge sf you wnted to ensure tht the (rstxme property of n euthor lss were not lnkD you ould do the followingX property or method

messge

ymfonygomponentlidtorgonstrintsxotflnk ymfonygomponentlidtorgonstrintsxotflnkli

ewv

properties: rstName: - NotBlank: ~


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\NotBlank() */ protected $rstName; }
UFIIF lidtion gonstrints eferene TRU

ymfony houmenttionD PFH yptions

message
typeX string defultX his vlue should not e lnk his is the messge tht will e shown if the vlue is lnkF
7.11.2 Blank

lidtes tht vlue is lnkD de(ned s equl to lnk string or equl to nullF o fore tht vlue stritly e equl to nullD see the xull onstrintF o fore tht vlue is not lnkD see xotflnkF epplies to yptions glss lidtor fsi sge sfD for some resonD you wnted to ensure tht the (rstxme property of n euthor lss were lnkD you ould do the followingX property or method

messge

ymfonygomponentlidtorgonstrintsflnk ymfonygomponentlidtorgonstrintsflnklidt

ewv

properties: rstName: - Blank: ~


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Blank() */ protected $rstName; }

TRV

UF eferene houments

ymfony houmenttionD PFH yptions

message
typeX string defultX his vlue should e lnk his is the messge tht will e shown if the vlue is not lnkF
7.11.3 NotNull

lidtes tht vlue is not stritly equl to nullF o ensure tht vlue is simply not lnk @not lnk stringAD see the xotflnk onstrintF epplies to yptions glss lidtor fsi sge sf you wnted to ensure tht the (rstxme property of n euthor lss were not stritly equl to nullD you wouldX property or method

messge

ymfonygomponentlidtorgonstrintsxotxull ymfonygomponentlidtorgonstrintsxotxulllid

ewv

properties: rstName: - NotNull: ~


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\NotNull() */ protected $rstName; }

UFIIF lidtion gonstrints eferene

TRW

ymfony houmenttionD PFH yptions

message
typeX string defultX his vlue should not e null his is the messge tht will e shown if the vlue is nullF
7.11.4 Null

lidtes tht vlue is extly equl to nullF o fore tht property is simply lnk @lnk string or nullAD see the flnk onstrintF o ensure tht property is not nullD see xotxullF epplies to yptions glss lidtor fsi sge sfD for some resonD you wnted to ensure tht the (rstxme property of n euthor lss extly equl to nullD you ould do the followingX property or method

messge

ymfonygomponentlidtorgonstrintsxull ymfonygomponentlidtorgonstrintsxulllidtor

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: rstName: - Null: ~


ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Null() */ protected $rstName; }
TSH UF eferene houments

ymfony houmenttionD PFH

yptions

message
typeX string defultX his vlue should e null his is the messge tht will e shown if the vlue is not nullF
7.11.5 True

lidtes tht vlue is trueF pei(llyD this heks to see if the vlue is extly trueD extly the integer ID or extly the string IF elso see plseF epplies to yptions glss lidtor fsi sge his onstrint n e pplied to properties @eFgF termseepted property on registrtion modelA or to getter methodF st9s most powerful in the ltter seD where you n ssert tht method returns true vlueF por exmpleD suppose you hve the following methodX property or method

messge

ymfonygomponentlidtorgonstrintsrue ymfonygomponentlidtorgonstrintsruelidtor

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; class Author { protected $token; public function isTokenValid() { return $this->token == $this->generateToken(); }

hen you n onstrin this method with rueF

UFIIF lidtion gonstrints eferene

TSI

ymfony houmenttionD PFH

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: getters: tokenValid: - "True": { message: "The token is invalid" }


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { protected $token; /** * @Assert\True(message = "The token is invalid") */ public function isTokenValid() { return $this->token == $this->generateToken(); }

wv

<?xml version="1.0" encoding="UTF-8" ?> <!-- src/Acme/Blogbundle/Resources/cong/validation.xml -->

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/ <class name="Acme\BlogBundle\Entity\Author"> <getter property="tokenValid"> <constraint name="True"> <option name="message">The token is invalid...</option> </constraint> </getter> </class> </constraint-mapping>
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\True;


TSP UF eferene houments

ymfony houmenttionD PFH

class Author { protected $token; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addGetterConstraint('tokenValid', new True(array( 'message' => 'The token is invalid', ))); } public function isTokenValid() { return $this->token == $this->generateToken(); }

sf the isokenlid@A returns flseD the vlidtion will filF yptions

message
typeX string defultX his vlue should e true his messge is shown if the underlying dt is not trueF
7.11.6 False

lidtes tht vlue is flseF pei(llyD this heks to see if the vlue is extly flseD extly the integer HD or extly the string HF elso see rueF epplies to yptions glss lidtor fsi sge he plse onstrint n e pplied to property or getter methodD ut is most ommonly useful in the ltter seF por exmpleD suppose tht you wnt to gurntee tht some stte UFIIF lidtion gonstrints eferene TSQ property or method

messge

ymfonygomponentlidtorgonstrintsplse ymfonygomponentlidtorgonstrintsplselidto

ymfony houmenttionD PFH property is not in dynmi invlidttes rryF pirstD you9d rete getter methodX

protected $state; protectd $invalidStates = array(); public function isStateInvalid() { return in_array($this->state, $this->invalidStates); }
sn this seD the underlying ojet is only vlid if the isttesnvlid method returns flseX

ewv

# src/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author getters: stateInvalid: - "False": message: You've entered an invalid state.
ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\False() */ public function isStateInvalid($message = "You've entered an invalid state.") { // ... } }
X hen using ewvD e sure to surround plse with quotes @4plse4A or else ewv will onvert this into foolen vlueF

yptions

message
typeX string defultX his vlue should e flse TSR UF eferene houments

ymfony houmenttionD PFH his messge is shown if the underlying dt is not flseF
7.11.7 Type

lidtes tht vlue is of spei( dt typeF por exmpleD if vrile should e n rryD you n use this onstrint with the rry type option to vlidte thisF epplies to yptions property or method

type messge

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintsype ymfonygomponentlidtorgonstrintsypelidto

ewv

# src/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: age: - Type: type: integer message: The value {{ value }} is not a valid {{ type }}.
ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Type(type="integer", message="The value {{ value }} is not a valid {{ type }}.") */ protected $age; }

UFIIF lidtion gonstrints eferene

TSS

ymfony houmenttionD PFH yptions

type
typeX string defult option his required option is the fully quli(ed lss nme or one of the r dttypes s determined y r9s is funtionsF

rry ool llle )ot doule int integer long null numeri ojet rel resoure slr string

message
typeX string defultX his vlue should e of type {{ type }} he messge if the underlying dt is not of the given typeF
7.11.8 Email

lidtes tht vlue is vlid emil ddressF he underlying vlue is st to string efore eing vlidtedF

TST

UF eferene houments

ymfony houmenttionD PFH epplies to yptions property or method

messge hekw

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintsimil ymfonygomponentlidtorgonstrintsimillidt

ewv

# src/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: email: - Email: message: The email "{{ value }}" is not a valid email. checkMX: true
ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Email( * message = "The email '{{ value }}' is not a valid email.", * checkMX = true *) */ protected $email; }
yptions

message
typeX string defultX his vlue is not vlid emil ddress his messge is shown if the underlying dt is not vlid emil ddressF

UFIIF lidtion gonstrints eferene

TSU

ymfony houmenttionD PFH

checkMX
typeX foolen defultX flse sf trueD then the hekdnsrr r funtion will e used to hek the vlidity of the w reord of the host of the given emilF
7.11.9 MinLength

lidtes tht the length of string is t lest s long s the given limitF epplies to yptions property or method

limit messge hrset

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintswinvength ymfonygomponentlidtorgonstrintswinvength

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Blog: properties: rstName: - MinLength: { limit: 3, message: Your name must have at least {{ limit}} characters. }
ennottions

// src/Acme/BlogBundle/Entity/Blog.php use Symfony\Component\Validator\Constraints as Assert; class Blog { /** * @Assert\MinLength( * limit=3, * message="Your name must have at least {{ limit}} characters." *) */ protected $summary; }

TSV

UF eferene houments

ymfony houmenttionD PFH

wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Blog"> <property name="summary"> <constraint name="MinLength"> <option name="limit">3</option> <option name="message">Your name must have at least {{ limit}} characters.</option> </constraint> </property> </class>
yptions

limit
typeX integer defult option his required option is the min vlueF lidtion will fil if the length of the give string is less thn this numerF

message
typeX string defultX his vlue is too shortF st should hve {{ limit }} hrters or more he messge tht will e shown if the underlying string hs length tht is shorter thn the limit optionF

charset
typeX hrset defultX pEV sf the r extension mstring is instlledD then the r funtion mstrlen will e used to lulte the length of the stringF he vlue of the hrset option is pssed s the seond rgument to tht funtionF
7.11.10 MaxLength

lidtes tht the length of string is not lrger thn the given limitF

UFIIF lidtion gonstrints eferene

TSW

ymfony houmenttionD PFH epplies to yptions property or method

limit messge hrset

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintswxvength ymfonygomponentlidtorgonstrintswxvength

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Blog: properties: summary: - MaxLength: 100


ennottions

// src/Acme/BlogBundle/Entity/Blog.php use Symfony\Component\Validator\Constraints as Assert; class Blog { /** * @Assert\MaxLength(100) */ protected $summary; }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Blog"> <property name="summary"> <constraint name="MaxLength"> <value>100</value> </constraint> </property> </class>

TTH

UF eferene houments

ymfony houmenttionD PFH yptions

limit
typeX integer defult option his required option is the mx vlueF lidtion will fil if the length of the give string is greter thn this numerF

message
typeX string defultX his vlue is too longF st should hve {{ limit }} hrters or less he messge tht will e shown if the underlying string hs length tht is longer thn the limit optionF

charset
typeX hrset defultX pEV sf the r extension mstring is instlledD then the r funtion mstrlen will e used to lulte the length of the stringF he vlue of the hrset option is pssed s the seond rgument to tht funtionF
7.11.11 Url

lidtes tht vlue is vlid v stringF epplies to yptions property or method

messge protools
ymfonygomponentlidtorgonstrintsrl ymfonygomponentlidtorgonstrintsrllidtor

glss lidtor fsi sge

ewv

# src/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties:

UFIIF lidtion gonstrints eferene

TTI

ymfony houmenttionD PFH

bioUrl: - Url:
ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Url */ protected $bioUrl; }
yptions

message
typeX string defultX his vlue is not vlid v his messge is shown if the v is invlidF

protocols
typeX rry defultX rry@9http9D 9https9A he protools tht will e onsidered to e vlidF por exmpleD if you lso needed ftpXGG type vs to e vlidD you9d rede(ne the protools rryD listing httpD httpsD nd lso ftpF
7.11.12 Regex

lidtes tht vlue mthes regulr expressionF epplies to yptions property or method

pttern mth messge

glss lidtor TTP

ymfonygomponentlidtorgonstrintsegex ymfonygomponentlidtorgonstrintsegexlidt UF eferene houments

ymfony houmenttionD PFH fsi sge uppose you hve desription (eld nd you wnt to verify tht it egins with vlid word hrterF he regulr expression to test for this would e GwCGD inditing tht you9re looking for t lest one or more word hrters t the eginning of your stringX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: description: - Regex: "/^\w+/"


ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Regex("/^\w+/") */ protected $description; }
elterntivelyD you n set the mth option to flse in order to ssert tht given string does not mthF sn the following exmpleD you9ll ssert tht the (rstxme (eld does not ontin ny numers nd give it ustom messgeX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: rstName: - Regex: pattern: "/\d/" match: false message: Your name cannot contain a number
ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity;

UFIIF lidtion gonstrints eferene

TTQ

ymfony houmenttionD PFH

use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Regex( * pattern="/\d/", * match=false, * message="Your name cannot contain a number" *) */ protected $rstName; }
yptions

pattern
typeX string defult option his required option is the regulr expression pttern tht the input will e mthed ginstF fy defultD this vlidtor will fil if the input string does not mth this regulr expression @vi the pregmth r funtionAF roweverD if mth is set to flseD then vlidtion will fil if the input string does mth this ptternF

match
typeX foolen defultX true sf true @or not setAD this vlidtor will pss if the given string mthes the given pttern regulr expressionF roweverD when this option is set to flseD the opposite will ourX vlidtion will pss only if the given string does not mth the pttern regulr expressionF

message
typeX string defultX his vlue is not vlid his is the messge tht will e shown if this vlidtor filsF

TTR

UF eferene houments

ymfony houmenttionD PFH


7.11.13 Ip

lidtes tht vlue is vlid s ddressF fy defultD this will vlidte the vlue s svRD ut numer of di'erent options exist to vlidte s svT nd mny other omintionsF epplies to yptions property or method

version messge
ymfonygomponentlidtorgonstrintssp ymfonygomponentlidtorgonstrintssplidtor

glss lidtor fsi sge

ewv

# src/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: ipAddress: - Ip:


ennottions

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Ip */ protected $ipAddress; }
yptions

version
typeX string defultX R his determines extly how the ip ddress is vlidted nd n tke one of vriety of di'erent vluesX UFIIF lidtion gonstrints eferene TTS

ymfony houmenttionD PFH ell rnges

R E lidtes for svR ddresses T E lidtes for svT ddresses ll E lidtes ll s formts
xo privte rnges

Rnopriv E lidtes for svR ut without privte s rnges Tnopriv E lidtes for svT ut without privte s rnges llnopriv E lidtes for ll s formts ut without privte s rnges
xo reserved rnges

Rnores E lidtes for svR ut without reserved s rnges Tnores E lidtes for svT ut without reserved s rnges llnores E lidtes for ll s formts ut without reserved s rnges
ynly puli rnges

Rpuli E lidtes for svR ut without privte nd reserved rnges Tpuli E lidtes for svT ut without privte nd reserved rnges llpuli E lidtes for ll s formts ut without privte nd reserved rnges

message
typeX string defultX his is not vlid s ddress his messge is shown if the string is not vlid s ddressF
7.11.14 Max

lidtes tht given numer is less thn some mximum numerF epplies to yptions property or method

limit messge invlidwessge

glss lidtor

ymfonygomponentlidtorgonstrintswx ymfonygomponentlidtorgonstrintswxlidtor

TTT

UF eferene houments

ymfony houmenttionD PFH fsi sge o verify tht the ge (eld of lss is not greter thn SHD you might dd the followingX

ewv

# src/Acme/EventBundle/Resources/cong/validation.yml Acme\EventBundle\Entity\Participant: properties: age: - Max: { limit: 50, message: You must be 50 or under to enter. }
ennottions

// src/Acme/EventBundle/Entity/Participant.php use Symfony\Component\Validator\Constraints as Assert; class Participant { /** * @Assert\Max(limit = 50, message = "You must be 50 or under to enter.") */ protected $age; }
yptions

limit
typeX integer defult option his required option is the mx vlueF lidtion will fil if the given vlue is greter thn this mx vlueF

message
typeX string defultX his vlue should e {{ limit }} or less he messge tht will e shown if the underlying vlue is greter thn the limit optionF

invalidMessage
typeX string defultX his vlue should e vlid numer

UFIIF lidtion gonstrints eferene

TTU

ymfony houmenttionD PFH he messge tht will e shown if the underlying vlue is not numer @per the isnumeri r funtionAF
7.11.15 Min

lidtes tht given numer is greter thn some minimum numerF epplies to yptions property or method

limit messge invlidwessge

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintswin ymfonygomponentlidtorgonstrintswinlidtor

o verify tht the ge (eld of lss is IV or greterD you might dd the followingX

ewv

# src/Acme/EventBundle/Resources/cong/validation.yml Acme\EventBundle\Entity\Participant: properties: age: - Min: { limit: 18, message: You must be 18 or older to enter. }
ennottions

// src/Acme/EventBundle/Entity/Participant.php use Symfony\Component\Validator\Constraints as Assert; class Participant { /** * @Assert\Min(limit = "18", message = "You must be 18 or older to enter") */ protected $age; }

TTV

UF eferene houments

ymfony houmenttionD PFH yptions

limit
typeX integer defult option his required option is the min vlueF lidtion will fil if the given vlue is less thn this min vlueF

message
typeX string defultX his vlue should e {{ limit }} or more he messge tht will e shown if the underlying vlue is less thn the limit optionF

invalidMessage
typeX string defultX his vlue should e vlid numer he messge tht will e shown if the underlying vlue is not numer @per the isnumeri r funtionAF
7.11.16 Date

lidtes tht vlue is vlid dteD mening either hteime ojet or string @or n ojet tht n e st into stringA tht follows vlid EwwEhh formtF epplies to yptions glss lidtor fsi sge property or method

messge

ymfonygomponentlidtorgonstrintshte ymfonygomponentlidtorgonstrintshtelidto

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: birthday: - Date: ~

UFIIF lidtion gonstrints eferene

TTW

ymfony houmenttionD PFH

ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Date() */ protected $birthday; }
yptions

message
typeX string defultX his vlue is not vlid dte his messge is shown if the underlying dt is not vlid dteF
7.11.17 DateTime

lidtes tht vlue is vlid dtetimeD mening either hteime ojet or string @or n ojet tht n e st into stringA tht follows vlid EwwEhh rrXwwX formtF epplies to yptions glss lidtor fsi sge property or method

messge

ymfonygomponentlidtorgonstrintshteime ymfonygomponentlidtorgonstrintshteimel

ewv

# src/Acme/EventBundle/Resources/cong/validation.yml Acme\BlobBundle\Entity\Author: properties: createdAt: - DateTime: ~


ennottions
TUH UF eferene houments

ymfony houmenttionD PFH

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\DateTime() */ protected $createdAt; }
yptions

message
typeX string defultX his vlue is not vlid dtetime his messge is shown if the underlying dt is not vlid dtetimeF
7.11.18 Time

lidtes tht vlue is vlid time string with formt rrXwwXF lidtes tht vlue is vlid timeD mening either hteime ojet or string @or n ojet tht n e st into stringA tht follows vlid rrXwwX formtF epplies to yptions glss lidtor fsi sge uppose you hve n ivent lssD with strtet (eld tht is the time of the dy when the event strtsX property or method

messge

ymfonygomponentlidtorgonstrintsime ymfonygomponentlidtorgonstrintsimelidto

ewv

# src/Acme/EventBundle/Resources/cong/validation.yml Acme\EventBundle\Entity\Event: properties:


UFIIF lidtion gonstrints eferene TUI

ymfony houmenttionD PFH

startsAt: - Time: ~
ennottions

// src/Acme/EventBundle/Entity/Event.php namespace Acme\EventBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Event { /** * @Assert\Time() */ protected $startsAt; }
yptions

message
typeX string defultX his vlue is not vlid time his messge is shown if the underlying dt is not vlid timeF
7.11.19 Choice

his onstrint is used to ensure tht the given vlue is one of given set of vlid hoiesF st n lso e used to vlidte tht eh item in n rry of items is one of those vlid hoiesF

TUP

UF eferene houments

ymfony houmenttionD PFH epplies to yptions property or method

hoies llk multiple min mx messge multiplewessge minwessge mxwessge strit

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintsghoie ymfonygomponentlidtorgonstrintsghoielid

he si ide of this onstrint is tht you supply it with n rry of vlid vlues @this n e done in severl wysA nd it vlidtes tht the vlue of the given property exists in tht rryF sf your vlid hoie list is simpleD you n pss them in diretly vi the hoies optionX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: gender: - Choice: choices: [male, female] message: Choose a valid gender.
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\EntityAuthor"> <property name="gender"> <constraint name="Choice"> <option name="choices"> <value>male</value> <value>female</value> </option> <option name="message">Choose a valid gender.</option> </constraint>

UFIIF lidtion gonstrints eferene

TUQ

ymfony houmenttionD PFH

</property> </class>
ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Choice(choices = {"male", "female"}, message = "Choose a valid gender.") */ protected $gender; }
r

// src/Acme/BlogBundle/EntityAuthor.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\Choice; class Author { protected $gender; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('gender', new Choice( 'choices' => array('male', 'female'), 'message' => 'Choose a valid gender', )); }

upplying the ghoies with gllk puntion ou n lso use llk funtion to speify your optionsF his is useful if you wnt to keep your hoies in some entrl lotion so thtD for exmpleD you n esily ess those hoies for vlidtion or for uilding selet form elementF

// src/Acme/BlogBundle/Entity/Author.php class Author { public static function getGenders() {


TUR UF eferene houments

ymfony houmenttionD PFH

return array('male', 'female');

ou n pss the nme of this method to the llk option of the ghoie onstrintF

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: gender: - Choice: { callback: getGenders }


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Choice(callback = "getGenders") */ protected $gender; }
wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Author"> <property name="gender"> <constraint name="Choice"> <option name="callback">getGenders</option> </constraint> </property> </class>
sf the stti llk is stored in di'erent lssD for exmple tilD you n pss the lss nme nd the method s n rryF

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: properties: gender: - Choice: { callback: [Util, getGenders] }


UFIIF lidtion gonstrints eferene TUS

ymfony houmenttionD PFH

wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Author"> <property name="gender"> <constraint name="Choice"> <option name="callback"> <value>Util</value> <value>getGenders</value> </option> </constraint> </property> </class>
ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Choice(callback = {"Util", "getGenders"}) */ protected $gender; }
eville yptions

choices
typeX rry defult option e required option @unless llk is spei(edA E this is the rry of options tht should e onsidered in the vlid setF he input vlue will e mthed ginst this rryF

callback
typeX string|rry|glosure his is llk method tht n e used insted of the hoies option to return the hoies rryF ee upplying the ghoies with gllk puntion for detils on its usgeF

TUT

UF eferene houments

ymfony houmenttionD PFH

multiple
typeX foolen defultX flse sf this option is trueD the input vlue is expeted to e n rry insted of singleD slr vlueF he onstrint will hek tht eh vlue of the input rry n e found in the rry of vlid hoiesF sf even one of the input vlues nnot e foundD the vlidtion will filF

min
typeX integer sf the multiple option is trueD then you n use the min option to fore t lest numer of vlues to e seletedF por exmpleD if min is QD ut the input rry only ontins P vlid itemsD the vlidtion will filF

max
typeX integer sf the multiple option is trueD then you n use the mx option to fore no more thn numer of vlues to e seletedF por exmpleD if mx is QD ut the input rry ontins R vlid itemsD the vlidtion will filF

message
typeX string defultX he vlue you seleted is not vlid hoie his is the messge tht you will reeive if the multiple option is set to flseD nd the underlying vlue is not in the vlid rry of hoiesF

multipleMessage
typeX string defultX yne or more of the given vlues is invlid his is the messge tht you will reeive if the multiple option is set to trueD nd one of the vlues on the underlying rry eing heked is not in the rry of vlid hoiesF

minMessage
typeX string defultX ou must selet t lest {{ limit }} hoies

UFIIF lidtion gonstrints eferene

TUU

ymfony houmenttionD PFH his is the vlidtion error messge tht9s displyed when the user hooses too few hoies per the min optionF

maxMessage
typeX string defultX ou must selet t most {{ limit }} hoies his is the vlidtion error messge tht9s displyed when the user hooses too mny options per the mx optionF

strict
typeX foolen defultX flse sf trueD the vlidtor will lso hek the type of the input vlueF pei(llyD this vlue is pssed to s the third rgument to the r inrry method when heking to see if vlue is in the vlid hoies rryF
7.11.20 Collection

his onstrint is used when the underlying dt is olletion @iFeF n rry or n ojet tht implements rversle nd erryeessAD ut you9d like to vlidte di'erent keys of tht olletion in di'erent wysF por exmpleD you might vlidte the emil key using the imil onstrint nd the inventory key of the olletion with the win onstrintF his onstrint n lso mke sure tht ertin olletion keys re present nd tht extr keys re not presentF epplies to yptions property or method (elds llowixtrpields extrpieldswessge llowwissingpields missingpieldswessge

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintsgolletion ymfonygomponentlidtorgonstrintsgolletionl

he golletion onstrint llows you to vlidte the di'erent keys of olletion individullyF ke the following exmpleX TUV UF eferene houments

ymfony houmenttionD PFH

namespace Acme\BlogBundle\Entity; class Author { protected $proleData = array( 'personal_email', 'short_bio', ); public function setProleData($key, $value) { $this->proleData[$key] = $value; }

o vlidte tht the personlemil element of the pro(leht rry property is vlid emil ddress nd tht the shortio element is not lnk ut is no longer thn IHH hrters in lengthD you would do the followingX

ewv

properties: proleData: - Collection: elds: personal_email: Email short_bio: - NotBlank - MaxLength: limit: 100 message: Your short bio is too long! allowMissingelds: true
ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\Collection( * elds = { * "personal_email" = @Assert\Email, * "short_bio" = { * @Assert\NotBlank(), * @Assert\MaxLength( * limit = 100,
UFIIF lidtion gonstrints eferene TUW

ymfony houmenttionD PFH

* message = "Your bio is too long!" * ) * } * }, * allowMissingelds = true *) */ protected $proleData = array( 'personal_email', 'short_bio', );

wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Author"> <property name="proleData"> <constraint name="Collection"> <option name="elds"> <value key="personal_email"> <constraint name="Email" /> </value> <value key="short_bio"> <constraint name="NotBlank" /> <constraint name="MaxLength"> <option name="limit">100</option> <option name="message">Your bio is too long!</option> </constraint> </value> </option> <option name="allowMissingFields">true</option> </constraint> </property> </class>
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\MaxLength; class Author { private $options = array();
TVH UF eferene houments

ymfony houmenttionD PFH

public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('proleData', new Collection(array( 'elds' => array( 'personal_email' => arraynew Email(), 'lastName' => array(new NotBlank(), new MaxLength(100)), ), 'allowMissingFields' => true, ))); }

Presence and Absence of Fields


fy defultD this onstrint vlidtes more thn simply whether or not the individul (elds in the olletion pss their ssigned onstrintsF sn ftD if ny keys of olletion re missing or if there re ny unreognized keys in the olletionD vlidtion errors will e thrownF sf you would like to llow for keys to e sent from the olletion or if you would like extr keys to e llowed in the olletionD you n modify the llowwissingpields nd llowixtrpields options respetivelyF sn the ove exmpleD the llowwissingpields option ws set to trueD mening tht if either of the personlemil or shortio elements were missing from the 6personlht propertyD no vlidtion error would ourF yptions

elds
typeX rry defult option his option is requiredD nd is n ssoitive rry de(ning ll of the keys in the olletion ndD for eh keyD extly whih vlidtor@sA should e exeuted ginst tht element of the olletionF

allowExtraFields
typeX foolen defultX flse sf this option is set to flse nd the underlying olletion ontins one or more elements tht re not inluded in the (elds optionD vlidtion error will e returnedF sf set to trueD extr (elds re okF

UFIIF lidtion gonstrints eferene

TVI

ymfony houmenttionD PFH

extraFieldsMessage
typeX foolen defultX he (elds {{ (elds }} were not expeted he messge shown if llowixtrpields is flse nd n extr (eld is detetedF

allowMissingFields
typeX foolen defultX flse sf this option is set to flse nd one or more (elds from the (elds option re not present in the underlying olletionD vlidtion error will e returnedF sf set to trueD it9s ok if some (elds in the (elds option re not present in the underlying olletionF

missingFieldsMessage
typeX foolen defultX he (elds {{ (elds }} re missing he messge shown if llowwissingpields is flse nd one or more (elds re missing from the underlying olletionF
7.11.21 UniqueEntity

lidtes tht prtiulr (eld @or (eldsA in hotrine entity re uniqueF his is ommonly usedD for exmpleD to prevent new user to register using n emil ddress tht lredy exists in the systemF epplies to yptions lss

(elds messge em

glss lidtor fsi sge

ymfonyfridgehotrinelidtorgonstrintsniquei ymfonyfridgehotrinelidtorgonstrintsniquei

uppose you hve n emeserfundle with ser entity tht hs n emil (eldF ou n use the nique onstrint to gurntee tht the emil (eld remins unique etween ll of the onstrins in your user tleX

ennottions

TVP

UF eferene houments

ymfony houmenttionD PFH

// Acme/UserBundle/Entity/User.php use Symfony\Component\Validator\Constraints as Assert; use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @DoctrineAssert\UniqueEntity("email") */ class Author { /** * @var string $email * * @ORM\Column(name="email", type="string", length=255, unique=true) * @Assert\Email() */ protected $email; } // ...

ewv

# src/Acme/UserBundle/Resources/cong/validation.yml constraints: - UniqueEntity: email


yptions

elds
typeX rry|string defult option his required option is the (eld @or list of (eldsA on whih this entity should e uniqueF por exmpleD you ould speify tht oth the emil nd nme (elds in the ser exmple ove should e uniqueF

message
typeX string defultX his vlue is lredy usedF he messge tht9s displyed with this onstrint filsF

UFIIF lidtion gonstrints eferene

TVQ

ymfony houmenttionD PFH

em
typeX string he nme of the entity mnger to use for mking the query to determine the uniquenessF sf left lnkD the defult entity mnger will e usedF
7.11.22 Language

lidtes tht vlue is vlid lnguge odeF epplies to yptions glss lidtor fsi sge property or method

messge

ymfonygomponentlidtorgonstrintsvnguge ymfonygomponentlidtorgonstrintsvngugeli

ewv

# src/UserBundle/Resources/cong/validation.yml Acme\UserBundle\Entity\User: properties: preferredLanguage: - Language:


ennottions

// src/Acme/UserBundle/Entity/User.php namespace Acme\UserBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class User { /** * @Assert\Language */ protected $preferredLanguage; }

TVR

UF eferene houments

ymfony houmenttionD PFH yptions

message
typeX string defultX his vlue is not vlid lnguge his messge is shown if the string is not vlid lnguge odeF
7.11.23 Locale

lidtes tht vlue is vlid loleF he vlue for eh lole is either the two letter syTQWEI lnguge ode @eFgF frAD or the lnguge ode followed y n undersore @AD then the syQITT ountry ode @eFgF frp for prenhGprneAF epplies to yptions glss lidtor fsi sge property or method

messge

ymfonygomponentlidtorgonstrintsvole ymfonygomponentlidtorgonstrintsvolelidt

ewv

# src/UserBundle/Resources/cong/validation.yml Acme\UserBundle\Entity\User: properties: locale: - Locale:


ennottions

// src/Acme/UserBundle/Entity/User.php namespace Acme\UserBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class User { /** * @Assert\Locale */ protected $locale; }
UFIIF lidtion gonstrints eferene TVS

ymfony houmenttionD PFH

yptions

message
typeX string defultX his vlue is not vlid lole his messge is shown if the string is not vlid loleF
7.11.24 Country

lidtes tht vlue is vlid twoEletter ountry odeF epplies to yptions glss lidtor fsi sge property or method

messge

ymfonygomponentlidtorgonstrintsgountry ymfonygomponentlidtorgonstrintsgountrylid

ewv

# src/UserBundle/Resources/cong/validation.yml Acme\UserBundle\Entity\User: properties: country: - Country:


ennottions

// src/Acme/UserBundle/Entity/User.php namespace Acme\UserBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class User { /** * @Assert\Country */ protected $country; }
TVT UF eferene houments

ymfony houmenttionD PFH yptions

message
typeX string defultX his vlue is not vlid ountry his messge is shown if the string is not vlid ountry odeF
7.11.25 File

lidtes tht vlue is vlid (leD whih n e one of the followingX

e string @or ojet with totring@A methodA pth to n existing (leY e vlid ymfonygomponentrttppoundtionpilepile ojet @inluding ojets of lss ymfonygomponentrttppoundtionpileplodedpileAF
his onstrint is ommonly used in forms with the (le form typeF X sf the (le you9re vlidting is n imgeD try the smge onstrintF epplies to yptions property or method

mxize mimeypes mxizewessge mimeypeswessge notpoundwessge notedlewessge uplodsniizeirrorwessge uplodpormizeirrorwessge uplodirrorwessge

glss lidtor fsi sge

ymfonygomponentlidtorgonstrintspile ymfonygomponentlidtorgonstrintspilelidtor

his onstrint is most ommonly used on property tht will e rendered in form s (le form typeF por exmpleD suppose you9re reting n uthor form where you n uplod io hp for the uthorF sn your formD the iopile property would e (le typeF he euthor lss might look s followsX

UFIIF lidtion gonstrints eferene

TVU

ymfony houmenttionD PFH

// src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; use Symfony\Component\HttpFoundation\File\File; class Author { protected $bioFile; public function setBioFile(File $le = null) { $this->bioFile = $le; } public function getBioFile() { return $this->bioFile; }

o gurntee tht the iopile pile ojet is vlidD nd tht it is elow ertin (le size nd vlid hpD dd the followingX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author properties: bioFile: - File: maxSize: 1024k mimeTypes: [application/pdf, application/x-pdf] mimeTypesMessage: Please upload a valid PDF
ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; class Author { /** * @Assert\File( * maxSize = "1024k", * mimeTypes = {"application/pdf", "application/x-pdf"}, * mimeTypesMessage = "Please upload a valid PDF" *) */
TVV UF eferene houments

ymfony houmenttionD PFH

protected $bioFile;

wv

<!-- src/Acme/BlogBundle/Resources/cong/validation.xml --> <class name="Acme\BlogBundle\Entity\Author"> <property name="bioFile"> <constraint name="File"> <option name="maxSize">1024k</option> <option name="mimeTypes"> <value>application/pdf</value> <value>application/x-pdf</value> </option> <option name="mimeTypesMessage">Please upload a valid PDF</option> </constraint> </property> </class>
r

// src/Acme/BlogBundle/Entity/Author.php // ... use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\File; class Author { // ... public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('bioFile', new File(array( 'maxSize' => '1024k', 'mimeTypes' => array( 'application/pdf', 'application/x-pdf', ), 'mimeTypesMessage' => 'Please upload a valid PDF', ))); }

he iopile property is vlidted to gurntee tht it is rel (leF sts size nd mime type re lso vlidted euse the pproprite options hve een spei(edF

UFIIF lidtion gonstrints eferene

TVW

ymfony houmenttionD PFH yptions

maxSize
typeX mixed sf setD the size of the underlying (le must e elow this (le size in order to e vlidF he size of the (le n e given in one of the following formtsX

ytesX o speify the mxize in ytesD pss vlue tht is entirely numeri @eFgF RHWTAY kiloytesX o speify the mxize in kiloytesD pss numer nd su0x it with lowerse k @eFgF PHHkAY megytesX o speify the mxize in megytesD pss numer nd su0x it with pitl w @eFgF RwAF

mimeTypes
typeX rry or string sf setD the vlidtor will hek tht the mime type of the underlying (le is equl to the given mime type @if stringA or exists in the olletion of given mime types @if n rryAF

maxSizeMessage
typeX string defultX he (le is too lrge @{{ size }}AF ellowed mximum size is {{ limit }} he messge displyed if the (le is lrger thn the mxize optionF

mimeTypesMessage
typeX string defultX he mime type of the (le is invlid @{{ type }}AF ellowed mime types re {{ types }} he messge displyed if the mime type of the (le is not vlid mime type per the mimeypes optionF

notFoundMessage
typeX string defultX he (le ould not e found he messge displyed if no (le n e found t the given pthF his error is only likely if the underlying vlue is string pthD s pile ojet nnot e onstruted with n invlid (le pthF TWH UF eferene houments

ymfony houmenttionD PFH

notReadableMessage
typeX string defultX he (le is not redle he messge displyed if the (le existsD ut the r isredle funtion fils when pssed the pth to the (leF

uploadIniSizeErrorMessage
typeX string defultX he (le is too lrgeF ellowed mximum size is {{ limit }} he messge tht is displyed if the uploded (le is lrger thn the uplodmx(lesize rFini settingF

uploadFormSizeErrorMessage
typeX string defultX he (le is too lrge he messge tht is displyed if the uploded (le is lrger thn llowed y the rwv (le input (eldF

uploadErrorMessage
typeX string defultX he (le ould not e uploded he messge tht is displyed if the uploded (le ould not e uploded for some unknown resonD suh s the (le uplod filed or it ouldn9t e written to diskF
7.11.26 Image

he smge onstrint works extly like the pile onstrintD exept tht its mimeypes nd mimeypeswessge options re utomtilly setup to work for imge (les spei(llyF ee the pile onstrint for the ulk of the doumenttion on this onstrintF yptions his onstrint shres ll of its options with the pile onstrintF st doesD howeverD modify two of the defult option vluesX

UFIIF lidtion gonstrints eferene

TWI

ymfony houmenttionD PFH

mimeTypes
typeX rry or string defultX n rry of jpgD gif nd png imge mime types

mimeTypesMessage
typeX string defultX his (le is not vlid imge
7.11.27 Callback

he purpose of the gllk ssertion is to let you rete ompletely ustom vlidtion rules nd to ssign ny vlidtion errors to spei( (elds on your ojetF sf you9re using vlidtion with formsD this mens tht you n mke these ustom errors disply next to spei( (eldD insted of simply t the top of your formF his proess works y speifying one or more llk methodsD eh of whih will e lled during the vlidtion proessF ih of those methods n do nythingD inluding reting nd ssigning vlidtion errorsF X e llk method itself doesn9t fil or return ny vlueF snstedD s you9ll see in the exmpleD llk method hs the ility to diretly dd vlidtor violtionsF epplies to yptions glss lidtor etup lss

methods

ymfonygomponentlidtorgonstrintsgllk ymfonygomponentlidtorgonstrintsgllklid

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: constraints: - Callback: methods: [isAuthorValid]


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert;


TWP UF eferene houments

ymfony houmenttionD PFH

/** * @Assert\Callback(methods={"isAuthorValid"}) */ class Author { }


he gllk wethod he llk method is pssed speil ixeutiongontext ojetF ou n set violtions diretly on this ojet nd determine to whih (eld those errors should e ttriutedX

// ... use Symfony\Component\Validator\ExecutionContext; class Author { // ... private $rstName; public function isAuthorValid(ExecutionContext $context) { // somehow you have an array of "fake names" $fakeNames = array(); // check if the name is actually a fake name if (in_array($this->getFirstName(), $fakeNames)) { $property_path = $context->getPropertyPath() . '.rstName'; $context->setPropertyPath($property_path); $context->addViolation('This name sounds totally fake!', array(), null); }

yptions

methods
typeX rry defultX rry@A defult option his is n rry of the methods tht should e exeuted during the vlidtion proessF ih method n e one of the following formtsX IF tring method nme

UFIIF lidtion gonstrints eferene

TWQ

ymfony houmenttionD PFH sf the nme of method is simple string @eFgF iseuthorlidAD tht method will e lled on the sme ojet tht9s eing vlidted nd the ixeutiongontext will e the only rgument @see the ove exmpleAF PF tti rry llk ih method n lso e spei(ed s stndrd rry llkX

ewv

# src/Acme/BlogBundle/Resources/cong/validation.yml Acme\BlogBundle\Entity\Author: constraints: - Callback: methods: - [Acme\BlogBundle\MyStaticValidatorClass, isAuthorValid]


ennottions

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Constraints as Assert; /** * @Assert\Callback(methods={ * { "Acme\BlogBundle\MyStaticValidatorClass", "isAuthorValid"} * }) */ class Author { }
r

// src/Acme/BlogBundle/Entity/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\Callback; class Author { public $name; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addConstraint(new Callback(array( 'methods' => array('isAuthorValid'), )));
TWR UF eferene houments

ymfony houmenttionD PFH

sn this seD the stti method iseuthorlid will e lled on the emeflogfundlewyttilidtorglss lssF st9s pssed oth the originl ojet eing vlidted @eFgF euthorA s well s the ixeutiongontextX

namespace Acme\BlogBundle; use Symfony\Component\Validator\ExecutionContext; use Acme\BlogBundle\Entity\Author; class MyStaticValidatorClass { static public function isAuthorValid(Author $author, ExecutionContext $context) { // ... } }
X sf you speify your gllk onstrint vi rD then you lso hve the option to mke your llk either r losure or nonE stti llkF st is not urrently possileD howeverD to speify servie s onstrintF o vlidte using servieD you should rete ustom vlidtion onstrint nd dd tht new onstrint to your lssF

7.11.28 All

hen pplied to n rry @or rversle ojetAD this onstrint llows you to pply olletion of onstrints to eh element of the rryF epplies to yptions glss lidtor fsi sge uppose tht you hve n rry of stringsD nd you wnt to vlidte eh entry in tht rryX property or method

onstrints
ymfonygomponentlidtorgonstrintsell ymfonygomponentlidtorgonstrintselllidtor

ewv

UFIIF lidtion gonstrints eferene

TWS

ymfony houmenttionD PFH

# src/UserBundle/Resources/cong/validation.yml Acme\UserBundle\Entity\User: properties: favoriteColors: - All: - NotBlank: ~ - MinLength: 5


ennottions

// src/Acme/UserBundle/Entity/User.php namespace Acme\UserBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class User { /** * @Assert\All({ * @Assert\NotBlank * @Assert\MinLength(5), * }) */ protected $favoriteColors = array(); }
xowD eh entry in the fvoritegolors rry will e vlidted to not e lnk nd to e t lest S hrters longF yptions

constraints
typeX rry defult option his required option is the rry of vlidtion onstrints tht you wnt to pply to eh element of the underlying rryF
7.11.29 UserPassword

PFIF his vlidtes tht n input vlue is equl to the urrent uthentited user9s psswordF his is useful in form where user n hnge his psswordD ut needs to enter his old pssword for seurityF

TWT

UF eferene houments

ymfony houmenttionD PFH X his should not e used vlidte login formD sine this is done utomtilly y the seurity systemF hen pplied to n rry @or rversle ojetAD this onstrint llows you to pply olletion of onstrints to eh element of the rryF epplies to yptions glss lidtor fsi sge uppose you hve sswordghnge lssD tht9s used in form where the user n hnge his pssword y entering his old pssword nd new psswordF his onstrint will vlidte tht the old pssword mthes the user9s urrent psswordX property or method

messge

ymfonygomponentlidtorgonstrintsserssword ymfonyfundleeurityfundlelidtorgonstrints

ewv

# src/UserBundle/Resources/cong/validation.yml Acme\UserBundle\Form\Model\ChangePassword: properties: oldPassword: - UserPassword: message: "Wrong value for your current password"
ennottions

// src/Acme/UserBundle/Form/Model/ChangePassword.php namespace Acme\UserBundle\Form\Model; use Symfony\Component\Validator\Constraints as Assert; class ChangePassword { /** * @Assert\UserPassword( * message = "Wrong value for your current password" *) */ protected $oldPassword; }

UFIIF lidtion gonstrints eferene

TWU

ymfony houmenttionD PFH yptions

message
typeX messge defultX his vlue should e the user urrent pssword his is the messge tht9s displyed when the underlying string does not mth the urrent user9s psswordF
7.11.30 Valid

his onstrint is used to enle vlidtion on ojets tht re emedded s properties on n ojet eing vlidtedF his llows you to vlidte n ojet nd ll suEojets ssoited with itF epplies to yptions glss fsi sge sn the following exmpleD we rete two lsses euthor nd eddress tht oth hve onstrints on their propertiesF purthermoreD euthor stores n eddress instne in the 6ddress propertyF property or method

trverse
ymfonygomponentlidtorgonstrintsype

// src/Acme/HelloBundle/Address.php class Address { protected $street; protected $zipCode; } // src/Acme/HelloBundle/Author.php class Author { protected $rstName; protected $lastName; protected $address; }
ewv

TWV

UF eferene houments

ymfony houmenttionD PFH

# src/Acme/HelloBundle/Resources/cong/validation.yml Acme\HelloBundle\Address: properties: street: - NotBlank: ~ zipCode: - NotBlank: ~ - MaxLength: 5 Acme\HelloBundle\Author: properties: rstName: - NotBlank: ~ - MinLength: 4 lastName: - NotBlank: ~
wv

<!-- src/Acme/HelloBundle/Resources/cong/validation.xml --> <class name="Acme\HelloBundle\Address"> <property name="street"> <constraint name="NotBlank" /> </property> <property name="zipCode"> <constraint name="NotBlank" /> <constraint name="MaxLength">5</constraint> </property> </class> <class name="Acme\HelloBundle\Author"> <property name="rstName"> <constraint name="NotBlank" /> <constraint name="MinLength">4</constraint> </property> <property name="lastName"> <constraint name="NotBlank" /> </property> </class>
ennottions

// src/Acme/HelloBundle/Address.php use Symfony\Component\Validator\Constraints as Assert; class Address { /**


UFIIF lidtion gonstrints eferene TWW

ymfony houmenttionD PFH

* @Assert\NotBlank() */ protected $street; /** * @Assert\NotBlank * @Assert\MaxLength(5) */ protected $zipCode;

// src/Acme/HelloBundle/Author.php class Author { /** * @Assert\NotBlank * @Assert\MinLength(4) */ protected $rstName; /** * @Assert\NotBlank */ protected $lastName; } protected $address;

// src/Acme/HelloBundle/Address.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\MaxLength; class Address { protected $street; protected $zipCode; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('street', new NotBlank()); $metadata->addPropertyConstraint('zipCode', new NotBlank()); $metadata->addPropertyConstraint('zipCode', new MaxLength(5)); }
UHH UF eferene houments

ymfony houmenttionD PFH

} // src/Acme/HelloBundle/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\MinLength; class Author { protected $rstName; protected $lastName; protected $address; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('rstName', new NotBlank()); $metadata->addPropertyConstraint('rstName', new MinLength(4)); $metadata->addPropertyConstraint('lastName', new NotBlank()); }

ith this mppingD it is possile to suessfully vlidte n uthor with n invlid ddressF o prevent thtD dd the lid onstrint to the 6ddress propertyF

ewv

# src/Acme/HelloBundle/Resources/cong/validation.yml Acme\HelloBundle\Author: properties: address: - Valid: ~


wv

<!-- src/Acme/HelloBundle/Resources/cong/validation.xml --> <class name="Acme\HelloBundle\Author"> <property name="address"> <constraint name="Valid" /> </property> </class>
ennottions

// src/Acme/HelloBundle/Author.php use Symfony\Component\Validator\Constraints as Assert;

UFIIF lidtion gonstrints eferene

UHI

ymfony houmenttionD PFH

class Author { /* ... */ /** * @Assert\Valid */ protected $address;

// src/Acme/HelloBundle/Author.php use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints\Valid; class Author { protected $address; public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('address', new Valid()); }

sf you vlidte n uthor with n invlid ddress nowD you n see tht the vlidtion of the eddress (elds filedF emerellofundleeuthorFddressFzipgodeX his vlue is too longF st should hve S hrters or less yptions

traverse
typeX string defultX true sf this onstrint is pplied to property tht holds n rry of ojetsD then eh ojet in tht rry will e vlidted only if this option is set to trueF he lidtor is designed to vlidte ojets ginst onstrintsF sn rel lifeD onstrint ould eX he ke must not e urnedF sn ymfonyPD onstrints re similrX hey re ssertions tht ondition is trueF

UHP

UF eferene houments

ymfony houmenttionD PFH


7.11.31 Supported Constraints

he following onstrints re ntively ville in ymfonyPX fsi gonstrints hese re the si onstrintsX use them to ssert very si things out the vlue of properties or the return vlue of methods on your ojetF

xotflnk flnk xotxull xull rue plse ype


tring gonstrints

imil winvength wxvength rl egex sp


xumer gonstrints

wx win
hte gonstrints

hte hteime

UFIIF lidtion gonstrints eferene

UHQ

ymfony houmenttionD PFH

ime
golletion gonstrints

ghoie golletion niqueintity vnguge vole gountry


pile gonstrints

pile smge
yther gonstrints

gllk ell serssword lid

7.12 The Dependency Injection Tags

gsX

dtolletor formFtype formFtypeextension formFtypeguesser kernelFhewrmer kernelFeventlistener monologFlogger


UHR UF eferene houments

ymfony houmenttionD PFH

monologFproessor templtingFhelper routingFloder trnsltionFloder twigFextension vlidtorFinitilizer


7.12.1 Enabling Custom PHP Template Helpers

o enle ustom templte helperD dd it s regulr servie in one of your on(gurtionD tg it with templtingFhelper nd de(ne n lis ttriute @the helper will e essile vi this lis in the templtesAX

ewv

services: templating.helper.your_helper_name: class: Fully\Qualied\Helper\Class\Name tags: - { name: templating.helper, alias: alias_name }


wv

<service id="templating.helper.your_helper_name" class="Fully\Qualied\Helper\Class\Name"> <tag name="templating.helper" alias="alias_name" /> </service>


r

$container ->register('templating.helper.your_helper_name', 'Fully\Qualied\Helper\Class\Name') ->addTag('templating.helper', array('alias' => 'alias_name')) ;

7.12.2 Enabling Custom Twig Extensions

o enle wig extensionD dd it s regulr servie in one of your on(gurtionD nd tg it with twigFextensionX

ewv

services: twig.extension.your_extension_name:
UFIPF he hependeny snjetion gs UHS

ymfony houmenttionD PFH

class: Fully\Qualied\Extension\Class\Name tags: - { name: twig.extension }


wv

<service id="twig.extension.your_extension_name" class="Fully\Qualied\Extension\Class\Name"> <tag name="twig.extension" /> </service>


r

$container ->register('twig.extension.your_extension_name', 'Fully\Qualied\Extension\Class\Name') ->addTag('twig.extension') ;

7.12.3 Enabling Custom Listeners

o enle ustom listenerD dd it s regulr servie in one of your on(gurtionD nd tg it with kernelFeventlistenerF ou must provide the nme of the event your servie listens toD s well s the method tht will e lledX

ewv

services: kernel.listener.your_listener_name: class: Fully\Qualied\Listener\Class\Name tags: - { name: kernel.event_listener, event: xxx, method: onXxx }
wv

<service id="kernel.listener.your_listener_name" class="Fully\Qualied\Listener\Class\Name"> <tag name="kernel.event_listener" event="xxx" method="onXxx" /> </service>


r

$container ->register('kernel.listener.your_listener_name', 'Fully\Qualied\Listener\Class\Name') ->addTag('kernel.event_listener', array('event' => 'xxx', 'method' => 'onXxx')) ;
X ou n lso speify priority s n ttriute of the kernelFeventlistener tg @muh like the method or event ttriutesAD with either positive or negtive integerF his UHT UF eferene houments

ymfony houmenttionD PFH llows you to mke sure your listener will lwys e lled efore or fter nother listener listening for the sme eventF

7.12.4 Enabling Custom Template Engines

o enle ustom templte engineD dd it s regulr servie in one of your on(gurtionD tg it with templtingFengineX

ewv

services: templating.engine.your_engine_name: class: Fully\Qualied\Engine\Class\Name tags: - { name: templating.engine }


wv

<service id="templating.engine.your_engine_name" class="Fully\Qualied\Engine\Class\Name"> <tag name="templating.engine" /> </service>


r

$container ->register('templating.engine.your_engine_name', 'Fully\Qualied\Engine\Class\Name') ->addTag('templating.engine') ;

7.12.5 Enabling Custom Routing Loaders

o enle ustom routing loderD dd it s regulr servie in one of your on(gurtionD nd tg it with routingFloderX

ewv

services: routing.loader.your_loader_name: class: Fully\Qualied\Loader\Class\Name tags: - { name: routing.loader }


wv

UFIPF he hependeny snjetion gs

UHU

ymfony houmenttionD PFH

<service id="routing.loader.your_loader_name" class="Fully\Qualied\Loader\Class\Name"> <tag name="routing.loader" /> </service>


r

$container ->register('routing.loader.your_loader_name', 'Fully\Qualied\Loader\Class\Name') ->addTag('routing.loader') ;

7.12.6 Using a custom logging channel with Monolog

wonolog llows you to shre its hndlers etween severl logging hnnelsF he logger servie uses the hnnel pp ut you n hnge the hnnel when injeting the logger in servieF

ewv

services: my_service: class: Fully\Qualied\Loader\Class\Name arguments: [@logger] tags: - { name: monolog.logger, channel: acme }
wv

<service id="my_service" class="Fully\Qualied\Loader\Class\Name"> <argument type="service" id="logger" /> <tag name="monolog.logger" channel="acme" /> </service>
r

$denition = new Denition('Fully\Qualied\Loader\Class\Name', array(new Reference('logger')); $denition->addTag('monolog.logger', array('channel' => 'acme')); $container->register('my_service', $denition);;
X his works only when the logger servie is onstrutor rgumentD not when it is injeted through setterF

UHV

UF eferene houments

ymfony houmenttionD PFH


7.12.7 Adding a processor for Monolog

wonolog llows you to dd proessors in the logger or in the hndlers to dd extr dt in the reordsF e proessor reeives the reord s n rgument nd must return it fter dding some extr dt in the extr ttriute of the reordF vet9s see how you n use the uiltEin sntrospetionroessor to dd the (leD the lineD the lss nd the method where the logger ws triggeredF ou n dd proessor glollyX

ewv

services: my_service: class: Monolog\Processor\IntrospectionProcessor tags: - { name: monolog.processor }


wv

<service id="my_service" class="Monolog\Processor\IntrospectionProcessor"> <tag name="monolog.processor" /> </service>


r

$denition = new Denition('Monolog\Processor\IntrospectionProcessor'); $denition->addTag('monolog.processor'); $container->register('my_service', $denition);


X sf your servie is not llle @using invokeA you n dd the method ttriute in the tg to use spei( methodF ou n dd lso proessor for spei( hndler y using the hndler ttriuteX

ewv

services: my_service: class: Monolog\Processor\IntrospectionProcessor tags: - { name: monolog.processor, handler: rephp }


wv

<service id="my_service" class="Monolog\Processor\IntrospectionProcessor"> <tag name="monolog.processor" handler="rephp" /> </service>


UFIPF he hependeny snjetion gs UHW

ymfony houmenttionD PFH

$denition = new Denition('Monolog\Processor\IntrospectionProcessor'); $denition->addTag('monolog.processor', array('handler' => 'rephp'); $container->register('my_service', $denition);


ou n lso dd proessor for spei( logging hnnel y using the hnnel ttriuteF his will register the proessor only for the seurity logging hnnel used in the eurity omponentX

ewv

services: my_service: class: Monolog\Processor\IntrospectionProcessor tags: - { name: monolog.processor, channel: security }


wv

<service id="my_service" class="Monolog\Processor\IntrospectionProcessor"> <tag name="monolog.processor" channel="security" /> </service>


r

$denition = new Denition('Monolog\Processor\IntrospectionProcessor'); $denition->addTag('monolog.processor', array('channel' => 'security'); $container->register('my_service', $denition);


X ou nnot use oth the hndler nd hnnel ttriutes for the sme tg s hndlers re shred etween ll hnnelsF

7.13 YAML

ewv wesite is  humn friendly dt seriliztion stndrd for ll progrmming lngugesF ewv is simple lnguge tht desries dtF es rD it hs syntx for simple types like stringsD oolensD )otsD or integersF fut unlike rD it mkes di'erene etween rrys @sequenesA nd hshes @mppingsAF he ymfonyP XnmespeXymfonygomponentml gomponent knows how to prse ewv nd dump r rry to ewvF

UIH

UF eferene houments

ymfony houmenttionD PFH X iven if the ewv formt n desrie omplex nested dt strutureD this hpter only desries the minimum set of fetures needed to use ewv s on(gurtion (le formtF

7.13.1 Reading YAML Files

he XmethodXymfonygomponentmlrserXXprse method prses ewv string nd onverts it to r rryX

use Symfony\Component\Yaml\Parser; $yaml = new Parser(); $value = $yaml->parse(le_get_contents('/path/to/le.yaml'));


sf n error ours during prsingD the prser throws n exeption inditing the error type nd the line in the originl ewv string where the error ourredX

try { $value = $yaml->parse(le_get_contents('/path/to/le.yaml')); } catch (\InvalidArgumentException $e) { // an error occurred during parsing echo "Unable to parse the YAML string: ".$e->getMessage(); }
X es the prser is reentrntD you n use the sme prser ojet to lod di'erent ewv stringsF hen loding ewv (leD it is sometimes etter XmethodXymfonygomponentmlmlXXprse wrpper methodX to use the

use Symfony\Component\Yaml\Yaml; $loader = Yaml::parse('/path/to/le.yml');


he mlXXprse@A stti method tkes ewv string or (le ontining ewvF snternllyD it lls the rserXXprse@A methodD ut with some dded onusesX

st exeutes the ewv (le s if it ws r (leD so tht you n emed r ommnds in ewv (lesY hen (le nnot e prsedD it utomtilly dds the (le nme to the error messgeD simplifying deugging when your pplition is loding severl ewv (lesF

UFIQF ewv

UII

ymfony houmenttionD PFH


7.13.2 Writing YAML Files

he XmethodXymfonygomponentmlhumperXXdump method dumps ny r rry to its ewv representtionX

use Symfony\Component\Yaml\Dumper; $array = array('foo' => 'bar', 'bar' => array('foo' => 'bar', 'bar' => 'baz')); $dumper = new Dumper(); $yaml = $dumper->dump($array); le_put_contents('/path/to/le.yaml', $yaml);
X here re some limittionsX the dumper is not le to dump resoures nd dumping r ojets is onsidered n lph fetureF sf you only need to dump one rryD you n use XmethodXymfonygomponentmlmlXXdump stti method shortutX the

$yaml = Yaml::dump($array, $inline);


he ewv formt supports the two ewv rry representtionsF fy defultD the dumper uses the inline representtionX

{ foo: bar, bar: { foo: bar, bar: baz } }


fut the seond rgument of the dump@A method ustomizes the level t whih the output swithes from the expnded representtion to the inline oneX

echo $dumper->dump($array, 1); foo: bar bar: { foo: bar, bar: baz } echo $dumper->dump($array, 2); foo: bar bar: foo: bar bar: baz

UIP

UF eferene houments

ymfony houmenttionD PFH


7.13.3 The YAML Syntax

trings

A string in YAML 'A singled-quoted string in YAML'


X sn single quoted stringD single quote 9 must e douledX

'A single quote '' in a single-quoted string' "A double-quoted string in YAML\n"
uoted styles re useful when string strts or ends with one or more relevnt spesF X he douleEquoted style provides wy to express ritrry stringsD y using espe sequenesF st is very useful when you need to emed n or uniode hrter in stringF hen string ontins line reksD you n use the literl styleD indited y the pipe @|AD to indite tht the string will spn severl linesF sn literlsD newlines re preservedX

\/ /| |\/| | / / | | | |__

elterntivelyD strings n e written with the folded styleD denoted y bD where eh line rek is repled y speX

> This is a very long sentence that spans several lines in the YAML but which will be rendered as a string without carriage returns.
X xotie the two spes efore eh line in the previous exmplesF hey won9t pper in the resulting r stringsF

UFIQF ewv

UIQ

ymfony houmenttionD PFH xumers

# an integer 12 # an octal 014 # an hexadecimal 0xC # a oat 13.4 # an exponential number 1.2e+34 # innity .inf
xulls xulls in ewv n e expressed with null or ~F foolens foolens in ewv re expressed with true nd flseF htes ewv uses the syEVTHI stndrd to express dtesX

2001-12-14t21:59:43.10-05:00 # simple date 2002-12-14


golletions e ewv (le is rrely used to desrie simple slrF wost of the timeD it desries olletionF e olletion n e sequene or mpping of elementsF foth sequenes nd mppings re onverted to r rrysF equenes use dsh followed y spe @E AX UIR UF eferene houments

ymfony houmenttionD PFH

- PHP - Perl - Python


he previous ewv (le is equivlent to the following r odeX

array('PHP', 'Perl', 'Python');


wppings use olon followed y spe @X A to mrk eh keyGvlue pirX

PHP: 5.2 MySQL: 5.1 Apache: 2.2.20


whih is equivlent to this r odeX

array('PHP' => 5.2, 'MySQL' => 5.1, 'Apache' => '2.2.20');


X sn mppingD key n e ny vlid slrF he numer of spes etween the olon nd the vlue does not mtterX

PHP: 5.2 MySQL: 5.1 Apache: 2.2.20


ewv uses indenttion with one or more spes to desrie nested olletionsX

"symfony 1.4": PHP: 5.2 Doctrine: 1.2 "Symfony2": PHP: 5.3 Doctrine: 2.0
he following ewv is equivlent to the following r odeX

array( 'symfony 1.4' => array( 'PHP' => 5.2, 'Doctrine' => 1.2, ), 'Symfony2' => array( 'PHP' => 5.3, 'Doctrine' => 2.0, ), );
UFIQF ewv UIS

ymfony houmenttionD PFH here is one importnt thing you need to rememer when using indenttion in ewv (leX sndenttion must e done with one or more spesD ut never with tultionsF ou n nest sequenes nd mppings s you likeX

'Chapter 1': - Introduction - Event Types 'Chapter 2': - Introduction - Helpers


ewv n lso use )ow styles for olletionsD using expliit inditors rther thn indenttion to denote sopeF e sequene n e written s omm seprted list within squre rkets @AX

[PHP, Perl, Python]


e mpping n e written s omm seprted list of keyGvlues within urly res @{}AX

{ PHP: 5.2, MySQL: 5.1, Apache: 2.2.20 }


ou n mix nd mth styles to hieve etter redilityX

'Chapter 1': [Introduction, Event Types] 'Chapter 2': [Introduction, Helpers] "symfony 1.4": { PHP: 5.2, Doctrine: 1.2 } "Symfony2": { PHP: 5.3, Doctrine: 2.0 }
gomments gomments n e dded in ewv y pre(xing them with hsh mrk @5AX

# Comment on a line "Symfony2": { PHP: 5.3, Doctrine: 2.0 } # Comment at the end of a line
X gomments re simply ignored y the ewv prser nd do not need to e indented ording to the urrent level of nesting in olletionF

hynmi ewv (les sn ymfonyPD ewv (le n ontin r ode tht is evluted just efore the prsing oursX UIT UF eferene houments

ymfony houmenttionD PFH

1.0: version: <?php echo le_get_contents('1.0/VERSION')."\n" ?> 1.1: version: "<?php echo le_get_contents('1.1/VERSION') ?>"
fe reful to not mess up with the indenttionF ueep in mind the following simple tips when dding r ode to ewv (leX

he `cphp cb sttements must lwys strt the line or e emedded in vlueF sf `cphp cb sttement ends lineD you need to expliitly output new line @nAF

7.14 Requirements for running Symfony2

o run ymfonyPD your system needs to dhere to list of requirementsF ou n esily see if your system psses ll requirements y running the weGon(gFphp in your symfony distriutionF ine the gvs often uses di'erent phpFini on(gurtion (leD it9s lso good ide to hek your requirements from the ommnd line viX

php app/check.php
felow is the list of required nd optionl requirementsF
7.14.1 Required

r needs to e minimum version of r SFQFP tyx needs to e enled type needs to e enled our rFini needs to hve the dteFtimezone setting
7.14.2 Optional

ou need to hve the rEwv module instlled ou need to hve t lest version PFTFPI of lixml r tokenizer needs to e enled mstring funtions need to e enled ionv needs to e enled ys needs to e enled @only on BnixA
UFIRF equirements for running ymfonyP UIU

ymfony houmenttionD PFH

sntl needs to e instlled with sg RC eg QFHFIUC @or nother opode he needs to e instlledA rFini reommended settings
! shortopentgsX o' ! mgiquotesgpX o' ! registerglolsX o' ! sessionFutostrtX o'
7.14.3 Doctrine

sf you wnt to use hotrineD you will need to hve hy instlledF edditionllyD you need to hve the hy driver instlled for the dtse server you wnt to useF

gon(gurtion yptionsX
iver wondered wht on(gurtion options you hve ville to you in (les suh s ppGon(gGon(gFymlc sn this setionD ll the ville on(gurtion is roken down y the key @eFgF frmeworkA tht de(nes eh possile setion of your ymfonyP on(gurtionF ! frmework ! dotrine ! seurity ! sseti ! swiftmiler ! twig ! monolog ! wepro(ler

porms nd lidtion
! porm pield ype eferene ! lidtion gonstrints eferene ! wig emplte puntion eferene

yther eres
! he hependeny snjetion gs ! ewv UIV UF eferene houments

ymfony houmenttionD PFH ! equirements for running ymfonyP

gon(gurtion yptionsX
iver wondered wht on(gurtion options you hve ville to you in (les suh s ppGon(gGon(gFymlc sn this setionD ll the ville on(gurtion is roken down y the key @eFgF frmeworkA tht de(nes eh possile setion of your ymfonyP on(gurtionF ! frmework ! dotrine ! seurity ! sseti ! swiftmiler ! twig ! monolog ! wepro(ler

porms nd lidtion
! porm pield ype eferene ! lidtion gonstrints eferene ! wig emplte puntion eferene

yther eres
! he hependeny snjetion gs ! ewv ! equirements for running ymfonyP

UFIRF equirements for running ymfonyP

UIW

ymfony houmenttionD PFH

UPH

UF eferene houments

V Bundles

UPI

ymfony houmenttionD PFH he ymfony tndrd idition omes with some undlesF vern more out themX

UPQ

ymfony houmenttionD PFH

UPR

Symfony SE Bundles
ensioprmeworkixtrfundle ensioqenertorfundle tweurityixtrfundle hotrinepixturesfundle hotrinewigrtionsfundle hotrinewongohffundle ensioprmeworkixtrfundle ensioqenertorfundle tweurityixtrfundle hotrinepixturesfundle hotrinewigrtionsfundle hotrinewongohffundle

UPS

ymfony houmenttionD PFH

UPT

VF ymfony i fundles

VI

UPU

ymfony houmenttionD PFH ymfonyPX

UPW

ymfony houmenttionD PFH

UQH

Contributing

9.1 Contributing Code


9.1.1 Reporting a Bug

henever you (nd ug in ymfonyPD we kindly sk you to report itF st helps us mke etter ymfonyPF X sf you think you9ve found seurity issueD plese use the speil proedure instedF fefore sumitting ugX

houleEhek the o0il doumenttion to see if you9re not misusing the frmeworkY esk for ssistne on the users milingElistD the forumD or on the 5symfony sg hnnel if you9re not sure if your issue is relly ugF
sf your prolem de(nitely looks like ugD report it using the o0il ug trker nd follow some si rulesX

se the title (eld to lerly desrie the issueY hesrie the steps needed to reprodue the ug with short ode exmples @providing unit test tht illustrtes the ug is estAY qive s muh detils s possile out your environment @yD r versionD ymfony versionD enled extensionsD FFFAY @optionlA etth pthF

UQI

ymfony houmenttionD PFH


9.1.2 Submitting a Patch

thes re the est wy to provide ug (x or to propose enhnements to ymfonyPF ghek vist he purpose of the hek list is to ensure tht ontriutions my e reviewed with needless feedk loops to ensure tht your ontriutions n e inluded into ymfonyP s quikly s possileF ell pull requests should inlude the following templte in the request desriptionX

Bug x: [yes|no] Feature addition: [yes|no] Backwards compatibility break: [yes|no] Symfony2 tests pass: [yes|no] Fixes the following tickets: [comma separated list of tickets xed by the PR]
en exmple sumission ould now look s followsX

Bug x: no Feature addition: yes Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: hnk you for inluding the (lled out templte in your sumission3 X ell feture ddition9s should e send to the mster rnhD while ll ug (xes should e send to the oldest still tive rnhF purthermore sumissions should s rule of thum not rek kwrds omptiilityF lese mrk ny sumissions s s in the title in se the sumission is not yet omplete @for exmple if the tests do not yet pssAF

snitil etup fefore working on ymfonyPD setup friendly environment with the following softwreX

qitY r version SFQFP or oveY rnit QFSFII or oveF


et up your user informtion with your rel nme nd working emil ddressX

UQP

WF gontriuting

ymfony houmenttionD PFH

$ git cong --global user.name "Your Name" $ git cong --global user.email you@example.com
X sf you re new to qitD we highly reommend you to red the exellent nd free roqit ookF qet the ymfonyP soure odeX

grete qitru ount nd sign inY pork the ymfonyP repository @lik on the pork uttonAY efter the hrdore forking tion hs ompletedD lone your fork lolly @this will rete symfony diretoryAX

$ git clone git@github.com:USERNAME/symfony.git


edd the upstrem repository s remoteX

$ cd symfony $ git remote add upstream git://github.com/symfony/symfony.git


xow tht ymfonyP is instlledD hek tht ll unit tests pss for your environment s explined in the dedited doumentF orking on th ih time you wnt to work on pth for ug or on n enhnementD you need to rete topi rnhF he rnh should e sed on the mster rnh if you wnt to dd new fetureF fut if you wnt to (x ugD use the oldest ut still mintined version of ymfony where the ug hppens @like PFHAF grete the topi rnh with the following ommndX

$ git checkout -b BRANCH_NAME master


X se desriptive nme for your rnh @tiket where is the tiket numer is good onvention for ug (xesAF he ove ommnd utomtilly swithes the ode to the newly reted rnh @hek the rnh you re working on with git rnhAF ork on the ode s muh s you wnt nd ommit s muh s you wntY ut keep in mind the followingX WFIF gontriuting gode UQQ

ymfony houmenttionD PFH

pollow the oding stndrds @use git di' !hek to hek for triling spesAY edd unit tests to prove tht the ug is (xed or tht the new feture tully worksY ho tomi nd logilly seprte ommits @use the power of git rese to hve len nd logil historyAY rite good ommit messgesF
X e good ommit messge is omposed of summry @the (rst lineAD optionlly followed y lnk line nd more detiled desriptionF he summry should strt with the gomponent you re working on in squre rkets @hependenysnjetionD prmeworkfundleD FFFAF se ver @(xed FFFD dded FFFD FFFA to strt the summry nd don9t dd period t the endF

umitting th fefore sumitting your pthD updte your rnh @needed if it tkes you while to (nish your hngesAX

$ git checkout master $ git fetch upstream $ git merge upstream/master $ git checkout BRANCH_NAME $ git rebase master
hen doing the rese ommndD you might hve to (x merge on)itsF git sttus will show you the unmerged (lesF esolve ll the on)itsD then ontinue the reseX

$ git add ... # add resolved les $ git rebase --continue


ghek tht ll tests still pss nd push your rnh remotelyX

$ git push origin BRANCH_NAME


ou n now disuss your pth on the dev milingElist or mke pull request @they must e done on the symfonyGsymfony repositoryAF o ese the ore tem workD lwys inlude the modi(ed omponents in your pull request messgeD like inX

[Yaml] foo bar [Form] [Validator] [FrameworkBundle] foo bar


sf you re going to send n emil to the milingElistD don9t forget to referene you rnh v @httpsXGGgithuFomGixewiGsymfonyFgit fexgrxewiA or the pull request vF

UQR

WF gontriuting

ymfony houmenttionD PFH fsed on the feedk from the milingElist or vi the pull request on qitruD you might need to rework your pthF fefore reEsumitting the pthD rese with msterD don9t mergeY nd fore the push to the originX

$ git rebase -f upstream/master $ git push -f origin BRANCH_NAME


X ell pthes you re going to sumit must e relesed under the ws lienseD unless expliitly spei(ed in the odeF ell ug (xes merged into mintenne rnhes re lso merged into more reent rnhes on regulr sisF por instneD if you sumit pth for the PFH rnhD the pth will lso e pplied y the ore tem on the mster rnhF
9.1.3 Reporting a Security Issue

pound seurity issue in ymfonyPc hon9t use the milingElist or the ug trkerF ell seurity issues must e sent to seurity t symfonyEprojetFom instedF imils sent to this ddress re forwrded to the ymfony oreEtem privte milingElistF por eh reportD we (rst try to on(rm the vulnerilityF hen it is on(rmedD the oreEtem works on solution following these stepsX IF end n knowledgement to the reporterY PF ork on pthY QF rite post desriing the vulnerilityD the possile exploitsD nd how to pthGupgrde 'eted pplitionsY RF epply the pth to ll mintined versions of ymfonyY SF ulish the post on the o0il ymfony logF X hile we re working on pthD plese do not revel the issue pulilyF

9.1.4 Running Symfony2 Tests

fefore sumitting pth for inlusionD you need to run the ymfonyP test suite to hek tht you hve not roken nythingF rnit o run the ymfonyP test suiteD instll rnit QFSFH or lter (rstX WFIF gontriuting gode UQS

ymfony houmenttionD PFH

$ pear channel-discover pear.phpunit.de $ pear channel-discover components.ez.no $ pear channel-discover pear.symfony-project.com $ pear install phpunit/PHPUnit
hependenies @optionlA o run the entire test suiteD inluding tests tht depend on externl dependeniesD ymfonyP needs to e le to utolod themF fy defultD they re utoloded from vendorG under the min root diretory @see utolodFphpFdistAF he test suite needs the following thirdEprty lirriesX

hotrine wiftmiler wig wonolog


o instll them llD run the vendors sriptX

$ php vendors install


X xote tht the sript tkes some time to (nishF efter instlltionD you n updte the vendors to their ltest version with the follow ommndX

$ php vendors update


unning pirstD updte the vendors @see oveAF henD run the test suite from the ymfonyP root diretory with the following ommndX

$ phpunit
he output should disply yuF sf notD you need to (gure out wht9s going on nd if the tests re roken euse of your modi(tionsF X un the test suite efore pplying your modi(tions to hek tht they run (ne on your on(gurtionF

UQT

WF gontriuting

ymfony houmenttionD PFH gode goverge sf you dd new fetureD you lso need to hek the ode overge y using the overgeEhtml optionX

$ phpunit --coverage-html=cov/
ghek the ode overge y opening the generted ovGindexFhtml pge in rowserF X he ode overge only works if you hve heug enled nd ll dependenies instlledF

9.1.5 Coding Standards

hen ontriuting ode to ymfonyPD you must follow its oding stndrdsF o mke long story shortD here is the golden ruleX smitte the existing ymfonyP odeF wost openEsoure fundles nd lirries used y ymfonyP lso follow the sme guidelinesD nd you should tooF ememer tht the min dvntge of stndrds is tht every piee of ode looks nd feels fmilirD it9s not out this or tht eing more redleF ine piture E or some ode E is worth thousnd wordsD here9s short exmple ontining most fetures desried elowX

<?php /* * This le is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * le that was distributed with this source code. */ namespace Acme; class Foo { const SOME_CONST = 42; private $foo; /** * @param string $dummy Some argument description */
WFIF gontriuting gode UQU

ymfony houmenttionD PFH

public function __construct($dummy) { $this->foo = $this->transform($dummy); } /** * @param string $dummy Some argument description * @return string|null Transformed input */ private function transform($dummy) { if (true === $dummy) { return; } elseif ('string' === $dummy) { $dummy = substr($dummy, 0, 5); } } return $dummy;

truture

xever use short tgs @`cAY hon9t end lss (les with the usul cb losing tgY sndenttion is done y steps of four spes @ts re never llowedAY se the linefeed hrter @HxHeA to end linesY edd single spe fter eh omm delimiterY hon9t put spes fter n opening prenthesis nd efore losing oneY edd single spe round opertors @aaD 88D FFFAY edd single spe efore the opening prenthesis of ontrol keyword @ifD elseD forD whileD FFFAY edd lnk line efore return sttementsY hon9t dd triling spes t the end of linesY se res to indite ontrol struture ody regrdless of the numer of sttements it ontinsY ut res on their own line for lssesD methodsD nd funtions delrtionY

UQV

WF gontriuting

ymfony houmenttionD PFH

eprte the onditionl sttements @ifD elseD FFFA nd the opening re with single spe nd no lnk lineY helre visiility expliitly for lssD methodsD nd properties @usge of vr is prohiitedAY se lowerse r ntive typed onstntsX flseD trueD nd nullF he sme goes for rry@AY se upperse strings for onstnts with words seprted with undersoresY he(ne one lss per (leY helre lss properties efore methodsY helre puli methods (rstD then proteted ones nd (nlly privte onesF
xming gonventions

se melgseD not undersoresD for vrileD funtion nd method nmesY se undersores for optionD rgumentD prmeter nmesY se nmespes for ll lssesY se ymfony s the (rst nmespe levelY u0x interfes with snterfeY se lphnumeri hrters nd undersores for (le nmesY hon9t forget to look t the more verose gonventions doument for more sujetive nming onsidertionsF
houmenttion

edd rho loks for ll lssesD methodsD nd funtionsY he dpkge nd dsupkge nnottions re not usedF
viense

ymfony is relesed under the ws lienseD nd the liense lok hs to e present t the top of every r (leD efore the nmespeF

WFIF gontriuting gode

UQW

ymfony houmenttionD PFH


9.1.6 Conventions

he goding tndrds doument desries the oding stndrds for the ymfonyP projets nd the internl nd thirdEprty undlesF his doument desries oding stndrds nd onventions used in the ore frmework to mke it more onsistent nd preditleF ou re enourged to follow them in your own odeD ut you don9t need toF wethod xmes hen n ojet hs min mny reltion with relted things @ojetsD prmetersD FFFAD the method nmes re normlizedX

get@A set@A hs@A ll@A reple@A remove@A ler@A isimpty@A dd@A register@A ount@A keys@A
he usge of these methods re only llowed when it is ler tht there is min reltionX

gookietr hs mny gookie ojetsY ervie gontiner hs mny servies nd mny prmeters @s servies is the min reltionD we use the nming onvention for this reltionAY gonsole snput hs mny rguments nd mny optionsF here is no min reltionD nd so the nming onvention does not pplyF
por mny reltions where the onvention does not pplyD the following methods must e used insted @where is the nme of the relted thingAX

URH

WF gontriuting

ymfony houmenttionD PFH win eltion get@A set@A nG hs@A ll@A reple@A remove@A ler@A isimpty@A dd@A register@A ount@A keys@A yther eltions get@A set@A reple@A hs@A gets@A sets@A remove@A ler@A isimpty@A dd@A register@A ount@A nG

X hile set nd reple re very similrD there is one notle di'ereneX set my repleD or dd new elements to the reltionF reple on the other hnd is spei(lly foridden to dd new elementsD ut most throw n exeption in these sesF

9.1.7 Symfony2 License

ymfonyP is relesed under the ws lienseF eording to ikipediX st is permissive lienseD mening tht it permits reuse within proprietry softwre on the ondition tht the liense is distriuted with tht softwreF he liense is lso qvEomptileD mening tht the qv permits omintion nd redistriution with softwre tht uses the ws vienseF he viense gopyright @A PHHREPHII pien otenier ermission is herey grntedD free of hrgeD to ny person otining opy of this softwre nd ssoited doumenttion (les @the oftwreAD to del in the oftwre without restritionD inluding without limittion the rights to useD opyD modifyD mergeD pulishD distriuteD sulienseD ndGor sell opies of the oftwreD nd to permit persons to whom the oftwre is furnished to do soD sujet to the following onditionsX he ove opyright notie nd this permission notie shll e inluded in ll opies or sustntil portions of the oftwreF

WFIF gontriuting gode

URI

ymfony houmenttionD PFH ri ypei s yshih e sD sry eex yp ex usxhD ii y swvsihD sxgvhsxq f xy vswsih y ri eexsi yp wigrexefsvsD psxi py e esgve yi exh xyxsxpsxqiwixF sx xy iix revv ri ery y gysqr ryvhi fi vsefvi py ex gveswD heweqi y yri vsefsvsD riri sx ex egsyx yp gyxegD y y yrisiD essxq pywD y yp y sx gyxxigsyx sr ri ypei y ri i y yri hievsxq sx ri ypeiF

9.2 Contributing Documentation


9.2.1 Contributing to the Documentation

houmenttion is s importnt s odeF st follows the ext sme priniplesX hD testsD ese of mintenneD extensiilityD optimiztionD nd reftoring just to nme fewF end of ourseD doumenttion hs ugsD typosD hrd to red tutorilsD nd moreF gontriuting fefore ontriutingD you need to eome fmilir with the mrkup lnguge used y the doumenttionF he ymfonyP doumenttion is hosted on qitruX

https://github.com/symfony/symfony-docs
sf you wnt to sumit pthD fork the o0il repository on qitru nd then lone your forkX

$ git clone git://github.com/YOURUSERNAME/symfony-docs.git


xextD rete dedited rnh for your hnges @for orgniztionAX

$ git checkout -b improving_foo_and_bar


ou n now mke your hnges diretly to this rnh nd ommit themF hen you9re doneD push this rnh to your qitru fork nd initite pull requestF he pull request will e etween your improvingfoondr rnh nd the symfonyEdos mster rnhF

qitru overs the topi of pull requests in detilF URP WF gontriuting

ymfony houmenttionD PFH

X he ymfonyP doumenttion is liensed under gretive gommons ettriutionEhre elike QFH nported vienseF

eporting n sssue he most esy ontriution you n mke is reporting issuesX typoD grmmr mistkeD ug in ode exmpleD missing explntionD nd so onF tepsX

umit ug in the ug trkerY @optionlA umit pthF


rnslting ed the dedited doumentF
9.2.2 Documentation Format

he ymfonyP doumenttion uses retruturedext s its mrkup lnguge nd phinx for uilding the output @rwvD hpD FFFAF retruturedext retruturedext is n esyEtoEredD whtEyouEseeEisEwhtEyouEget plintext mrkup syntx nd prser systemF ou n lern more out its syntx y reding existing ymfonyP douments or y reding the retruturedext rimer on the phinx wesiteF sf you re fmilir with wrkdownD e reful s things s sometimes very similr ut di'erentX

vists strts t the eginning of line @no indenttion is llowedAY snline ode loks use douleEtiks @like thisAF
phinx phinx is uild system tht dds some nie tools to rete doumenttion from retruturedext doumentsF es suhD it dds new diretives nd interpreted text roles to stndrd re mrkupF WFPF gontriuting houmenttion URQ

ymfony houmenttionD PFH

Syntax Highlighting
ell ode exmples uses r s the defult highlighted lngugeF ou n hnge it with the odeElok diretiveX

.. code-block:: yaml { foo: bar, bar: { foo: bar, bar: baz } }


sf your r ode egins with `cphpD then you need to use htmlCphp s the highlighted pseudoElngugeX

.. code-block:: html+php <?php echo $this->foobar(); ?>


X e list of supported lnguges is ville on the ygments wesiteF

Conguration Blocks
henever you show on(gurtionD you must use the on(gurtionElok diretive to show the on(gurtion in ll supported on(gurtion formts @rD ewvD nd wvA

.. conguration-block:: .. code-block:: yaml # Conguration in YAML .. code-block:: xml <!-- Conguration in XML //--> .. code-block:: php // Conguration in PHP
he previous re snippet renders s followX

ewv

# Conguration in YAML
wv

URR

WF gontriuting

ymfony houmenttionD PFH

<!-- Conguration in XML //-->


r

// Conguration in PHP
he urrent list of supported formts re the followingX wrkup formt html xml php yml jinj htmlCjinj jinjChtml phpChtml htmlCphp ini phpEnnottions hisplyed rwv wv r ewv wig wig wig r r sxs ennottions

Testing Documentation
o test doumenttion efore ommitX

snstll phinxY un the phinx quik setupY snstll the on(gurtionElok phinx extension @see elowAY un mke html nd view the generted rwv in the uild diretoryF

Installing the conguration-block Sphinx extension


hownlod the extension from the on(gurtionElok soure repository gopy the on(gurtionlokFpy to the exts folder under your soure folder @where onfFpy is lotedA edd the following to the onfFpy (leX

# ... sys.path.append(os.path.abspath('_exts')) # ...

WFPF gontriuting houmenttion

URS

ymfony houmenttionD PFH

# add congurationblock to the list of extensions extensions = ['congurationblock']

9.2.3 Translations

he ymfonyP doumenttion is written in inglish nd mny people re involved in the trnsltion proessF gontriuting pirstD eome fmilir with the mrkup lnguge used y the doumenttionF henD susrie to the ymfony dos milingElistD s ollortion hppens thereF pinllyD (nd the mster repository for the lnguge you wnt to ontriute forF rere is the list of the o0il mster repositoriesX

inglishX httpXGGgithuFomGsymfonyGsymfonyEdos prenhX httpsXGGgithuFomGgsorpioGsymfonyEdosEfr stlinX httpsXGGgithuFomGgrkGsymfonyEdosEit tpneseX httpsXGGgithuFomGsymfonyEjpnGsymfonyEdosEj olishX httpXGGgithuFomGmplusoGsymfonyEdosEpl omninX httpXGGgithuFomGseioGsymfonyEdosEro ussinX httpXGGgithuFomGvlnheIPQGsymfonyEdosEru pnishX httpsXGGgithuFomGgitnhoGsymfonyEdosEes
X sf you wnt to ontriute trnsltions for new lngugeD red the dedited setionF

toining the rnsltion em sf you wnt to help trnslting some douments for your lnguge or (x some ugsD onsider joining usY it9s very esy proessX

sntrodue yourself on the ymfony dos milingElistY @optionlA esk whih douments you n work onY pork the mster repository for your lnguge @lik the pork utton on the qitru pgeAY
URT WF gontriuting

ymfony houmenttionD PFH

rnslte some doumentsY esk for pull request @lik on the ull equest from your pge on qitruAY he tem mnger epts your modi(tions nd merges them into the mster repositoryY he doumenttion wesite is updted every other night from the mster repositoryF
edding new vnguge his setion gives some guidelines for strting the trnsltion of the ymfonyP doumenttion for new lngugeF es strting trnsltion is lot of workD tlk out your pln on the ymfony dos milingE list nd try to (nd motivted people willing to helpF hen the tem is redyD nominte tem mngerY he will e responsile for the mster repositoryF grete the repository nd opy the inglish doumentsF he tem n now strt the trnsltion proessF hen the tem is on(dent tht the repository is in onsistent nd stle stte @everything is trnsltedD or nonEtrnslted douments hve een removed from the totrees ! (les nmed indexFrst nd mpFrstFinAD the tem mnger n sk tht the repository is dded to the list of o0il mster repositories y sending n emil to pien @fien t symfonyFomAF wintenne rnsltion does not end when everything is trnsltedF he doumenttion is moving trget @new douments re ddedD ugs re (xedD prgrphs re reorgnizedD FFFAF he trnsltion tem need to losely follow the inglish repository nd pply hnges to the trnslted douments s soon s possileF X xon mintined lnguges re removed from the o0il list of repositories s osolete doumenttion is dngerousF

9.2.4 Symfony2 Documentation License

he ymfonyP doumenttion is liensed under gretive gommons ettriutionEhre elike QFH nported vienseF ou re freeX

to hre " to opyD distriute nd trnsmit the workY


WFPF gontriuting houmenttion URU

ymfony houmenttionD PFH

to emix " to dpt the workF


nder the following onditionsX

ettriution " ou must ttriute the work in the mnner spei(ed y the uthor or liensor @ut not in ny wy tht suggests tht they endorse you or your use of the workAY hre elike " sf you lterD trnsformD or uild upon this workD you my distriute the resulting work only under the sme or similr liense to this oneF
ith the understnding thtX

iver " eny of the ove onditions n e wived if you get permission from the opyright holderY uli homin " here the work or ny of its elements is in the puli domin under pplile lwD tht sttus is in no wy 'eted y the lienseY yther ights " sn no wy re ny of the following rights 'eted y the lienseX
! our fir deling or fir use rightsD or other pplile opyright exeptions nd limittionsY ! he uthor9s morl rightsY ! ights other persons my hve either in the work itself or in how the work is usedD suh s puliity or privy rightsF

xotie " por ny reuse or distriutionD you must mke ler to others the liense terms of this workF he est wy to do this is with link to this we pgeF
his is humnEredle summry of the vegl gode @the full lienseAF

9.3 Community
9.3.1 IRC Meetings

he purpose of this meeting is to disuss topis in rel time with mny of the ymfonyP devsF enyone my propose topis on the symfonyEdev milingElist until PR hours efore the meetingD idelly inluding well prepred relevnt informtion vi some vF PR hours efore the meeting link to doodle will e posted inluding list of ll proposed topisF enyone n vote on the topis until the eginning of the meeting to de(ne the order in the gendF ih topi will e timeoxed to ISmins nd the meeting lsts one hourD leving enough time for t lest R topisF

URV

WF gontriuting

ymfony houmenttionD PFH X xote tht its not the expeted gol of them meeting to (nd (nl solutionsD ut more to ensure tht there is ommon understnding of the issue t hnd nd move the disussion forwrd in wys whih re hrd to hieve with less rel time ommunition toolsF weetings will hppen eh hursdy t IUXHH gi @CHIXHHA on the 5symfonyEdev hnnel on the preenode sg serverF he sg logs will lter e pulished on the tr wikiD whih will inlude short summry for eh of the topisF ikets will e reted for ny tsks or issues identi(ed during the meeting nd referened in the summryF ome simple guidelines nd pointers for prtiiptionX

st9s possile to hnge votes until the eginning of the meeting y liking on idit n entryY he doodle will e losed for voting t the eginning of the meetingY egend is de(ned y whih topis got the most votes in the doodleD or whihever ws proposed (rst in se of tieY et the eginning of the meeting one person will identify himGherself s the modertorY he modertor is essentilly responsile for ensuring the ISmin timeox nd ensuring tht tsks re lerly identi(edY sully the modertor will lso hndle writing the summry nd reting tr tikets unless someone else steps upY enyone n join nd is expliitly invited to prtiipteY sdelly one should fmilirize oneself with the proposed topi efore the meetingY hen strting on new topi the proposer is invited to strt things o' with few wordsY enyone n then omment s they see (tY hepending on how mny people prtiipte one should potentilly retrin oneself from pushing spei( rgument too hrdY ememer the sg logs will e pulished lter onD so people hve the hne to review omments lter on one moreY eople re enourged to rise their hnd to tke on tsks de(ned during the meetingF
rere is n exmple doodleF

WFQF gommunity

URW

ymfony houmenttionD PFH


9.3.2 Other Resources

sn order to follow wht is hppening in the ommunity you might (nd helpful these dditionl resouresX

vist of open pull requests vist of reent ommits vist of open ugs nd enhnements vist of open soure undles godeX
! fugs | ! thes | ! eurity | ! ests | ! goding tndrds | ! gode gonventions | ! viense

houmenttionX
! yverview | ! pormt | ! rnsltions | ! viense

gommunityX
! sg weetings | ! yther esoures

godeX
! fugs | ! thes | ! eurity | ! ests | ! goding tndrds | ! gode gonventions | USH WF gontriuting

ymfony houmenttionD PFH ! viense

houmenttionX
! yverview | ! pormt | ! rnsltions | ! viense

gommunityX
! sg weetings | ! yther esoures

WFQF gommunity

USI

ymfony houmenttionD PFH

USP

WF gontriuting

Symbols

gon(gurtionD SII
B

D IVI rnitD IVP D IVW D VS D VR D TV D TV D US D ITW D IUI D IUR D IVI D IUI D IUQ grwlerD IUU D IVS vlidtorD IVU D IWH D IVW D IWH D IVV D SPR
A

fundle ixtension gon(gurtionD RQV snheritneD RQV yverridingD RQV fundles fest rtiesD RQQ ixtensionD RRH xming gonventionsD RQQ
C

esseti gon(gurtion efereneD STQ eutoloder

gheD PTH gheEgontrol rederD PTS gheEgontrol hederD PTV gonditionl qetD PUI gon(gurtionD PUQ isD PUQ itg hederD PTW ixpires hederD PTV qtewyD PTI rD PTR r ixpirtionD PTU snvlidtionD PUU vstEwodi(ed hederD PUH roxyD PTI everse roxyD PTI fe methodsD PTT ymfonyP everse roxyD PTP wigD IPR ypes ofD PTP USQ

ymfony houmenttionD PFH lidtionD PTW rnishD SHR ryD PUP gvs hotrine ywD ITV gon(gurtion eutoloderD SII gheD PUQ gonventionD RRV heug modeD RHR hotrine hfevD STV emntiD RQV ewvD UIH gon(gurtion eferene essetiD STQ hotrine ywD STR prmeworkD SSU wonologD SUT wiftmilerD SUR wigD SUR ero(lerD SUV gontrollerD VU RHR pgesD WT eessing serviesD WT es erviesD QRQ fse ontroller lssD WQ gommon sksD WQ gontroller rgumentsD WH porwrdingD WR wnging errorsD WT ediretingD WR endering templtesD WS equest ojetD WW equestEontrollerEresponse lifeyleD VU esponse ojetD WW outes nd ontrollersD VW imple exmpleD VV tring nming formtD IIS he sessionD WU gonvention gon(gurtionD RRV
D

heuggingD SPQ hependeny snjetion gontinerD PWQ hependeny snjetionD ixtensionD RRH hotrineD IRQ edding mpping metdtD IRS hfevD QUT hfev on(gurtionD STV pormsD PIS qenerting entities from existing dtseD QUQ yw gon(gurtion efereneD STR yw gonsole gommndsD ITV
E

imilsD RRW qmilD RSI invironmentsD RHI ghe diretoryD RHU gon(gurtion (lesD RHP greting new environmentD RHS ixeuting di'erent environmentsD RHR ixternl rmetersD RHV isD PUQ ivent uernelD QIU kernelFontrollerD QIV kernelFexeptionD QPH kernelFrequestD QIV kernelFresponseD QIW kernelFviewD QIW ivent hisptherD QPHD SPWD SQI greting nd hispthing n iventD QPR ivent ulssesD QPP ivent susriersD QPU iventsD QPI vistenersD QPP xming onventionsD QPI topping event )owD QPV
F

hfev hotrineD QUT USR

pinderD SIQ pormsD IWW fsi templte renderingD PHP fuiltEin pield ypesD PHU grete form in ontrollerD PHI

ymfony houmenttionD PFH grete simple formD IWW greting form lssesD PIR gp rotetionD PPR gustomizing (eldsD PIV hotrineD PIS imedded formsD PIT pield type guessingD PHWD PIH pield type optionsD PHW pields irthdyD SUW hekoxD SVI hoieD SVQD THH olletionD SVV ountryD SVV srfD SWI dteD SWP dtetimeD SWS emilD SWV (eldD THU (leD THS formD THW hiddenD THW integerD THW lngugeD TII loleD TIR moneyD TIU numerD TPH psswordD TPP perentD TPR rdioD TPT repetedD TPV serhD TQI textD TQP textreD TQR timeD TQT timezoneD TQV urlD TRI qlol hemingD PPI rndling form sumissionD PHQ endering eh (eld y hndD PIP endering in emplteD PII emplte prgment snheritneD PPI emplte frgment nmingD PPH hemingD PIV wig form funtion refereneD TRS ypes efereneD SUW lidtionD PHR lidtion qroupsD PHT
H

r QHRD PUI equestEresponse prdigmD RH r heders gheEgontrolD PTSD PTV itgD PTW ixpiresD PTV vstEwodi(edD PUH ryD PUP
I

snstlltionD TQ snternlsD QIR gontroller esolverD QIT snternl equestsD QIU uernelD QIS equest rndlingD QIT
J

tvsripts snluding tvsriptsD IQS


K

uernel iventD QIU


L

vyoutD SHU
M

wonolog gon(gurtion efereneD SUT


N

xming gonventions fundlesD RQQ xming onventions ivent hisptherD QPI


P

erformne USS

ymfony houmenttionD PFH eutoloderD QIQ footstrp (lesD QIQ fyte ode heD QIP r empltesD SHT rnit D IVP ro(lerD QPV sing the pro(ler servieD QPW isulizingD QPWD QQH ro(ling ht golletorD SQR ixtension on(gurtionD PWW importsD PWV eferening serviesD QHI ht is serviecD PWR ht iscD PWR essionD WU htse torgeD RQH single emplte yverriding exeption templtesD IQW yverriding templtesD IQV single ession R plsh messgesD WU equest lotD SHV edd request formt nd mime typeD SQP tylesheets equirementsD UIU snluding stylesheetsD IQS outingD IHH ymfonyP gomponentsD RV formt prmeterD IIQ ymfonyP pundmentlsD QW esolute vsD IPH equests nd responsesD RQ edvned exmpleD IIQ T ellow G in route prmeterD QRT empltingD IPI fsisD IHH gontrollersD IIS imedding tionD IQI greting routesD IHP imedding gesD SHW heuggingD IIW pile votionsD IPV qenerting vsD IIW pormtsD IRI qenerting vs in templteD IPH relpersD IPWD SIH snludeD SHW smporting routing resouresD IIT wethod requirementD III snluding other templtesD IQH leholdersD IHR snluding stylesheets nd tvsriptsD IQS equirementsD IHV snheritneD IPR heme requirementD QRR vyoutD SHU nder the hoodD IHP vinking to ssetsD IQS vinking to pgesD IQQ S xming gonventionsD IPV eurity yutput espingD IRH eess gontrol vists @egvsAD RUH lotD SHV edvned egv oneptsD RUR gs nd relpersD IPW gon(gurtion efereneD SUH he templting servieD IQU gustom euthentition roviderD RWQ hreeElevel inheritne ptternD IQW rget rediret pthD SHQ ht is templtecD IPP eurityD otersD RTU estsD QIPD RSU ervie gontinerD PWQ hotrineD RSW edvned on(gurtionD QHV r euthentitionD RST gon(guring serviesD PWS ro(lingD RSV UST

ymfony houmenttionD PFH rnsltionsD PUV fsi trnsltionD PVH gon(gurtionD PUW greting trnsltion resouresD PVR pllk nd defult loleD PVU sn templtesD PWI wessge tloguesD PVQ wessge dominsD PVU wessge pleholdersD PVI lurliztionD PVW rnsltion resoure lotionsD PVQ ser9s loleD PVU wig gheD IPR gon(gurtion efereneD SUR sntrodutionD IPP
V

lidtion gonstrint trgetsD IWQ gustom onstrintsD QWW qetter onstrintsD IWR roperty onstrintsD IWQ rnish on(gurtionD SHR snvlidtionD SHS
W

e ervies yeD SQU


Y

ewvD UIH

USU

You might also like