问题
I've been banging my head against the wall trying to figure out why my Emails (belongsToMany Guests (belongsToMany Emails)) won't save. When I attempt to save the email model with associated data (guests) it fails at $this->Emails->save($email) with:
Unknown type "" Error InvalidArgumentException
I've followed the CakeBookmarks example (http://book.cakephp.org/3.0/en/tutorials-and-examples/bookmarks/intro.html) to the tee at this point for relationships and the edit form. And even built it and pulled code from it.
Here's the relevant code from my project, any help or speculation is appreciated:
Create statement for the emails_guests join 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::intialize
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'
]);
}
Emails create/update view 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',
[
// 'type' => 'select',
'options' => $guests,
// 'multiple' => true,
// 'empty' => 'Please select the recipients.',
// 'label'=>'Recipients'
]
); ?>
</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 lastly the controller handling the save in question:
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']);
}
The request data when I save an email and select one or more guests (which triggers the 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 according to the docs and examples. Thanks in advance!
回答1:
Looks like something is wrong with either the read/cached schema, or you are defining an incorrect primary key for the join table class. With a compound primary key like the one you are showing here, it should never reach the point in code where that excpetion is thrown.
Delete tmp/cache/models/
, and in case you have a EmailsGuestsTable
class, check if and what it sets via Table::primaryKey()
, in case used, it should be
['email_id', 'guest_id']
Maybe your table initially had a different primary key, and you've made changes to it afterwards without clearing the cache and/or updating the corresponding table class.
来源:https://stackoverflow.com/questions/32017981/cakephp-3-saving-belongstomany-association-unknown-type-error