La deuxième semaine de Jobeet a pris un bon départ avec l'introduction du framework de test de symfony. Nous allons continuer aujourd'hui avec le framework de formulaire
Le framework de formulaire
Tout site Web a des formulaires : du simple formulaire de contact à celui avec beaucoup plus de champs. L'écriture de formulaire est aussi une des tâches les plus complexes et l'une des plus fastidieuses pour un développeur web : vous devez écrire le formulaire HTML, implémenter des règles de validation pour chaque champ, traiter les valeurs pour les stocker dans une base de données, afficher les messages d'erreur, repeupler les champs dans le cas d'erreurs, et bien plus encore ...
Bien sûr, au lieu de réinventer la roue, encore et encore, symfony fournit un framework pour faciliter la gestion de formulaire. Le framework de formulaire est composé de trois parties :
- validation: Le sous-framework de validation fournit les classes pour valider les saisies (entier, chaine, adresse email, ...)
- widgets: Le sous-framework de widget fournit les classes pour la production des champs HTML (input, textarea, select, ...)
- forms: Les classes formulaire représentent des formulaires faits de widgets et de validateurs et fournit des méthodes pour aider la gestion du formulaire. Chaque champs du formulaire a son propre validateur et son propre widget.
Les formulaires
Un formulaire de symfony est une classe composé de champs. Chaque champ a un nom, un validateur
et un widget. Un simple ContactForm
peut être défini avec la classe suivante :
class ContactForm extends sfForm { public function configure() { $this->setWidgets(array( 'email' => new sfWidgetFormInput(), 'message' => new sfWidgetFormTextarea(), )); $this->setValidators(array( 'email' => new sfValidatorEmail(), 'message' => new sfValidatorString(array('max_length' => 255)), )); } }
Les champs du formulaire sont configurés dans la méthode configure()
, en utilisant
les méthodes setValidators()
et setWidgets()
.
tip
Le frameework de formulaire est livré avec un lot de widgets et validators. L'API les décrit assez largement avec toutes les options, les erreurs et les messages d'erreur par défaut.
Les noms des classes des widgets et des validateurs sont assez explicites : le champ email
sera rendu par une balise HTML <input>
(sfWidgetFormInputText
) et sera
validé par une adresse email (sfValidatorEmail
). Le champ message
sera
rendu par une balise <textarea>
(sfWidgetFormTextarea
), et doit être une
chaine d'au plus 255 caractères (sfValidatorString
).
Par défaut, tous les champs sont obligatoires, car
la valeur par défaut pour l'option required
est true
. Ainsi, la définition de la validation
pour email
est équivalente à new sfValidatorEmail(array('required' => true))
.
tip
Vous pouvez fusionner un formulaire dans un autre en utilisant la méthode mergeForm()
,
ou incorporer un formulaire à l'aide de la méthode embedForm()
:
$this->mergeForm(new AnotherForm()); $this->embedForm('name', new AnotherForm());
Les formulaires de Propel
La plupart du temps, un formulaire doit être sérialisé à la base de données. Comme
symfony sait déjà tout sur le modèle de votre base de données, il peut générer automatiquement
des formulaires basés sur ces informations. En fait, lorsque vous avez lancé la tâche
propel:build-all
au cours du jour 3, symfony a automatiquement appelé la tâche
propel:build-forms
:
$ php symfony propel:build-forms
La tâche propel:build-forms
génère des classes de formulaires dans le répertoire
lib/form/
. L'organisation de ces fichiers générés est semblable à celle de
lib/model/
. Chaque classe du modèle a une classe de formulaire correspondante (par
exemple JobeetJob
a JobeetJobForm
), qui est vide par défaut car il hérite d'une
classe de base :
// lib/form/JobeetJobForm.class.php class JobeetJobForm extends BaseJobeetJobForm { public function configure() { } }
tip
En parcourant les fichiers générés dans le sous-répertoire lib/form/base/
, vous
pourrez voir de nombreux exemples d'usage de symfony intégré dans les widgets et
les validateurs.
Personnalisation du formulaire d'emploi
Le formulaire d'emploi est un parfait exemple pour apprendre la personnalisation du formulaires. Voyons comment le personnaliser, étape par étape.
D'abord, changez le lien "Post a Job" dans la mise en page pour être en mesure de vérifier les modifications directement dans votre navigateur :
<!-- apps/frontend/templates/layout.php -->
<a href="<?php echo url_for('@job_new') ?>">Post a Job</a>
Par défaut, un formulaire Propel affiche des champs pour toutes les colonnes de la table. Mais pour le formulaire d'emploi, certains d'entre eux ne doit pas être modifiable par l'utilisateur final. La suppression des champs à partir d'un formulaire est aussi simple que d'en désactiver :
// lib/form/JobeetJobForm.class.php class JobeetJobForm extends BaseJobeetJobForm { public function configure() { unset( $this['created_at'], $this['updated_at'], $this['expires_at'], $this['is_activated'] ); } }
La désactivation d'un champ signifie que le widget et le validateur du champs sont supprimés.
La configuration du formulaire doit parfois être plus précis que l'introspection
à partir du schéma de la base de données. Par exemple, la colonne email
est un
varchar
dans le schéma, mais nous avons besoin de cette colonne pour être validé comme
un email. Changeons la valeur par défaut sfValidatorString
par sfValidatorEmail
:
// lib/form/JobeetJobForm.class.php public function configure() { // ... $this->validatorSchema['email'] = new sfValidatorEmail(); }
Le remplacement de la validation par défaut n'est pas toujours la meilleure solution,
comme les règles de validation par défaut introspectés depuis le schéma de la base de données
sont perdues (new sfValidatorString(array('max_length' => 255))
). Il est presque toujours
préférable d'ajouter le nouveau validateur à celui déjà existant à l'aide du validateur
spécial sfValidatorAnd
:
// lib/form/JobeetJobForm.class.php public function configure() { // ... $this->validatorSchema['email'] = new sfValidatorAnd(array( $this->validatorSchema['email'], new sfValidatorEmail(), )); }
Le validateur sfValidatorAnd
prend un tableau de validateurs qui doivent tous passer
pour que cette valeur soit valide. L'astuce ici est de faire référence au validateur
actuel ($this->validatorSchema['email']), et d'ajouter le nouveau.
note
Vous pouvez également utiliser le validateur sfValidatorOr
pour forcer une
valeur à passer pour au moins un validateur. Et bien sûr, vous pouvez mélanger et
fusionner les validateurs sfValidatorAnd
et sfValidatorOr
pour créer des validateurs
complexes sur base de booléen.
Même si la colonne type
est également un varchar
dans le schéma, nous voulons sa
valeur pour se limiter à une liste de choix : temps plein, temps partiel, ou freelance.
D'abord, nous allons définir les valeurs possibles dans JobeetJobPeer
:
// lib/model/JobeetJobPeer.php class JobeetJobPeer extends BaseJobeetJobPeer { static public $types = array( 'full-time' => 'Full time', 'part-time' => 'Part time', 'freelance' => 'Freelance', ); // ... }
Puis, utilisez sfWidgetFormChoice
pour le widget type
:
$this->widgetSchema['type'] = new sfWidgetFormChoice(array( 'choices' => JobeetJobPeer::$types, 'expanded' => true, ));
sfWidgetFormChoice
représente un widget de choix qui peut être affiché par un
widget différent selon certaines options de configuration (expanded
et
multiple
) :
- Liste déroulante (
<select>
) :array('multiple' => false, 'expanded' => false)
- Boîte déroulante (
<select multiple="multiple">
) :array('multiple' => true, 'expanded' => false)
- Liste de radiobuttons :
array('multiple' => false, 'expanded' => true)
- List de checkboxes :
array('multiple' => true, 'expanded' => true)
note
Si vous voulez que l'un des radiobutton soit sélectionné par défaut (full-time
par exemple), vous pouvez changer la valeur par défaut dans le schéma de base de données.
Même si vous pensez que personne peut soumettre un valeur non valide, un pirate peut facilement contourner les choix du widget en utilisant des outils comme curl ou la barre d'outils de développeur web de Firefox. Changeons le validateur pour restreindre les choix possibles :
$this->validatorSchema['type'] = new sfValidatorChoice(array( 'choices' => array_keys(JobeetJobPeer::$types), ));
Comme la colonne logo
va stocker le nom du fichier du logo associé à l'emploi,
nous devons changer le widget en une balise file input :
$this->widgetSchema['logo'] = new sfWidgetFormInputFile(array( 'label' => 'Company logo', ));
Pour chaque champ, symfony génère automatiquement un label (qui
sera utilisé dans la balise <label>
rendue). Ceci peut être modifié avec l'option label
.
Vous pouvez également modifier les labels d'un batch avec la méthode setLabels()
du tableau de widget :
$this->widgetSchema->setLabels(array( 'category_id' => 'Category', 'is_public' => 'Public?', 'how_to_apply' => 'How to apply?', ));
Nous devons également changer le validateur par défaut :
$this->validatorSchema['logo'] = new sfValidatorFile(array( 'required' => false, 'path' => sfConfig::get('sf_upload_dir').'/jobs', 'mime_types' => 'web_images', ));
sfValidatorFile
est assez intéressant car il fait un certain nombre de choses :
- Valider que le fichier téléchargé est une image dans un format web (
mime_types
) - Renomme le fichier en quelque chose d'unique
- Stocke le fichier dans le
path
donné - Met à jour la colonne
logo
avec le nom généré
note
Vous devez créer le répertoire logo (web/uploads/jobs/
) et vérifier qu'il est
accessible en écriture par le serveur web.
Comme le validateur enregistrera le chemin relatif dans la base de données, changer le
chemin utilisé dans le template showSuccess
:
// apps/frontend/modules/job/templates/showSuccess.php <img src="/uploads/jobs/<?php echo $job->getLogo() ?>" alt="<?php echo $job->getCompany() ?> logo" />
tip
Si une méthode generateLogoFilename()
existe dans le modèle, il sera appelé
par le validateur et le résultat remplacera le nom de fichier logo
généré par
défaut. La méthode est donné à l'objet sfValidatedFile
comme argument.
Tout comme vous pouvez remplacer le label généré de n'importe quel champ, vous pouvez aussi
définir un message d'aide. Ajoutons en un pour la colonne is_public
pour mieux expliquer sa signification :
$this->widgetSchema->setHelp('is_public', 'Whether the job can also be published on affiliate websites or not.');
La classe JobeetJobForm
finale se lit comme suit :
// lib/form/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' => JobeetJobPeer::$types, 'expanded' => true, )); $this->validatorSchema['type'] = new sfValidatorChoice(array( 'choices' => array_keys(JobeetJobPeer::$types), )); $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.'); } }
Le template du formulaire
Maintenant que la classe de formulaire a été personnalisé, nous avons besoin de
l'afficher. Le Template du formulaire est le même, que vous vouliez créer
un nouvel emploi ou modifier un existant. En fait, les deux Templates newSuccess.php
et editSuccess.php
sont assez similaires:
<!-- apps/frontend/modules/job/templates/newSuccess.php --> <?php use_stylesheet('job.css') ?> <h1>Post a Job</h1> <?php include_partial('form', array('form' => $form)) ?>
note
Si vous n'avez pas ajouté de la feuille de style job
pour le moment, il est
temps de le faire dans les deux Templates (<?php use_stylesheet('job.css') ?>
).
Le formulaire est lui-même rendu dans le partial _form
.
Remplacez le contenu du partial généré _form
par le code suivant :
<!-- apps/frontend/modules/job/templates/_form.php --> <?php include_stylesheets_for_form($form) ?> <?php include_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>
Les helpers include_javascripts_for_form()
et include_stylesheets_for_form()
incluent des dépendances de JavaScript et de feuille de style nécessaires pour les
widgets du formulaire.
tip
Même si le formulaire emploi n'a pas besoin de JavaScript ou d'un fichier de style, c'est une bonne habitude de garder l'appels de ces helpers "juste au cas où". Il peut sauver votre journée plus tard, si vous décidez de changer un widget qui a besoin de quelques JavaScript ou d'une feuille de style spécifique.
Le helper form_tag_for()
génère une balise <form>
pour le
formulaire et la route donnés et modifie les méthodes HTTP en
POST
ou en PUT
PUT selon si l'objet est
nouveau ou non. Il s'occupe aussi de l'attribut ~multipart|Formulaires
(Multipart)~
si le formulaire a aucune balise input file.
Finalement, le <?php echo $form ?>
rend les widgets du formulaire.
L'action du formulaire
Nous avons maintenant une classe de formulaire et un template qui fait le rendu. Maintenant, il est temps de le faire réellement fonctionner avec certaines actions.
Le formulaire emploi est géré par cinq méthodes dans le module job
:
- new: Affiche un formulaire non renseigné pour créer un nouvel emploi
- edit: Affiche un formulaire pour modifier un emploi existant
- create: Crée un nouvel emploi avec les valeurs soumises par l'utilisateur
- update: Met à jour un emploi avec les valeurs soumises par l'utilisateur
- processForm: Appelé par
create
etupdate
, il traite le formulaire (validation, repopulation du formulaire et sérialisation vers la base de données)
Tous les formulaires ont le cycle de vie suivant :
Comme nous avons créé une collection de route Propel il y a 5 jours pour le module job
,
nous pouvons simplifier le code pour les méthodes de gestion de formulaire :
// 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)); } }
Lorsque vous naviguez vers la page /job/new
, une nouvelle instance du formulaire
est créé et transmise au Template (action new
).
Lorsque l'utilisateur soumet le formulaire (action create
), le formulaire est lié (méthode
bind()
) avec les valeurs soumises par l'utilisateur et la validation est déclenchée.
Une fois que le formulaire est lié, il est possible de vérifier sa validité en utilisant
la méthode isValid()
: si le formulaire est valide (elle retourne true
), l'emploi est sauvé
dans la base de données ($form->save()
), et l'utilisateur est redirigé vers la
page de prévisualisation d'emploi, sinon, le template newSuccess.php
s'affiche à nouveau avec
les valeurs soumises par l'utilisateur et les messages d'erreur associés.
tip
La méthode setTemplate()
change le Template utilisé pour une action donnée. Si
le formulaire soumis n'est pas valide, les méthodes create
et update
utilisent le même
template respectif que l'action new
et edit
pour ré-afficher le formulaire avec
les messages d'erreur.
La modification d'un emploi existant est assez similaire. La seule différence
entre l'action new
et edit
est que l'objet job à modifier, est passé comme
premier argument au constructeur du formulaire. Cet objet sera utilisé pour les
valeurs par défaut de widget dans le Template (les valeurs par défaut sont un objet
pour le formulaire Propel, mais un simple tableau pour des formulaires simples).
Vous pouvez également définir des valeurs par défaut pour le formulaire de création.
Une solution est de déclarer les valeurs dans le schéma de base de données. Une autre
est de passer un objet Job
pré-modifié au constructeur du formulaire.
Changer la méthode executeNew()
pour définir full-time
comme étant la valeur
par défaut pour la colonne 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); }
note
Lorsque le formulaire est lié, les valeurs par défaut sont remplacées par celles soumises par l'utilisateur. Les valeurs soumises par l'utilisateur seront utilisées pour le repeuplement du formulaire lorsque ce dernier est à nouveau affichée en cas d'erreurs de validation.
Protection du formulaire d'emploi avec un jeton (token)
Tout doit fonctionner correctement maintenant. Pour l'instant, l'utilisateur doit saisir le jeton pour l'emploi. Mais le jeton de l'emploi doit être généré automatiquement quand un nouvel emploi est créé, car nous ne pouvons pas se fier à l'utilisateur pour fournir un jeton unique.
Mettez à jour la méthode save()
de JobeetJob
pour ajouter la logique qui
génère le jeton avant qu'un nouvel emploi soit enregistré :
// lib/model/JobeetJob.php public function save(PropelPDO $con = null) { // ... if (!$this->getToken()) { $this->setToken(sha1($this->getEmail().rand(11111, 99999))); } return parent::save($con); }
Vous pouvez maintenant supprimer le champ token
du formulaire :
// lib/form/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 vous vous souvenez des histoires d'utilisateurs du jour 2, un emploi peut être modifié que si
l'utilisateur connaît le jeton associé. À l'heure actuelle, il est assez facile de modifier ou de
supprimer n'importe quel emploi, en essayant juste de deviner l'URL. Car l'URL de edit est
/job/ID/edit
, où ID
est la clé primaire de l'emploi.
Par défaut, une route sfPropelRouteCollection
génère des URL avec la clé primaire,
mais elle peut être changée par n'importe quelle colonne unique en faisant passer
l'option column
:
# apps/frontend/config/~routing|Routing~.yml job: class: sfPropelRouteCollection options: { model: JobeetJob, column: token } requirements: { token: \w+ }
Notez que nous avons également modifié le paramètre requirements token
pour faire correspondre
n'importe quelle chaîne car le requirements de symfony par défaut est \d+
pour la clé unique.
Maintenant, toutes les routes liées aux emplois, à l'exception des job_show_user
, incorporent
le jeton. Par exemple, la route pour modifier un emploi est maintenant sur le modèle suivant :
http://jobeet.localhost/job/TOKEN/edit
Vous aurez aussi besoin de changer le lien "Edit" dans le Template showSuccess
:
<!-- apps/frontend/modules/job/templates/showSuccess.php -->
<a href="<?php echo url_for('job_edit', $job) ?>">Edit</a>
La page de prévisualisation
La page de prévisualisation est la même que l'affichage de la page emploi. Grâce au
routage, si l'utilisateur arrive avec le bon jeton, il sera accessible
dans le paramètre de la requête token
.
Si l'utilisateur entre dans l'URL sous forme de jeton, nous allons ajouter une barre
d'admininistrateur en haut. Au début du Template showSuccess
, ajoutez un partial pour
mettre la barre d'administrateur et supprimer le lien edit
en bas :
<!-- 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; ?>
Ensuite, créez le 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>
Il y a beaucoup de code, mais la plupart du code est simple à comprendre.
Pour rendre le Template plus lisible, nous avons ajouté un ensemble de raccourci
de méthodes dans la classe JobeetJob
:
// lib/model/JobeetJob.php public function getTypeName() { return $this->getType() ? JobeetJobPeer::$types[$this->getType()] : ''; } public function isExpired() { return $this->getDaysBeforeExpires() < 0; } public function expiresSoon() { return $this->getDaysBeforeExpires() < 5; } public function getDaysBeforeExpires() { return floor(($this->getExpiresAt('U') - time()) / 86400); }
a barre d'administrateur affiche les différentes actions en fonction de l'état de l'emploi :
note
Vous serez capable de voir la barre "activée" après la section suivante.
Activation et Publication d'un emploi
Dans la section précédente, il y a un lien pour publier l'emploi. Le lien doit être
changé pour pointer vers une nouvelle action publish
. Au lieu de créer une nouvelle
route, on peut juste configurer la route job
existante :
# apps/frontend/config/routing.yml job: class: sfPropelRouteCollection options: model: JobeetJob column: token object_actions: { publish: put } requirements: token: \w+
Le object_actions
prend un tableau des actions supplélentaires pour un objet
donné. Nous pouvons maintenant modifier le lien du lien "Publish" :
<!-- apps/frontend/modules/job/templates/_admin.php --> <li> <?php echo link_to('Publish', 'job_publish', $job, array('method' => 'put')) ?> </li>
La dernière étape est de créer l'action 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)); }
Le lecteur attentif aura remarqué que le lien "Publish" est soumis avec la méthode HTTP put. Pour simuler la méthode put, le lien est automatiquement converti en un formulaire lorsque vous cliquez dessus.
Et comme nous avons activé la protection CSRF, le helper link_to()
embarque
un jeton CSRF dans le lien et la méthode checkCSRFProtection()
de l'objet de la
requête vérifie la validité de celui-ci lors de la soumission.
La méthode executePublish()
utilise une nouvelle méthode publish()
qui peut
être définie comme suit :
// lib/model/JobeetJob.php public function publish() { $this->setIsActivated(true); $this->save(); }
Vous pouvez maintenant tester la nouvelle fonctionnalité de publication dans votre navigateur.
Mais nous avons encore quelque chose à corriger. Les emplois non-activés ne doivent pas
être accessibles. Ce qui signifie qu'ils ne doivent pas apparaître sur la page d'accueil Jobeet
et ne doivent pas être accessibles par leur URL. Comme nous avons créé une méthode
addActiveJobsCriteria()
pour limiter une Criteria
aux emplois actifs, nous pouvons
le modifier et ajouter des nouvelles exigences à la fin :
// lib/model/JobeetJobPeer.php static public function addActiveJobsCriteria(Criteria $criteria = null) { // ... $criteria->add(self::IS_ACTIVATED, true); return $criteria; }
C'est tout. Vous pouvez maintenant le tester dans votre navigateur. Tous les emplois non-activés ont disparu de la page d'accueil, même si vous connaissez son URL, ils ne sont plus accessibles. Ils sont cependant accessibles si l'on connait URL du jeton de l'emploi. Dans ce cas, l'aperçu de l'emploi sera affichée avec la barre d'administration.
C'est un des grands avantages du modèle MVC et la refactorisation nous a fait faire du chemin. Un seul changement dans une seule méthode a été nécessaire pour ajouter la nouvelle exigence.
note
Lorsque nous avons créé la méthode getWithJobs()
, nous avons oublié d'utiliser
la méthode addActiveJobsCriteria()
. Donc, nous avons besoin de la modifier et ajouter
la nouvelle exigence :
class JobeetCategoryPeer extends BaseJobeetCategoryPeer { static public function getWithJobs() { // ... $criteria->add(JobeetJobPeer::IS_ACTIVATED, true); return self::doSelect($criteria); }
À demain
Le tutoriel d'aujourd'hui a été composé avec beaucoup de nouvelles informations, mais nous espérons que vous avez maintenant une meilleure compréhension du framework de formulaire de symfony.
Je sais que certains d'entre vous ont remarqué que nous avons oublié quelque chose aujourd'hui ... Nous n'avons pas mis en œuvre de test pour les nouvelles fonctionnalités. Parce que l'écriture de test est une partie importante du développement d'une application, c'est la première chose que nous ferons demain.
This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License license.