Outils personnels
Vous êtes ici : Accueil Symfony Symfony 1.0 Utiliser le contrôle admin_double_list dans vos formulaires Symfony
Actions sur le document
  • Send this page to somebody
  • Print this page
  • Add Bookmarklet

Utiliser le contrôle admin_double_list dans vos formulaires Symfony

Par Pierre-Yves Landuré - Dernière modification 28/10/2008 09:38

Le contrôle admin_double_list est un champ normallement réservé à l'admin generator de Symfony. Ce champ permet de gérer de manière élégante les relations N:N. Cet article décrit comment l'utiliser dans vos formulaires hors de l'admin generator.

Dans cet article, nous établissons une relation N:N entre une table User et une table Group.

Schéma de base de données

Pour notre relation N:N, il faut une table reliant  la table User et la table Group. Nous nommons cette table UserGroup.

Syntaxe XML

Si vous utilisez le XML pour décrire votre schéma (fichier schema.xml), voici un exemple de syntaxe :

<table name="user_group" phpName="UserGroup">
    <column name="user_id" type="INTEGER" primaryKey="true" />
    <foreign-key foreignTable="user" onDelete="cascade">
       <reference local="user_id" foreign="id" />
    </foreign-key>
    <column name="group_id" type="INTEGER" primaryKey="true" />
    <foreign-key foreignTable="group" onDelete="cascade">
       <reference local="group_id" foreign="id" />
    </foreign-key>
</table>

Formulaire

Deux élément sont à modifier dans le formulaire destiné à recevoir votre "admin_double_list".

Le helper ObjectAdmin

Pour pouvoir afficher un champ "admin_double_list", vous devez faire appel au helper ObjectAdmin dans votre formulaire :

<?php use_helper('ObjectAdmin'); ?>

La balise FORM

Votre balise FORM doit contenir deux éléments obligatoire pour que votre "admin_double_list" fonctionne et renvoie des valeurs. Ces éléments sont:

  • Un Id (par exemple: 'user-edit-form').
  • Un appel à la fonction Javascript 'double_list_submit' avec l'id du formulaire en argument (par exemple: double_list_submit('user-edit-form')).

Balise FORM standard

<?php echo form_tag('user/update', array(
      'onsubmit'    => "double_list_submit('user-edit-form'); return true;",
      'id'        => 'user-edit-form',
    )
) ?>

Balise FORM Ajax

Voici un exemple de balise FORM Ajax :

<?php echo form_remote_tag(array(
      'name'      => 'edit-form',
      'update'    => 'ajax-content',
      'url'       => 'user/update',
      'before'    => "double_list_submit('user-edit-form')",
    ), array(
      'id'        => 'user-edit-form',
    )
) ?>

Le champ admin_double_list

Pour afficher le champ admin_double_list dans votre formulaire, vous pouvez utiliser le code PHP suivant :

<?php echo object_admin_double_list($user, 'getUserGroups', array(
'through_class' => 'UserGroup',
'associated' => 'groups',
'unassociated' => 'not_groups',
'associated_label' => __('Member of'),
'unassociated_label' => __('Not member of'),
)) ?>

Remarque: les classes CSS des select 'associated' et 'unassociated' sont respectivement 'sf_admin_multiple-selected' et 'sf_admin_multiple'.

Le champ admin_check_list

Pour afficher le champ admin_check_list dans votre formulaire, vous pouvez utiliser le code PHP suivant :

<?php echo object_admin_check_list($user, 'getUserGroups', array(
'through_class' => 'UserGroup',
'associated' => 'groups',
)) ?>

L'action

Dans l'action update utilisée pour sauvegarder le formulaire, vous pouvez utiliser le code suivant pour sauvegarder les saisies obtenues à l'aide de votre champ admin_double_list :

// Fetching admin_double_list values
$group_ids = $this->getRequestParameter('associated_user_groups[]', array());

// Deleting removed Groups if it is not a new object.
if($user->getId())
{
$criteria = new Criteria();
$criteria->add(UserGroupPeer::USER_ID, $user->getId(), Criteria::EQUAL);
$criteria->add(UserGroupPeer::GROUP_ID, $group_ids, Criteria::NOT_IN);
UserGroupPeer::doDelete($criteria);
}

// Fetch groups that are not already associated to the user.
$criteria = new Criteria();
$criterion = $criteria->getNewCriterion(GroupPeer::ID, $group_ids, Criteria::IN);
$sql_query = sprintf('%s NOT IN (SELECT %s FROM %s WHERE %s = %d)', GroupPeer::ID,
UserGroupPeer::GROUP_ID, UserGroupPeer::TABLE_NAME,
UserGroupPeer::USER_ID, $user->getId());
$criterion->addAnd($criteria->getNewCriterion(GroupPeer::ID, $sql_query, Criteria::CUSTOM));
$criteria->add($criterion);
$groups = GroupPeer::doSelect($criteria);

// We create the new UserGroup associations.
foreach($groups as $group)
{
$user_group = new UserGroup();
$user_group->setGroupId($group->getId());

// This is a little trick for Symfony to do all the saving in one time.
$user->addUserGroup($user_group);
}

// Save $user object and new UserGroup objects.
$user->save();

Remerciements

  • Merci à Fabien Tillon qui a effectué la majeur partie du travail de documentation pour cet article.
  • Merci aux développeurs de Symfony pour leur superbe travail.

Erreur lors de la mise en place

Posté par Toma le 23/01/2009 10:08
Bonjour,

je souhaite mettre en place ce système tres pratique du coté admin...
Or j'ai le soucis suivant lorsque je test votre technique:
Class 'Peer' not found in \lib\symfony\addon\propel\sfPropelManyToMany.class.php
J'utilise symfony 1.0.16
Pouvez-vous m'aider?
merci.

pas vraiment mais....

Posté par lwolf le 23/01/2009 17:01
Si vous utilisez l'admin-generator de symfony, ce champs est très facile à mettre en place. Il s'agit d'un type de champs documenté dans le livre symfony (je ne sais plus son nom).

Cet article ne concerne que la mise en place de ce champs dans un module modifié "à la main". Votre erreur me fait penser un une erreur de nommage de classe. La classe "Peer" ne peut exiter. On trouve le plus souvent des classes "TablePeer" qui accompagnent les classes "Table".

Je ne peut vous aider plus.

Bon courrage


Réalisé avec Plone

Ce site respecte les normes suivantes :

Wikio