1) Antes de empezar, lo primero es crear un BUNDLE Un bundle no es nada ms que un directorio que alberga todo lo relacionado con una caracterstica especica, inclu!endo las clases de "#", la coniguraci$n, e incluso %o&as de estilo ! los arc%i'os (a'a)cript "ara crear un paquete llamado AcmeHelloBundle *un paquete que usted 'a a construir en este captulo), e&ecute el comando siguiente ! siga las instrucciones que aparecen en pantalla *utilizar todas las opciones por deecto)+ php app / generate consola: paquete - namespace = Acme / HelloBundle - format = yml ,on este comando se crea el directorio+ src-Acme-#elloBundle . se a/ade una lnea al arc%i'o app-App0ernel1p%p para que el bundle - paquete se registre con el 0ernel1 // app/AppKernel.php public function registerBundles() { $bundles = array( // ... new Acme\HelloBundle\AcmeHelloBundle(), ); // ... return $bundles; } Creacin de una pgina en Symfony2 )on s$lo 2 pasos+ 2) ,rear un camino o ruta+ una ruta deine una U3L *e&+ -about) a tu pgina ! especiica un controlador que s!mon!2 e&ecutar cuando la U3L de petici$n coincida con la ruta padre1 "or deecto la coniguraci$n de rutas en las aplicaciones )!mon!2 est en+ app/config/routing.yml1 *se puede escoger e4tensi$n "#", o 56L) ,uando se %a creado el Bundle o paquete, en este arc%i'o se %a a/adido las siguientes lineas+ 7 app-conig-routing1!ml AcmeelloBundle! resource! "#AcmeelloBundle/$esources/config/routing.yml" prefi%! / En la lnea resource se indica el camino de la coniguraci$n de enrutamiento de dentro del bundle Acme#elloBundle1 *src-Acme-#elloBundle-3esources-conig-routing1!ml) El contenido de este arc%i'o es el siguiente en este caso+ 7 src-Acme-#elloBundle-3esources-conig-routing1!ml hello! pattern! /hello/{name& defaults! { 'controller! AcmeelloBundle!ello!inde% & pattern! es la ($) *ue la ruta e+ecutar,. {name& es un par,metro de la ($). -efaults! especifica el controlador *ue ser, e+ecutado. 8) ,rear un controlador+ es una unci$n "#" que recoge las peticiones de entrada ! la transorma en un ob&eto 3E)"9N)E de )!mon!2 que se de'uel'e al usuario1 El controlador : Acme#elloBundle+ #ello+inde4 es el nombre l$gico del controlador, ! se asigna al m;todo inde4Action de una clase "#" llamado Acme < #elloBundle < ,ontrolador < #ello1 -- src-Acme-#elloBundle-,ontroller-#ello,ontroller1p%p namespace Acme.elloBundle./ontroller; use 0ymfony./omponent.ttp1oundation.$esponse; class ello/ontroller { public function inde%Action($name) { return ne2 $esponse(34html54body5ello 3.$name.364/body54/html53); & & El controlador es simple+ se crea un nue'o ob&eto de respuesta, cu!o primer argumento es el contenido que se debe utilizar en la respuesta *una peque/a pgina #=6L en este e&emplo)1 >?elicitaciones@ Despu;s de crear s$lo una ruta ! un controlador, que !a tiene una pgina completamente uncional@ )i usted tiene todo lo conigurado correctamente, la aplicaci$n debe darle la bien'enida+ %ttp+--local%ost-appAde'1p%p-%ello-3!an B) "aso opcional+ crear un template1 El template te permite mo'er toda la presentaci$n *e&+ c$digo #=6L) en un arc%i'o separado ! reusarlo1 En lugar de escribir el #=6L dentro del controlador, se renderiza una template1 -- src-Acme-#elloBundle-,ontroller-#ello,ontroller1p%p namespace Acme.elloBundle./ontroller; use 0ymfony.Bundle.1rame2or7Bundle./ontroller./ontroller; class ello/ontroller e%tends /ontroller { public function inde%Action($name) { return $this85render(3AcmeelloBundle!ello!inde%.html.t2ig39 array(3name3 =5 $name)); // render a :: template instead // return $this85render(3AcmeelloBundle!ello!inde%.html.php39 array(3name3 =5 $name)); & & El m;todo render *) crea un ob&eto de respuesta rellleno con el contenido de la template renderizada1 Al igual que cualquier otro controlador, que en Cltima instancia 'a a de'ol'er ese ob&eto 3esponse1
El controlador renderiza la template Acme#elloBundle-#ello-inde41%tml1tDig , el cual usa la siguiente con'enci$n de nombres+ BundleName+ControllerName+TemplateName Este es el nombre l$gico de la template, el cual es mapeado en la localizaci$n sica+ /path/to/BundleName-3esources-'ieDs-ControllerName-TemplateName En este caso+ Acme#elloBundle es el nombre del bundle1 #ello es el controlador1 Ende41%tml1tDig es la template - plantilla1 F7 src-Acme-#elloBundle-3esources-'ieDs-#ello-inde41%tml1tDig 7G {; e%tends 3!!base.html.t2ig3 ;& {; bloc7 body ;& ello {{ name &&6 {; endbloc7 ;& Tareas comunes del controlador Redireccion ( mtodo redirect() ) Para redirigir al usuario a otra pgina. public function inde%Action() { return $this85redirect($this85generate(rl(3homepage3)); & <l m=todo generate(rl es una funci>n *ue genera la ($) de una ruta dada. :or defecto el m=todo redirect() e+ecuta un redirect ?@A (temporal) . :ara e+ecutar un redirect ?@B (permanente) se modifica el segundo argumento. public function inde%Action() { return $this85redirect($this85generate(rl(3homepage3)9 ?@B); & orwarding() !irigir a otro controlador con el mtodo "orward() #ue de$uel$e el o%&eto respuesta #ue de$uel$e ese controlador. '&( public function inde%Action($name) { $response = $this85for2ard(3AcmeelloBundle!ello!fancy39 array( 3name3 =5 $name9 3color3 =5 3green3 )); // further modify the response or return it directly return $response; & Renderi)ar plantillas 'l mtodo render*iew() renderi)a una plantilla + de$uel$e su contenido. 'l contenido de la template puede ser usado para crear un o%&eto Response. '&( $content = $this85renderCie2(3AcmeelloBundle!ello!inde%.html.t2ig39 array(3name3 =5 $name)); return ne2 $esponse($content); > en una lDnea! return $this85render(3AcmeelloBundle!ello!inde%.html.t2ig39 array(3name3 =5 $name)); <n ambos casos9 la template $esources/Eie2s/ello/inde%.html.t2ig de AcmeelloBundle ser, renderiFada. Accediendo a otros ser$icios $re*uest = $this85get$e*uest(); $templating = $this85get(3templating3); $router = $this85get(3router3); $mailer = $this85get(3mailer3); :ara Eer la lista de los serEicios habilitados! php app/console container!debug ,estionando errores + pginas -.- (pginas no encontradas) /uando no se encuentra algun recurso9 se debe deEolEer una respuesta del tipo G@G. :ara hacer esto9 se lanFa una e%cepci>n especial. public function inde%Action() { $product = // retrieEe the ob+ect from database if (6$product) { thro2 /t0is12create3otound'4ception(3Hhe product does not e%ist3); & return $this85render(...); & <l m=todo createIot1ound<%ception() crea un ob+eto especial Iot1oundttp<%ception9 el cu,l lanFar, triggers G@G HH: response dentro de 0ymfony. ,estionando sesiones 0ymfonyA proEee un ob+eto agradable de sesi>n *ue se puede utiliFar para almacenar informaci>n del usuario entre peticiones. :or defecto9 0ymfonyA almacena los atributos en una coo7ie usando las sesiones :: natiEas. <+emplo de codigo en un controlador! $session = $this85get$e*uest()85get0ession(); // store an attribute for reuse during a later user re*uest $session85set(3foo39 3bar3); // in another controller for another re*uest $foo = $session85get(3foo3); // set the user locale $session85set)ocale(3fr3); 5ensa&es 6A7H( :uedes almacenar pe*ueJos mensa+es *ue ser,n guardados en la sesi>n del usuario para una petici>n adicional. <sto es muy Ktil cuando se procesa un formulario9 cuando *uieres redirigir y mostrar un mensa+e especial en la siguiente petici>n. <ste tipo de mensa+es se llaman mensa+es 1)A0. Lmagina *ue est,s procesando el enEDo de un formulario! public function updateAction() { $form = $this85create1orm(...); $form85bind$e*uest($this85get$e*uest()); if ($form85isCalid()) { // do some sort of processing $this85get(3session3)85set1lash(3notice39 3Mour changes 2ere saEed63); return $this85redirect($this85generate(rl(...)); & return $this85render(...); & <l nombre 3notice3 no es importante9 se utiliFa para identificar el tipo de mensa+e. <n la plantilla de la siguiente acci>n9 el siguiente c>digo podrDa ser usado para renderiFar el mensa+e 3noticia3 {; if app.session.has1lash(3notice3) ;& 4diE class="flash8notice"5 {{ app.session.flash(3notice3) && 4/diE5 {; endif ;& 'l o%&eto R'7P837' <l Knico re*uisito para un controlador es deEolEer un ob+eto $<0:NI0<. )a clase $<0:NI0< es una abstraccion :: de la respuesta HH:. // create a simple $esponse 2ith a A@@ status code (the default) $response = ne2 $esponse(3ello 3.$name9 A@@); // create a O0NI8response 2ith a A@@ status code $response = ne2 $esponse(+son'encode(array(3name3 =5 $name))); $response85headers85set(3/ontent8Hype39 3application/+son3); 'l o%&eto R'9:'7T <l controlador tambi=n tiene acceso al ob+eto $e*uest cuando e%tiende la clase base /ontroller. $re*uest = $this85get$e*uest(); $re*uest85isPmlttp$e*uest(); // is it an A+a% re*uestQ $re*uest85get:referred)anguage(array(3en39 3fr3)); $re*uest85*uery85get(3page3); // get a $'R<H parameter $re*uest85re*uest85get(3page3); // get a $':N0H parameter
Routing 0ymfonyA te permite definir ($)0 *ue mapean diferentes ,reas de tu aplicaci>n. Routing en acci;n (na ruta es un mapa a partir de un modelo de direcci>n ($) a un controlador. :or e+emplo9 supongamos *ue usted *uiere para adaptarse a cual*uier ($) como /blog/my8post o /blog/all8about8symfony y lo enEDa a un controlador *ue puede mirar para arriba y renderiFar esa entrada de blog. )a ruta es simple! S app/config/routing.yml blog'sho2! pattern! /blog/{slug& defaults! { 'controller! AcmeBlogBundle!Blog!sho2 & <l modelo definido por el pattern blog'sho2 actKa como /blog/T9 donde el comodDn es dado por el nombre UslugV. Controlador dado en defaults: // src/Acme/BlogBundle//ontroller/Blog/ontroller.php namespace Acme.BlogBundle./ontroller; use 0ymfony.Bundle.1rame2or7Bundle./ontroller./ontroller; class Blog/ontroller e%tends /ontroller { public function sho2Action($slug) { $blog = // use the $slug Earible to *uery the database return $this85render(3AcmeBlogBundle!Blog!sho2.html.t2ig39 array( 3blog3 =5 $blog9 )); & & Routing, %a&o la capuc0a( /uando una petici>n se realiFa a tu aplicaci>n9 contiene una direcci>n e%acta al recurso *ue el cliente est, pidiendo. <sta direcci>n se llama ($) o (($L) y podria ser! /contact /blog/read8me o algo parecido. /omo e+emplo tomaremos! R<H /blog/my8blog8post <l ob+etiEo del sistema de rutas de 0ymfonyA es parsear esta ($) y determinar *u= controlador deberDa ser e+ecutado. <l proceso completo serDa el siguiente! B. )a petici>n es mane+ada por el fron controller de symfonyA (e+! app.php) A. <l core de 0ymfonyA (es decir el Kernel) pide al router inspeccionar la petici>n ?. <l router empare+a /iguala la ($) entrante a una ruta especDfica y deEuelEe informaci>n sobre la ruta9 incluyendo el controlador *ue deberDa ser e+ecutado. G. <l Kernel de 0ymfonyA e+ecuta el controlador el cu,l deEuelEe el ob+eto $<0:NI0<. <reando Rutas 0ymfony carga todas las rutas para su aplicaci>n a partir de un Knico archiEo de configuraci>n de enrutamiento. <l archiEo suele ser app/config/routing.yml9 pero puede ser configurado para ser cual*uier cosa (incluyendo un archiEo PW) o ::) a traE=s del archiEo de configuraci>n de la aplicaci>n. S app/config/config.yml frame2or7! S ... router! { resource! ";7ernel.root'dir;/config/routing.yml" & <on"iguraci;n de ruta %sica -efinir una ruta es sencillo9 y una aplicaci>n tendr, muchDsimas rutas definidas! (na ruta b,sica tiene dos partes9 el pattern para empare+ar9 y el array de"aults. <+emplo! '2elcome! pattern! / defaults! { 'controller! Acme-emoBundle!Wain!homepage & <sta ruta empare+a la raiF ( / ) y la mapea al controlador Acme-emoBundle!Wain!homepage Routing con marcadores '&emplo( blog'sho2! pattern! /blog/{slug& defaults! { 'controller! AcmeBlogBundle!Blog!sho2 & <ste pattern empare+ar, cual*uier cosa *ue se pareFca a /blog/T. <n otras palabras9 si la ($) es /blog/hello82orld la Eariable $slug tendr, el Ealor Uhello82orldV. <l pattern no empare+ar, simplemente la ($) /blog por*ue por defecto todos los marcadores son necesarios. 5arcadores re#ueridos + opcionales blog! pattern! /blog/{page& defaults! { 'controller! AcmeBlogBundle!Blog!inde%9 page! B & =%log >page} ? @ =%log=@ >page} ? @ =%log=A >page} ? A ABadiendo re#uerimientos( blog! pattern! /blog/{page& defaults! { 'controller! AcmeBlogBundle!Blog!inde%9 page! B & blog'sho2! pattern! /blog/{slug& defaults! { 'controller! AcmeBlogBundle!Blog!sho2 & <l problema est, *ue solo se Ea a e+ecutar la ruta UblogV y nunca la Ublog'sho2V por*ue ambas tienen un par,metro9 la primera par,metro UpageV9 la segunda par,metro UslugV. <l enrutador de symfonyA siempre escoger, la primera ruta *ue coincida /empare+e con la ($). blog! pattern! /blog/{page& defaults! { 'controller! AcmeBlogBundle!Blog!inde%9 page! B & re*uirements! page! .dX <l re*uerimiento .dX re*uirement es una e%presi>n regular *ue indica *ue el Ealor del par,metro {pageY debe ser un dDgito. /on eso solucionamos *ue las ($)0 del tipo /blog/? Eayan por la primera ruta9 y *ue las ($)0 del tipo /blog/hello82orld Eayan por la segunda ruta. <sto significa *ue el orden de las rutas es muy importante. Ntros e+emplos! homepage! pattern! /{culture& defaults! { 'controller! Acme-emoBundle!Wain!homepage9 culture! en & re*uirements! culture! enZfr :ara peticiones entrantes! / {culture& = en /en {culture& = en /fr {culture& = fr /es won't match this route ABadiendo Re#uerimientos de mtodo HTTP Adem,s puedes indicar en la ruta el m=todo *ue se utiliFa en la petici>n entrante. (R<H9 <A-9 :N0H9 :(H9 -<)<H<). <+emplo! suponemos *ue tenemos un formulario de contacto con dos controladores (uno para mostrar el formulario en una petici>n R<H). M otro para procesar el formulario cuando es enEiado (en una petici>n :N0H). Ejemplo de configuracin de ruta: contact! pattern! /contact defaults! { 'controller! Acme-emoBundle!Wain!contact & re*uirements! 'method! R<H contact'process! pattern! /contact defaults! { 'controller! Acme-emoBundle!Wain!contact:rocess & re*uirements! 'method! :N0H 0i no se especifica el m=todo de re*uerimiento la ruta empare+ar, con todos los m=todos. ,enerando :R67 <n realidad el sistema de routing de 0ymfonyA es un sistema bidireccional! mapea la ($) a un controladorXparametros y de una rutaXparametros deEuelEe una ($). )os m=todos matc0() y generate() forman este sistema bidireccional. $params = $router85matc0(3/blog/my8blog8post3); // array(3slug3 =5 3my8blog8post39 3'controller3 =5 3AcmeBlogBundle!Blog!sho23) $uri = $router85generate(3blog'sho239 array(3slug3 =5 3my8blog8post3)); // /blog/my8blog8post class Wain/ontroller e%tends /ontroller { public function sho2Action($slug) { // ... $url = $this85get(3router3)85generate(3blog'sho239 array(3slug3 =5 3my8 blog8post3)); & & ,enerando :R67 a%solutas :or defecto el router genera direcciones relatiEas. :ara generar direcciones ($) absolutas s>lo hay *ue pasarle al tercer argumento del m=todo generate() el Ealor H$(<. $router85generate(3blog'sho239 array(3slug3 =5 3my8blog8post3)9 true); // http!//222.e%ample.com/blog/my8blog8post ,enerando :R67 con 9uer+ 7trings $router85generate(3blog39 array(3page3 =5 A9 3category3 =5 30ymfony3)); // /blog/AQcategory=0ymfony ,enerando :R67 desde una plantilla = template 4a href="{{ pat0(3blog'sho239 { 3slug3! 3my8blog8post3 &) &&"5 $ead this blog post. 4/a5 Hambien se pueden generar ($)0 absolutas! 4a href="{{ url(3blog'sho239 { 3slug3! 3my8blog8post3 &) &&"5 $ead this blog post. 4/a5 T'5P6AT'7 <n symfonyA se suele usar como templates el lenguage H2ig. H2ig define dos tipos de sinta%is especial! 46-N/HM:< html5 4html5 4head5 4title5[elcome to 0ymfony64/title5 4/head5 4body5 4hB5{{ page'title &&4/hB5 4ul id="naEigation"5 {; for item in naEigation ;& 4li54a href="{{ item.href &&"5{{ item.caption &&4/a54/li5 {; endfor ;& 4/ul5 4/body5 4/html5 {{ ... &&! es como el echo9 para imprimir una Eariable o el resultado de una e%presi>n. {; ... ;&! hace algo. (na eti*ueta *ue controla la l>gica de la plantilla9 es usada para e+ecutar sentencias como los bucles9 los ifs... /rear comentarios! {S this is a comment S& Hambi=n usa filtros *ue modifican el contenido antes de renderiFarlo! <+! {{ titleZupper && a*uD la Eariable title se pone en Wayusculas antes de renderiFarla. <+emplo de plantilla H[LR! 4ul5 {; for user in users ;& 4li5{{ user.username &&4/li5 {; else ;& 4li5Io users found4/li5 {; endfor ;& 4/ul5 Herencia de plantillas + la+outs :rimero construimos un archiEo con el layout base. {S app/$esources/Eie2s/base.html.t2ig S& 46-N/HM:< html5 4html5 4head5 4meta http8e*uiE="/ontent8Hype" content="te%t/html; charset=utf8\" /5 4title5{; bloc7 title ;&Hest Application{; endbloc7 ;&4/title5 4/head5 4body5 4diE id="sidebar"5 {; bloc7 sidebar ;& 4ul5 4li54a href="/"5ome4/a54/li5 4li54a href="/blog"5Blog4/a54/li5 4/ul5 {; endbloc7 ;& 4/diE5 4diE id="content"5 {; bloc7 body ;&{; endbloc7 ;& 4/diE5 4/body5 4/html5 <sta plantilla base define el es*ueleto base HW) en una p,gina de dos columnas. <n este e+emplo ? {; bloc7 ;& areas son definidos (title9 sidebar y body). /ada blo*ue puede ser sobreescrito por una plantilla hi+a o mantener su implementaci>n por defecto. (na plantilla hi+a podrDa ser asD! {S src/Acme/BlogBundle/$esources/Eie2s/Blog/inde%.html.t2ig S& {; e%tends 3!!base.html.t2ig3 ;& {; bloc7 title ;&Wy cool blog posts{; endbloc7 ;& {; bloc7 body ;& {; for entry in blog'entries ;& 4hA5{{ entry.title &&4/hA5 4p5{{ entry.body &&4/p5 {; endfor ;& {; endbloc7 ;& )a plantilla padre se identifica con una sinta%is de cadena especial (!! base.html.t2ig) *ue indica *ue la plantilla EiEe en el directorio app/$esources/Eie2s. /uando se traba+a con herencia de plantillas hay *ue tener en cuenta lo siguiente! 0i se usa {; e%tends ;& en una plantilla9 debe ser el primer tag en esa plantilla. /uantas m,s eti*uetas {; bloc7 ;& tengas en tu plantilla base me+or9 para *ue asi tu plantilla sea m,s fle%ible. )as plantillas hi+as no pueden definir blo*ues. 0i necesitas conseguir el contenido de un blo*ue de la plantilla base9 puedes usar la funcion {{ parent() && <s muy util si se *uiere aJadir los contenidos del blo*ue padre en EeF de sobreescribirlo. {; bloc7 sidebar ;& 4h?5Hable of /ontents4/h?5 ... {{ parent() && {; endbloc7 ;& 3om%res de las plantillas + d;nde se locali)an = guardan -os localiFaciones! 1) app/$esources/Eie2s/ 2) path/to/bundle/$esources/Eie2s/ 0ymfonyA usa un sinta%is %undle!controller!template para las plantillas. <+emplo! AcmeBlogBundle!Blog!inde%.html.t2ig. <sto significa lo siguiente! AcmeBlogBundle! (bundle) la plantilla se encuentra dentro de la carpeta src/Acme/BlogBundle Blog! (controller) indica *ue la plantilla se encuentra dentro del subdirectorio UBlogV en $esources/Eie2s inde%.html.t2ig! (plantilla) el nombre actual de la plantilla. <l path final serDa! src=Acme=BlogBundle=Resources=$iews=Blog=inde4.0tml.twig.
Cncludes de otras templates <sta serDa la plantilla *ue *ueremos reutiliFar! {S src/Acme/ArticleBundle/$esources/Eie2s/Article/article-etails.html.t2ig S& 4hA5{{ article.title &&4/hA5 4h? class="byline"5by {{ article.authorIame &&4/h?5 4p5 {{ article.body && 4/p5 Incluimos esta plantilla en otra plantilla: {S src/Acme/ArticleBundle/$esources/Article/list.html.t2ig S& {; e%tends 3AcmeArticleBundle!!layout.html.t2ig3 ;& {; bloc7 body ;& 4hB5$ecent Articles4hB5 {; for article in articles ;& {; include DAcmeArticleBundle(Article(article!etails.0tml.twigD wit0 >DarticleD( article} ;& {; endfor ;& {; endbloc7 ;& 'm%e%iendo controladores Lmaginemos *ue tienes una Fona en tu plantilla *ue contiene los ? articulos mas recientes. /onseguir estos ? Kltimos artDculos re*uerir, una consulta a la base de datos *ue no puede ser realiFado dentro de una plantilla (debe hacerse desde un controlador) )a soluci>n es simplemente embeber el resultado de un controlador enteramente en tu plantilla. :rimero Eamos a crear el controlador *ue renderiFa un cierto nKmero de artDculos! // src/Acme/ArticleBundle//ontroller/Article/ontroller.php class Article/ontroller e%tends /ontroller { public function recentArticlesAction($ma% = ?) { // ma7e a database call or other logic to get the "$ma%" most recent articles $articles = ...; return /t0is12render(DAcmeArticleBundle(Article(recent6ist.0tml.twigD, arra+(DarticlesD ?2 /articles)); & & la plantilla recent)ist.html.t2ig contendr, el siguiente c>digo! {S src/Acme/ArticleBundle/$esources/Eie2s/Article/recent)ist.html.t2ig S& {; for article in articles ;& 4a href="/article/{{ article.slug &&"5 {{ article.title && 4/a5 {; endfor ;& :ara incluir el controlador9 se debe usar la sinta%is de cadena est,ndar para los controladores (es decir bundle!controller!action) {S app/$esources/Eie2s/base.html.t2ig S& ... 4diE id="sidebar"5 {; render "AcmeArticleBundle!Article!recentArticles" 2ith {3ma%3! ?& ;& 4/diE5 6inEando a pginas desde una plantilla /rear lin7s a otras p,ginas en una aplicaci>n con symfony es el traba+o m,s comKn de una template. 0e suele usar el m=todo pat0() para generar ($)0 basadas en la configuraci>n de routing. Ejemplo sencillo: /onfiguracion de routing de la p,gina 2elcome. '2elcome! pattern! / defaults! { 'controller! Acme-emoBundle![elcome!inde% & :ara lin7ar a esta p,gina solamente usa el m=todo path en la plantilla! 4a href="{{ path(3'2elcome3) &&"5ome4/a5 Ejemplo con una ruta con parmetros: article'sho2! pattern! /article/{slug& defaults! { 'controller! AcmeArticleBundle!Article!sho2 & <n este caso se necesita especificar el el nombre de la ruta (article'sho2) y un Ealor para el par,metro {slug& {S src/Acme/ArticleBundle/$esources/Eie2s/Article/recent)ist.html.t2ig S& {; for article in articles ;& 4a href="{{ pat0(3article'sho239 { 3slug3! article.slug &) &&"5 {{ article.title && 4/a5 {; endfor ;& Hambi=n se pueden generar una ($) absoluta de =sta manera! 4a href="{{ url(3'2elcome3) &&"5ome4/a5 6inEando a los "ic0eros = imgenes = arc0i$os = &a$ascripts... 1unci>n asset() 4img src="{{ asset(3images/logo.png3) &&" alt="0ymfony6" /5 4lin7 href="{{ asset(3css/blog.css3) &&" rel="stylesheet" type="te%t/css" /5 Cnclu+endo 0o&as de estilo + &a$ascripts en plantillas Twig <mpeFamos aJadiendo dos blo*ues en tu plantilla base *ue contendr,n tus assets (st+les0eets dentro de la eti*ueta head y &a$ascripts +usto antes del cierre de la eti*ueta body) {S 3app/$esources/Eie2s/base.html.t2ig3 S& 4html5 4head5 {S ... S& {; bloc7 st+les0eets ;& 4lin7 href="{{ asset(3/css/main.css3) &&" type="te%t/css" rel="stylesheet" /5 {; endbloc7 ;& 4/head5 4body5 {S ... S& {; bloc7 &a$ascripts ;& 4script src="{{ asset(3/+s/main.+s3) &&" type="te%t/+aEascript"54/script5 {; endbloc7 ;& 4/body5 4/html5 <s muy f,cil. ]M *ue ocurrirDa si se *uisiera incluir una ho+a de estilos o c>digo +aEascript desde una plantilla hi+aQ :lantilla hi+a! {S src/Acme/-emoBundle/$esources/Eie2s//ontact/contact.html.t2ig S& {; e%tends 3!!base.html.t2ig3 ;& {; bloc7 stylesheets ;& {{ parent() && 4lin7 href="{{ asset(3/css/contact.css3) &&" type="te%t/css" rel="stylesheet" /5 {; endbloc7 ;& {S ... S& 0implemente se sobreescribe el blo*ue stylesheets9 pero si no *ueremos modificar el contenido del blo*ue stylesheet base por*ue lo *ue *ueremos es aJadir nueEo c>digo9 entonces es importante poner {{ parent && para incluir todo el contenido del blo*ue stylesheets de la plantilla base. *aria%les glo%ales de plantilla )a Eariable UappV es una instancia de RlobalCariables (0ymfony/Bundle/1rame2or7Bundle/Hemplating/RlobalCariables) app.securit+ The security conte!t" app.user The current user o#$ect" app.re#uest The re%uest o#$ect" app.session The session o#$ect" app.en$ironment The current en&ironment 'de&( prod( etc)" app.de%ug True if in de#ug mode" *alse other+ise" <+emplo de uso! 4p5(sername! {{ app.user.username &&4/p5 {; if app.debug ;& 4p5$e*uest method! {{ app.re*uest.method &&4/p5 4p5Application <nEironment! {{ app.enEironment &&4/p5 {; endif ;& Bases de datos + doctrine -octrine es una biblioteca cuyo Knico ob+etiEo es ofrecer herramientas muy Ktiles y poderosas para hacer f,cil el acceso a la bbdd. -octrine est, totalmente desacoplada de 0ymfony y su uso es opcional. <ste capDtulo trata sobre -octrine N$W el cu,l tiene como ob+etiEo permitir el mapeo de ob+etos hacia una base de datos relacional (mys*l9 postgres*l9 microsoft s*l) :asos para este e+emplo! B) Reneramos un bundle Acme0toreBundle php app/console generate:bundle --namespace=Acme/StoreBundle A) /onfigurando la base de datos. <n an app/config/parameters.ini Ahora *ue -octrine conoce tu bbdd9 usted puede crear la base de datos. /on el comando! php app/console doctrine!database!create ?) /reamos una entidad producto en Usrc/Acme/0toreBundle/<ntity/:roduct.phpV // src/Acme/0toreBundle/<ntity/:roduct.php namespace Acme.0toreBundle.<ntity; class :roduct { protected $name; protected $price; protected $description; & G) (sustitucion del paso ?) :uedes crear esta clase / entidad a traE=s de la biblioteca -octrine. php app/console doctrine!generate!entity 88entity="Acme0toreBundle!:roduct" 88fields="name!string(A^^) price!float description!te%t" ^) AJadir informaci>n de mapeo :ara *ue -octrine sea capaF de hacer este mapeo9 se debe crear el UmetadataV o la configuraci>n *ue le dice a -octrine e%actamente como deberDan ser mapeadas la clase :roducto y sus propiedades a la bbdd. <ste metadata puede ser especificado en diferentes formatos (MAW)9 PW) o directamente a traE=s de anotaciones en la clase :roducto) ,enerando ,etters y Setters Aun*ue -octrine ahora sabe como persistir un ob+eto :roducto a la bbdd9 la clase :roducto en si misma no es muy Ktil. _) 0e deben crear m=todos de inicialiFaci>n de los atributos y de recogida de esos atributos (puesto *ue las propiedades est,n protegidas ` protected 8 ) <+! getIame()9 setIame(). A"ortunadamente !octrine puede 0acer sto por tF e&ecutando el comando( php app/console doctrine!generate!entities Acme/0toreBundle/<ntity/:roduct <ste comando te asegura *ue todos los getters y setters son generados para la clase :roducto. <s un comando seguro ` se puede e+ecutar tantas Eeces como se *uiera. 0olo genera getters y setters *ue no e%istan9 es decir9 no reemplaFa tus m=todos ya e%istentes. <+ecutando el comando9 se han creado en el archiEo src/Acme/0toreBundle/<ntity/:roduct.php los m=todos! public function getLd(); public function setIame($name); public function getIame(); public function set:rice($price); public function get:rice(); public function set-escription($description); y public function get-escription(). <l comando doctrine!generate!entities guarda una copia de seguridad de la product1p%p original nombrandolo product1p%p H1 En algunos casos, la presencia de este arc%i'o puede causar un error del tipo INo se puede redeclare claseI )e puede quitar sin problemas1 0e pueden generar todas las entidades conocidas de un bundle o de un nombre de espacios entero! php app/console doctrine!generate!entities Acme0toreBundle php app/console doctrine!generate!entities Acme <reando el es#uema = ta%las de la %%dd J) -octrine y la creaci>n de la nueEa tabla de productos. Ahora tenemos una clase :roducto con informaci>n de mapeo para *ue -octrine sepa e%actamente como se persiste en bbdd. -e momento no tenemos creada ninguna tabla en bbdd para los productos. -octrine nos puede ayudar a crear todas las tablas de la bbdd *ue se necesiten para cada entidad en tu aplicaci>n. 0e e+ecuta el siguiente comando! p%p app-console doctrine+sc%ema+update ::orce Persisting 8%&ects to t0e !ata%ase K) Una 'ez que se tiene la entidad "roducto mapeada, ! la tabla product correspondiente a los productos, se est preparado para poder persistir datos en la base de datos1 Lsto se realiza desde el interior de un controlador *controller)1 )e a/ade el siguiente m;todo al controller por deecto del bundle Acme)toreBundle *src-Acme-)toreBundle-,ontroller-Deault,ontroller1p%p)1 -- src-Acme-)toreBundle-,ontroller-Deault,ontroller1p%p use Acme.0toreBundle.<ntity.:roduct; use 0ymfony./omponent.ttp1oundation.$esponse; // ... public function createAction() { //se crea un nueEo producto y se inicialiFan sus propiedades. $product = ne2 :roduct(); $product85setIame(3A 1oo Bar3); $product85set:rice(3Ba.aa3); $product85set-escription(3)orem ipsum dolor3); //esta linea recoge el ob+eto gestor de la entidad9 el cual es responsable de mane+ar el proceso de persistencia y recoleccion de ob+etos hacia y desde la bbdd. $em = $this85get-octrine()85get<ntityWanager(); //el m=todo persists le indica a -octrine *ue mane+e el ob+eto $product. <sto no e+ecuta ninguna *uery sobre la bbdd todaEDa. $em85persist($product); // -octrine mira todos los ob+etos *ue est, mane+ando para Eer si necesitan ser persistentes en la bbdd. A*ui es donde se e+ecuta la *uery9 en este caso9 de inserci>n. $em85flush(); return ne2 $esponse(3/reated product id 3.$product85getLd()); & M) "ara probar este e&emplo se necesita crear una ruta que apunte a esta acci$n para probar que unciona1 En mi caso %e modiicado+ app-conig-routing1!ml ! en lugar de Acme)toreBundle+ 7 resource+ INAcme)toreBundle-,ontroller-I 7 t!pe+ annotation 7 prei4+ - #e escrito+ Acme)toreBundle+ resource+ INAcme)toreBundle-3esources-conig-routing1!mlI prei4+ - Luego, %e creado el arc%i'o src-Acme-)toreBundle-3esources-conig-routing1!ml Acme)toreBundleA%omepage+ pattern+ -store- deaults+ F Acontroller+ Acme)toreBundle+Deault+create G . e&ecutando la siguiente ruta+ %ttp+--DDD1gas'i1com-appAde'1p%p-store- )e a/ade un nue'o registro en la tabla product de la bbdd -ecoger o#$etos de la BB.. En el controlador *src/Acme/StoreBundle/Controller/.efaultController"php) se a/ade una nue'a unci$n *unction s%oDAction*Oid)) public unction s%oDAction*Oid) F Oproduct P Ot%is:QgetDoctrine*) :Qget3epositor!*RAcme)toreBundle+"roductR) :Qind*Oid)S i *@Oproduct) F t%roD Ot%is:QcreateNot?oundE4ception*RNo product ound or id R1Oid)S G -- do somet%ing, liTe pass t%e Oproduct ob&ect into a template --return neD 3esponse*R)e %a conseguido el producto con id R1Oproduct:QgetEd*)1RUbrQ El nombre es + R1Oproduct: QgetDescription*)1RUbrQ El precio del producto es+ R1Oproduct:Qget"rice*))S return Ot%is:Qrender*RAcme)toreBundle+Deault+s%oD1%tml1tDigR, arra!*RproductR PQ Oproduct))S G --llamada a la 'ista s%oD1%tml1tDig que se encuentra en src-Acme-)toreBundle-'ieDs-Deault- En src-Acme-)toreBundle-3esources-conig-routing1!ml se a/ade la siguiente ruta+ Acme)toreBundleAs%oDproduct+ pattern+ -store-FidG deaults+ F Acontroller+ Acme)toreBundle+Deault+s%oD G 7u%ir los css, imagenes etc instalados en %undle=Resources=pu%lic a we%=%undles=%undledemo= /omando! php app/console assets!install 2eb <omo generar entidades desde una %ase de datos e4istente <l primer paso hacia la construcci>n de las entidades de una base de datos e%istente es pedir a -octrine la introspecci>n la base de datos y generar los archiEos de metadatos correspondientes. )os archiEos de metadatos describen la entidad para generar sobre la base de los campos de las tablas. p0p app=console doctrine(mapping(con$ert 4ml .=src=Acme=7toreBundle=Resources=con"ig=doctrine=metadata=orm 11"rom1data%ase 11"orce <s posible generar los metadatos en formato MAW) cambiado el primer argumento a yml (na EeF *ue los archiEos de metadatos se generan9 usted puede pedir a -octrine importar el es*uema y construir las clases relacionadas con la entidad mediante la e+ecuci>n de los siguientes dos comandos. p0p app=console doctrine(mapping(import Acme7toreBundle annotation p0p app=console doctrine(generate(entities Acme7toreBundle El primer comando genera las clases de entidad con mapas de anotaciones, tu puedes por supuesto cambiar el argumento annotation a 4ml o !ml1 El segundo comando genera todos los getters ! setters para sus entidades php doctrine orm!conEert8mapping 88from8database yml src/Acme/0toreBundle/$esources/config/doctrine/metadata/orm/(suarios.orm.yml