Store data in cakephp hasmany and belong to the association at once

I know this question is asked many times here, but I also tried to follow the suggested solutions. As I am learning cakephp, some solutions seemed difficult to implement in code. I am using cakephp 2.5.

What I am trying to do is generate an issue report with one or more uploads attached. Here are some of my possibilities: -

I have the following models:

  • candidate
  • CandidatesProblemReport
  • CandidatesProblemReportsUpload

There are the following associations:

  • ApplicantsProblemReport hasMany ApplicantsProblemReportsUpload

  • Candidate hasMany CandidatesProblemReport

  • CandidatesProblemReport belongs to Candidate

  • CandidatesProblemReportsUpload belongs to 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 happens is I can save the main data of the model, i.e. CandidatesProblemReports, but when I save the bound data, it again saves the main model creating the second duplicate record, but the load is not saved.

+3


source to share


1 answer


Saving data with associations

To prevent the expected behavior saveAssociated()

from only keeping related records, it will also keep the main record, so you should only use saveAssociated()

, no need to manually set the foreign key, etc. CakePHP will do this automatically.

controller

public function create() {
    // ...

    if ($this->request->is('post') && !empty($this->request->data)):

        $this->CandidatesProblemReport->create();

        if ($this->CandidatesProblemReport->saveAssociated($this->request->data)):
            // ...
        endif;

    endif;
}

      

Remember your aliases

The reason your uploads are not being generated is because you are not using the correct alias in your form / data, you have set an alias Uploads

but in your form you are using CandidatesProblemReportsUpload

and therefore CakePHP will ignore that data.

The form

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>

      

Saving file data

As mentioned in the comments, CakePHP does not handle file upload data out of the box, you will have to prepare it ahead of time for it to be stored on disk, for example, and the model stores the file path.

While the above code usually works, it will likely throw 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, validate them, and also search stackoverflow here and validate docs for examples of how to modify data before saving it.

To start:

0


source







All Articles