« Sauvegarde/Restauration de filtres Symfony » : différence entre les versions
mAucun résumé des modifications |
|||
| Ligne 277 : | Ligne 277 : | ||
Ainsi, dans le partial _filters.php, qui a déjà accès à une instance de la classe bookmarkGeneratorConfiguration, nous sommes maintenant capables d'afficher en boucle les filtres sauvegardés que nous avons récupéré afin d'en afficher la liste : | Ainsi, dans le partial _filters.php, qui a déjà accès à une instance de la classe bookmarkGeneratorConfiguration, nous sommes maintenant capables d'afficher en boucle les filtres sauvegardés que nous avons récupéré afin d'en afficher la liste : | ||
<pre> | |||
<nowiki> | |||
// in apps/backend/modules/bookmark/templates/_filters.php from line 11 | // in apps/backend/modules/bookmark/templates/_filters.php from line 11 | ||
[...] | [...] | ||
<tr> | <tr> | ||
<td colspan="2"> | <td colspan="2"> | ||
<h3><?php echo __('Saved filters') ?>< | <h3><?php echo __('Saved filters') ?><h3> | ||
<?php if (count($savedFilters = $configuration->getSavedFilters())): ?> | <?php if (count($savedFilters = $configuration->getSavedFilters())): ?> | ||
<ul> | <ul> | ||
| Ligne 300 : | Ligne 301 : | ||
</tr> | </tr> | ||
</tbody> | </tbody> | ||
</nowiki> | |||
</pre> | |||
Maintenant vous êtes donc capable de sauvegarder en base et de lister des filtres, les charger et les faire fonctionner sur votre liste d'objets, et bien entendu, supprimer les filtres existant. Si vous avez suivi méticuleusement les étapes de ce tutoriel, vous devriez voir quelque chose comme cela sous le formulaire de filtres : | Maintenant vous êtes donc capable de sauvegarder en base et de lister des filtres, les charger et les faire fonctionner sur votre liste d'objets, et bien entendu, supprimer les filtres existant. Si vous avez suivi méticuleusement les étapes de ce tutoriel, vous devriez voir quelque chose comme cela sous le formulaire de filtres : | ||
Dernière version du 9 décembre 2013 à 17:14
Les exemples à venir sont basés sur un modèle simple que pris sur les précédents articles que NiKo a publié précédemment, concernant l'embriquement de relations dans des formulaires Doctrine, auxquelles il va ajouter des facilitations pour ses marque-pages :
# in ./config/doctrine/schema.yml
User:
columns:
id:
type: integer(4)
primary: true
autoincrement: true
name:
type: string(255)
notnull: true
relations:
Bookmarks:
type: many
class: Bookmark
local: id
foreign: user_id
onDelete: CASCADE
Bookmark:
actAs:
I18n:
fields: [name]
actAs:
Sluggable:
fields: [name]
uniqueBy: [name, lang]
columns:
id:
type: integer(4)
primary: true
autoincrement: true
name:
type: string(255)
notnull: true
url:
type: string(255)
notnull: true
user_id:
type: integer(4)
notnull: true
relations:
User:
type: one
local: user_id
foreign: id
Tags:
class: Tag
refClass: BookmarkTag
local: bookmark_id
foreign: tag_id
foreignAlias: Bookmarks
Tag:
columns:
id:
type: integer(4)
primary: true
autoincrement: true
name:
type: string(255)
notnull: true
BookmarkTag:
columns:
bookmark_id:
type: integer(4)
primary: true
notnull: true
tag_id:
type: integer(4)
primary: true
notnull: true
Pas besoin de dire que vous devriez reconstruire votre modèle...
Le fichier de fixtures mis à jour :
# in ./data/fixtures/fixtures.yml
User:
niko:
name: niko
Bookmark:
niko_bookmark1:
User: niko
name: Slashdot
url: http://slashdot.org/
Tags: [geek_tag, tech_tag, php_tag]
niko_bookmark2:
User: niko
name: Delicious
url: http://delicious.com/
Tags: [geek_tag, tech_tag]
niko_bookmark3:
User: niko
name: Digg
url: http://digg.com/
Tags: [geek_tag, php_tag]
Tag:
geek_tag:
name: geek
php_tag:
name: php
tech_tag:
name: tech
Génération de l'admin du modèle Bookmark
Générons une application "backend" et un module "Bookmark" :
$ ./symfony generate:app backend $ ./symfony doctrine:generate-admin backend Bookmark
Maintenant améliorons un peu ce module d'admin en modifiant le fichier generator.yml :
generator:
class: sfDoctrineGenerator
param:
model_class: Bookmark
theme: admin
non_verbose_templates: true
with_show: false
singular: Bookmark
plural: Bookmarks
route_prefix: bookmark
with_doctrine_route: true
actions_base_class: sfActions
config:
actions: ~
fields: ~
list:
display: [=name, url, User]
filter: ~
form: ~
edit: ~
new: ~
Vous devriez à présent pouvoir naviguer dans l'interface d'admin ainsi générée :
Enregistrer les filtres dans une table Doctrine dédiée, et les gérer depuis le contrôleur
Nous allons utiliser Doctrine pour stocker les filtrer à enregistrer, ajoutons donc la définition d'une nouvelle table dans notre schema.yml :
SavedFilter:
columns:
id:
type: integer(4)
primary: true
autoincrement: true
name:
type: string(255)
type:
type: enum
values: [Bookmark, User]
notnull: true
filter:
type: string()
Bien entendu, pas besoin de rappeler qu'il faut reconstruire votre modèle...
Ok, maintenant nous allons enregistrer les valeurs sérialisées du filtre dans la colonne "filter" de la table et la colonne "name" sera pratique pour donner un nom aux filtres. La colonne "type" va référencer la table Doctrine dont fait référence le filtre. Rien de difficile ici.
Dans le module d'admin, les filtres sont stockés dans l'attribut tableName.filters de la session utilisateur (où tableName est le nom du module d'admin d'où les paramètres du filtre sont donnés).
Donc ajoutons maintenant une méthode executeSaveFilter() dans le controlleur bookmarkActions. Et tant que nous seront là-dessus, ajoutons également les méthodes executeLoadFilter() et executeDeleteFilter()...
<?php
# in apps/backend/modules/bookmark/actions/actions.class.php
class bookmarkActions extends autoBookmarkActions
{
public function executeDeleteFilter(sfWebRequest $request)
{
$this->forward404Unless($filter = Doctrine::getTable('SavedFilter')->findOneByTypeAndId('Bookmark', $request->getParameter('id')), sprintf('Bookmark filter #%d not found', $request->getParameter('id'))) ;
$filter->delete();
$this->getUser()->setFlash('notice', sprintf('Bookmark saved filters "%s" deleted', $filter->getName()));
$this->redirect('bookmark');
}
public function executeLoadFilter(sfWebRequest $request)
{
$this->forward404Unless($filter = Doctrine::getTable('SavedFilter')->findOneByTypeAndId('Bookmark', $request->getParameter('id')));
$this->setFilters(unserialize($filter->getFilter()));
$this->getUser()->setFlash('notice', sprintf('Bookmark saved filters "%s" loaded', $filter->getName()));
$this->redirect('bookmark');
}
public function executeSaveFilter(sfWebRequest $request)
{
$name = trim($request->getGetParameter('name'));
$savedFilter = new SavedFilter();
$savedFilter->fromArray(array(
'name' => $name ? $name : 'Untitled filter',
'type' => 'Bookmark',
'filter' => serialize($this->getUser()->getAttribute('bookmark.filters', array(), 'admin_module')),
));
$savedFilter->save();
$this->getUser()->setFlash('notice', 'Bookmark filters saved');
$this->redirect('bookmark');
}
}
Bien entendu, nous allons avoir besoin d'ajouter les routes correspondantes dans le fichier routing.yml de l'application (app/YOURAPP/config/routing.yml) :
# in apps/backend/config/routing.yml
bookmark_filter_delete:
url: /bookmark/filter/:id/delete
param: { module: bookmark, action: deleteFilter }
requirements:
id: \d+
bookmark_filter_load:
url: /bookmark/filter/:id/load
param: { module: bookmark, action: loadFilter }
requirements:
id: \d+
bookmark_filter_save:
url: /bookmark/filter/save
param: { module: bookmark, action: saveFilter }
Attendez, nous n'avons aucun lien pour enregistrer un filtre depuis l'interface d'admin ! Ajoutons-en un près du bouton Reset de la partie Filtres, en réécrivant le partial _filters.php (dont l'original se trouve dans cache/YOURAPP/YOURENV/modules/autoBookmark/templates/_filters.php) :
// in apps/backend/modules/bookmark/templates/_filters.php from line 11 [...] <tfoot>
<?php echo $form->renderHiddenFields() ?>
<a href="<?php echo url_for('@bookmark_filter_save') ?>" onclick="document.location = this.href+'?name='+prompt('Enter a name:');return false">
<?php echo __('Save') ?>
</a>
<?php echo link_to(__('Reset', array(), 'sf_admin'), 'bookmark_collection', array('action' => 'filter'), array('query_string' => '_reset', 'method' => 'post')) ?>
<input type="submit" value="<?php echo __('Filter', array(), 'sf_admin') ?>" />
</tfoot>
[...]
Notez qu'un prompt javascript va vous demander un nom pour votre filtre avant de le sauvegarder...
Ainsi nous pouvons enregistrer un filtre en base de donnée. Maintenant, listons-les après le formulaire de filtres !
Lister les filtres existants
Pour moi, le meilleur endroit pour retrouver des filtres enregistrés c'est la classe bookmarkGeneratorConfiguration, qui a été générée dans le sous-répertoire lib/ du module Bookmark d'admin. Ajoutons-y une nouvelle méthode getSavedFilters() :
<?php
# in apps/backend/modules/bookmark/lib/bookmarkGeneratorConfiguration.class.php
class bookmarkGeneratorConfiguration extends BaseBookmarkGeneratorConfiguration
{
public function getSavedFilters()
{
return Doctrine::getTable('SavedFilter')
->createQuery()
->where('type = ?', 'Bookmark')
->execute()
;
}
}
Ainsi, dans le partial _filters.php, qui a déjà accès à une instance de la classe bookmarkGeneratorConfiguration, nous sommes maintenant capables d'afficher en boucle les filtres sauvegardés que nous avons récupéré afin d'en afficher la liste :
// in apps/backend/modules/bookmark/templates/_filters.php from line 11
[...]
<tr>
<td colspan="2">
<h3><?php echo __('Saved filters') ?><h3>
<?php if (count($savedFilters = $configuration->getSavedFilters())): ?>
<ul>
<?php foreach ($savedFilters as $filter): ?>
<li>
<a href="<?php echo url_for('@bookmark_filter_load?id='.$filter['id']) ?>">
<?php echo $filter['name'] ?>
</a>
(<a href="<?php echo url_for('@bookmark_filter_delete?id='.$filter['id']) ?>"></a>)
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>No filters saved</p>
<?php endif; ?>
</td>
</tr>
</tbody>
Maintenant vous êtes donc capable de sauvegarder en base et de lister des filtres, les charger et les faire fonctionner sur votre liste d'objets, et bien entendu, supprimer les filtres existant. Si vous avez suivi méticuleusement les étapes de ce tutoriel, vous devriez voir quelque chose comme cela sous le formulaire de filtres :
20 minutes, le boulot est fait. Même si ce fût rapide et même un peu trop parfois.
Conclusion
Oui, je peux vous entendre, vous les Symfony nerds : on peut faire vraiment mieux, mieux écrit, mieux inclus dans la structure de Symfony, et probablement abstrait pour offrir une solution générique de stockage de filtres à travers l'ensemble des modules admin-generated... mais en 20 minutes ? Vraiment ? ;c) Mais alors je dirais :
- Allez-y, prouvez le !! :c)
Références
Ceci est une traduction libre de l'article datant de 2009 de NiKo sur son blog Prendre Un Café. Merci à lui pour l'original : http://prendreuncafe.com/blog/post/2009/12/02/Saving-Search-Filters-in-Symfony-s-Doctrine-Admin-Generator
[Catégorie:Informatique]

