Saving Additional Data to a Unified Table in CakePHP 3.0

I am trying to store some data in a concatenated table using CakePHP. This is the part of the application that I would like to fix - this is the usual association of BelongsToMany with additional columns:

Model> Object:

/* Durations */
class Duration extends Entity {
  protected $_accessible = [
    'duration' => true,
    'cost' => true,
  ];
}

/* Commercials */
class Commercial extends Entity {

  protected $_accessible = [
    'info' => true,
    'commercial_durations' => true,
  ];
}

/* CommercialDurations */
class CommercialDuration extends Entity {
  protected $_accessible = [
    'duration_id' => true,
    'commercial_id' => true,
    'quantity' => true,
    'duration' => true,
    'commercial' => true,
  ];
}

      

Model> Table:

class DurationsTable extends Table {
  public function initialize(array $config)
  {
    $this->table('durations');
    $this->displayField('id');
    $this->primaryKey('id');

    $this->belongsToMany('Commercials', [
        'through' => 'CommercialDurations',
    ]);
  }
}

class CommercialsTable extends Table
{
  public function initialize(array $config){
    $this->table('commercials');
    $this->displayField('id');
    $this->primaryKey('id');

    $this->belongsToMany('Durations', [
        'through' => 'CommercialDurations'
    ]);

    $this->hasMany('CommercialDurations', [
        'foreignKey' => 'commercial_id'
    ]);

  }
}

class CommercialDurationsTable extends Table {
  public function initialize(array $config)
  {
    $this->table('commercial_durations');
    $this->displayField('id');
    $this->primaryKey('id');
    $this->belongsTo('Durations', [
        'foreignKey' => 'duration_id',
        'joinType' => 'INNER'
    ]);
    $this->belongsTo('Commercials', [
        'foreignKey' => 'commercial_id',
        'joinType' => 'INNER'
    ]);
  }
}

      

Now I have created a new View in which I want people to be able to select one Duration, enter the amount and add that value to the database. I am using the following code:

<?php 
  echo $this->Form->create($commercial); 
    echo $this->Form->input('durations._duration', ['options' => $durations]);
    echo $this->Form->input('durations._joinData.quantity'); 
    echo $this->Form->submit(__('Next'), ['class' => 'button small right', 'escape' => false]);
  echo $this->Form->end() 
?>

      

The problem with this form is that the duration selection does not show the duration field from the Durations table, but instead displays all the fields from that table (one per line) as JSON

<option value="0">{ "id": 1, "duration": "30 sec", "cost": 450 }</option>

      

Once I submit the form, I cannot save this information in a Commercials or CommercialDurations object. This is what I get from the $ this-> request-> data object:

[
'durations' => [
    '_duration' => '2',
    '_joinData' => [
        'quantity' => '2'
    ]
  ] 
]

      

The debug ((string) $ commercial) output before the start of the form:

/src/Template/Commercials/features.ctp (line 22)
'{
  "id": 2,
  "info": "AAAAAA ",
  "created": "2015-04-16T21:48:48+0000",
  "updated": null,
  "durations": [],
}'

      

How can I display the data in the form correctly? How can I get and store this data?

Thank!!

+3


source to share


1 answer


I am not getting your relationship with the models because as per your post, duration belongs to commercials and belongs to duration.

To explain to you how the request should be submitted and what the form looks like, let's say for this example that your models are:

Your commercial ad has a commercial duration and that commercial duration refers to the duration

So your models will look like this:

  • Commercial advertising has a lot of sales duration.

  • The commercial duration belongs to the commercial.

  • Commercial duration refers to duration.

  • The duration has many sales durations.

Your add function should be like this (unless you store new duration, just commercial and commercial duration)

    $commercial = $this->Commercials->newEntity($this->request->data,[
        'associated' => ['Commercialdurations']
    ]);
    if ($this->Commercials->save($commercial)) {
    $success = true;
    }else{
    $success = false;
    }

      

The request data should look like this:

{  
   "commercialdurations":{  
      "Commercialduration":{
      "duration_id":"1",
      "quantity":"1",
      "duration":"1"  
      }
   },
   "info":"something"
}

      

Basically you are submitting data of a new Commercial (info) and commercial duration associated with this (you can submit multiple commercial durations).

For your form to display duration basically you have to serialize this information without a controller, go to your add action and add this. (You can use anyway you want to get the data, all that matters is that you send it back to the view)



    $durations = $this->Commercials->Commercialdurations->Durations->find('list', ['limit' => 200]);
    $this->set(compact('commercial',durations'));
    $this->set('_serialize', ['commercial']);

      

Then in your form you can use the data

echo $ this-> Form-> input ('duration_id', ['options' => $ durations]);

So your form will look something like this:

    echo $this->Form->input('info');
    echo $this->Form->input('commercials.Commercial.duration_id', ['options' => $durations]);
    echo $this->Form->input('commercials.Commercial.quantity');
    echo $this->Form->input('commercials.Commercial.duration');

      

Basically you want to send a request with all levels of related data.

Have a look at another question about storing related data:

Cake PhP 3 Saving Related Data in Multiple Layers

More on how to create a form:

http://book.cakephp.org/3.0/en/views/helpers/form.html#creating-inputs-for-associated-data

0


source







All Articles