Salut à toutes et à tous, j'essaie de créer un système de proposition commerciale avec CMS.
Le sujet est un peu long mais c'est uniquement parce que j'ai voulu vous donner toutes les sources où il n'y qu'une seule part qui ne fonctionne pas au niveau du controller.
J'ai créé le système de façon à remplir les tables en 2 fois. Dans une première page step 1, j'ai créé une nouvelle proposition avec un formulaire qui remplit à la fois la table proposals et clients grâce à leur association. En seconde page, j'ai créé un formulaire qui remplit un premier produit avec ses specifications et ses annexes. Ces champs specifications et annexes sont chacun dans une boucle car un produit hasMany specifications et appendices. Une fois cette step 2 complétés, soit je termine soit je regénère la page pour entrer un autre produit avec specs et annexes.
Pour la page step1, pas de soucis les données sont enregistrer dans les 2 tables proposals et clients en une fois grâce à leur liaison. Par contre arrivé en step 2, ça n'enregistre pas et c'est là où je m'arrache es cheveux à comprendre pourquoi. J'ai eu beau passé des heures ur le book de cakephp et forums, ça n'a fait que m'embrouiller davantage. Maintenant ça bloque au niveau de mon array $success dans le controller. Apparemment la condition if($this->product->save($success)) ne fonctionne pas et passe sur le else pour m'afficher mon erreur.
Si quelqu'un arrive à me pointer l'erreur je lui serait vraiment reconnaissant parce que je complètement coincé. Désolé encore pour la longueur du topic mais j'ai trouvé plus logique de vous donner les sources comme ça la recherche peut être "simplifiée".
Je vous remercie d'avance pour vos lumières!
Bien cordialement,
Julian.
Mon système possède 5 tables avec les associations suivantes :
Les models pour chaque table sont les suivants :
Proposal.php:
<?php
class Proposal extends AppModel {
public $actsAs = array('Containable');
public $validate = array(
'name' => array(
'rule' => 'notEmpty',
'message' => "Veuillez préciser un titre"
)
) ;
public $hasOne = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'proposal_id',
'dependent' => true
)
);
}
Client.php:
<?php
class Client extends AppModel {
public $actsAs = array('Containable');
public $belongsTo = array(
'Proposal' => array(
'className' => 'Proposal',
'foreignKey' => 'proposal_id'
)
);
public $hasMany = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'client_id',
'conditions' => '',
'order' => '',
'limit' => '',
'dependent' => true
)
);
}
Product.php:
<?php
class Product extends AppModel {
public $actsAs = array('Containable');
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id'
)
);
public $hasMany = array(
'Specification' => array(
'className' => 'Specification',
'foreignKey' => 'product_id',
'conditions' => '',
'order' => '',
'limit' => '',
'dependent' => true
),
'Appendice' => array(
'className' => 'Appendice',
'foreignKey' => 'product_id',
'conditions' => '',
'order' => '',
'limit' => '',
'dependent' => true
)
);
}
Specification.php:
<?php
class Specification extends AppModel {
public $actsAs = array('Containable');
public $belongsTo = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id'
)
);
}
Appendice.php:
<?php
class Appendice extends AppModel {
public $actsAs = array('Containable');
public $belongsTo = array(
'ProductAppend' => array(
'className' => 'Product',
'foreignKey' => 'product_id'
)
);
}
Ensuite voici ProposalsController.php:
function admin_add_step1(){
if (!empty($this->request->data)) {
$proposal = $this->Proposal->save($this->request->data);
if (!empty($proposal)) {
$this->request->data'Client']'proposal_id'] = $this->Proposal->id;
$this->Proposal->Client->save($this->request->data);
$id = $this->Proposal->Client->getLastInsertId();
$this->redirect(array('action' => 'add_step2', $id));
// debug($this->request->data);
}
}
}
function admin_add_step2($id){
// debug($this->params'pass']);
$this->loadModel('Product');
$this->loadModel('Client');
if ($this->request->is('post')) {
if (!empty($this->request->data)) {
$data = $this->request->data'Product'][0];
$success = array(
'Product.0.name' => $data'name'],
'Product.0.reference' => $data'reference'],
'Product.0.image' => $data'image'],
'Product.0.pu' => $data'pu'],
'Product.0.quantity' => $data'quantity'],
'Product.0.ce' => $data'ce'],
'Product.0.nf' => $data'nf'],
'Product.0.rohs' => $data'rohs'],
'Product.0.client_id' => $id
);
}
if($this->Client->Product->save($success)){
$this->redirect(array('action' => 'admin_index'));
debug($this->request->data);
debug($id);
}
else{
echo 'The save failed';
debug($success);
debug($this->request->data);
}
}
}
Puis la vue admin_add_step1.ctp :
<?php
echo $this->Form->create('proposal');
?>
<hr/>
<h1>Proposition</h1>
<hr/>
<?php
echo $this->Form->input('Proposal.name', array('label' => "Nom de la proposition"));
echo $this->Form->input('Proposal.created', array('label' => "Date de création"));
echo $this->Form->input('Proposal.due', array('label' => "Date d'échéance"));
echo $this->Form->input('Proposal.content', array('label' => "Termes & conditions"));
?>
<hr/>
<h1>Client</h1>
<hr/>
<?php
echo $this->Form->input('Client.name', array('label' => "Nom du client"));
echo $this->Form->input('Client.project', array('label' => "Nom du projet"));
echo $this->Form->input('Client.address', array('label' => "Adresse"));
echo $this->Form->input('Client.phone', array('label' => "Téléphone"));
echo $this->Form->input('Client.email', array('label' => "Email"));
?>
<?php echo $this->Form->end('suivant'); ?>
Enfin la vue admin_add_step2.ctp :
<?php
echo $this->Form->create('product');
?>
<hr/>
<h1>Produits</h1>
<hr/>
<?php
echo $this->Form->input('Product.0.name', array('label' => "Nom du produit"));
echo $this->Form->input('Product.0.reference', array('label' => "Référence"));
echo $this->Form->input('Product.0.image', array('label' => "Image"));
echo $this->Form->input('Product.0.pu', array('label' => "Prix Unitaire"));
echo $this->Form->input('Product.0.quantity', array('label' => "Quantité"));
echo $this->Form->input('Product.0.ce', array('label' => "CE"));
echo $this->Form->input('Product.0.rohs', array('label' => "RoHS"));
echo $this->Form->input('Product.0.nf', array('label' => "NF"));
echo $this->Form->hidden('Product.0.client_id');
?>
<hr/>
<h1>Spécifications :</h1>
<hr/>
<?php
// foreach (range(0,1) as $i):
// $a=$i+1;
// echo '<p>Spécification '.$a.'</p>';
// echo $this->Form->input('Specification.'.$i.'.name', array('label' => "Nom de la spécification"));
// echo $this->Form->input('Specification.'.$i.'.value', array('label' => "Valeur de la spécification"));
// endforeach;
?>
<hr/>
<h1>Annexes :</h1>
<hr/>
<?php
// foreach (range(0,1) as $j):
// $b=$j+1;
// echo '<p>Annexe '.$b.'</p>';
// echo $this->Form->input('Appendice.'.$j.'.name', array('label' => "Image"));
// echo $this->Form->input('Appendice.'.$j.'.content', array('label' => "Description de l'annexe"));
// endforeach;
?>
<?php echo $this->Form->end('valider'); ?>
Merci encore pour votre aide!
hehe on va y arriver :)
voici le résultat de debug ($success); :
array(
'Product.name' => 'Produit 3',
'Product.reference' => 'Référence Produit 3',
'Product.image' => 'Image Produit 3',
'Product.pu' => '100.77',
'Product.quantity' => '500',
'Product.ce' => '1',
'Product.nf' => '0',
'Product.rohs' => '0',
(int) 56 => ''
)
Jusque là ça à l'air d'aller non?
J'aimerais bien voir le résultat de cette valeur :
echo $this->Form->hidden('Product.0.client_id');
après j'aimerais bien comprendre...
Product.0.client_id va remplir l'id de product ? l'id product n'est pas en auto-incrément ?
Donc un produit est unique à un client ? Un autre client ne peut pas avoir le même produit ? J'aurais fais la création de produit séparément pour ensuite le choisir via un ascenseur...
Peut être que j'ai rien compris (au vu de tout ce qu'il fallait lire... moi qui suis extérieur à ton projet, c'est assez chaud de tout assimiler :p )
++
Je pense que tu prends la problématique à l'envers :s
Merci coloo, en effet ça fait un long post :)
Product.0.client_id va remplir la clé étrangère de la table products. Son id est bien auto-enregistré en AI.
Normalement je n'ai pas besoin de le renseigner sachant que j'ai suivis les conventions de cake et qu'avec mes associations des models il s'en charge automatiquement.
Un Produit est bien unique à un Client et sont associés par Product hasMany Client & Client belongs to Product.
Pour éviter d'avoir à faire une liste déroulante en ajoutant un nouveau produit, je fais passer l'id de client dans $params'pass']. Du coup le produit est censé s'enregistrer avec l'id client passé dans la colonne client_id qui est la FK de products.
Je vois vraiment pas pourquoi ça fonctionne pas dans la page step 2. Je récupère bien l'id du client du formulaire de la page 1, mon array $this->request->data est correctement complété avec les données enregistré depuis le form. Il y a quelque chose qui cloche quand le script arrive à la condition if($this->save->('Product')){echo 'succès';}else{echo 'erreur';} parce qu'il bascule sur le else. C'est ce que je n'arrive pas à comprendre. La sauvegarde devrait normalement se faire...
Merci à toi pour ton intérêt!
je comprends pas cette ligne en fait :
'Product.0.client_id' => $id
ça serais pas plutôt :
$id => $data'client_id']
Tu peux faire un debug de "$this->Client->Product->save($success)"
Je pense que tu as raison pour
$id => $data'client_id']
, ça n'a pas de sens que je mette Product.0.client_id sachant que ce champs n'existe pas, j'ai fais une erreur d'inversion. Merci pour cette correction, je n'y aurais jamais fais attention!
Comme tu me l'as demandé, j'ai fais le debug de
$this->Client->Product->save($success)
avant et après correction de la ligne pour $id et j'ai un false. Ca veut dire quoi?
euh pardon. J'imagine que ton save ne s'effectue pas (mais ça nous fait pas avancer :p...
debug ($success);
Il nous manque notre product id et notre foreign_key
dans ton form il te faut :
<?php echo $this->Form->hidden('Product.0.id');?>
il te faut changer cette ligne
(int) 56 => ''
en
Product.client_id => '56'
Si j'ai bien compris ?
Toujours rien, voici les modifs peut être que j'ai mal compris :
ProposalsController.php :
function admin_add_step2($id){
// debug($this->params'pass']);
$this->loadModel('Product');
$this->loadModel('Client');
if ($this->request->is('post')) {
if (!empty($this->request->data)) {
$data = $this->request->data'Product'];
$success = array(
'Product.name' => $data'name'],
'Product.reference' => $data'reference'],
'Product.image' => $data'image'],
'Product.pu' => $data'pu'],
'Product.quantity' => $data'quantity'],
'Product.ce' => $data'ce'],
'Product.nf' => $data'nf'],
'Product.rohs' => $data'rohs'],
'Product.client_id' => 56 // J'ai comenté la ligne en dessous mais 56 = $id, l'id que je fais passer en param
// 'Product.client_id' => $id
);
}
if($this->Product->save($success)){
$this->redirect(array('action' => 'admin_index'));
}else{
echo 'The save failed';
debug($success);
debug($this->request->data);
}
debug($success);
}
Et sa vue admin_add_step2.ctp :
<?php
echo $this->Form->create('product');
?>
<hr/>
<h1>Produits</h1>
<hr/>
<?php
echo $this->Form->input('Product.name', array('label' => "Nom du produit"));
echo $this->Form->input('Product.reference', array('label' => "Référence"));
echo $this->Form->input('Product.image', array('label' => "Image"));
echo $this->Form->input('Product.pu', array('label' => "Prix Unitaire"));
echo $this->Form->input('Product.quantity', array('label' => "Quantité"));
echo $this->Form->input('Product.ce', array('label' => "CE"));
echo $this->Form->input('Product.rohs', array('label' => "RoHS"));
echo $this->Form->input('Product.nf', array('label' => "NF"));
echo $this->Form->hidden('Product.client_id');
echo $this->Form->hidden('Product.0.id'); // Rajout du champ pour l'id
?>
<?php echo $this->Form->end('valider'); ?>
J'ai commenté les 2 lignes modifiés, pour l'instant rien n'a changé. Normalement à ce stade ça devrait fonctionner il me semble. Est ce que tu penses que le problème pourrait venir d'ailleurs, les models par exemples, ou alors le manque d'un $this->loadModel() ou d'un contain?
Je sais pas vraiment où chercher, j'ai passé pas mal de temps à comprendre le book de cake mais mon cas est asser particulier pour le coup.
(*commence à avoir la tête qui chauffe*)
$this->Product->save($success)
Tu peux me montrer ton :
public $uses();
un screen de cette table sql
Put**, je me suis trompé...
'Product.client_id' => 56
remplacer par
'Product.client_id' => $data'client_id']
Remontre le debug après... Arretes de changer ton nommage à chaque fois, je me perds :P
Je sais que c'est un gros morceau si tu laisse tomber je comprendrais, c'est déjà beaucoup d'avoir essayer, merci à toi.
Voici le diagramme de mes tables avec leurs associations cake :
Diagramme tables
C'était ça que tu me demandais?
Par contre il est minuit chez moi en Chine :)
Donc je continuerais demain, tu peux faire tomber la température de ta tête ;) hehe
En tout cas vraiment merci de t'intéresser au sujet et de ton aide!
je demandais :
un screen de la table product phpmyadmin
le debug $success
de voir le public $uses de ton controller
Bonne nuit ;)
Bonjour Coloo
Voici le sreen de la table products :
Screen products table
Debug($success) :
array(
'Product.name' => 'Produit 3',
'Product.reference' => 'Référence Produit 3',
'Product.image' => 'Image Produit 3',
'Product.pu' => '10.7',
'Product.quantity' => '500',
'Product.ce' => '1',
'Product.nf' => '0',
'Product.rohs' => '0',
'Product.client_id' => (int) 56
)
Par contre je n'ai pas déclaré la fonction public $uses, ça pourrait venir de là donc?
Merci Coloo
$success = array(
Product => array(
'id' => $data'id'],
'name' => $data'name'],
'reference' => $data'reference'],
'image' => $data'image'],
'pu' => $data'pu'],
'quantity' => $data'quantity'],
'ce' => $data'ce'],
'nf' => $data'nf'],
'rohs' => $data'rohs'],
'client_id' => $id)
);
Hum il devrait pas y avoir de problème vu que tu charge tes modèles via load...
Salut Coloo,
Le browse n'est pas grisé parce que j'ai 2 entrées de produits:
id | name | reference | image | pu | quantity | ce | nf | rohs | client_id
7 | produit 1 | reference 1 | image 1 | 100.77 | 500 | 0 | 0 | 0 | 1
8 | produit 2 | reference 2 | image 2 | 50.79 | 1000 | 0 | 0 | 0 | 1
Ces 2 produits sont rattaché à un client dont l'id est le 1 qui lui même est rattché à une proposition.
Mais c'est juste pour des tests et ça ne devrit pas perturber l'insertion. Ma page step 1 fonctionne
correctement en enregistrant une nouvelle proposition et un nouveau client en même temps.
Mais la page step 2 ne fait toujours rien :(
Comme tu vois c'est une prise de tête et difficile de savoir où le problème se situe...
Désolé pour cette réponse tardive Coloo.
En changeant le tableau que tu m'as donné ça fonctionne!
Mais c'est pas un moyen détourné de faire l'insertion?
Cake devrait savoir que c'est le model Product utilisé et qu'il est lié à la table products.
Comment ça se fait?
En fait non, avec ton tableau, cake recherche dans la table product les entrée product.name, product.qty... En fait un simple save data serais suffisant si tu mettais dans ton formulaire que l'entrer client_id est égal à id comme je l'avais fait dans mon projet de crm :
<?php echo $this->Form->hidden('id');?>
<?php echo $this->Form->input('post_id',array('type'=>'hidden','value'=>$post'Post']'id']));?>
ce qui me donnait dans le controler juste :
if($this->Contact->save($this->data)){
$this->Session->setFlash('contact envoyé');
debug($this->data);
}
else{
$this->Session->setFlash('Commentaire error');
}
Après le $uses c'est si tes tables sont relier à la table du dit controller. Avec mes compétences je ne suis pas enmesure de te dire si tu aurais pu éviter de faire un load car j'en sais fichtrement rien (je suis un amateur avant tout :p ). Mais je pense que dans la logique c'est le chemin à optimiser...
En tout cas ton projet est très intéressant ;). J'aimerais bien voir le projet terminé pour voir la gueule qu'il a.
Bonne continuation
Ps : Si ton problème est résolu, tu peux valider la réponse qui t'a débloquer
++
Ok super je vais creuser ça davantage. Comme tu dis c'est un projet intéressant et j'ai placé la barre un peu haute.
Quoiqu'il en soit j'ai appris beaucoup et ça continu parce que qu'on a passé la barrière de la sauvegarde product, y'a d'autres champs dans cette même page qui vont remplir la table specifications qui contient les caractéristiques produits. Du coup il y a 2 champs et je vais devoir faire un système phpmyadmin pour pouvoir choisir combien de champs il y aura. En gros ces 2 champs seront généré avec une boucle qu'il faudra que je sauvegarde ensuite. J'ai pas fini lol :)
Je te montrerais tout ça bien volontier, c'est dommage qu'on puisse pas s'envoyer de MP. Tu veux faire comment pour que je te montre ça plus tard?
Oh c'est pas fini :p en même temps on me montre toujours les miettes :calimero:, dont c'est sur que si tu as une autre table à enregistrer sur cette page le save data est à proscrire :p
comment voir le projet $_$ :
mail : mail@mail.fr
Ok c'est bien reçu je t'ai envoyé un mail.
Oui j'ai 5 tables pour le système et 2 formualires qui se chargent de les remplir.
Un $this->save('associate') est nécessaire dans le cas de liaison. Donc je vais revenir sur le doc encore et encore!
Mais heureusement qu'on l'a ce book, c'est bien fourni comme le dit Jonathan.
Encore un grand merci à toi d'avoir eu le courage de te pencher sur le sujet! :)
A bientôt Coloo!