3.7.4 Sauvegarder vos données
CakePHP rend la sauvegarde des données d’un modèle très rapide. Les données prêtes à être sauvegardées doivent être passées à la méthode save() du modèle en utilisant le format basique suivant :
Array
(
[NomDuModele] => Array
(
[nomduchamp1] => 'valeur'
[nomduchamp2] => 'valeur'
)
)
Array([NomDuModele] => Array([nomduchamp1] => 'valeur'[nomduchamp2] => 'valeur'))
La plupart du temps vous n’aurez même pas à vous préoccuper de ce format : le HtmlHelper, FormHelper et les méthodes de recherche de CakePHP réunissent les données sous cette forme. Si vous utilisez un de ces helpers, les données sont également disponibles dans $this->data pour un usage rapide et pratique.
Voici un exemple simple d’une action de contrôleur qui utilise un modèle CakePHP pour sauvegarder les données dans une table de la base de données :
function modifier($id) {
//Est-ce que des données de formulaires ont été POSTées ?
if(!empty($this->data)) {
//Si les données du formulaire peuvent être validées et sauvegardées ...
if($this->Recette->save($this->data['Recette'])) {
//On définit une message flash en session et on redirige.
$this->Session->setFlash("Recette sauvegardée !");
$this->redirect('/recettes');
exit(0);
}
}
//Si aucune données de formulaire, on récupère la recette à éditer
//et on la passe à la vue
$this->set('recette', $this->Recette->findById($id));
}
function modifier($id) {//Est-ce que des données de formulaires ont été POSTées ?if(!empty($this->data)) {//Si les données du formulaire peuvent être validées et sauvegardées ...if($this->Recette->save($this->data['Recette'])) {//On définit une message flash en session et on redirige.$this->Session->setFlash("Recette sauvegardée !");$this->redirect('/recettes');exit(0);}}//Si aucune données de formulaire, on récupère la recette à éditer//et on la passe à la vue$this->set('recette', $this->Recette->findById($id));}
Note additionnelle : quand save() est appelée, la donnée qui lui est passée en premier paramètre est validée en utilisant le mécanisme de validation de CakePHP (voir le chapitre Validation des Données pour plus d’informations). Si pour une raison quelconque vos données ne se sauvegardent pas, pensez à regarder si des règles de validation ne sont pas insatisfaites.
Il y a quelques autres méthodes du modèle liées à la sauvegarde que vous trouverez utiles :
La méthode ci-dessus sauvegarde des données formatées sous forme tabulaire. Le second paramètre vous permet de mettre de côté la validation, et le troisième vous permet de fournir une liste des champs du modèle devant être sauvegardés. Pour une sécurité accrue, vous pouvez limiter les champs sauvegardés à ceux listés dans $listeDesChamps.
Une fois qu’une sauvegarde a été effectuée, l’ID de l’objet peut-être trouvé dans l’attribut $id de l’objet modèle – ceci est particulièrement pratique lorsque l’on crée de nouveaux objets.
$this->Ingredient->save($nouvelleDonnees); $idDuNouvelIngredient = $this->Ingredient->id;
$this->Ingredient->save($nouvelleDonnees);$idDuNouvelIngredient = $this->Ingredient->id;
Cette méthode initialise la classe du modèle pour sauvegarder de nouvelles informations. Si vous allez appeler save() à l’intérieur d’une boucle (pour créer plusieurs enregistrements à la fois), assurez-vous d’appeler create() juste avant save().
Si vous renseignez le paramètre $data (en utilisant le format de tableau mentionné plus haut), le nouveau modèle créé sera prêt à être sauvegardé avec ces données (accessibles à $this->data).
Utilisé pour sauvegarder la valeur d’un seul champ. Fixez l’ID du modèle ($this->NomDuModele->id = $id) juste avant d’appeler saveField().
Met à jour plusieurs enregistrements en un seul appel. Les enregistrements à mettre à jour sont identifiés par le tableau $conditions, et les champs devant être mis à jour, ainsi que leurs valeurs, sont identifiés par le tableau $champs.
Par exemple, si je voulais approuvais tous les utilisateurs qui sont membres depuis plus d’un an, l’appel à update devrait ressembler à quelque chose du style :
$cette_annee = date('Y-m-d h:i:s', strtotime('-1 year'));
$this->Utilisateur->updateAll(
array('Utilisateur.created' => "<= $cette_annee"),
array('Utilisateur.approuve' => true)
);
$cette_annee = date('Y-m-d h:i:s', strtotime('-1 year'));$this->Utilisateur->updateAll(array('Utilisateur.created' => "<= $cette_annee"),array('Utilisateur.approuve' => true));
Efface les enregistrements identifies par $id. Par défaut, supprime aussi les enregistrements dépendants de l’enregistrement devant être supprimé.
Par exemple, lorsque l’on supprime un enregistrement Utilisateur qui est rattaché à plusieurs enregistrements Recettes :
- Si $cascade vaut true, les enregistrements Recette liés sont aussi supprimés.
- Si $cascade vaut false, les enregistrements Recette resterons une fois que l’Utilisateur aura été supprimé.
Identique à del() et remove(), excepté que deleteAll() efface tous les enregistrements qui correspondent aux conditions fournies. Le tableau $conditions doit être fourni comme une portion SQL ou un tableau.
3.7.4.1 Sauvegarder les données des modèles liés (hasOne, hasMany, belongsTo)
Quand on travaille avec des modèles associés, il est important de réaliser que sauvegarder les données d'un modèle doit toujours se faire depuis le modèle CakePHP correspondant. Si vous sauvegardez un nouveau Post et ses Commentaires associés, vous devrez alors utiliser à la fois les modèles Post et Commentaire durant l'opération de sauvegarde.
Si aucun enregistrement des modèles associés n'existe dans le système à ce moment là (par exemple si vous souhaitez sauvegarder un nouvel Utilisateur et ses enregistrements de Profil liés en même temps), vous devrez d'abord sauvegarder le modèle primaire (ou parent).
Pour avoir une idée de comment cela fonctionne, imaginons que nous ayons une action dans notre contrôleur UtilisateurController qui permette de sauvegarder un nouvel Utilisateur et un Profil lié. L'exemple d'action ci-dessous supposera que vous ayez POSTé suffisamment de données (en utilisant le FormHelper) pour créer un Utilisateur et un Profil.
<?php
function add() {
if (!empty($this->data)) {
// On peut sauvegarder les données Utilisateur
// elles devraient être dans $this->data['Utilisateur']
$this->Utilisateur->save($this->data);
// Maintenant ajouton cette information aux données à sauvegarder
// et sauvegardons le Profil
// L'ID de l'Utilisateur nouvellement créé a été stockée dans
// $this->User->id.
$this->data['Profil']['utilisateur_id'] = $this->Utilisateur->id;
// Car Utilisateur hasOne Profil, nous pouvons accéder
// au modèle Profil à travers le modèle Utilisateur :
$this->Utilisateur->Profil->save($this->data);
}
}
?>
<?phpfunction add() {if (!empty($this->data)) {// On peut sauvegarder les données Utilisateur// elles devraient être dans $this->data['Utilisateur']$this->Utilisateur->save($this->data);// Maintenant ajouton cette information aux données à sauvegarder// et sauvegardons le Profil// L'ID de l'Utilisateur nouvellement créé a été stockée dans// $this->User->id.$this->data['Profil']['utilisateur_id'] = $this->Utilisateur->id;// Car Utilisateur hasOne Profil, nous pouvons accéder// au modèle Profil à travers le modèle Utilisateur :$this->Utilisateur->Profil->save($this->data);}}?>
Une règle lorsque l'on travaille avec les associations hasOne, hasMany et belongsTo : tout n'est que manipulation de clés. L'idée de base est de prendre la clé d'un modèle et de la placer dans le champ de clé étrangère de l'autre. Quelquefois, cela peut impliquer l'utilisation de l'attribut $id de la classe de modèle après une sauvegarde (save()), mais dans d'autres cas cela peut simplement être la récupération d'un ID depuis le champ caché du formulaire qui a été POSTé vers une action de contrôleur.
3.7.4.1.1 counterCache - Mettre en cache les "count()"
Cette fonction vous aide à garder le compte du nombre de données reliées. Au lieu de compter en effectuant un SELECT (i.e en utilisant find('count')), le modèle repère lui-même tous les ajouts/suppressions qui ont lieu pour un modèle référencé dans $hasMany et incrémente/décrémente un champ entier dans sa table (table du modèle parent).
Le nom de ce champ est le nom au singulier du nom du modèle suivi d'un underscore et du mot "counter".
Imaginons que vous ayez un modèle nommé "AlbumDimage" et un modèle nommé "Image", vous devriez ajouter un champ de type "INT" à la table "album_dimage" et le nommer "image_count". Si vos noms sont plus complexes, voici un autre exemple : Avec "MessageBlog" et "CommentaireMessageBlog", le nom du champ serait "commentaire_message_blog_count" et devrait être ajouté à la table "message_blogs".
Une fois que vous avez ajouté le champ de compteur vous pouvez activer cette fonctionnalité en ajoutant la clé "counterCache" au tableau d'association "$belongsTo" et fixer sa valeur à "true".
class AlbumDimage extends AppModel {
var $hasMany = array(
'Image'
)
}
class Image extends AppModel {
var $belongsTo = array(
'AlbumDimage' => array('counterCache' => true);
)
}
class AlbumDimage extends AppModel {var $hasMany = array('Image')}class Image extends AppModel {var $belongsTo = array('AlbumDimage' => array('counterCache' => true);)}
Maintenant, à chaque fois que vous ajouterez une nouvelle "Image" à "AlbumDimage", le nombre contenu dans "image_count" augmentera (ou diminuera si vous effectuez une suppression).
3.7.4.2 Sauvegarder les données des modèles liés (HABTM)
Sauvegarder des modèles qui sont associés par un hasOne, belongsTo et hasMany est relativement simple : vous n'avez qu'à renseigner la clé étrangère avec l'ID du modèle associé. Une fois que ceci est fait, il vous suffit d'appeler la méthode save() sur le modèle et tout se reliera correctement.
Avec les relations HABTM, vous devez fixer l'ID du modèle associé dans votre tableau de données. Nous allons construire un formulaire qui crée un nouveau tag et l'associe à la volée à une recette.
Le formulaire le plus simpliste ressemblerait à quelque chose comme ceci (nous supposerons que $recette_id contient déjà une valeur) :
<?php echo $form->create('Tag');?>
<?php echo $form->input(
'Recette.id',
array('type'=>'hidden', 'value' => $recette_id)); ?>
<?php echo $form->input('Tag.nom'); ?>
<?php echo $form->end('Ajouter le tag'); ?>
<?php echo $form->create('Tag');?><?php echo $form->input('Recette.id',array('type'=>'hidden', 'value' => $recette_id)); ?><?php echo $form->input('Tag.nom'); ?><?php echo $form->end('Ajouter le tag'); ?>
Dans cet exemple, vous pouvez remarquer le champ caché "Recette.id" dont la valeur est l'ID de la recette à laquelle nous voulons relier le tag. L'action du contrôleur qui se charge de sauvegarder le formulaire est très simple :
function add() {
// Sauvegarde l'association
if ($this->Tag->save($this->data)) {
// Faire quelque chose en cas d'enregistrement réussi
}
}
function add() {// Sauvegarde l'associationif ($this->Tag->save($this->data)) {// Faire quelque chose en cas d'enregistrement réussi}}
De cette manière, notre nouveau Tag est créé et associé avec une Recette, dont l'ID était défini dans $this->data['Recette']['id'].
