Я знаю, что этот вопрос задают здесь много раз, но я также пытался следовать решениям, предоставленным в моих силах. По мере того, как я изучал CakePHP, некоторые решения казалось сложным для реализации в коде. Я использую CakePHP 2.5.
Я пытаюсь создать отчет о проблеме с одной или несколькими добавленными загрузками. Вот кое-что из того, что я реализовал до сих пор:
У меня есть следующие модели:
Есть ассоциации:
КандидатыПроблемаСообщение имеет много КандидатовПроблемаРепортыЗагрузить
Кандидат имеет много кандидатовПроблема отчета
КандидатыПроблема отчета принадлежит кандидату
КандидатыПроблемаРепортыЗагрузка принадлежит КандидатамПроблемаРепорт
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>
Теперь происходит то, что я могу сохранить основные данные модели, т.е. CandidatesProblemReports, но когда я сохраняю связанные данные, он снова сохраняет основную модель, создавая вторую дублирующую запись, но загрузки не сохраняются.
Это ожидаемое поведение, saveAssociated()
Он предназначен не только для сохранения связанных записей, но и для основной записи, поэтому вам следует использовать saveAssociated()
только, не нужно вручную устанавливать внешний ключ и т. д., CakePHP сделает это автоматически.
контроллер
public function create() {
// ...
if ($this->request->is('post') && !empty($this->request->data)):
$this->CandidatesProblemReport->create();
if ($this->CandidatesProblemReport->saveAssociated($this->request->data)):
// ...
endif;
endif;
}
Причина того, что ваши загружаемые записи не создаются, заключается в том, что вы не используете правильный псевдоним в своей форме / данных, вы установили псевдоним как Uploads
, но в вашей форме вы используете CandidatesProblemReportsUpload
и поэтому CakePHP будет игнорировать эти данные.
форма
echo $this->Form->input('Uploads.0.report_upload', array(
'type' => 'file'
));
<script type="text/javascript">
var i = 1;
$('.add-new-upload').click(function () {
$('.file').append('<input type="file" name="data[Uploads]['
+ i +
'][report_upload]" id="Uploads'
+ i +
'ReportUpload">');
i++;
});
</script>
Как упомянуто в комментариях, CakePHP не обрабатывает данные загрузки файла из коробки, вам нужно будет подготовить их заранее, чтобы они, например, сохранялись на диске, а модель сохраняла путь к файлу.
Хотя приведенный выше код в целом должен работать, он, скорее всего, вызовет ошибку, поскольку попытается сохранить массив загрузки файлов в базе данных вместо простых данных.
Существуют плагины, которые могут обрабатывать загрузки файлов, проверять их, а также искать здесь в stackoverflow и проверять в документах примеры того, как изменить данные перед их сохранением.
Для начинающих:
Других решений пока нет …