I banged my head against the wall, trying to understand why my emails (owned by Guests (owned by many emails)) would not be saved. When I try to save the email model with the associated data (guests), it fails in $ this-> Emails-> save ($ email) with:
Unknown type "" Error InvalidArgumentException
I followed the CakeBookmarks example ( http://book.cakephp.org/3.0/en/tutorials-and-examples/bookmarks/intro.html ) to tee at this point for relationships and form editing. And even built it and pulled the code from it.
Here is the relevant code from my project, any help or speculation is evaluated:
Create an operator for the emails_guests connection table:
CREATE TABLE emails_guests ( email_id INT NOT NULL, guest_id INT NOT NULL, PRIMARY KEY (email_id, guest_id), FOREIGN KEY guest_key(guest_id) REFERENCES guests(id), FOREIGN KEY email_key(email_id) REFERENCES emails(id) );
EmailsTable :: initialize
public function initialize(array $config) { // parent::initialize($config); $this->table('emails'); $this->displayField('title'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); $this->belongsToMany('Guests', [ 'foreignKey' => 'email_id', 'targetForeignKey' => 'guest_id', 'joinTable' => 'emails_guests' ]); }
GuestsTable :: initialize
public function initialize(array $config){ parent::initialize($config); $this->table('guests'); $this->displayField('name'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); $this->belongsTo('Invitations', [ 'foreignKey' => 'invitation_id' ]); $this->hasMany('Messages', [ 'foreignKey' => 'guest_id' ]); $this->belongsTo('SeatingGroups', [ 'foreignKey' => 'seating_group_id' ]); $this->belongsToMany('Emails', [ 'foreignKey' => 'guest_id', 'targetForeignKey' => 'email_id', 'joinTable' => 'emails_guests' ]); }
Create / update email manage.ctp
<?= $this->Form->create($email); ?> <div class="row"> <div class="col-sm-12"> <?= $this->Form->input('title', ['id' => false]); ?> </div> </div> <div class="row"> <div class="col-sm-12"> <?= $this->Form->input('subject'); ?> </div> </div> <div class="row"> <div class="col-sm-12"> <?= $this->Form->input('message', ['class'=>'email-body']); ?> </div> </div> <div class="row"> <div class="col-sm-6"> <?= $this->Form->input( 'guests._ids', [ </div> <div class="col-sm-6"> <div class="row"> <div class="col-sm-12"> <?= $this->Form->input('send_by', ['id' => 'send-by', 'type' => 'text']); ?> </div> </div> <div class="row"> <div class="col-sm-6"> <?= $this->Form->checkbox('now'); ?> <label for="now">Send Now</label> </div> <div class="col-sm-6"> <?= $this->Form->input( __('Save'), [ 'type' => 'submit', 'class' => 'inline', 'label' => false ] ) ?> </div> </div> </div> </div> <div class="row"> <div class="col-sm-12"> </div> </div> <div class="clearfix"></div> <?= $this->Form->end() ?>
And finally, the controller processes the specified save:
public function manage($id = null) { $this->set('title', 'Manage Emails'); if(isset($id)) { $email = $this->Emails->get($id, [ 'contain' => ['Guests'] ]); $this->set('title', 'Email: ' . $email->title); } else { $email = $this->Emails->newEntity(); $this->set('title', 'Create Email'); } if ($this->request->is(['patch', 'post', 'put'])) { debug($email); $email = $this->Emails->patchEntity($email, $this->request->data); debug($email); debug($this->request->data); if ($this->Emails->save($email)) { if($email->now == true) { $this->process($email->id, $id); } $this->Flash->success('The email has been saved.'); return $this->redirect(['action' => 'manage', $email->id]); } else { $this->Flash->error('The email could not be saved. Please, try again.'); } } $guests = $this->Emails->Guests->find('list')->select(['id', 'first_name', 'last_name', 'email'])->toArray(); $this->set('email', $email); $this->set('guests', $guests); $emails = $this->Emails->find(); $this->set('emails', $this->paginate($emails)); $this->set('_serialize', ['emails']); }
Request data when I save an email and select one or more guests (which causes an invalid type error):
[ 'title' => 'Test Email Edit', 'subject' => 'Hi! {{guest.first_name}}, we're testing some new features!2', 'message' => 'Hi {{guest.first_name}} {{guest.last_name}}, We're testing some new features with recursive data. Let me tell you a bit about you: Your seating group is: {{guest.seating_group.name}}. Your invitation is: {{guest.invitation.name}} Which we sent to: {{guest.invitation.address}} Thanks! Hope this comes out okay... ', 'guests' => [ '_ids' => [ (int) 0 => '1' ] ], 'send_by' => '', 'now' => '0' ]
Stack trace:
β© Cake\Database\Type::build CORE/src/ORM/Table.php, line 1552 β© Cake\ORM\Table->_newId CORE/src/ORM/Table.php, line 1489 β© Cake\ORM\Table->_insert CORE/src/ORM/Table.php, line 1436 β© Cake\ORM\Table->_processSave CORE/src/ORM/Table.php, line 1367 β© Cake\ORM\Table->Cake\ORM\{closure} CORE/src/Database/Connection.php, line 561 β© Cake\Database\Connection->transactional CORE/src/ORM/Table.php, line 1368 β© Cake\ORM\Table->save CORE/src/ORM/Association/BelongsToMany.php, line 557 β© Cake\ORM\Association\BelongsToMany->_saveLinks CORE/src/ORM/Association/BelongsToMany.php, line 506 β© Cake\ORM\Association\BelongsToMany->_saveTarget CORE/src/ORM/Association/BelongsToMany.php, line 750 β© Cake\ORM\Association\BelongsToMany->Cake\ORM\Association\{closure} CORE/src/Database/Connection.php, line 561 β© Cake\Database\Connection->transactional CORE/src/ORM/Association/BelongsToMany.php, line 769 β© Cake\ORM\Association\BelongsToMany->replaceLinks CORE/src/ORM/Association/BelongsToMany.php, line 445 β© Cake\ORM\Association\BelongsToMany->saveAssociated CORE/src/ORM/AssociationCollection.php, line 254 β© Cake\ORM\AssociationCollection->_save CORE/src/ORM/AssociationCollection.php, line 230 β© Cake\ORM\AssociationCollection->_saveAssociations CORE/src/ORM/AssociationCollection.php, line 195 β© Cake\ORM\AssociationCollection->saveChildren CORE/src/ORM/Table.php, line 1447 β© Cake\ORM\Table->_processSave CORE/src/ORM/Table.php, line 1367 β© Cake\ORM\Table->Cake\ORM\{closure} CORE/src/Database/Connection.php, line 561 β© Cake\Database\Connection->transactional CORE/src/ORM/Table.php, line 1368 β© Cake\ORM\Table->save APP/Controller/EmailsController.php, line 61 β© App\Controller\EmailsController->manage [internal function] β© call_user_func_array CORE/src/Controller/Controller.php, line 411 β© Cake\Controller\Controller->invokeAction CORE/src/Routing/Dispatcher.php, line 114 β© Cake\Routing\Dispatcher->_invoke CORE/src/Routing/Dispatcher.php, line 87 β© Cake\Routing\Dispatcher->dispatch ROOT/webroot/index.php, line 37
It should work fine in accordance with documents and examples. Thanks in advance!