I know this question is asked here a many times but I also tried to follow the solutions provided at my best. As I am learning a cakephp some solutions seemed difficult to implement in a code. I am using cakephp 2.5.
What I am trying to do is creating a problem report with attached one or more uploads. Here is some of what I have implemented so far:-
I have following models:
- Candidate
- CandidatesProblemReport
- CandidatesProblemReportsUpload
There associations are as follows:
CandidatesProblemReport hasMany CandidatesProblemReportsUpload
Candidate hasMany CandidatesProblemReport
CandidatesProblemReport belongsTo Candidate
CandidatesProblemReportsUpload belongsTo CandidatesProblemReport
Candidate.php
<?php
class Candidate extends AppModel {
public $name = 'Candidate';
public $hasMany = array(
'CandidatesProblemReport' => array(
'className' => 'CandidatesProblemReport',
'foreignKey' => 'candidate_id'
)
);
}
CandidatesProblemReport.php
<?php
class CandidatesProblemReport extends AppModel {
public $name = "CandidatesProblemReport";
public $belongsTo = array(
'Candidate' => array(
'className' => 'Candidate'
)
);
public $hasMany = array(
'Uploads' => array(
'className' => 'CandidatesProblemReportsUpload'
),
'Replies' => array(
'className' => 'CandidatesProblemReportsReply'
)
);
}
CandidatesProblemReportsController.php
class CandidatesProblemReportsController extends AppController {
public $name = "CandidatesProblemReports";
// ############# Report a Problem #############
// ********************************************
public function create() {
$userid = $this->Auth->user('id'); // Grabs the current user id
$this->set('userId', $userid); // Sends the current user id to the form
if ($this->request->is('post') && !empty($this->request->data)):
$this->CandidatesProblemReport->create();
$report = $this->CandidatesProblemReport->save($this->request->data);
if (!empty($report)):
$this->request->data['CandidatesProblemReportsUpload']['candidates_problem_report_id'] = $this->CandidatesProblemReport->id;
endif;
if ($this->CandidatesProblemReport->saveAssociated($this->request->data)):
$this->Session->setFlash('Your report has been submitted '
. 'successfully. Thank you!');
$this->redirect(array(
'action' => 'viewall')
);
else:
$this->Session->setFlash('Your report could not be submitted, '
. 'please try again');
endif;
endif;
}
}
create.ctp
<h1>Create a report</h1>
<?php
echo $this->Form->create('CandidatesProblemReport', array('type' => 'file'));
echo $this->Form->input('CandidatesProblemReport.report_subject');
echo $this->Form->input('CandidatesProblemReport.report_handle_department', array(
'options' => array(
'Technical' => 'Technical',
'Sales' => 'Sales',
'Support' => 'Support',
'Other' => 'Other'
)
));
echo $this->Form->input('CandidatesProblemReport.report_description');
echo $this->Form->input('CandidatesProblemReport.report_date', array(
'type' => 'hidden',
'value' => date('Y-m-d H:i:s'))
);
echo $this->Form->input('CandidatesProblemReport.candidate_id', array(
'type' => 'hidden',
'value' => $userId)
);
?>
<div>
<p><strong>Upload Screenshot/Files</strong></p>
<hr>
</div>
<?php
echo $this->Form->input('CandidatesProblemReportsUpload.0.report_upload', array(
'type' => 'file'
));
?>
<button class="add-new-upload" type="button">Add more</button>
<?php
echo $this->Form->end('submit');
echo $this->Html->script('jquery-2.1.1.min.js');
?>
<script type="text/javascript">
var i = 1;
$('.add-new-upload').click(function () {
$('.file').append('<input type="file" name="data[CandidatesProblemReportsUpload]['
+ i +
'][report_upload]" id="CandidatesProblemReportsUpload'
+ i +
'ReportUpload">');
i++;
});
</script>
Now what is happening is I am able to save the main model data i.e. CandidatesProblemReports but when I saveAssociated data it again saves the main model creating second duplicate entry but the uploads are not getting saved.
You can user
$this->CandidatesProblemReport->saveAssociated($this->request->data)
code to save associate data in multiple tables using one query.Saving data with associations
That's the expected behavior,
saveAssociated()
is not ment to save only the associated records, it will save the main record as well, so you should usesaveAssociated()
only, no need to manually set the foreign key, etc, CakePHP will do that automatically.Controller
Mind your aliases
The reason for your upload records not being created, is that you are not using the proper alias in your form/data, you've set the alias to be
Uploads
, but in your form you are usingCandidatesProblemReportsUpload
, and so CakePHP will ignore this data.Form
Storing file data
As mentioned in the comments, CakePHP doesn't handle file upload data out of the box, you'll have to prepare it in beforehand so that it is for example being stored on disk, and the model stores the path to the file.
While the above code should generally work, it will most likely trigger an error as it will try to store the file upload array in the database instead of flat data.
There are plugins out there that can handle file uploads, check them out, also search here on stackoverflow and check the docs for examples on how to modify data before it is being saved.
For starters: