Development

Documentation/es_ES: my-first-project.htm

You must first sign up to be able to contribute.

Documentation/es_ES: my-first-project.htm

File my-first-project.htm, 56.0 kB (added by tecniloco, 10 years ago)

Traducción al español del tutorial El primer proyecto de Symfony (spanish)

Line 
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/2000/REC-xhtml1-200000126/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
3
4  
5     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6     <meta name="title" content="symfony - open-source PHP web framework">
7 <meta name="robots" content="index, follow">
8 <meta name="description" content="symfony - open-source PHP web framework">
9 <meta name="keywords" content="symfony, project, framework, php, php5, open-source, mit, symphony">
10 <meta name="language" content="en"><title>symfony Web PHP Framework » My first symfony project</title>
11
12    
13
14     <link rel="alternate" type="application/rss+xml" title="Blog Entries" href="http://feeds.feedburner.com/symfony/blog">
15     <link rel="alternate" type="application/rss+xml" title="Blog Comments" href="http://feeds.feedburner.com/symfony/blog/comments">
16     <link rel="alternate" type="application/rss+xml" title="Forum Entries" href="http://www.symfony-project.com/forum/rdf.php?mode=m&amp;l=1&amp;n=10&amp;basic=1">
17     <link rel="alternate" type="application/rss+xml" title="User Mailing-List Messages" href="http://groups.google.com/group/symfony-users/feed/atom_v1_0_msgs.xml">
18     <link rel="alternate" type="application/rss+xml" title="Dev Mailing-List Messages" href="http://groups.google.com/group/symfony-devs/feed/atom_v1_0_msgs.xml">
19     <link rel="alternate" type="application/rss+xml" title="Project Timeline" href="http://trac.symfony-project.com/trac/timeline?milestone=on&amp;ticket=on&amp;ticket_details=on&amp;changeset=on&amp;wiki=on&amp;max=10&amp;daysback=10&amp;format=rss">
20
21     <link rel="shortcut icon" href="http://www.symfony-project.com/favicon.ico">
22   <link rel="stylesheet" type="text/css" media="all" href="my-first-project_files/main.css">
23 <link rel="stylesheet" type="text/css" media="print" href="my-first-project_files/print.css">
24 <link rel="stylesheet" type="text/css" media="screen" href="my-first-project_files/highlight.css"></head><body>
25     <table id="topbar" cellpadding="0" cellspacing="0" width="100%">
26       <tbody><tr>
27         <td id="header"><a href="http://www.symfony-project.com/"><img src="my-first-project_files/symfony_logo.gif" alt="Symfony_logo"></a></td>
28         <td id="navigation">
29           <ul>
30             <li><a href="http://www.symfony-project.com/about">About</a></li>
31             <li><a href="http://www.symfony-project.com/installation">Installation</a></li>
32             <li><a href="http://www.symfony-project.com/doc/1_0/">Documentation</a></li>
33             <li><a href="http://www.symfony-project.com/community">Community</a></li>
34             <li><a href="http://www.symfony-project.com/blog/">Blog</a></li>
35             <li class="last"><a href="http://trac.symfony-project.com/trac/timeline">Development</a></li>
36           </ul>        </td>
37       </tr>
38       <tr><td id="topseparator" colspan="2"></td></tr>
39               <tr>
40           <td colspan="2">
41             <h1>  <a href="http://www.symfony-project.com/doc/1_0/">Tutorial Symfony </a></h1>
42             <h2> Mi primer proyecto symfony</h2>                      </td>
43         </tr>
44           </tbody></table>
45
46    
47
48
49
50 <div id="bar">
51   <a href="http://www.symfony-project.com/doc/1_0/">« Back to documentation</a></div>
52
53 <div id="documentation_release_info">Tu está viendo actualmente la documentación de Symfony  versiónl 1,0 . Cambiar a:
54   <ul>
55                 <li>
56                   <a href="http://www.symfony-project.com/tutorial/dev/my-first-project">development</a>              </li>
57             </ul>
58 </div>
59
60 <div id="license">
61   <table>
62     <tbody><tr>
63       <td>
64         <a target="_blank" rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">
65           <img alt="Creative Commons License" style="border-width: 0pt;" src="my-first-project_files/80x15.png" align="left">
66         </a>
67       </td>
68       <td>
69         This <span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/MovingImage" rel="dc:type">work</span> is licensed under a
70         <a target="_blank" rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License</a>.
71       </td>
72     </tr>
73   </tbody></table>
74 </div>
75
76 <div id="content1" class="documentation">
77   <p>Así que, ¿quieres probarla? Vamos a construir juntos una aplicaciones web plenamente  funcional  en una hora. Un blog!. <br />
78     <br />
79 Suponemos que se trabaja con apache/PHP5 instalado y puesto en  marcha en su equipo local. También tendrá la extensión SQLite, que está  incluido y compilado por defecto en PHP5. Sin embargo, a partir de PHP  5.1.0 el usuario debe activar manualmente la extensión en <code>php.ini</code> (ver howto <a href="http://fr3.php.net/manual/en/ref.sqlite.php">aqui</a>).</p>
80
81 <a name="Install symfony and initialize the project"></a><h2>Instalar Symfony e iniciar el proyecto</h2>
82
83 <p>Para ir más rápido, vamos a utilizar  the symfony sandbox (También puede descargar el <a href="http://www.symfony-project.com/downloads/my_first_project.tgz">código fuente final</a>). Se trata de un proyecto Symfony vacío en el que todas las bibliotecas requeridas ya están  incluidas y la configuración básica  definida. La gran ventaja de sandbox sobre otro tipo de instalaciones es que puede comenzar a experimentar con symfony inmediatamente.</p>
84
85 <p>Consígalo aqui: <a href="http://www.symfony-project.com/get/sf_sandbox.tgz">sf_sandbox.tgz</a>,
86 y descomprímalo en su directorio web raíz. Consulte el archivo readme  incluido para obtener más información. El archivo resultante debe tener  esta estructura:</p>
87
88 <pre><code>www/
89   sf_sandbox/
90     apps/
91       frontend/
92     batch/
93     cache/
94     config/
95     data/
96       sql/
97     doc/
98     lib/
99       model/
100     log/
101     plugins/
102     test/
103     web/
104       css/
105       images/
106       js/
107 </code></pre>
108
109 <p>El esquema muestra el <strong>proyecto</strong> <code>sf_sandbox</code> conteniendo una <strong>aplicación</strong> <code>frontend</code> . Pruebe sandbox mediante  la siguiente URL:</p>
110
111 <pre class="url"><code>http://localhost/sf_sandbox/web/index.php/
112 </code></pre>
113
114 <p>Debería ver una página felicitacion.</p>
115
116 <p><img src="my-first-project_files/first_congrats.gif" alt="Congratulations"></p>
117
118 <p>También puede instalar Symfony en una carpeta personalizada y configurar su servidor web con un Virtual Host o un Alias. El libro contiene capítulos detallados sobre la instalación de Symfony y su configuración <a href="http://www.symfony-project.com/book/trunk/03-Running-Symfony">instalación Symfony</a> y  <a href="http://www.symfony-project.com/book/trunk/02-Exploring-Symfony-s-Code">Estructura de directorios Symfony</a>.</p>
119
120 <a name="Initialize the data model"></a>
121 <h2>Inicialización del modelo de datos (data model)</h2>
122
123 <p>Así, el weblog se encargará de manejar los posts , y le permitirá realizar  comentarios sobre ellos. Cree un archivo schema.yml  en sf_sandbox/configuración/ y pegue el siguiente modelo de datos:</p>
124
125 <pre><code>propel:
126   weblog_post:
127     _attributes: { phpName: Post }
128     id:
129     title:       varchar(255)
130     excerpt:     longvarchar
131     body:        longvarchar
132     created_at:
133   weblog_comment:
134     _attributes: { phpName: Comment }
135     id:
136     post_id:
137     author:      varchar(255)
138     email:       varchar(255)
139     body:        longvarchar
140     created_at:
141 </code></pre>
142
143 <p>Este fichero de configuración utiliza  sintaxis YAML . Se trata de un  simple lenguaje XML que permite   estructuras  descritas por indexación. Además, es más rápido de leer y escribir que  XML. La única cosa es que el sangrado tiene un significado y las tabulaciones  están prohibidas, por lo que debe recuerdar  usar espacios para el sangrado. Usted  encontrará más información sobre la configuración de YAML y Symfony  en el <a href="http://www.symfony-project.com/book/trunk/05-Configuring-Symfony">capítulo configuración</a>.</p>
144
145 <p>Este esquema describe la estructura de dos de las tablas necesarias para el Weblog. <code>Post</code> y <code>Comment </code> que son los nombres de las clases que se generan.. Guarde el fichero y abra una consola de comandos, posicionese dentro del  directorio  <code>sf_sandbox/</code> y escriba:</p>
146
147 <pre class="command-line"><code>$ php symfony propel-build-model
148 </code></pre>
149
150 <blockquote class="note">
151   <p>: Asegúrese de estar en el directorio raiz de su proyecto (<code>sf_sandbox/</code>) cuando use el comando <code>symfony</code> .</p>
152 </blockquote>
153
154 <p>Algunas clases se crearán en el directorio <code>sf_sandbox/lib/model/</code>
155 . Estas son las clases de Mapeo de Objetos Relacionados (object-relational mapping), que nos permiten tener acceso a una base de datos relacional desde  dentro de un código orientado a objetos sin escribir una sola consulta  SQL. Symfony usa la libreira
156  Propel para este propósito. Nosotros llamaremos a estos objetos <strong>model</strong> (ver mas en el <a href="http://www.symfony-project.com/book/trunk/08-Inside-the-Model-Layer"> capítulo model </a>).</p>
157
158 <p>Ahora introduzca en la linea de comandos:</p>
159
160 <pre class="command-line"><code>$ php symfony propel-build-sql
161 </code></pre>
162
163 <p>Un fichero <code>lib.model.schema.sql</code> se creará en  <code>sf_sandbox/data/sql/</code>.
164 Esta consulta SQL puede utilizarse para inicializar una base de datos con la misma estructura de la tabla. Se puede crear una base de datos en MySQL con la línea de comandos o desde  una interfaz web (como se describe en el  <a href="http://www.symfony-project.com/book/trunk/08-Inside-the-Model-Layer">capítulo </a><a href="http://www.symfony-project.com/book/trunk/08-Inside-the-Model-Layer">model </a>).
165 Afortunadamente,  symfony sandbox está configurado para trabajar fuera de la caja con un simple archivo  de SQLite, por lo que no es necesaria la inicialización de la base de datos. Por defecto, el proyecto <code>sf_sandbox</code>utilizará una base de datos denominada sandbox.db situado en <code>sf_sandbox/data/</code>. Para construir la estructura de la tabla basada en el el archivoSQL , escriba:</p>
166
167 <pre class="command-line"><code>$ php symfony propel-insert-sql
168 </code></pre>
169
170 <blockquote class="note">
171   <p>: No te preocupes si hay una advertencia en ese punto, es normal. El comando <code>insert-sql </code>elimina las tablas existentes antes de añadir las de su <code>lib.model.schema.sql</code>, la advertencia se produce por que no hay ninguna tabla que eliminar en ese momento.</p>
172 </blockquote>
173
174 <a name="Create the application scaffolding"></a>
175 <h2>Crear la aplicación (scaffolding)</h2>
176
177 <p>Las características básicas de un weblog debe de ser capaz de Crear,  Obtener, Actualizar y Borrar (CRUD) y añadir comentarios. Como usted es nuevo  en Symfony,  Symfony no crea código desde cero, sino más bien le permite   crear un scaffolding (andamiaje) que usted puede usar y modificar según sea  necesario. Symfony puede interpretar el modelo de datos para generar interfaz  CRUD  automáticamente:</p>
178
179 <pre class="command-line"><code>$ php symfony propel-generate-crud frontend post Post
180 $ php symfony propel-generate-crud frontend comment Comment
181 $ php symfony clear-cache
182
183 On *nix systems, you will have to change some rights:
184 $ chmod 777 data
185 $ chmod 777 data/sandbox.db
186 </code></pre>
187
188 <p>Ahora tiene dos módulos (<code>post</code> y <code>comment</code>) que le permitirá manipular las classes de los objetos  <code>Post</code> y <code>Comment</code> . Un módulo representa habitualmente una página o un grupo de páginas con  un propósito similar. Sus nuevos módulos se encuentran en el directorio <code>sf_sandbox/apps/frontend/modules/</code> y ya son accesibles a través de las siguientes  URL´s:</p>
189
190 <pre class="url"><code>http://localhost/sf_sandbox/web/frontend_dev.php/post
191 http://localhost/sf_sandbox/web/frontend_dev.php/comment
192 </code></pre>
193
194 <p>Tómese la libertad de crear un nuevo post para hacer que el Weblog contenga alguna información y no esté vacio.</p>
195 <p>&nbsp;</p>
196 <p><img src="my-first-project_files/first_crud.gif" alt="post CRUD"></p>
197
198 <p>Busque más información acerca de <a href="http://www.symfony-project.com/book/trunk/14-Generators">scaffolding</a> y explicaciones de la <a href="http://www.symfony-project.com/book/trunk/04-The-Basics-of-Page-Creation">estructura</a> de proyectos Symfony (project, application, module).</p>
199
200 <blockquote class="note">
201   <p>: En la URL de  arriba, el nombre del archivo principal  de comandos  llamado <em>front controller</em> en Symfony - se cambió de index.php a  frontend_dev.php. Los dos scripts de acceso a la misma aplicación  (frontend), pero en diferentes entornos. Con frontend_dev.php, usted  accede a la aplicación en el entorno de desarrollo, que prevé el  desarrollo práctico de herramientas como la barra de herramientas de  depuración en la parte superior derecha de la pantalla y la  configuración del motor en tiempo real. Esa es la razón de que la tramitación de  cada una de las páginas sea más lenta que cuando se utiliza index.php &quot;,  que es la parte <em>front controller</em> de los<strong> entornos de producción</strong>,  optimizado para la velocidad. Si desea seguir usando el entorno de la  producción, sustituir frontend_dev.php / index.php por / en la  siguiente URL, pero no se olvide de limpiar la caché antes de ver los  cambios:</p>
202   <pre class="command-line"><code>$ php symfony clear-cache
203
204 http://localhost/sf_sandbox/web/index.php/
205 </code></pre>
206 </blockquote>
207
208 <p>Buscar mas sobre <a href="http://www.symfony-project.com/book/trunk/05-Configuring-Symfony#Environments">entornos (environments)</a>.</p>
209
210 <a name="Modify the layout"></a>
211 <h2>Modificar el diseño (layout)</h2>
212
213 <p>Con el fin de navegar entre los dos nuevos módulos, el weblog   necesita algunas modificaciones en la navegación global.</p>
214 <p>Edite la template (plantilla) global <code>sf_sandbox/apps/frontend/templates/layout.php</code> y cambie el contenido de la etiqueta <code>&lt;body&gt;</code> :</p>
215
216 <pre class="php">&lt;div id=<span class="st0">"container"</span> style=<span class="st0">"width:600px;margin:0 auto;border:1px solid grey;padding:10px"</span>&gt;
217   &lt;div id=<span class="st0">"navigation"</span> style=<span class="st0">"display:inline;float:right"</span>&gt;
218     &lt;ul&gt;
219       &lt;li&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="st0">'List of posts'</span>, <span class="st0">'post/list'</span><span class="br0">)</span> ?&gt;&lt;/li&gt;
220       &lt;li&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="st0">'List of comments'</span>, <span class="st0">'comment/list'</span><span class="br0">)</span> ?&gt;&lt;/li&gt;
221     &lt;/ul&gt;
222   &lt;/div&gt;
223   &lt;div id=<span class="st0">"title"</span>&gt;
224     &lt;h1&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="st0">'My first symfony project'</span>, <span class="st0">'@homepage'</span><span class="br0">)</span> ?&gt;&lt;/h1&gt;
225   &lt;/div&gt;
226 &nbsp;
227   &lt;div id=<span class="st0">"content"</span> style=<span class="st0">"clear:right"</span>&gt;
228     <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$sf_data</span>-&gt;<span class="me1">getRaw</span><span class="br0">(</span><span class="st0">'sf_content'</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
229   &lt;/div&gt;
230 &lt;/div&gt;
231 &nbsp;</pre>
232
233 <p>Por favor perdonen este pobre diseño y el desuso de etiquetas css, pero una hora es poco tiempo para mas.</p>
234
235 <p><img src="my-first-project_files/first_crud_layout.gif" alt="post CRUD in layout"></p>
236
237 <p>Mientras está en ello, puede cambiar el título de sus páginas. Editar  el archivo de configuración de vista de la aplicación (sf_sandbox apps/Frontend/configuración/view.yml), busque la línea que indica el  título clave y cámbiela a:</p>
238 <p>default:
239     http_metas:
240   content-type: text/html</p>
241 <pre><code>metas:
242   title:        The best weblog ever
243   robots:       index, follow
244   description:  symfony project
245   keywords:     symfony, project
246   language:     en
247 </code></pre>
248
249 <p>La página en sí se tiene que cambiar. Utiliza la opción predeterminada de la plantilla por default module, que se mantiene en el marco, pero no en su directorio de aplicaciones. Para anular, usted tiene que crear un custom <code>main</code> module:</p>
250
251 <pre class="command-line"><code>$ php symfony init-module frontend main
252 </code></pre>
253
254 <p>Por defecto, muestra el <code>index</code> action predeterminado  pantalla de felicitaciones. Para eliminarla, editar el sf_sandbox/apps/frontend/modules/main/actions/actions.class.php y elimine el contenido de la  executeIndex () de la siguiente forma:</p>
255 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executeIndex<span class="br0">(</span><span class="br0">)</span>
256 <span class="br0">{</span>
257 <span class="br0">}</span>
258 &nbsp;</pre>
259
260 <p>Edite el fichero <code>sf_sandbox/apps/frontend/modules/main/templates/indexSuccess.php</code> para mostrar un bonito mensaje de bienvenida:</p>
261
262 <pre class="php">&lt;h1&gt;Bienvenido a mi weblog&lt;/h1&gt;
263 &lt;p&gt;Tu eres el visitante <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <a href="http://www.php.net/rand"><span class="kw3">rand</span></a><span class="br0">(</span><span class="nu0">1000</span>,<span class="nu0">5000</span><span class="br0">)</span> ?&gt;th hoy.&lt;/p&gt;
264 &nbsp;</pre>
265
266 <p>Ahora, hay que decirle a Symfony, que acción debe ejecutar cuando la página se solicita. Modificar <code>sf_sandbox/apps/frontend/config/routing.yml</code> y cambiar la regla de la  <code>homepage</code>  de    la siguiente forma:</p>
267 <pre>homepage:
268   url:   /
269   param: { module: main, action: index }
270 &nbsp;</pre>
271
272 <p>Comprobar el resultado  de la página de inicio de nuevo:</p>
273 <pre class="url"><code>http://localhost/sf_sandbox/web/frontend_dev.php/
274 </code></pre>
275
276 <p><img src="my-first-project_files/first_welcome.gif" alt="New home page"></p>
277
278 <p>Comience a utilizar su nueva aplicacion web: Crear una nueva prueba de post  y una prueba de comment.</p>
279
280 <p>Buscar mas acerca de  <a href="http://www.symfony-project.com/book/trunk/07-Inside-the-View-Layer">vistas y plantillas (views and templates)</a>.</p>
281
282 <a name="Pass data from the action to the template"></a>
283 <h2>Pase de datos de la acción (action) a la plantilla (template)</h2>
284
285 <p>A que fué rápido, no? Ahora es el momento de mexclar el módulo <code>comment</code> dentro de <code>post</code> para obtener un comentario que aparece debajo de los posts.</p>
286
287 <p>En primer lugar, necesita que esté disponible el post comments en la plantilla de visualización (template display). En Symfony, este tipo de lógica  se mantiene en acciones.</p>
288 <p>First, you need to make the post comments available for the post display template. In symfony, this kind of logic is kept in <strong>actions</strong>. Editar el archivo de actions <code>sf_sandbox/apps/frontend/modules/post/actions/actions.class.php</code> y cambiar el método (method) <code>executeShow()</code>  por Añadir las 4 últimas líneas:</p>
289 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executeShow<span class="br0">(</span><span class="br0">)</span>
290 <span class="br0">{</span>
291   <span class="re0">$this</span>-&gt;<span class="me1">post</span> = PostPeer::<span class="me2">retrieveByPk</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'id'</span><span class="br0">)</span><span class="br0">)</span>;
292   <span class="re0">$this</span>-&gt;<span class="me1">forward404Unless</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">post</span><span class="br0">)</span>;
293 &nbsp;
294   <span class="re0">$c</span> = <span class="kw2">new</span> Criteria<span class="br0">(</span><span class="br0">)</span>;
295   <span class="re0">$c</span>-&gt;<span class="me1">add</span><span class="br0">(</span>CommentPeer::<span class="me2">POST_ID</span>, <span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'id'</span><span class="br0">)</span><span class="br0">)</span>;
296   <span class="re0">$c</span>-&gt;<span class="me1">addAscendingOrderByColumn</span><span class="br0">(</span>CommentPeer::<span class="me2">CREATED_AT</span><span class="br0">)</span>;
297   <span class="re0">$this</span>-&gt;<span class="me1">comments</span> = CommentPeer::<span class="me2">doSelect</span><span class="br0">(</span><span class="re0">$c</span><span class="br0">)</span>;
298 <span class="br0">}</span>
299 &nbsp;</pre>
300
301 <p>Los objects <code>Criteria</code> y<code>-Peer</code>  son parte del mapeo de objetos relacionales de Propel. Básicamente, estas cuatro líneas se encargarán de tramitar  una consulta SQL a la  tabla <code>Comment</code>, para obtener los comentarios relacionados con el  actual <code>Post</code> (el primer designado por el  parámetro <code>id</code> de la URL ). La línea de acción<code> $this-&gt;comments</code>   dará acceso a la variable   <code>$comments</code> en la plantilla (template) correspondiente. Ahora,  modificar el post display template <code>sf_sandbox/apps/frontend/modules/post/templates/showSuccess.php</code> añadiendo al final:</p>
302 <pre class="php">...
303 <span class="kw2">&lt;?php</span> use_helper<span class="br0">(</span><span class="st0">'Text'</span>, <span class="st0">'Date'</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
304 &nbsp;
305 &lt;hr /&gt;
306 <span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$comments</span><span class="br0">)</span> : <span class="kw2">?&gt;</span>
307   &lt;p&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">(</span><span class="re0">$comments</span><span class="br0">)</span> <span class="kw2">?&gt;</span> comment&lt;?php <span class="kw1">if</span> <span class="br0">(</span><a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">(</span><span class="re0">$comments</span><span class="br0">)</span> &gt; <span class="nu0">1</span><span class="br0">)</span> : ?&gt;s&lt;?php <span class="kw1">endif</span>; <span class="kw2">?&gt;</span> to this post.&lt;/p&gt;
308   <span class="kw2">&lt;?php</span> <span class="kw1">foreach</span> <span class="br0">(</span><span class="re0">$comments</span> <span class="kw1">as</span> <span class="re0">$comment</span><span class="br0">)</span>: <span class="kw2">?&gt;</span>
309     &lt;p&gt;&lt;em&gt;posted by <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$comment</span>-&gt;<span class="me1">getAuthor</span><span class="br0">(</span><span class="br0">)</span> <span class="kw2">?&gt;</span> on <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> format_date<span class="br0">(</span><span class="re0">$comment</span>-&gt;<span class="me1">getCreatedAt</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> ?&gt;&lt;/em&gt;&lt;/p&gt;
310     &lt;div <span class="kw2">class</span>=<span class="st0">"comment"</span> style=<span class="st0">"margin-bottom:10px;"</span>&gt;
311       <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> simple_format_text<span class="br0">(</span><span class="re0">$comment</span>-&gt;<span class="me1">getBody</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
312     &lt;/div&gt;
313   <span class="kw2">&lt;?php</span> <span class="kw1">endforeach</span>; <span class="kw2">?&gt;</span>
314 <span class="kw2">&lt;?php</span> <span class="kw1">endif</span>; <span class="kw2">?&gt;</span>
315 &nbsp;</pre>
316
317 <p>Esta página utiliza las nuevas funciones de PHP (<code>format_date()</code> and <code>simple_format_text()</code>)
318 proporcionada por Symfony, y llamadas 'helpers' ya que para realizan algunas tareas que normalmente requieren más tiempo y código. Crear un nuevo comentario para su primer post, a continuación,  comprobar una vez más el primer post, ya sea haciendo clic sobre su  número en la lista, o escribiendo directamente :</p>
319
320 <pre class="url"><code>http://localhost/sf_sandbox/web/frontend_dev.php/post/show?id=1
321 </code></pre>
322
323 <p><img src="my-first-project_files/first_comments_under_post.gif" alt="Comment under post"></p>
324
325 <p>Buscar mas acerca de <a href="http://www.symfony-project.com/book/trunk/07-Inside-the-View-Layer">Convenciones de nombres (naming conventions) </a>Vinculación de una action a una template.</p>
326
327 <a name="Add a record relative to another table"></a>
328 <h2>Añadir una relación registro hacia otra tabla</h2>
329
330 <p>Cuando añada un comentario, puede elegir la <code>id</code> del post relacionado. Eso no es  fácil de usar. Vamos a  cambiar esto, y asegurarse de que el usuario  vuelve al  post que el estaba viendo después de añadir un comentario.<br />
331 En primer  lugar, en la todavía fresca módulos / puesto / plantillas /  showSuccess.php plantilla, añadir una línea en la parte inferior:</p>
332 <p>&nbsp;</p>
333 <p>Primero, en la reciente template <code>modules/post/templates/showSuccess.php</code> Añadir la siguiente línea en la parte inferior:</p>
334
335 <pre class="php"><span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="st0">'Add a comment'</span>, <span class="st0">'comment/create?post_id='</span>.<span class="re0">$post</span>-&gt;<span class="me1">getId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
336 &nbsp;</pre>
337
338 <p>El helper <code>link_to() </code>crea un hipervínculo que apunta al action <code>create</code> del módulo  <code>comment</code> , por lo que puede añadir un comentario directamente desde la página details del post. A continuación, abra el <code>modules/comment/templates/editSuccess.php</code> y sustiuya las siguientes líneas:</p>
339
340 <pre class="php">&lt;tr&gt;
341   &lt;th&gt;Post:&lt;/th&gt;
342   &lt;td&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> object_select_tag<span class="br0">(</span><span class="re0">$comment</span>, <span class="st0">'getPostId'</span>, <a href="http://www.php.net/array"><span class="kw3">array</span></a> <span class="br0">(</span>
343   <span class="st0">'related_class'</span> =&gt; <span class="st0">'Post'</span>,
344 <span class="br0">)</span><span class="br0">)</span> ?&gt;&lt;/td&gt;
345 &lt;/tr&gt;
346 &nbsp;</pre>
347
348 <p>Por:</p>
349
350 <pre class="php"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$sf_params</span>-&gt;<span class="me1">has</span><span class="br0">(</span><span class="st0">'post_id'</span><span class="br0">)</span><span class="br0">)</span>: <span class="kw2">?&gt;</span>
351   <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> input_hidden_tag<span class="br0">(</span><span class="st0">'post_id'</span>,<span class="re0">$sf_params</span>-&gt;<span class="me1">get</span><span class="br0">(</span><span class="st0">'post_id'</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
352 <span class="kw2">&lt;?php</span> <span class="kw1">else</span>: <span class="kw2">?&gt;</span>
353   &lt;tr&gt;
354     &lt;th&gt;Post*:&lt;/th&gt;
355     &lt;td&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> object_select_tag<span class="br0">(</span><span class="re0">$comment</span>, <span class="st0">'getPostId'</span>, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="st0">'related_class'</span> =&gt; <span class="st0">'Post'</span><span class="br0">)</span><span class="br0">)</span> ?&gt;&lt;/td&gt;
356   &lt;/tr&gt;
357 <span class="kw2">&lt;?php</span> <span class="kw1">endif</span>; <span class="kw2">?&gt;</span>
358 &nbsp;</pre>
359
360 <p>El formulario en el <code>comment/create</code> puntos de página hacia un action en <code>comment/update</code> , que redireccciona hacia <code>comment/show</code>
361 cuando se presentan (Este es el comportamiento por defecto  generado en CRUDs). Para el weblog,  significa que, después de añadir comentario a un  post , los detalles del comentario son visualizados. Es mejor   mostrar el post con los comentarios en ese momento. Por lo tanto, abrir <code>modules/comment/actions/actions.class.php</code> y buscar el method  <code>executeUpdate()</code> . Tenga en cuenta que el campo <code>created_at</code> no está definido por la action: Symfony sabe que un campo llamado <code>created_at</code>
362 tiene que ser establecido a la hora del sistema cuando se crea un registro. La redirección final del action tiene que ser modificado para apuntar a la acción correspondiente . Cámbielo a:</p>
363
364 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executeUpdate <span class="br0">(</span><span class="br0">)</span>
365 <span class="br0">{</span>
366   <span class="kw1">if</span> <span class="br0">(</span>!<span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'id'</span>, <span class="nu0">0</span><span class="br0">)</span><span class="br0">)</span>
367   <span class="br0">{</span>
368     <span class="re0">$comment</span> = <span class="kw2">new</span> Comment<span class="br0">(</span><span class="br0">)</span>;
369   <span class="br0">}</span>
370   <span class="kw1">else</span>
371   <span class="br0">{</span>
372     <span class="re0">$comment</span> = CommentPeer::<span class="me2">retrieveByPk</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'id'</span><span class="br0">)</span><span class="br0">)</span>;
373     <span class="re0">$this</span>-&gt;<span class="me1">forward404Unless</span><span class="br0">(</span><span class="re0">$comment</span><span class="br0">)</span>;
374   <span class="br0">}</span>
375 &nbsp;
376   <span class="re0">$comment</span>-&gt;<span class="me1">setId</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'id'</span><span class="br0">)</span><span class="br0">)</span>;
377   <span class="re0">$comment</span>-&gt;<span class="me1">setPostId</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'post_id'</span><span class="br0">)</span><span class="br0">)</span>;
378   <span class="re0">$comment</span>-&gt;<span class="me1">setAuthor</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'author'</span><span class="br0">)</span><span class="br0">)</span>;
379   <span class="re0">$comment</span>-&gt;<span class="me1">setEmail</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'email'</span><span class="br0">)</span><span class="br0">)</span>;
380   <span class="re0">$comment</span>-&gt;<span class="me1">setBody</span><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'body'</span><span class="br0">)</span><span class="br0">)</span>;
381 &nbsp;
382   <span class="re0">$comment</span>-&gt;<span class="me1">save</span><span class="br0">(</span><span class="br0">)</span>;
383 &nbsp;
384   <span class="kw1">return</span> <span class="re0">$this</span>-&gt;<span class="me1">redirect</span><span class="br0">(</span><span class="st0">'post/show?id='</span>.<span class="re0">$comment</span>-&gt;<span class="me1">getPostId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;
385 <span class="br0">}</span>
386 &nbsp;</pre>
387
388 <p>Los usuarios pueden agregar comentarios al post y volver al post después. Usted quería un weblog? Usted tiene un weblog.</p>
389
390 <p>Buscar mas información acerca de <a href="http://www.symfony-project.com/book/trunk/06-Inside-the-Controller-Layer">actions</a>.</p>
391
392 <a name="Form Validation"></a>
393 <h2> Validación de Formulario (Form Validation)</h2>
394
395 <p>Los visitantes pueden entrar en comentarios, pero ¿que pasa si se envía el formulario sin datos? Usted tendrá una base de datos sucia. Para evitarlo, cree un archivo llamado update.yml en el directorio <code>sf_sandbox/apps/frontend/modules/comment/validate/</code> (también  hay que crear el directorio) </p>
396 <p>y escriba:</p>
397 <pre><code>methods:
398   post:           [author, email, body]
399   get:            [author, email, body]
400
401 fillin:
402   enabled:       on
403
404 names:
405   author:
406     required:     Yes
407     required_msg: The name field cannot be left blank
408
409   email:
410     required:     No
411     validators:   emailValidator
412
413   body:
414     required:     Yes
415     required_msg: The text field cannot be left blank
416
417 emailValidator:
418   class:          sfEmailValidator
419   param:
420     email_error:  The email address is not valid.
421 </code></pre>
422
423 <blockquote class="note">
424   <p>: Tenga en cuenta de  no copiar 4 espacios adicionales al comienzo  de cada línea, ya que el analizador de YAML  no funcionaría en ese caso. La  primera letra de este archivo debe ser la 'm' de 'methods'.</p>
425   </blockquote>
426
427 <p>La activación de <code>fillin</code> permite a la repoblación del formulario con el valor  previamente introducido por el usuario en caso de fallo de validación. Llas  declaraciones <code>names</code> establecen las reglas de validación para cada entrada  del formulario.</p>
428 <p>Por si mismo , el controlador redirige al usuario hacia la template <code>updateError.php</code> si algún error es detectado. Sería mejor  mostrar el form  nuevamente con un mensaje de error.  Para ello, añadir un método (method) <code>handleErrorUpdate</code> en el  actions.class del fichero  <code>modules/comment/actions/actions.class.php</code> :</p>
429 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> handleErrorUpdate<span class="br0">(</span><span class="br0">)</span>
430 <span class="br0">{</span>
431   <span class="re0">$this</span>-&gt;<span class="me1">forward</span><span class="br0">(</span><span class="st0">'comment'</span>, <span class="st0">'create'</span><span class="br0">)</span>;
432 <span class="br0">}</span>
433 &nbsp;</pre>
434
435 <p>Ahora para terminar, abrir nuevamente la template <code>modules/comment/templates/editSuccess.php</code> e insertar en la parte superior:</p>
436 <pre class="php"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$sf_request</span>-&gt;<span class="me1">hasErrors</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>: <span class="kw2">?&gt;</span> 
437   &lt;div id=<span class="st0">"errors"</span> style=<span class="st0">"padding:10px;"</span>&gt;
438     Please correct the following errors and resubmit:
439     &lt;ul&gt;
440     <span class="kw2">&lt;?php</span> <span class="kw1">foreach</span> <span class="br0">(</span><span class="re0">$sf_request</span>-&gt;<span class="me1">getErrors</span><span class="br0">(</span><span class="br0">)</span> <span class="kw1">as</span> <span class="re0">$error</span><span class="br0">)</span>: <span class="kw2">?&gt;</span>
441       &lt;li&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$error</span> ?&gt;&lt;/li&gt;
442     <span class="kw2">&lt;?php</span> <span class="kw1">endforeach</span>; <span class="kw2">?&gt;</span>
443     &lt;/ul&gt;
444   &lt;/div&gt;
445 <span class="kw2">&lt;?php</span> <span class="kw1">endif</span>; <span class="kw2">?&gt;</span>
446 &nbsp;</pre>
447
448 <p>Usted ahora tiene un formulario correcto y fiable.</p>
449
450 <p><img src="my-first-project_files/first_form_validation.gif" alt="Form validation"></p>
451
452 <p>buscar mas información acerca de  <a href="http://www.symfony-project.com/book/trunk/10-Forms">validación de formulario (form validation)</a>.</p>
453
454 <a name="Change the URL aspect"></a>
455 <h2> Cambiar el aspecto de las URL</h2>
456
457 <p>¿Nota usted  la forma en que la URL se visualizó? Puede hacer mas amigable  la búsqueda. Vamos a utilizar el title del post como una URL para post.</p>
458
459 <p>El problema es que después de post titles puede contener caracteres especiales como espacios. Si usted acaba con ellos, la URL se muestran este tipo de cosas feas <code>%20</code> , así que más vale que extender  el model para añadir un nuevo método para el objeto <code>Post</code> y obtener un  limpio y mejorado title. Para ello, editar el fichero <code>Post.php</code> situado  en el directorio <code>sf_sandbox/lib/model/</code> y añadir el siguiente método:</p>
460 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> getStrippedTitle<span class="br0">(</span><span class="br0">)</span>
461 <span class="br0">{</span>
462   <span class="re0">$result</span> = <a href="http://www.php.net/strtolower"><span class="kw3">strtolower</span></a><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getTitle</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;
463 &nbsp;
464   <span class="co1">// strip all non word chars</span>
465   <span class="re0">$result</span> = <a href="http://www.php.net/preg_replace"><span class="kw3">preg_replace</span></a><span class="br0">(</span><span class="st0">'/<span class="es0">\W</span>/'</span>, <span class="st0">' '</span>, <span class="re0">$result</span><span class="br0">)</span>;
466 &nbsp;
467   <span class="co1">// replace all white space sections with a dash</span>
468   <span class="re0">$result</span> = <a href="http://www.php.net/preg_replace"><span class="kw3">preg_replace</span></a><span class="br0">(</span><span class="st0">'/<span class="es0">\ </span>+/'</span>, <span class="st0">'-'</span>, <span class="re0">$result</span><span class="br0">)</span>;
469 &nbsp;
470   <span class="co1">// trim dashes</span>
471   <span class="re0">$result</span> = <a href="http://www.php.net/preg_replace"><span class="kw3">preg_replace</span></a><span class="br0">(</span><span class="st0">'/<span class="es0">\-</span>$/'</span>, <span class="st0">''</span>, <span class="re0">$result</span><span class="br0">)</span>;
472   <span class="re0">$result</span> = <a href="http://www.php.net/preg_replace"><span class="kw3">preg_replace</span></a><span class="br0">(</span><span class="st0">'/^<span class="es0">\-</span>/'</span>, <span class="st0">''</span>, <span class="re0">$result</span><span class="br0">)</span>;
473 &nbsp;
474   <span class="kw1">return</span> <span class="re0">$result</span>;
475 <span class="br0">}</span>
476 &nbsp;</pre>
477
478 <p>Ahora tu puedes crear un action <code>permalink</code> para el módulo <code>post</code> . Añadir el siguiente método en <code>modules/post/actions/actions.class.php</code>:</p>
479
480 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executePermalink<span class="br0">(</span><span class="br0">)</span>
481 <span class="br0">{</span>
482   <span class="re0">$posts</span> = PostPeer::<span class="me2">doSelect</span><span class="br0">(</span><span class="kw2">new</span> Criteria<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;
483   <span class="re0">$title</span> = <span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'title'</span><span class="br0">)</span>;
484   <span class="kw1">foreach</span> <span class="br0">(</span><span class="re0">$posts</span> <span class="kw1">as</span> <span class="re0">$post</span><span class="br0">)</span>
485   <span class="br0">{</span>
486     <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$post</span>-&gt;<span class="me1">getStrippedTitle</span><span class="br0">(</span><span class="br0">)</span> == <span class="re0">$title</span><span class="br0">)</span>
487     <span class="br0">{</span>
488       <span class="kw1">break</span>;
489     <span class="br0">}</span>
490   <span class="br0">}</span>
491   <span class="re0">$this</span>-&gt;<span class="me1">forward404Unless</span><span class="br0">(</span><span class="re0">$post</span><span class="br0">)</span>;
492 &nbsp;
493   <span class="re0">$this</span>-&gt;<span class="me1">getRequest</span><span class="br0">(</span><span class="br0">)</span>-&gt;<span class="me1">setParameter</span><span class="br0">(</span><span class="st0">'id'</span>, <span class="re0">$post</span>-&gt;<span class="me1">getId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;
494 &nbsp;
495   <span class="re0">$this</span>-&gt;<span class="me1">forward</span><span class="br0">(</span><span class="st0">'post'</span>, <span class="st0">'show'</span><span class="br0">)</span>;
496 <span class="br0">}</span>
497 &nbsp;</pre>
498
499 <p>El listado post puede llamar este <code>permalink</code> en lugar de mostrarl uno para cada post. En  <code>modules/post/templates/listSuccess.php</code>, elimine el <code>id</code> table header y  cell, y  cambiar el cell <code>Title</code> desde:</p>
500 <pre class="php">&lt;td&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$post</span>-&gt;<span class="me1">getTitle</span><span class="br0">(</span><span class="br0">)</span> ?&gt;&lt;/td&gt;
501 &nbsp;</pre>
502
503 <p>por:</p>
504
505 <pre class="php">&lt;td&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="re0">$post</span>-&gt;<span class="me1">getTitle</span><span class="br0">(</span><span class="br0">)</span>, <span class="st0">'post/permalink?title='</span>.<span class="re0">$post</span>-&gt;<span class="me1">getStrippedTitle</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> ?&gt;&lt;/td&gt;
506 &nbsp;</pre>
507
508 <p>Solo un paso más: Editar el fichero <code>routing.yml</code> localizado en el directorio <code>sf_sandbox/apps/frontend/config/</code> y añadir estas reglas en la parte superior:</p>
509
510 <pre><code>list_of_posts:
511   url:   /latest_posts
512   param: { module: post, action: list }
513
514 post:
515   url:   /weblog/:title
516   param: { module: post, action: permalink }
517 </code></pre>
518
519 <p>Ahora navega nuevamente en tu aplicación y observa las URLs.</p>
520 <p><img src="my-first-project_files/first_routing.gif" alt="Routed URLs"></p>
521 <p>Buscar mas acerca de <a href="http://www.symfony-project.com/book/trunk/09-Links-and-the-Routing-System">URL inteligentes. (smart URLs)</a>.</p>
522
523 <a name="Cleanup in the frontend"></a><h2>Limpieza en el Frontend</h2>
524
525 <p>Bien, si este es un weblog, entonces todo el mundo tiene el derecho de  entrada. Esto no es exactamente lo que pensaba acerca de derechos, ¿verdad? Muy  bien, vamos a limpiar nuestras templates un poco. <br />
526   <br />
527 En la  template <code>modules/post/templates/showSuccess.php</code>,  eliminar el vínculo 'editar' mediante la eliminación de la línea:</p>
528 <pre class="php"><span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="st0">'edit'</span>, <span class="st0">'post/edit?id='</span>.<span class="re0">$post</span>-&gt;<span class="me1">getId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
529 &nbsp;</pre>
530
531 <p>Haga lo mismo la template <code>modules/post/templates/listSuccess.php</code> y elimine:</p>
532
533 <pre class="php"><span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">(</span><span class="st0">'create'</span>, <span class="st0">'post/create'</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
534 &nbsp;</pre>
535
536 <p>También hay que eliminar los siguientes métodos de <code>modules/post/actions/actions.class.php</code>:</p>
537
538 <pre><code>* executeCreate
539 * executeEdit
540 * executeUpdate
541 * executeDelete
542 </code></pre>
543
544 <p>Bueno, los lectores pueden enviar  más post.</p>
545
546 <a name="Generation of the backend"></a><h2>Generación de backend</h2>
547
548 <p>Para que usted escriba post, vamos a crear un servidor de aplicación  escribiendo en la línea de comandos (todavía en el directorio del proyecto sf_sandbox  ):</p>
549 <pre class="command-line"><code>$ php symfony init-app backend
550 $ php symfony propel-init-admin backend post Post
551 $ php symfony propel-init-admin backend comment Comment
552 </code></pre>
553
554 <p>Esta vez, utilizamos el <a href="http://www.symfony-project.com/book/trunk/14-Generators">admin generator</a>. Ofrece mucho más funciones y capacidades de personalización que los básicos del generador CRUD. </p>
555
556 <p>Como hizo para la aplicación <code>frontend</code> , editar el layout (<code>apps/backend/templates/layout.php</code>) para añadir navegación global:</p>
557
558 <pre><code>&lt;div id="navigation"&gt;
559   &lt;ul style="list-style:none;"&gt;
560     &lt;li&gt;&lt;?php echo link_to('Manage posts', 'post/list') ?&gt;&lt;/li&gt;
561     &lt;li&gt;&lt;?php echo link_to('Manage comments', 'comment/list') ?&gt;&lt;/li&gt;
562   &lt;/ul&gt;
563 &lt;/div&gt;
564 &lt;div id="content"&gt;
565   &lt;?php echo $sf_data-&gt;getRaw('sf_content') ?&gt;
566 &lt;/div&gt;
567 </code></pre>
568
569 <p>Puede acceder a su nueva aplicación  back-office y en el entorno de desarrollo, llamando a:</p>
570 <pre class="url"><code>http://localhost/sf_sandbox/web/backend_dev.php/post
571 </code></pre>
572
573 <p><img src="my-first-project_files/first_basic_admin.gif" alt="basic generated admin"></p>
574
575 <p>La gran ventaja del generated admin es que se puede personalizar  fácilmente mediante la edición de un archivo de configuración.  <br />
576 Cambia el <code>backend/modules/post/config/generator.yml</code> a:</p>
577
578 <pre><code>generator:
579   class:              sfPropelAdminGenerator
580   param:
581     model_class:      Post
582     theme:            default
583     fields:
584       title:          { name: Title }
585       excerpt:        { name: Exerpt }
586       body:           { name: Body }
587       nb_comments:    { name: Comments }
588       created_at:     { name: Creation date }
589     list:
590       title:          Post list
591       layout:         tabular
592       display:        [=title, excerpt, nb_comments, created_at]
593       object_actions:
594         _edit:        ~
595         _delete:      ~
596       max_per_page:   5
597       filters:        [title, created_at]
598     edit:
599       title:          Post detail
600       fields:
601         title:        { type: input_tag, params: size=53 }
602         excerpt:      { type: textarea_tag, params: size=50x2 }
603         body:         { type: textarea_tag, params: size=50x10 }
604         created_at:   { type: input_date_tag, params: rich=on }
605 </code></pre>
606
607 <p>Tenga en cuenta que entre las  columnas existentes de la tabla <code>Post</code>, el  administrador  buscará un <code>nb_comments</code>.. No hay asociados get aún, pero  es simple de añadir a la <br />
608   <br />
609 Cambia el</p>
610 <p>Note that among the existing columns of the <code>Post</code> table, the admin will look for a <code>nb_comments</code>. No hay aún asociados getter todavía, Pero es sencillo, agregar a  <code>sf_sandbox/lib/model/Post.php</code>:</p>
611 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> getNbComments<span class="br0">(</span><span class="br0">)</span>
612 <span class="br0">{</span>
613   <span class="kw1">return</span> <a href="http://www.php.net/count"><span class="kw3">count</span></a><span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getComments</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;
614 <span class="br0">}</span>
615 &nbsp;</pre>
616
617 <p>Ahora actualice el Post administration y vea los cambios:</p>
618
619 <p><img src="my-first-project_files/first_custom_admin.gif" alt="customized generated admin"></p>
620
621 <a name="Restrict access to the backend"></a>
622 <h2>Restringir el acceso al backend</h2>
623
624 <p>El backend puede se accedido por todo el mundo. Hay que añadir la restricción de acceso.</p>
625
626 <p>en <code>apps/backend/modules/post/config/</code>, añada un <code>security.yml</code> con el siguiente contenido:</p>
627
628 <pre><code>all:
629   is_secure: on
630 </code></pre>
631
632 <p>Repita la operación para el módulo <code>comment</code>. Ahora no se puede acceder a estos módulos a menos que se registren. <br />
633 Pero el loggin action no existe! Ok, así que usted puede agregarlo  fácilmente. En primer lugar, crear el módulo de seguridad skeleton:</p>
634 <pre class="command-line"><code>$ php symfony init-module backend security
635 </code></pre>
636
637 <p>Este nuevo módulo será utilizado para tramitar el formulario login y de solicitud. Editar <code>apps/backend/modules/security/templates/indexSuccess.php</code> para crear el formulario de  acceso:</p>
638 <pre class="php">&lt;h2&gt;Authentication&lt;/h2&gt;
639 &nbsp;
640 <span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$sf_request</span>-&gt;<span class="me1">hasErrors</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>: <span class="kw2">?&gt;</span>
641   Identification failed - please try again
642 <span class="kw2">&lt;?php</span> <span class="kw1">endif</span>; <span class="kw2">?&gt;</span>
643 &nbsp;
644 <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> form_tag<span class="br0">(</span><span class="st0">'security/login'</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
645   &lt;label <span class="kw1">for</span>=<span class="st0">"login"</span>&gt;login:&lt;/label&gt;
646   <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> input_tag<span class="br0">(</span><span class="st0">'login'</span>, <span class="re0">$sf_params</span>-&gt;<span class="me1">get</span><span class="br0">(</span><span class="st0">'login'</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
647 &nbsp;
648   &lt;label <span class="kw1">for</span>=<span class="st0">"password"</span>&gt;password:&lt;/label&gt;
649   <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> input_password_tag<span class="br0">(</span><span class="st0">'password'</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
650 &nbsp;
651   <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> submit_tag<span class="br0">(</span><span class="st0">'submit'</span>, <span class="st0">'class=default'</span><span class="br0">)</span> <span class="kw2">?&gt;</span>
652 &lt;/form&gt;
653 &nbsp;</pre>
654
655 <p>Añadir el action login que es llamado a través de un formulario por el fochero del módulo <code>security</code>  (en <code>apps/backend/modules/security/actions/actions.class.php</code>):</p>
656 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executeLogin<span class="br0">(</span><span class="br0">)</span>
657 <span class="br0">{</span>
658   <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'login'</span><span class="br0">)</span> == <span class="st0">'admin'</span> &amp;&amp; <span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'password'</span><span class="br0">)</span> == <span class="st0">'password'</span><span class="br0">)</span>
659   <span class="br0">{</span>
660     <span class="re0">$this</span>-&gt;<span class="me1">getUser</span><span class="br0">(</span><span class="br0">)</span>-&gt;<span class="me1">setAuthenticated</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span>;
661 &nbsp;
662     <span class="kw1">return</span> <span class="re0">$this</span>-&gt;<span class="me1">redirect</span><span class="br0">(</span><span class="st0">'main/index'</span><span class="br0">)</span>;
663   <span class="br0">}</span>
664   <span class="kw1">else</span>
665   <span class="br0">{</span>
666     <span class="re0">$this</span>-&gt;<span class="me1">getRequest</span><span class="br0">(</span><span class="br0">)</span>-&gt;<span class="me1">setError</span><span class="br0">(</span><span class="st0">'login'</span>, <span class="st0">'incorrect entry'</span><span class="br0">)</span>;
667 &nbsp;
668     <span class="kw1">return</span> <span class="re0">$this</span>-&gt;<span class="me1">forward</span><span class="br0">(</span><span class="st0">'security'</span>, <span class="st0">'index'</span><span class="br0">)</span>;
669   <span class="br0">}</span>
670 <span class="br0">}</span>
671 &nbsp;</pre>
672
673 <p>En cuanto al modulo <code>main</code> eliminar el código predeterminado en el <code>index</code> action:</p>
674 <pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executeIndex<span class="br0">(</span><span class="br0">)</span>
675 <span class="br0">{</span>
676 <span class="br0">}</span>
677 &nbsp;</pre>
678
679 <p>La última cosa que debe hacer es establecer el módulo <code>security</code>  por  defecto como el módulo de conexión para manejar login actions.  Para ello abra el fichero de configuración en <code>apps/backend/config/settings.yml</code> y añada:</p>
680
681 <pre><code>all:
682   .actions:
683     login_module:           security
684     login_action:           index   
685 </code></pre>
686
687 <p>En ese momento, si se intenta acceder a los post de gestión, tendrá que introducir un login y una contraseña:</p>
688
689 <p><img src="my-first-project_files/first_login.gif" alt="login form"></p>
690
691 <p>Buscar mas acerca de  <a href="http://www.symfony-project.com/book/trunk/06-Inside-the-Controller-Layer#Action%20Security">seguridad (security)</a>.</p>
692
693 <a name="Conclusion"></a>
694 <h2>Conclusión</h2>
695
696 <p>Ok, es el final. Usted lo hizo. Ahora puede utilizar  las aplicaciones en el entorno de producción y jugar con ellos:</p>
697
698 <pre><code>frontend:   http://localhost/sf_sandbox/web/index.php/
699 backend:    http://localhost/sf_sandbox/web/backend.php/
700 </code></pre>
701
702 <p>En este punto, si se produce un mensaje de error, puede ser debido a  que cambió el modelo después de algunas acciones se quedaron en la  memoria caché (la caché no está activada en el entorno de desarrollo).  Para borrar la caché, simplemente escriba:</p>
703
704 <pre class="command-line"><code>$ php symfony cc
705 </code></pre>
706
707 <p>Vèa si la aplicación es rápida y se ejecuta sin problemas. es así? Siéntase libre de explorar el código, añadir nuevos  módulos, y cambiar el diseño de páginas. <br />
708 Y no se olvide de mencionar su trabajo en las aplications Symfony en el Symfony Wiki!</p>
709
710 <div class="feedback">
711   <h3>Preguntas y Comentarios</h3>
712     <p>Si encuentra una errata o un error, por favor <a href="http://www.symfony-project.com/trac/newticket">abra un ticket (open a ticket)</a>.</p>
713     <p>Si necesita ayuda o tiene una cuestión técnica, por favor enviar a la <a href="http://groups.google.com/group/symfony-users">user mailing-list</a>
714       o en el <a href="http://www.symfony-project.com/forum/">forum</a>.</p>
715 </div>
716 </div>
717
718 <div id="footer">
719       <a href="http://www.symfony-project.com/content/credits">Contacts &amp; Credits</a>&nbsp;-&nbsp;
720       <a href="http://www.symfony-project.com/donate">Make a donation</a>&nbsp;-&nbsp;
721       Powered by <a href="http://www.symfony-project.com/"><img src="my-first-project_files/symfony_button.gif" alt="Symfony_button" align="middle"></a>&nbsp;-&nbsp;
722       Sponsored by <a target="_blank" href="http://www.sensio-labs.com/"><img src="my-first-project_files/sensio_labs_button.gif" alt="Sensio_labs_button" align="middle"></a>
723     </div>
724
725           <script src="my-first-project_files/urchin.js" type="text/javascript"></script>
726       <script type="text/javascript">_uacct = "UA-89393-1"; urchinTracker();</script>
727    
728   </body></html>