I'm trying to set up a commercial proposal system using CakePHP 2.3.
It has 5 tables which are associated (see details below). This system will have 1 page on which are 5 forms for each table. (see details below).
Form 1: table proposals
Form 2: table clients FK proposal_id
Form 3: table products FK client_id
Form 4: table specifications FK product_id (of the product)
Form 5: table appendices FK product_id (of the product)
WHERE:
proposals hasOne clients.
----------v----------
clients beongsTo proposals AND hasMany products.
----------v----------
products belongsTo clients AND hasMany specifications & appendices.
----------v----------
specifications belongsTo products.
appendices belongsTo products.
The form 4 can have multiple row so it's inside a foreach loop to generate more input. Same for the form 5. Because 1 product can have multiple specifications and appendices.
I admit, it's pretty tricky :)
This is the solution I finally chose, but maybe there is better. For exemple, I could make a multi-step form but it seems quite difficult to put in place. Anyway, i'm open to suggestion.
Meanwhile, I'm sure we can make this work so here are the details. For each table, I have created a model and made the appropriated connections. In each model I have enable the containable behaviour: public $actsAs = array('Containable');
.
Now here is the ProposalsController.php:
function admin_edit($id=null){
$this->loadModel('Proposal','Client','Product', 'Specification', 'Appendice');
$this->Proposal->contain('Proposal','Client','Product', 'Specification', 'Appendice');
if ($this->request->is('put') || $this->request->is('Post')) {
$data = $this->request->data;
if (!empty($data)) {
// Use the following to avoid validation errors:
// unset($this->Proposal->Client->validate['proposal_id']);
// $this->Proposal->saveAssociated($data);
// $this->Session->setFlash("Le contenu a bien été édité");
// $this->redirect(array('action' => 'index', $data['Product']['id']));
debug($data);
}
}
elseif($id){
$this->Proposal->id = $id;
$this->request->data = $this->Proposal->read(null,$id);
}
}
This edit action has many errors because I don't know how to set it up correctly in that case. So forgive me but I give you a raw code :). I would like this admin_function to add or edit, but again, in this case I don't know how to handle it.
And the view admin_edit.ctp :
<hr/>
<h1>Proposition</h1>
<hr/>
<?php echo $this->Form->create('Product'); ?>
<?php echo $this->Form->input('Proposal.name', array('label' => "Nom de la proposition")); ?>
<?php echo $this->Form->input('Proposal.created', array('label' => "Date de création")); ?>
<?php echo $this->Form->input('Proposal.due', array('label' => "Date d'échéance")); ?>
<?php 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")); ?>
<?php echo $this->Form->input('Client.project', array('label' => "Nom du projet")); ?>
<?php echo $this->Form->input('Client.address', array('label' => "Adresse")); ?>
<?php echo $this->Form->input('Client.phone', array('label' => "Téléphone")); ?>
<?php echo $this->Form->input('Client.email', array('label' => "Email")); ?>
<?php echo $this->Form->hidden('Client.proposal_id'); ?>
<hr/>
<h1>Produit</h1>
<hr/>
<?php echo $this->Form->input('Product.0.name', array('label' => "Nom du produit")); ?>
<?php echo $this->Form->input('Product.0.reference', array('label' => "Référence")); ?>
<?php echo $this->Form->input('Product.0.image', array('label' => "Image")); ?>
<?php echo $this->Form->input('Product.0.pu', array('label' => "Prix Unitaire")); ?>
<?php echo $this->Form->input('Product.0.quantity', array('label' => "Quantité")); ?>
<?php echo $this->Form->input('Product.0.ce', array('label' => "CE")); ?>
<?php echo $this->Form->input('Product.0.nf', array('label' => "NF")); ?>
<?php echo $this->Form->input('Product.0.rohs', array('label' => "RoHS")); ?>
<?php 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"));
echo $this->Form->hidden('Specification.'.$i.'.product_id');
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"));
echo $this->Form->hidden('Appendice.'.$j.'.product_id');
endforeach;
?>
<?php echo $this->Form->end('valider'); ?>
And finally, here is the array result of the debug($data):
array(
'Proposal' => array(
'name' => 'Proposition 3',
'created' => array(
'month' => '02',
'day' => '19',
'year' => '2013',
'hour' => '08',
'min' => '27',
'meridian' => 'am'
),
'due' => array(
'month' => '02',
'day' => '19',
'year' => '2013',
'hour' => '08',
'min' => '27',
'meridian' => 'am'
),
'content' => 'Termes & conditions'
),
'Client' => array(
'name' => 'Client 3',
'project' => 'Projet Client 3',
'address' => 'Adresse Client 3',
'phone' => 'Téléphone Client 3',
'email' => '[email protected]',
'proposal_id' => ''
),
'Product' => array(
(int) 0 => array(
'name' => 'Produit 3',
'reference' => 'Référence Produit 3',
'image' => 'Image Produit 3',
'pu' => '100.77',
'quantity' => '1000',
'ce' => '1',
'nf' => '0',
'rohs' => '0',
'client_id' => ''
)
),
'Specification' => array(
(int) 0 => array(
'name' => 'Specification 1',
'value' => 'Valeur 1',
'product_id' => ''
),
(int) 1 => array(
'name' => 'Specification 2',
'value' => 'Valeur 2',
'product_id' => ''
)
),
'Appendice' => array(
(int) 0 => array(
'name' => 'Image annexe 1',
'content' => 'Description de l'annexe',
'product_id' => ''
),
(int) 1 => array(
'name' => 'Image annexe 2',
'content' => 'Description de l'annexe',
'product_id' => ''
)
)
)
So in this array, everything is there. I just need to take these data and save them all in the corresponding tables. The first problem is to manage with the table's associations. Then the 2 foreach loops that generate multiple row.
I would like to save it all at once but is it even possible?
After trying many ways to get it work, I've gone completely crazy and I just lost myself. I'm really desperate on that one, i mix up everything between the saving method and the request->data that contains everything but cannot get it saved. Anyway, i'm desperately in need for help!
Thank you very much in advance for all the help you can give me, I really appreciate!
[EDIT]
I add my model to the present post for more detail.
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'
)
);
}