| 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&l=1&n=10&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&ticket=on&ticket_details=on&changeset=on&wiki=on&max=10&daysback=10&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> </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 ", 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><body></code> :</p> |
|---|
| 215 |
|
|---|
| 216 |
<pre class="php"><div id=<span class="st0">"container"</span> style=<span class="st0">"width:600px;margin:0 auto;border:1px solid grey;padding:10px"</span>> |
|---|
| 217 |
<div id=<span class="st0">"navigation"</span> style=<span class="st0">"display:inline;float:right"</span>> |
|---|
| 218 |
<ul> |
|---|
| 219 |
<li><?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> ?></li> |
|---|
| 220 |
<li><?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> ?></li> |
|---|
| 221 |
</ul> |
|---|
| 222 |
</div> |
|---|
| 223 |
<div id=<span class="st0">"title"</span>> |
|---|
| 224 |
<h1><?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> ?></h1> |
|---|
| 225 |
</div> |
|---|
| 226 |
|
|---|
| 227 |
<div id=<span class="st0">"content"</span> style=<span class="st0">"clear:right"</span>> |
|---|
| 228 |
<span class="kw2"><?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$sf_data</span>-><span class="me1">getRaw</span><span class="br0">(</span><span class="st0">'sf_content'</span><span class="br0">)</span> <span class="kw2">?></span> |
|---|
| 229 |
</div> |
|---|
| 230 |
</div> |
|---|
| 231 |
</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 |
</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"><h1>Bienvenido a mi weblog</h1> |
|---|
| 263 |
<p>Tu eres el visitante <span class="kw2"><?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> ?>th hoy.</p> |
|---|
| 264 |
</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 |
</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>-><span class="me1">post</span> = PostPeer::<span class="me2">retrieveByPk</span><span class="br0">(</span><span class="re0">$this</span>-><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>-><span class="me1">forward404Unless</span><span class="br0">(</span><span class="re0">$this</span>-><span class="me1">post</span><span class="br0">)</span>; |
|---|
| 293 |
|
|---|
| 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>-><span class="me1">add</span><span class="br0">(</span>CommentPeer::<span class="me2">POST_ID</span>, <span class="re0">$this</span>-><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>-><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>-><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 |
</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->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"><?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">?></span> |
|---|
| 304 |
|
|---|
| 305 |
<hr /> |
|---|
| 306 |
<span class="kw2"><?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$comments</span><span class="br0">)</span> : <span class="kw2">?></span> |
|---|
| 307 |
<p><?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">?></span> comment<?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> > <span class="nu0">1</span><span class="br0">)</span> : ?>s<?php <span class="kw1">endif</span>; <span class="kw2">?></span> to this post.</p> |
|---|
| 308 |
<span class="kw2"><?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">?></span> |
|---|
| 309 |
<p><em>posted by <span class="kw2"><?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$comment</span>-><span class="me1">getAuthor</span><span class="br0">(</span><span class="br0">)</span> <span class="kw2">?></span> on <span class="kw2"><?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>-><span class="me1">getCreatedAt</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> ?></em></p> |
|---|
| 310 |
<div <span class="kw2">class</span>=<span class="st0">"comment"</span> style=<span class="st0">"margin-bottom:10px;"</span>> |
|---|
| 311 |
<span class="kw2"><?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>-><span class="me1">getBody</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?></span> |
|---|
| 312 |
</div> |
|---|
| 313 |
<span class="kw2"><?php</span> <span class="kw1">endforeach</span>; <span class="kw2">?></span> |
|---|
| 314 |
<span class="kw2"><?php</span> <span class="kw1">endif</span>; <span class="kw2">?></span> |
|---|
| 315 |
</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> </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"><?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>-><span class="me1">getId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?></span> |
|---|
| 336 |
</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"><tr> |
|---|
| 341 |
<th>Post:</th> |
|---|
| 342 |
<td><?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> => <span class="st0">'Post'</span>, |
|---|
| 344 |
<span class="br0">)</span><span class="br0">)</span> ?></td> |
|---|
| 345 |
</tr> |
|---|
| 346 |
</pre> |
|---|
| 347 |
|
|---|
| 348 |
<p>Por:</p> |
|---|
| 349 |
|
|---|
| 350 |
<pre class="php"><span class="kw2"><?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$sf_params</span>-><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">?></span> |
|---|
| 351 |
<span class="kw2"><?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>-><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">?></span> |
|---|
| 352 |
<span class="kw2"><?php</span> <span class="kw1">else</span>: <span class="kw2">?></span> |
|---|
| 353 |
<tr> |
|---|
| 354 |
<th>Post*:</th> |
|---|
| 355 |
<td><?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> => <span class="st0">'Post'</span><span class="br0">)</span><span class="br0">)</span> ?></td> |
|---|
| 356 |
</tr> |
|---|
| 357 |
<span class="kw2"><?php</span> <span class="kw1">endif</span>; <span class="kw2">?></span> |
|---|
| 358 |
</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>-><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>-><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>-><span class="me1">forward404Unless</span><span class="br0">(</span><span class="re0">$comment</span><span class="br0">)</span>; |
|---|
| 374 |
<span class="br0">}</span> |
|---|
| 375 |
|
|---|
| 376 |
<span class="re0">$comment</span>-><span class="me1">setId</span><span class="br0">(</span><span class="re0">$this</span>-><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>-><span class="me1">setPostId</span><span class="br0">(</span><span class="re0">$this</span>-><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>-><span class="me1">setAuthor</span><span class="br0">(</span><span class="re0">$this</span>-><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>-><span class="me1">setEmail</span><span class="br0">(</span><span class="re0">$this</span>-><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>-><span class="me1">setBody</span><span class="br0">(</span><span class="re0">$this</span>-><span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'body'</span><span class="br0">)</span><span class="br0">)</span>; |
|---|
| 381 |
|
|---|
| 382 |
<span class="re0">$comment</span>-><span class="me1">save</span><span class="br0">(</span><span class="br0">)</span>; |
|---|
| 383 |
|
|---|
| 384 |
<span class="kw1">return</span> <span class="re0">$this</span>-><span class="me1">redirect</span><span class="br0">(</span><span class="st0">'post/show?id='</span>.<span class="re0">$comment</span>-><span class="me1">getPostId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>; |
|---|
| 385 |
<span class="br0">}</span> |
|---|
| 386 |
</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>-><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 |
</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"><?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$sf_request</span>-><span class="me1">hasErrors</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>: <span class="kw2">?></span> |
|---|
| 437 |
<div id=<span class="st0">"errors"</span> style=<span class="st0">"padding:10px;"</span>> |
|---|
| 438 |
Please correct the following errors and resubmit: |
|---|
| 439 |
<ul> |
|---|
| 440 |
<span class="kw2"><?php</span> <span class="kw1">foreach</span> <span class="br0">(</span><span class="re0">$sf_request</span>-><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">?></span> |
|---|
| 441 |
<li><?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$error</span> ?></li> |
|---|
| 442 |
<span class="kw2"><?php</span> <span class="kw1">endforeach</span>; <span class="kw2">?></span> |
|---|
| 443 |
</ul> |
|---|
| 444 |
</div> |
|---|
| 445 |
<span class="kw2"><?php</span> <span class="kw1">endif</span>; <span class="kw2">?></span> |
|---|
| 446 |
</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>-><span class="me1">getTitle</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>; |
|---|
| 463 |
|
|---|
| 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 |
|
|---|
| 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 |
|
|---|
| 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 |
|
|---|
| 474 |
<span class="kw1">return</span> <span class="re0">$result</span>; |
|---|
| 475 |
<span class="br0">}</span> |
|---|
| 476 |
</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>-><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>-><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>-><span class="me1">forward404Unless</span><span class="br0">(</span><span class="re0">$post</span><span class="br0">)</span>; |
|---|
| 492 |
|
|---|
| 493 |
<span class="re0">$this</span>-><span class="me1">getRequest</span><span class="br0">(</span><span class="br0">)</span>-><span class="me1">setParameter</span><span class="br0">(</span><span class="st0">'id'</span>, <span class="re0">$post</span>-><span class="me1">getId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>; |
|---|
| 494 |
|
|---|
| 495 |
<span class="re0">$this</span>-><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 |
</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"><td><?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$post</span>-><span class="me1">getTitle</span><span class="br0">(</span><span class="br0">)</span> ?></td> |
|---|
| 501 |
</pre> |
|---|
| 502 |
|
|---|
| 503 |
<p>por:</p> |
|---|
| 504 |
|
|---|
| 505 |
<pre class="php"><td><?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>-><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>-><span class="me1">getStrippedTitle</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> ?></td> |
|---|
| 506 |
</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"><?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>-><span class="me1">getId</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="kw2">?></span> |
|---|
| 529 |
</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"><?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">?></span> |
|---|
| 534 |
</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><div id="navigation"> |
|---|
| 559 |
<ul style="list-style:none;"> |
|---|
| 560 |
<li><?php echo link_to('Manage posts', 'post/list') ?></li> |
|---|
| 561 |
<li><?php echo link_to('Manage comments', 'comment/list') ?></li> |
|---|
| 562 |
</ul> |
|---|
| 563 |
</div> |
|---|
| 564 |
<div id="content"> |
|---|
| 565 |
<?php echo $sf_data->getRaw('sf_content') ?> |
|---|
| 566 |
</div> |
|---|
| 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>-><span class="me1">getComments</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>; |
|---|
| 614 |
<span class="br0">}</span> |
|---|
| 615 |
</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"><h2>Authentication</h2> |
|---|
| 639 |
|
|---|
| 640 |
<span class="kw2"><?php</span> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$sf_request</span>-><span class="me1">hasErrors</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>: <span class="kw2">?></span> |
|---|
| 641 |
Identification failed - please try again |
|---|
| 642 |
<span class="kw2"><?php</span> <span class="kw1">endif</span>; <span class="kw2">?></span> |
|---|
| 643 |
|
|---|
| 644 |
<span class="kw2"><?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">?></span> |
|---|
| 645 |
<label <span class="kw1">for</span>=<span class="st0">"login"</span>>login:</label> |
|---|
| 646 |
<span class="kw2"><?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>-><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">?></span> |
|---|
| 647 |
|
|---|
| 648 |
<label <span class="kw1">for</span>=<span class="st0">"password"</span>>password:</label> |
|---|
| 649 |
<span class="kw2"><?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">?></span> |
|---|
| 650 |
|
|---|
| 651 |
<span class="kw2"><?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">?></span> |
|---|
| 652 |
</form> |
|---|
| 653 |
</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>-><span class="me1">getRequestParameter</span><span class="br0">(</span><span class="st0">'login'</span><span class="br0">)</span> == <span class="st0">'admin'</span> && <span class="re0">$this</span>-><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>-><span class="me1">getUser</span><span class="br0">(</span><span class="br0">)</span>-><span class="me1">setAuthenticated</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span>; |
|---|
| 661 |
|
|---|
| 662 |
<span class="kw1">return</span> <span class="re0">$this</span>-><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>-><span class="me1">getRequest</span><span class="br0">(</span><span class="br0">)</span>-><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 |
|
|---|
| 668 |
<span class="kw1">return</span> <span class="re0">$this</span>-><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 |
</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 |
</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 & Credits</a> - |
|---|
| 720 |
<a href="http://www.symfony-project.com/donate">Make a donation</a> - |
|---|
| 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> - |
|---|
| 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> |
|---|