I have a form that has multiple entries to the same table, the problem I'm having is that it only sends the last entry to the database and doesn't send the rest. I have used the debug and it only prints out the last field in the form.
With each iteration of field its meant to input into the fields_invoices table a invoice_id, field_id, entered_value
Here is my form
<?php echo $this->Form->create('FieldsInvoice'); ?>
<?php foreach ($fields as $field): ?>
<?php echo $this->Form->hidden('FieldsInvoice.id'); ?>
<?php echo $this->Form->hidden('FieldsInvoice.field_id', array('default' =>$field['Field']['id'])); ?>
<?php echo $this->Form->input('FieldsInvoice.invoice_id', array('default' =>$invoice_id, 'type'=>'hidden')); ?>
<?php echo $this->Form->Input('FieldsInvoice.entered_value', array('label'=>$field['Field']['name'], 'default' =>$field['Field']['default_value'])); ?>
<?php endforeach ;?>
<?php echo $this->Form->End('Submit');?>
Here is the related controller
public function create($id)
{
$this->set('title_for_layout', 'Create Invoice');
$this->set('stylesheet_used', 'homestyle');
$this->set('image_used', 'eBOXLogoHome.png');
$this->layout='home_layout';
if (!is_numeric($id)) throw new BadMethodCallException('I need an ID');
$this->Invoice->id = $id;
if (!$this->Invoice->exists()) throw new NotFoundException('Invalid ID');
$this->set('invoice_id',$id);
$names = $this->Invoice->find('list',array(
'fields'=>array('template_id'),
'conditions'=>array('id'=>$id)));
$fields = $this->Field->find('all', array(
'conditions'=>array(
'template_id'=>$names)));
$this->set(compact('fields'));
$this->set(compact('invoice_id'));
$this->set('name',$names);
$this->Invoice->create();
if(empty($this->data)){
$this->data= $this->Field->read($id);
}
else{
if($this->request->is('post'))
{
//die(debug($this->data));
$this->Invoice->create();
if($this->FieldsInvoice->save($this->request->data, array('deep'=>true)));
{
$this->Session->setFlash('The field has been updated');
$this->redirect(array('controller'=>'invoices', 'action'=>'index'));
}
//else{
$this->Session->setFlash('Could not be saved');
//}
}
}
}
\app\Controller\InvoicesController.php (line 134)
array(
'FieldsInvoice' => array(
(int) 0 => array(
'id' => '',
'field_id' => '0',
'invoice_id' => '97',
'entered_value' => '1'
),
(int) 1 => array(
'id' => '',
'field_id' => '99',
'invoice_id' => '97',
'entered_value' => '2'
),
(int) 2 => array(
'id' => '',
'field_id' => '999',
'invoice_id' => '97',
'entered_value' => '3'
),
(int) 3 => array(
'id' => '',
'field_id' => '9999',
'invoice_id' => '97',
'entered_value' => '4'
)
)
)
To post multiple fields, use:
foreach ($fields as $idx => $field):
echo $this->Form->hidden('FieldsInvoice.'.$idx.'.id');
echo $this->Form->hidden('FieldsInvoice.'.$idx.'.field_id', ...);
...
and then use $this->FieldsInvoice->saveMany() (instead of ->save()) to save multiple records.
Related
I have an Up which has to do a lot with pictures. I have a problem. I know might seems stupid, and even i know that im missing something, but i havent found out yet. So in few words. Let's say I have an Item. |id|name|price|condition|location|picture|
picture is the picture path that i save to DB. So when i create a new Item all the field are required. Till here everything works Fine.Now lets say i open Item x to edit. I edit only the name and the price and other i leave them as they are, and i press save, browse button, of the picture field is still required and i have to open galerry find the pic again in order to save. So my question is this: How can i do a picture upload only if i browse for the picture, but not to forget that on creation must not be empty. To Ilustrate it here is some code:
<?php
App::uses('AppModel', 'Model');
class Item extends AppModel {
public $name = 'Item';
public $primaryKey = 'id';
public $displayField = 'title';
public $validate = array(
'id' => array(
'blank' => array(
'rule' => 'blank',
'on' => 'create',
),
),
'title' => array(
'words' => array(
'rule' => array('custom', '/[0-9A-Za-z\._-]/'),
'message' => 'The Item name can only contain letters, numbers and spaces.',
),
'maxLength' => array(
'rule' => array('maxLength', 100),
'message' => 'The Item name must not be longer than 100 characters.',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'The Item name must not be empty.',
),
'isUnique' => array(
'rule' => 'isUnique',
'message' => 'This Item name already exists.',
),
),
'picture' => array(
'uploadError' => array(
'rule'=>'uploadError',
'message' => 'The File Did NOT Upload. Please Try Again!',
),
'fileSize'=>array(
'rule'=>array('fileSize','<=','30MB'),
'message'=>'File Size should be less then 30MB',
),
'processMediaUpload'=>array(
'rule' =>'processMediaUpload',
'message'=>'Uploading File Failed!',
),
),
'item_location_id' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'You Must Choose a Location',
),
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
),
),
'address' => array(
'words' => array(
'rule' => array('custom', '/[0-9A-Za-z\._-]/'),
'message' => 'The Item Address can only contain letters, numbers and spaces.',
),
'maxLength' => array(
'rule' => array('maxLength', 150),
'message' => 'Address can not be longer then 150 characters long',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'You Should Put an Address',
),
),
);
public $belongsTo = array(
'ItemLocation' => array(
'className' => 'ItemLocation',
'foreignKey' => 'item_location_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
public function processMediaUpload($mediacheck = array()) {
$dir = 'img/uploads/item/media/';
if (isset($mediacheck['media_path']['name'])) {
if(is_uploaded_file($mediacheck['media_path']['tmp_name'])) {
if (trim($mediacheck['media_path']['name'])!=""){
// here we delete if the image exist and replace it.
if (file_exists(WWW_ROOT . $dir . $mediacheck['media_path']['name'])) {
unlink(WWW_ROOT . $dir . $mediacheck['media_path']['name']);
return true;
}
}
$allowedExts = array('jpeg', 'png', 'jpg', 'gif');
$extension=strtolower(end(explode(".", $mediacheck['media_path']['name'])));
if (($mediacheck['media_path']['size'] < 55000000)) {
if(in_array($extension, $allowedExts)){
if ($mediacheck['media_path']["error"] > 0) {
$this->invalidate('media_path', $mediacheck['media_path']['error']);
return false;
} else {
if (file_exists( WWW_ROOT . $dir) && is_dir( WWW_ROOT . $dir)) {
if (file_exists( WWW_ROOT . $dir . $mediacheck['media_path']['name'])) {
$this->invalidate('media_path', 'File Allredy Exists!');
return false;
} else {
move_uploaded_file($mediacheck['media_path']['tmp_name'], WWW_ROOT . $dir . mktime() . $mediacheck['media_path']['name']);
$this->data[$this->alias]['media_path'] = mktime() . $mediacheck['media_path']['name'];
return TRUE;
}
} else { // in this case the directory doesent exist so we create it
mkdir($dir, 0777, true);
move_uploaded_file($mediacheck['media_path']['tmp_name'], WWW_ROOT . $dir . mktime() . $mediacheck['media_path']['name']);
$this->data[$this->alias]['media_path'] = mktime() . $mediacheck['media_path']['name'];
return TRUE;
}
}
}else { $this->invalidate('media_path', 'Invalid File Format! '); return false;}
} else { $this->invalidate('media_path', 'File size is To big!'); return false; }
} else { $this->invalidate('media_path', 'You must upload a file before you Submit!'); return false; }
} else { $this->invalidate('media_path', 'You must upload a file before you Submit!'); return false; }
// better safe then sorry!
return false;
}
Add Form:
<div class="items form">
<?php echo $this->Form->create('Item', array('type'=>'file')); ?>
<fieldset>
<legend><?php echo __('Add New Item'); ?></legend>
<?php
echo $this->Form->input('id');
echo $this->Form->input('title');
echo $this->Form->input('item_description');
echo $this->Form->input('location_description');
echo $this->Form->input('media_path', array('label'=>'Media','type'=>'file'));
echo $this->Form->input('item_location_id', array('label'=>'Location'));
echo $this->Form->input('item_characteristic_id', array('label'=>'Characteristics'));
echo $this->Form->input('address', array('id' => 'address'));
echo "<div id=\"map_canvas\" style=\"width:98%; height:400px;\"> </div>";
echo $this->Form->input('longitude', array('id'=>'longitude', 'readonly'=>'readonly'));
echo $this->Form->input('latitude', array('id'=>'latitude', 'readonly'=>'readonly'));
echo $this->Form->input('first_seller_id');
echo $this->Form->input('second_seller_id');
echo $this->Form->input('brochure_path', array('label'=>'Broshure','type'=>'file'));
echo $this->Form->input('seo_title');
echo $this->Form->input('seo_description' , array('label' => 'SEO Description'));
echo $this->Form->input('seo_url' , array('label' => 'SEO Url'));
echo $this->Form->input('seo_keywords' , array('label' => 'SEO Keywords'));
?>
</fieldset>
Edit Form:
<div class="items form">
<?php echo $this->Form->create('Item', array('type'=>'file')); ?>
<fieldset>
<legend><?php echo __('Edit Item'); ?></legend>
<?php
$dir = "/img/uploads/item/media/";
echo $this->Form->input('id');
echo $this->Form->input('title');
echo $this->Form->input('item_description');
echo $this->Form->input('location_description');
echo $this->Form->input('media_path', array('label'=>'Media','type'=>'file'));
echo $this->Form->input('hiddenimage', array('type'=>'hidden','value'=> $this->Form->value('media_path') ));
$Image = $this->Form->value( 'media_path');
if(empty($Image) || $Image==NULL)
{$Image = "/img/uploads/noimg.jpg";}
else {$Image = $dir . $Image; }
echo $this->Html->image($Image,array('align'=>'absbottom','style'=>'max-height:100px'));
echo "<h3> Test: ". $this->Form->value('media_path') . "</h3>";
echo $this->Form->input('item_location_id', array('label'=>'Location'));
echo $this->Form->input('item_characteristic_id', array('label'=>'Characteristics'));
echo $this->Form->input('address', array('id' => 'address'));
echo "<div id=\"map_canvas\" style=\"width:98%; height:400px;\"> </div>";
echo $this->Form->input('longitude', array('id'=>'longitude', 'readonly'=>'readonly'));
echo $this->Form->input('latitude', array('id'=>'latitude', 'readonly'=>'readonly'));
echo $this->Form->input('first_seller_id');
echo $this->Form->input('second_seller_id');
echo $this->Form->input('brochure_path', array('label'=>'Broshure','type'=>'file'));
echo $this->Form->input('seo_title');
echo $this->Form->input('seo_description' , array('label' => 'SEO Description'));
echo $this->Form->input('seo_url' , array('label' => 'SEO Url'));
echo $this->Form->input('seo_keywords' , array('label' => 'SEO Keywords'));
?>
</fieldset>
Look at adding the on parameter to your rules.
'on' => 'create'
Will only trigger the validation on an insert (i.e. a new record).
If a rule has defined ‘on’ => ‘create’, the rule will only be enforced
during the creation of a new record. Likewise, if it is defined as
‘on’ => ‘update’, it will only be enforced during the updating of a
record.
In your edit action could you not just check the field and remove it if it's empty? Is that what you mean? Like:
if (empty($this->request->data['Item']['media_path'])) {
unset($this->request->data['Item']['media_path']);
}
It would probably be more complicated than that, checking to see if it's valid upload I guess, but would something like that work?
in my project I have database
"Products" hasAndBelongsToMany "Sizes"
"ProductsSize" belongsTo "Products"
"ProductSize" belongsTo "Size"
In ProductsSize, one product_id may have many size_id.
hence, i want to do a form that have a select type input that list down all the size_id where the product_id = $id.
What i have done is:
in controller:
$size = $this->Product->ProductsSize->find('all', array(
'conditions' => array('ProductsSize.product_id' => $id),
'fields' => array('ProductsSize.size_id'),
));
in view:
<?php echo $this->form->create('Cart', array('action' => 'add')); ?>
<?php echo $this->form->input('size_id', array('label' => 'Size', 'options' => $size)); ?>
then i got error: Undefined index: ProductsSize
but when i put foreach, the data shown:
<?php foreach ($size_apparel as $size): ?>
<?php echo $size['ProductsSize']['size_id'];?><br/>
<?php endforeach; ?>
can anyone please help me to do the foreach in options.
The problem is that you are using an invalid array for the options. You are requesting:
$size = $this->Product->ProductsSize->find('all', array(
'conditions' => array('ProductsSize.product_id' => $id),
'fields' => array('ProductsSize.size_id'),
));
What you should be requesting is:
$size = $this->Product->ProductsSize->find('list', array(
'conditions' => array('ProductsSize.product_id' => $id),
));
This will return the options for the form field in the format it expects which is:
array(
{id} => {size},
{id} => {size},
{id} => {size},
{id} => {size},
...
)
I think you meant to say
<?php echo $this->form->input('size_id', array('label' => 'Size', 'options' => $size)); ?>
note 'options' instead of 'value'
$List = Set::classicExtract($size, '{n}.ProductSize.product_id');
$List will contain key value(ProductSize.product_id) pair.
OR you can change your query as
$size = $this->Product->ProductSize->find('list', array(
'conditions' => array('ProductSize.product_id' => $id),
));
Hope it will work for you
still a novice, but I am fighting with the paginator to limit my view to 10 records [properties] and to sort it on a field in the properties model. What am I doing wrong or miss in my code to get the paginator to control my view???
I have 2 models, Regions and Properties, a region has many properties, for example, my view is /region/view/13 This shows all properties for region 13.
The paginator is displaying the correct amount of properties, set the pages correct and all seems correct, but the paginator is not limiting my view, it just displays all properties by that region in one huge list instead of limit the view to 10 per page.
The sort per sleeps doesn't work either although the url in the browser seems to be ok.
/regions/view/13/sort:sleeps/direction:asc
/regions/view/13/sort:sleeps/direction:desc
Model:
<?php
App::uses('AppModel', 'Model');
/**
* Region Model
*
* #property Country $Country
* #property Property $Property
*/
class Region extends AppModel {
/**
* Display field
*
* #var string
*/
public $displayField = 'regionname';
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Country' => array(
'className' => 'Country',
'foreignKey' => 'country_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Property' => array(
'className' => 'Property',
'foreignKey' => 'region_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
Controller:
public function view($id = null) {
if (!$this->Region->exists($id)) {
throw new NotFoundException(__('Invalid region'));
}
$this->Region->recursive = 2; // related to associated model data, Region -> Properties -> PropertyImages
$options = array('conditions' => array('Region.' . $this->Region->primaryKey => $id));
$total = $this->Region->Property->find('count', array(
'conditions' => array('Property.region_id' => $id)
));
$this->set('total', $total); // Push to counter the view.
$this->set('region', $this->Region->find('first', $options)); // Push the properties to the view.
$this->paginate = array(
'limit' => 10,
'conditions' => array('Property.region_id' => $id),
);
$this->Region->Property->virtualFields['sleeps'] = 'Property.sleeps';
$this->set('regions', $this->paginate('Property'));
}
View:
<div class="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled')); ?>
</div>
<br>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}'))); ?><br>
Total properties: <?php echo $total . "\n"; ?><br>
Sort by: <?php echo $this->Paginator->sort('sleeps'); ?>
<?php if (!empty($region['Property'])): ?>
<div class="regionviewfooter"></div>
<?php
$i = 0;
foreach ($region['Property'] as $property): ?>
<!-- We only need 1 image to show up -->
<?php foreach ($property['PropertyImage'] as $key =>$propertyImage): ?>
<div class="regionview">
<div class="regionviewleft">
<?php echo '<span style="font-size:12px;line-height:18px;font-weight:bold;">'; echo $this->Html->link(__($property['description']), array('controller' => 'properties', 'action' => 'view', $property['id'])); echo '</span>'; ?>
<div class="regionviewheader">Sleeps <?php echo $property['sleeps']; echo ' :: ' ?>
<?php
if ($property['minPrice'] == 0) {
echo 'Please call for prices';
} else {
echo 'Prices from ';
echo $this->Number->currency($property['minPrice'], 'GBP');
if ($property['maxPrice'] == 0) {
echo ' PW';
} else {
echo ' - ';
echo $this->Number->currency($property['maxPrice'], 'GBP');
echo ' PW';
}
}
echo '<span style="font-size:11px;line-height:18px;font-weight:normal;">'; echo ' :: ';
echo $this->Html->link(__('View Property'), array('controller' => 'properties', 'action' => 'view', $property['id'])); echo '</span>'; ?>
</div>
<?php echo ($property['shortDesc']); ?><br>
Add to my Enquiry List :: Property Ref. (<?php echo strtoupper($property['ref']); ?>)
</div>
<div class="regionviewright">
<!-- display image -->
<?php echo $this->Html->image(($propertyImage['filename']), array('alt' => ($propertyImage['description']),'width' => '150' ,'height' => '77')); $key ?>
<?php $key++; ?>
</div>
</div>
<div class="clear"></div>
<div class="regionviewfooter"></div>
<?php if ($key == 1) {
break; // Stop, we did 1 image.
}
?>
<?php endforeach; ?>
<?php endforeach; ?>
<?php endif; ?>
<br>Top of Page<br><br>
You're setting your paginated results to $regions, yet in your view, you're looping through and displaying $region (singular), which is a straight-up find() above, with recursive 2, which will pull all properties.
So - although there are many other things that need cleaned up with your code, for now, just use $regions (plural) instead of $region singular in your View.
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#test.com',
'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'
)
);
}
What's the output when you save the data?
if (!empty($this->data)) {
$this->Proposal->save($this->data);
}
You should also check the sql-output
echo $this->element('sql_dump');
edit:
Well after your edit, on the first look it seems that your relations are wrong.
Check out the examples in the book: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
For example hasOne: the other model contains the foreign key.
As I said earlier, you should try to start with just one relation, getting it to work. Afterwords, it'll be much easier to get the other working. So try to comment-out everything except your Proposal and Client model. Then try saving just those two.
When a user enters data into my form it isn't saving to the database, this is the structure of my tables
Invoice - id, sender_id, receiver_id, template_id
Field - id, name, description, default_value, template_id
fields_invoices - id, invoice_id, field_id, entered_value
here is the invoice model
class Invoice extends AppModel{
var $name='Invoice';
var $hasMany = array(
'FieldsInvoice');
here is the field model
var $hasMany = array(
'FieldsInvoice'
);
and here is the fieldsInvoice model
<?php
class FieldsInvoice extends AppModel {
public $belongsTo = array(
'Field' => array(
'className' => 'Field',
'foreignKey' => 'field_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'invoice_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
here is the create function in the invoices controller
public function create($id)
{
$this->set('title_for_layout', 'Create Invoice');
$this->set('stylesheet_used', 'homestyle');
$this->set('image_used', 'eBOXLogoHome.png');
$this->layout='home_layout';
if (!is_numeric($id)) throw new BadMethodCallException('I need an ID');
$this->Invoice->id = $id;
if (!$this->Invoice->exists()) throw new NotFoundException('Invalid ID');
$this->set('invoice_id',$id);
$names = $this->Invoice->find('list',array(
'fields'=>array('template_id'),
'conditions'=>array('id'=>$id)));
$fields = $this->Field->find('all', array(
'conditions'=>array(
'template_id'=>$names)));
$this->set(compact('fields'));
$this->set(compact('invoice_id'));
$this->set('name',$names);
$this->Invoice->create();
if(empty($this->data)){
$this->data= $this->Field->read($id);
}
else{
if($this->request->is('post'))
{
$this->Invoice->create();
if($this->FieldsInvoice->save($this->request->data, array('deep'=>true)));
{
$this->Session->setFlash('The field has been updated');
$this->redirect(array('controller'=>'invoices', 'action'=>'index'));
}
//else{
$this->Session->setFlash('Could not be saved');
//}
}
}
}
here is the view for the create function
<?php echo $this->Form->create('FieldsInvoice'); ?>
<?php foreach ($fields as $field): ?>
<?php echo $this->Form->hidden('Invoice.id'); ?>
<?php echo $this->Form->hidden($field['Field']['id']); ?>
<?php echo $this->Form->Input($field['Field']['name'], array('default' =>$field['Field']['default_value'])); ?>
<?php endforeach ;?>
<?php echo $this->Form->End('Submit');?>
when debugging the view this is the output received
array(
'Invoice' => array(
'id' => ''
),
'FieldsInvoice' => array(
(int) 5 => '',
'amount' => 'test',
(int) 6 => '',
'description' => 'test1',
(int) 7 => '',
'totalacctowing' => 'test2',
(int) 8 => '',
'pmtinfo' => 'test3'
)
)
Instead of:
$this->Invoice->save($this->request->data);
in your if condition use the following syntax;
$this->Invoice->save($this->request->data, array('deep' => true));
This link will guide you to save associated data.
Have you tried debugging? Try viewing your form data and see if all fields are ok. Use debug() or pr().