Utiliser le contrôle admin_double_list dans vos formulaires Symfony
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.
Ce guide est testé sur:
- Symfony 1.0
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.