Bonjour à tous,
Je suis le super tutoriel "créer un site de A à Z" et j'ai un petit soucis lors de la modification d'un post.
Quand j'édite un post, les données s'enregistrent dans deux tables différentes (post et post_traduction car je fais un site multilingue).Le problème est que quand je veux modifier un post ou ajouter un nouveau post (avec la technique du online = -1), ça me fait toujours un INSERT et jamais un UPDATE.
Voici mon action admin_edit() du fichier PostsController.php
function admin_edit($id = null){
$this->loadModel('Post');
$this->loadModel('Post_traduction');
if($id === null){
$post= $this->Post->findFirst(array(
'conditions' => array('online' => -1)
));
if(!empty($post)){
$id = $post->id_post;
}else{
$this->Post->save(array(
'online' => -1
));
$id = $this->Post->id_post;
}
}
$d'id'] = $id;
if($this->request->data){
if($this->Post->validates($this->request->data)){
$this->Post->save(array(
'id_post' => $d'id'],
'dateCreer' => date('Y-m-d H:i:s'),
'online' => $this->request->data->online,
'type' => 'post'
));
$this->Post_traduction->save(array(
'langue_code' => 'FR',
'post_id' => $this->Article->id,
'nom' => $this->request->data->nom,
'description' => $this->request->data->description,
'slug' => $this->request->data->slug
));
$this->Session->setFlash('Le contenu a bien été modifié');
//$this->redirect('admin/posts/index');
}else{
$this->Session->setFlash('Merci de corriger vos informations','danger in fade');
}
}else{
$this->request->data = $this->Post->findFirst(array(
'join' => array('post_traduction' => 'id_post = post_id'),
'conditions' => array('id_post' => $id)
));
}
$this->set($d);
}
La fonction save() du fichier model.php est le même que celui du tutoriel.
Voici la partie du code au ca coince, la condition isset($data->$key) && !empty($data->$key) n'est pas vrai donc pas d'update :
public function save($data){
$key = $this->primaryKey; //id_post
$fields = array();
$d = array();
foreach($data as $k => $v){
if($k != $this->primaryKey){
$fields] = "$k=:$k";
$d":$k"] = $v;
}elseif(!empty($v)){
$d":$k"] = $v;
}
}
if(isset($data->$key) && !empty($data->$key)){
$sql = 'UPDATE '.$this->table.' SET '.implode(',',$fields).' WHERE '.$key.'=:'.$key;
$this->id = $data->$key;
$action = 'update';
}else{
$sql = 'INSERT INTO '.$this->table.' SET '.implode(',',$fields);
$action = 'insert';
}
debug($sql); die();
$pre = $this->db->prepare($sql);
$pre->execute($d);
if($action == 'insert'){
$this->id = $this->db->lastInsertId();
}
}
Merci pour votre aide ;-)
bonjour
ton problème est typique de l'id ne correspondant pas au PrimaryKey.
pour que l'update soit possible, il faut que:
$data->$key = $this->primaryKey
en parcourant ton code, plusieurs interrogations surgissent:
as-tu penser à rendre dynamique la valeur de $this->PrimaryKey vu que tu as modifié la structure des noms de champs (id_post par exple) dans les tables? si non, vu que la valeur initiale de $PrimaryKey est 'id', tu devrais mettre ceci dans le constructeur de ta classe modele:
$this->PrimaryKey = $this->PrimaryKey.'_'.rtrim(strtolower(trim(getclass($this))),'s');
ou
$this->PrimaryKey = $this->PrimaryKey.''.rtrim($this->table,'s');
à condition que $this->table soit déja defini
comment utilises tu les jointures s'il n'ya aucune trace de celles-ci dans ta methode save?
je confirme qu'il est bien possible de faire des jointures lors de l'update;
exemple:
UPDATE photo
JOIN article_photo ON article_photo.photo = photo.id
JOIN article ON article.id = article_photo.article
SET photo.title = article.title
WHERE photo.title IS NULL OR photo.title = ''
seulement tu dois modifier la methode save() en conséquence.
je te conseille ce topic où je fais la meme chose avec la methode find():
http://www.grafikart.fr/forum/topic/5960
çà peut etre un bon point de depart pour cette modification.
quand tu initialises $primaryKey = 'id_post'; cela signifie que dans toutes les tables de ta bdd la clé primaire doit avoir comme nom 'id_post' ce qui n'est pas logique vu que 'post' fait reference au nom de la table 'posts'.
il n'est pas possible d'utiliser la commande join en elle même mais avec les sous requete oui:
INSERT INTO t_tabl(col_list)
SELECT col_list
FROM t_table2
[WHERE Expr]
[ORDER BY Expr [ASC|DESC]]
[LIMIT X [OFFSET Y]];
mais dans le cadre de ce tuto elles ne sont pas prises en charge. necessite don des adaptations.
vu que le tuto utilise la PDO je te conseille de te servir de $this->db->lastInsertId() (donc pluisieurs requete)
car contrairement au select, c'est pas tous les jours qu'on fait des insert de contenus sur un site. donc pas de reelle conséquence niveau performance.
Bonsoir.
Un conseil, regardes à nouveau le tutoriel vidéo et revois toute la fonction car il y a trop d'erreurs pour te les citer et te donner toute la correction ne t'aiderais pas.
Juste pour te mettre sur la voie, tu fais des save en dehors et d'autres à l'intérieur des vérifications de l'existence des données par requête.
Après il y a d'autres trucs, mais comme je te l'ai dit, je ne te les citerait pas.
Merci Lartak11 pour ta réponse et de m'avoir aiguillé ;-)
Je vais repasser en revu tout le code.
Bonjour Iriven,
Merci de tes réponses et questions.
J'ai initialisé ma variable $primaryKey = 'id_post'; mais c'est vrai que la rendre dynamique comme tu l'as soulignés serait plus logique vu mon cas, j'ai pense a faire comme toi (deuxième solution avec $this->table) pour dynamiser la valeur de $primaryKey.
Pour les jointures, c'est la que je cale un peu car apres m'etre renseigner sur google et avoir lu différentes réponses sur le sujet, il n'est pas possible de faire des jointures dans un UPDATE ou un INSERT donc c'est pour cela que je fais un save dans ma 1ere table 'Post' puis un autre save dans ma table 'Post_traduction'. Je ne sais pas si c'est la meilleure solution pour insérer des données dans deux tables différents.
J'ai lu aussi qu'on peut mettre en place un TRIGGER mais n'étant pas expert la dessus, j'ai opté pour une manière simple.
Merci pour vos idées et solutions en tout cas ;-)
Effectivement, je viens de le lire dans cette article : ICI pour les jointures lors de l'UPDATE.
Très bon topic qui va bien m'aider (merci Iriven) mais concernant l'INSERT, les jointures ne fonctionnent pas ou c'est possible?
Oui comme tu me le dis, je dois initialisé $primaryKey pas avec 'id_post' sinon c'est pas logique mais de manière dynamique tel que tu me l'as expliqué plus haut ($this->PrimaryKey = $this->PrimaryKey.'_'.rtrim($this->table,'s'); ), c'est plus logique et ca fonctionnera déjà mieux ;-)
Je vais modifier ma méthode save() pour y ajouter les jointures lors de l'UPDATE .
Ok ok, merci pour tes précieux conseils iriven!
Ca m'aide beaucoup et je vais pouvoir continue à mener à bien ce super tuto que nous offre grafikart :-)