lunes, 25 de agosto de 2014
Symfony - Día 10: Los Formularios
El Framework de Formularios
Cualquier sitio web tiene formularios; desde el simple formulario de contacto hasta los complejos con decenas de campos. Crear formularios es también una de las más complejas y tediosas tareas de un desarrollador web: necesitas crear el HTML del formulario, implementar las reglas de validación para cada campo, procesar los valores para luego guardarlos en la base de datos, mostrar mensajes de error, rellenar los campos en caso de errores, y mucho más ...
Por supuesto, en lugar de reinventar la rueda una y otra vez, Symfony proporciona una framework para facilitar la administración de un formulario. El framework de formularios esta hecho de tres partes:
- validación: El sub-framework validation ofrece clases para validar las entradas (entero, cadenas, dirección de correo electrónico, ...)
- widgets: El sub-framework de widgets ofrece clases para la salida de los campos HTML (input, textarea, select, ...)
- forms: La clases form representan formularios hechos de widgets y validadores y dan métodos para ayudar a gestionar el formulario. Cada campo del formulario tiene su propio validador y su widget.
Formularios
En Symfony un formulario es una clase hecha de campos. Cada campo tiene un nombre, un validador, y un widget. Un simple
ContactForm
puede definirse con la siguiente clase:class ContactForm extends sfForm { public function configure() { $this->setWidgets(array( 'email' => new sfWidgetFormInputText(), 'message' => new sfWidgetFormTextarea(), )); $this->setValidators(array( 'email' => new sfValidatorEmail(), 'message' => new sfValidatorString(array('max_length' => 255)), )); } }
Los campos del formulario se configuran en el método
configure()
, usando los métodossetValidators()
y setWidgets()
.
El framework de formularios trae incluida una gran cantidad de widgets yvalidators. La API los describe muy ampliamente con todas las opciones, los errores, y mensajes de error por defecto.
Los nombres de las clases de los widgets y validadores son muy explícitos: el campo
email
se muestra como una etiqueta HTML <input>
(sfWidgetFormInputText
) y validado como una dirección de correo electrónico (sfValidatorEmail
). El campo message
se muestra como una etiqueta HTML <textarea>
(sfWidgetFormTextarea
), y debe ser una cadena de no más de 255 caracteres (sfValidatorString
).
Por defecto, todos los campos son obligatorios, así el valor por defecto para
required
es true
. Por lo tanto, la definición de la validación para email
es equivalente a new sfValidatorEmail(array('required' => true))
.
Es posible combinar un formulario en otro usando el método
mergeForm()
, o incluir un formulario dentro de otro mediante el método embedForm()
:$this->mergeForm(new AnotherForm()); $this->embedForm('name', new AnotherForm());
Formularios Doctrine
La mayoría de las veces, un formulario tiene que ser serializado (guardado) para la base de datos. Como Symfony ya sabe todo acerca de su modelo de base de datos, puede generar automáticamente formularios basados sobre esta información. De hecho, cuando se puso en marcha la tarea
doctrine:build --all
durante el día 3, Symfony automáticamente llamó a la tarea doctrine:build --forms
:$ php symfony doctrine:build --forms
La tarea
doctrine:build --forms
genera las clases form en lib/form/
. La organización de estos archivos generados es similar a la de lib/model/
. Cada modelo de clase tiene una clase form relacionada (por ejemplo JobeetJob
tiene JobeetJobForm
), que está vacío por defecto, ya que hereda de una clase base:// lib/form/doctrine/JobeetJobForm.class.php class JobeetJobForm extends BaseJobeetJobForm { public function configure() { } }
Navegando por los archivos generados en el sub-directorio
lib/form/doctrine/base/
verás un montón de ejemplos de uso de widgets symfony incluidos y de validadores.Personalización del Job Form
El formulario Job es un ejemplo perfecto para aprender la personalización de un formulario. Vamos a ver cómo personalizarlo, paso a paso.
En primer lugar, cambia el enlace "Post a Job" en el layout para poder comprobar los cambios directamente en tu navegador:
<!-- apps/frontend/templates/layout.php -->
<a href="<?php echo url_for('@job_new') ?>">Post a Job</a>
De manera predeterminada, un formulario Doctrine muestra todos los campos de la columnas de la tabla. Sin embargo, para el job form, algunos de ellos no deben ser editables por el usuario final. Eliminar los campos del formulario es simple:
// lib/form/doctrine/JobeetJobForm.class.php class JobeetJobForm extends BaseJobeetJobForm { public function configure() { unset( $this['created_at'], $this['updated_at'], $this['expires_at'], $this['is_activated'] ); } }
La desconexión de un campo significa que tanto el widget como validador se eliminan.
La configuración del formulario a veces tienen que ser más precisa que lo que se puede inspeccionar desde el esquema de base de datos. Por ejemplo, la columna
email
es un varchar
en el esquema, pero necesitamos que esta columna sea validada como un email. Vamos a cambiar el valor por defecto sfValidatorString
a sfValidatorEmail
:// lib/form/doctrine/JobeetJobForm.class.php public function configure() { // ... $this->validatorSchema['email'] = new sfValidatorEmail(); }
Reemplar el validador por defecto no siempre es la mejor solución, ya que las reglas de validación por defecto inferidas del esquema de la base de datos se pierden (
new sfValidatorString(array('max_length' => 255))
). Es casi siempre mejor para agregar un nuevo validador a uno existente usar el validador especial sfValidatorAnd
:// lib/form/doctrine/JobeetJobForm.class.php public function configure() { // ... $this->validatorSchema['email'] = new sfValidatorAnd(array( $this->validatorSchema['email'], new sfValidatorEmail(), )); }
El validador
sfValidatorAnd
toma un arreglo o array de validadores que deben pasarse para que el aor sea válido. El truco aquí es referenciar al actual validador ($this->validatorSchema['email']), y añadirle uno nuevo.
También puede usar el validador
sfValidatorOr
para forzar un valor a pasar al menos un validador. Y por supuesto, puedes mezclar y coinicidir los validadoressfValidatorAnd
y sfValidatorOr
para crear complejos validadores basados en boleanos.
Incluso si el
type
de la columna es también un varchar
en el esquema, queremos que su valor este restringido a una lista de opciones: full time, part time, o freelance.
En primer lugar, vamos a definir los posibles valores en
JobeetJobTable
:// lib/model/doctrine/JobeetJobTable.class.php class JobeetJobTable extends Doctrine_Table { static public $types = array( 'full-time' => 'Full time', 'part-time' => 'Part time', 'freelance' => 'Freelance', ); public function getTypes() { return self::$types; } // ... }
A continuación, utiliza
sfWidgetFormChoice
para el type
del widget:$this->widgetSchema['type'] = new sfWidgetFormChoice(array( 'choices' => Doctrine_Core::getTable('JobeetJob')->getTypes(), 'expanded' => true, ));
sfWidgetFormChoice
representa un widget de opciones el cual mostrará un diferente widget de acuerdo a las opciones de configuración (expanded
y multiple
):- Lista desplegable (
<select>
):array('multiple' => false, 'expanded' => false)
- Combo Lista (
<select multiple="multiple">
):array('multiple' => true, 'expanded' => false)
- Lista de botones radio:
array('multiple' => false, 'expanded' => true)
- Lista de checkboxes:
array('multiple' => true, 'expanded' => true)
Si quieres que uno de los radio button este seleccionado por defecto (
full-time
por ejemplo), puedes cambiar el valor por defecto en el esquema de base de datos.
Incluso si piensas que nadie pueda enviar un valor no-válido, un hacker fácilmente puede pasar por alto las opciones del widget usando herramientas como curl o la Firefox Web Developer Toolbar. Vamos a cambiar el validador para restringir a las opciones posibles:
$this->validatorSchema['type'] = new sfValidatorChoice(array( 'choices' => array_keys(Doctrine_Core::getTable('JobeetJob')->getTypes()), ));
Como la columna
logo
almacenará el nombre del archivo del logotipo relacionados con el puesto de trabajo, tenemos que cambiar el widget a file input tag:$this->widgetSchema['logo'] = new sfWidgetFormInputFile(array( 'label' => 'Company logo', ));
Para cada uno de los campos, Symfony automáticamente genera un label (que se utilizarán al mostrar la etiqueta
<label>
). Esto puede ser cambiado con la opción label
.
También puedes cambiar labels en un batch con el método
setLabels()
del widget array:$this->widgetSchema->setLabels(array( 'category_id' => 'Category', 'is_public' => 'Public?', 'how_to_apply' => 'How to apply?', ));
También tenemos que cambiar el valor por defecto del validador:
$this->validatorSchema['logo'] = new sfValidatorFile(array( 'required' => false, 'path' => sfConfig::get('sf_upload_dir').'/jobs', 'mime_types' => 'web_images', ));
sfValidatorFile
es muy interesante ya que hace una serie de cosas:- Valida que el archivo subido es una imagen en un formato web (
mime_types
) - Cambia el nombre del archivo a algo único
- Almacena el archivo en un
path
dado - Actualiza la columna
logo
con el nombre generado
Necesitas crear el directorio logo (
web/uploads/jobs/
) y comprobar que tenga permisos de escritura por el servidor web.
Como el validador guarda la ruta relativa en la base de datos, cambia la ruta de acceso utilizada en la plantilla
showSuccess
:// apps/frontend/modules/job/templates/showSuccess.php <img src="/uploads/jobs/<?php echo $job->getLogo() ?>" alt="<?php echo $job->getCompany() ?> logo" />
Si un método
generateLogoFilename()
existe en el modelo, este será llamado por el validador y el resultado sobreescribirá el nombre del archivo generado por defecto logo
. El método tiene un objeto sfValidatedFile
como un argumento.
Así como puedes sobreescribir el label generado de cualquier campo, puedes tambien definir un mensaje de ayuda. Vamos agregar uno para la columna
is_public
para explicar mejor su significado:$this->widgetSchema->setHelp('is_public', 'Whether the job can also be published on affiliate websites or not.');
La clase final
JobeetJobForm
se lee como sigue:// lib/form/doctrine/JobeetJobForm.class.php class JobeetJobForm extends BaseJobeetJobForm { public function configure() { unset( $this['created_at'], $this['updated_at'], $this['expires_at'], $this['is_activated'] ); $this->validatorSchema['email'] = new sfValidatorAnd(array( $this->validatorSchema['email'], new sfValidatorEmail(), )); $this->widgetSchema['type'] = new sfWidgetFormChoice(array( 'choices' => Doctrine_Core::getTable('JobeetJob')->getTypes(), 'expanded' => true, )); $this->validatorSchema['type'] = new sfValidatorChoice(array( 'choices' => array_keys(Doctrine_Core::getTable('JobeetJob')->getTypes()), )); $this->widgetSchema['logo'] = new sfWidgetFormInputFile(array( 'label' => 'Company logo', )); $this->widgetSchema->setLabels(array( 'category_id' => 'Category', 'is_public' => 'Public?', 'how_to_apply' => 'How to apply?', )); $this->validatorSchema['logo'] = new sfValidatorFile(array( 'required' => false, 'path' => sfConfig::get('sf_upload_dir').'/jobs', 'mime_types' => 'web_images', )); $this->widgetSchema->setHelp('is_public', 'Whether the job can also be published on affiliate websites or not.'); } }
La Plantilla del Formulario
Ahora que la clase form ha sido personalizada, necesitamos mostrarla. La plantilla para el formulario es la misma si quieres crear un nuevo puesto de trabajo o editar uno existente. De hecho, ambas plantilla
newSuccess.php
y editSuccess.php
son bastante similares:<!-- apps/frontend/modules/job/templates/newSuccess.php --> <?php use_stylesheet('job.css') ?> <h1>Post a Job</h1> <?php include_partial('form', array('form' => $form)) ?>
Si no has agregado la hoja de estilo
job
aún, es tiempo de hacerlo para ambas plantillas (<?php use_stylesheet('job.css') ?>
).
El formulario en sí mismo es mostrado en el partial
_form
. Reemplaza el contenido del partial generado _form
con el siguiente código:<!-- apps/frontend/modules/job/templates/_form.php --> <?php use_stylesheets_for_form($form) ?> <?php use_javascripts_for_form($form) ?> <?php echo form_tag_for($form, '@job') ?> <table id="job_form"> <tfoot> <tr> <td colspan="2"> <input type="submit" value="Preview your job" /> </td> </tr> </tfoot> <tbody> <?php echo $form ?> </tbody> </table> </form>
Los helpers
use_javascripts_for_form()
y use_stylesheets_for_form()
incluyen el JavaScript y hoja de estilo necesarios para los form widgets.
Incluso si el formulario job no necesita ningún JavaScript o hoja de estilo, se trata de un buen hábito mantener estos helper llamandolos "por las dudas". Puede salvar tu día si decides cambiar un widget que necesite de algunos JavaScript o una hoja de estilo específica.
El helper
form_tag_for()
genera una etiqueta <form>
para un formulario y ruta dado y cambia los métodos HTTP a POST
o PUT
dependiendo de si el objeto es nuevo o no. También se ocupa del atributo multipart
si el formulario tiene algun file input.
Eventualmente,
<?php echo $form ?>
muestra los form widgets.
Personalizar el Look and Feel de un Form
Por defecto,
<?php echo $form ?>
muestra los form widgets como una tabla.
La mayoría de las veces, tendrás que personalizar el diseño de tus formularios. El objeto form ofrece muchos métodos útiles para esta personalización:
Método | Descripción |
---|---|
render() | Muestra el formulario (equivalente a la salida de echo $form ) |
renderHiddenFields() | Muestra los campos ocultos |
hasErrors() | Devuelve true si el form tiene algunos errores |
hasGlobalErrors() | Devuelve true si el form tiene errores globales |
getGlobalErrors() | Devuelve un array de errores globales |
renderGlobalErrors() | Muestra errores globales |
El formulario también se comporta como un array de campos. Puedes acceder al campo
company
con $form['company']
. El objeto devuelto proporciona métodos para mostrar cada uno de los elementos del campo:Método | Descripción |
---|---|
renderRow() | Muestra el campo fila |
render() | Muestra el campo widget |
renderLabel() | Muestra el campo label |
renderError() | Muestra el campo mensajes de error en caso de haber |
renderHelp() | Muestra el campo de mensajes de ayuda |
La sentencia
echo $form
es equivalente a:<?php foreach ($form as $widget): ?> <?php echo $widget->renderRow() ?> <?php endforeach ?>
La Acció del Formulario
Tenemos una clase form y una plantilla que la muestra. Ahora, es el momento de realmente hacer que funcione con algunas acciones.
El formulario job es gestionado por cinco métodos en el módulo
job
:- new: Muestra un formulario en blanco para crear un nuevo puesto de trabajo
- edit: Muestra un formulario para editar uno existente
- create: Crea un nuevo puesto de trabajo con los valores enviados por el usuario
- update: Actualiza uno existente con los valores enviados
- processForm: Invocado por
create
yupdate
, este procesa el form (validación, rellena el formulario, y serialización a la base de datos)
Todos los formularios tienen el siguieten ciclo de vida:
Como hemos creado una colección de rutas Doctrine 5 días atras para el módulo
job
, podemos simplificar el código del formulario y sus métodos de gestión:// apps/frontend/modules/job/actions/actions.class.php public function executeNew(sfWebRequest $request) { $this->form = new JobeetJobForm(); } public function executeCreate(sfWebRequest $request) { $this->form = new JobeetJobForm(); $this->processForm($request, $this->form); $this->setTemplate('new'); } public function executeEdit(sfWebRequest $request) { $this->form = new JobeetJobForm($this->getRoute()->getObject()); } public function executeUpdate(sfWebRequest $request) { $this->form = new JobeetJobForm($this->getRoute()->getObject()); $this->processForm($request, $this->form); $this->setTemplate('edit'); } public function executeDelete(sfWebRequest $request) { $request->checkCSRFProtection(); $job = $this->getRoute()->getObject(); $job->delete(); $this->redirect('job/index'); } protected function processForm(sfWebRequest $request, sfForm $form) { $form->bind( $request->getParameter($form->getName()), $request->getFiles($form->getName()) ); if ($form->isValid()) { $job = $form->save(); $this->redirect($this->generateUrl('job_show', $job)); } }
Cuando navegamos a la página
/job/new
, una nueva instancia de form es creada y pasada a la plantilla (acción new
).
Cuando el usuario envía el formulario (acción
create
), el formulario es atado (método bind()
) con los valores envíados por el usuario y la validación es desencadenada.
Una vez que el formulario está, es posible de comprobar su validez usando el método
isValid()
: Si el formulario es válido (regresa true
), el job es guardado en la base de datos ($form->save()
), y el usuario es redirigido a la página de vista previa; si no, la plantilla newSuccess.php
es mostrada de nuevo con los valores envíados por el usuario y los mensajes de error asociados.
El método
setTemplate()
cambia la plantilla empleada para una acción dada. Si el formulario envíado no es válido, los métodos create
y update
usan la misma plantilla para las acciones new
y edit
respectivamente, para mostrar el formulario con mensajes de error.
La modificación de un puesto de trabajo existente es bastante similar. La única diferencia entre la acción
new
y edit
es que el objeto job para ser modificado es pasado como el primer argumento del constructor de form. Este objeto se utilizará por defecto en la plantilla (los valores por defecto son un objeto para los formularios Doctrine, un simple array de simples formularios).
Tambien puedes definir los valores por defecto para la creación. Una forma es declarar los valores en el esquema de base de datos. Otra es pasar un pre-modificado objeto
Job
al constructor de form.
Cambia el método
executeNew()
para definir full-time
como el valor por defecto para la columna type
:// apps/frontend/modules/job/actions/actions.class.php public function executeNew(sfWebRequest $request) { $job = new JobeetJob(); $job->setType('full-time'); $this->form = new JobeetJobForm($job); }
Cuando el formulario es tomado, los valores por defecto se sustituirán por los del usuario. El usuario envía valores que se utilizarán para rellenar el formulario cuando el formulario se devuelve en caso de errores de validación.
Proteger el formulario Job con un Token
Todo debe funcionar bien por ahora. A partir de ahora, el usuario debe ingresar el token para el puesto de trabajo (job). Pero el token del puesto de trabajo debe ser generado automáticamente cuando un nuevo puesto de trabajo es creado, ya que no queremos proporcionarle al usuario un único token.
Actualiza el método
save()
de JobeetJob
para agregar la lógica que genera los token antes de que un nuevo puesto de trabajo sea guardado:// lib/model/doctrine/JobeetJob.class.php public function save(Doctrine_Connection $conn = null) { // ... if (!$this->getToken()) { $this->setToken(sha1($this->getEmail().rand(11111, 99999))); } return parent::save($conn); }
Puedes ahora eliminar el campo
token
del form:// lib/form/doctrine/JobeetJobForm.class.php class JobeetJobForm extends BaseJobeetJobForm { public function configure() { unset( $this['created_at'], $this['updated_at'], $this['expires_at'], $this['is_activated'], $this['token'] ); // ... } // ... }
Si recuerdas los casos de uso del día 2, un puesto de trabajo o job puede ser editado solo si el usuario conoce el token asociado. En este momento, es bastante fácil de editar o eliminar cualquier puesto de trabajo, simplemente adivinando la URL. Esto se debe a que la edición del URL es como
/job/ID/edit
, donde ID
es la clave principal del puesto de trabajo (job).
Por defecto, una ruta
sfDoctrineRouteCollection
genera URLs con la clave primaria, pero puede ser cambiado a una única columna pasando la opción column
:# apps/frontend/config/routing.yml job: class: sfDoctrineRouteCollection options: { model: JobeetJob, column: token } requirements: { token: \w+ }
Nota que tenemos también que cambiar el parámetro de requirement
token
para que coincida con cualquier cadena ya que el requirements por defecto de Symfony es \d+
para la clave única.
Ahora, todas las rutas, excepto la
job_show_user
, tienen un token. Por ejemplo, la ruta para editar un job es ahora:http://www.jobeet.com.localhost/job/TOKEN/edit
También tendrás que cambiar el enlace "Edit" en la plantilla
showSuccess
:<!-- apps/frontend/modules/job/templates/showSuccess.php -->
<a href="<?php echo url_for('job_edit', $job) ?>">Edit</a>
También hemos cambiado los requisitos para la columna
token
ya que para Symfony y su requirements por defecto es \d+
para la clave principal.La Página de Vista Previa
La página de vista previa es la misma que para la visualización de la página de los puestos de trabajo. Gracias a la ruta, el usuario viene con el correcto token, accesible en el parametro
token
.
Si el usuario entra con una URL con token, vamos a añadir una barra de admin en la parte superior. Al comienzo de la plantilla
showSuccess
, añadir un partial para mostrar la barra de administrador y eliminar el enlace edit
en la parte inferior:<!-- apps/frontend/modules/job/templates/showSuccess.php --> <?php if ($sf_request->getParameter('token') == $job->getToken()): ?> <?php include_partial('job/admin', array('job' => $job)) ?> <?php endif ?>
Entonces, crea el partial
_admin
:<!-- apps/frontend/modules/job/templates/_admin.php --> <div id="job_actions"> <h3>Admin</h3> <ul> <?php if (!$job->getIsActivated()): ?> <li><?php echo link_to('Edit', 'job_edit', $job) ?></li> <li><?php echo link_to('Publish', 'job_edit', $job) ?></li> <?php endif ?> <li><?php echo link_to('Delete', 'job_delete', $job, array('method' => 'delete', 'confirm' => 'Are you sure?')) ?></li> <?php if ($job->getIsActivated()): ?> <li<?php $job->expiresSoon() and print ' class="expires_soon"' ?>> <?php if ($job->isExpired()): ?> Expired <?php else: ?> Expires in <strong><?php echo $job->getDaysBeforeExpires() ?></strong> days <?php endif ?> <?php if ($job->expiresSoon()): ?> - <a href="">Extend</a> for another <?php echo sfConfig::get('app_active_days') ?> days <?php endif ?> </li> <?php else: ?> <li> [Bookmark this <?php echo link_to('URL', 'job_show', $job, true) ?> to manage this job in the future.] </li> <?php endif ?> </ul> </div>
Hay un montón de código, pero la mayor parte del código es fácil de entender.
Para hacer la plantilla más fácil de leer, hemos añadido un montón de métodos de acceso directo en la clase
JobeetJob
:// lib/model/doctrine/JobeetJob.class.php public function getTypeName() { $types = Doctrine_Core::getTable('JobeetJob')->getTypes(); return $this->getType() ? $types[$this->getType()] : ''; } public function isExpired() { return $this->getDaysBeforeExpires() < 0; } public function expiresSoon() { return $this->getDaysBeforeExpires() < 5; } public function getDaysBeforeExpires() { return ceil(($this->getDateTimeObject('expires_at')->format('U') - time()) / 86400); }
La barra de admin muestra diferentes acciones, dependiendo del estado del puesto de trabajo:
Activación y Publicación del Puesto de Trabajo
En la sección anterior, hay un enlace para publicar el trabajo. El enlace debe ser cambiado para que apunte a una nueva acción
publish
. En lugar de crear una nueva ruta, podemos configurar la actual ruta job
:# apps/frontend/config/routing.yml job: class: sfDoctrineRouteCollection options: model: JobeetJob column: token object_actions: { publish: put } requirements: token: \w+
El
object_actions
toma un array de acciones adicionales para el objeto dado. Ahora podemos cambiar el vínculo del enlace "Publish":<!-- apps/frontend/modules/job/templates/_admin.php --> <li> <?php echo link_to('Publish', 'job_publish', $job, array('method' => 'put')) ?> </li>
El último paso es crear la acción
publish
:// apps/frontend/modules/job/actions/actions.class.php public function executePublish(sfWebRequest $request) { $request->checkCSRFProtection(); $job = $this->getRoute()->getObject(); $job->publish(); $this->getUser()->setFlash('notice', sprintf('Your job is now online for %s days.', sfConfig::get('app_active_days'))); $this->redirect($this->generateUrl('job_show_user', $job)); }
El lector astuto se habrá dado cuenta que el enlace "Publish" es enviado con el método HTTP put. Para simular el método put, el enlace es automáticamente convertido a un formulario cuando haces clic en él.
Y debido a que hemos activado la protección CSRF, el helper
link_to()
tiene un token CSRF en el enlace y el método checkCSRFProtection()
del objeto comprueba la validez del envío.
El método
executePublish()
usa un nuevo método publish()
que puede definirse como sigue:// lib/model/doctrine/JobeetJob.class.php public function publish() { $this->setIsActivated(true); $this->save(); }
Ahora puedes probar la nueva característica para publicar desde tu navegador.
Pero todavía tenemos algo que arreglar. Los puestos de trabajo inactivos no deben ser accesibles, lo que significa que no debe aparecer en la página principal Jobeet, y no deben ser accesible por sus URL. Como hemos creado un método
addActiveJobsCriteria()
para restringir un Doctrine_Query
a puestos de trabajo activos, podemos editarlo y añadir la nueva exigencia al final:// lib/model/doctrine/JobeetJobTable.class.php public function addActiveJobsQuery(Doctrine_Query $q = null) { // ... $q->andWhere($alias . '.is_activated = ?', 1); return $q; }
Eso es todo. Puedes probar ahora en tu navegador. Todos los puestos de trabajo no activos han desaparecido de la página principal, incluso si conoces su URL, ya no son accesibles. Sin embargo, son accesibles si se conoce el token URL del puesto de trabajo. En ese caso, el puesto de trabajo se mostrará con una vista previa y el admin bar.
Esta es una de las grandes ventajas del modelo MVC y la refactorización que hemos hecho a lo largo del camino. Un solo cambio en un método fue necesario para añadir el nuevo requisito.
Cuando creamos el método
getWithJobs()
, hemos olvidado de utilizar el métodoaddActiveJobsQuery()
. Por lo tanto, tenemos que editar y añadir el nuevo requisito:class JobeetCategoryTable extends Doctrine_Table { public function getWithJobs() { // ... $q->andWhere('j.is_activated = ?', 1); return $q->execute(); }
Suscribirse a:
Enviar comentarios
(
Atom
)
Sígueme en las Redes Sociales
Donaciones
Datos personales
Entradas populares
-
En este apartado vamos a explicar como ejercutar archivos PHP a través del terminal de Ubuntu. Lo primero que tendríamos que hacer es inst...
-
En este blog voy a comentar un tema que se utilizan en casi todas las páginas web que existen, y es el tema de la paginación. La paginaci...
-
Este post trata de la integración de la librería PHPExcel en Codeigniter, aunque se podría aplicar a cualquier librería, como por ejemplo mP...
-
Ejemplo para añadir o sumar un número determinado de hora/s, minuto/s, segundo/s a una fecha en php. Con la función strtotime se puede ...
-
Este tema es uno de los temas primordiales sobre el framework Codeigniter, ya que en alguna ocación nos hemos visto obligados a recoger dato...
© Espacio Daycry - Espacio de programación 2013 . Powered by Bootstrap , Blogger templates and RWD Testing Tool
No hay comentarios :
Publicar un comentario