CakePHP3:如何保存具有两级HABTM的实体?
此问题中的表格包括:CakePHP3:如何保存具有两级HABTM的实体?,cakephp,cakephp-3.0,Cakephp,Cakephp 3.0,此问题中的表格包括: 塔里法斯(属于康塔托斯) 区域(habtm tarifas) tarifas_地区(habtm turnos) 塔里法斯图诺斯地区 Tarifas还有habtmDias,但这种关联没有问题,因为它是一种简单的关联 TarifasTable: <?php namespace App\Model\Table; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Val
- 塔里法斯(属于康塔托斯)
- 区域(habtm tarifas)
- tarifas_地区(habtm turnos)
- 塔里法斯图诺斯地区
Tarifas
还有habtmDias
,但这种关联没有问题,因为它是一种简单的关联
TarifasTable:
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Tarifas Model
*
* @property \Cake\ORM\Association\BelongsTo $Contratos
* @property \Cake\ORM\Association\BelongsToMany $Areas
* @property \Cake\ORM\Association\BelongsToMany $Dias
*
* @method \App\Model\Entity\Tarifa get($primaryKey, $options = [])
* @method \App\Model\Entity\Tarifa newEntity($data = null, array $options = [])
* @method \App\Model\Entity\Tarifa[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\Tarifa|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Tarifa patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\Tarifa[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\Tarifa findOrCreate($search, callable $callback = null)
*/
class TarifasTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('tarifas');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Contratos', [
'foreignKey' => 'contrato_id',
'joinType' => 'INNER'
]);
$this->belongsToMany('Areas', [
'foreignKey' => 'tarifa_id',
'targetForeignKey' => 'area_id',
'joinTable' => 'tarifas_areas'
]);
$this->belongsToMany('Dias', [
'foreignKey' => 'tarifa_id',
'targetForeignKey' => 'dia_id',
'joinTable' => 'tarifas_dias'
]);
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->requirePresence('nome', 'create')
->notEmpty('nome');
$validator
->date('dataInicial')
->requirePresence('dataInicial', 'create')
->notEmpty('dataInicial');
$validator
->date('dataFinal')
->requirePresence('dataFinal', 'create')
->notEmpty('dataFinal');
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['contrato_id'], 'Contratos'));
return $rules;
}
public function salvaTarifasContrato($idContrato, $dadosTarifas){
$tarifas = $this->newEntities(
$dadosTarifas,
['associated' => ['TarifasAreas', 'TarifasAreas.TarifasAreasTurnos']]
);
debug($tarifas); die();
}
}
因此,在TarifasTable
中,我编写了这个函数来保存所有tarifas
(但我仍在调试):
我有这样的回报:
{
"message": "Cannot marshal data for \"TarifasAreas\" association. It is not associated with \"Tarifas\".",
"url": "/project/api/contratos",
"code": 500
}
那么,我如何告诉CakePHP这些表是如何相互关联的呢?有没有一种方法可以一次保存所有数据?您需要定义
Tarifas
和tarifasreas
之间的关系。在表上定义belongToMany
关系时,它只关联显式声明的表,而不关联直通表
// TarifasTable.php
$this->hasMany('TarifasAreas');
只要TarifasAreas
的TarifasAreas
中的外键是tarifa\u id
就可以了 是的,很管用!但我不得不更改表名,因为CakePHP3似乎有一个错误,ORM“无法描述TarifasAreas表:它有0列”。这很奇怪!这和命名惯例有什么关系吗通常联接表名称按字母顺序排列AreasTarifas
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* TarifasAreasTurnos Model
*
* @property \Cake\ORM\Association\BelongsTo $TarifaAreas
* @property \Cake\ORM\Association\BelongsTo $Turnos
*
* @method \App\Model\Entity\TarifasAreasTurno get($primaryKey, $options = [])
* @method \App\Model\Entity\TarifasAreasTurno newEntity($data = null, array $options = [])
* @method \App\Model\Entity\TarifasAreasTurno[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\TarifasAreasTurno|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\TarifasAreasTurno patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\TarifasAreasTurno[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\TarifasAreasTurno findOrCreate($search, callable $callback = null)
*/
class TarifasAreasTurnosTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('tarifas_areas_turnos');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('TarifaAreas', [
'foreignKey' => 'tarifa_area_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Turnos', [
'foreignKey' => 'turno_id',
'joinType' => 'INNER'
]);
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->numeric('valor')
->requirePresence('valor', 'create')
->notEmpty('valor');
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['tarifa_area_id'], 'TarifaAreas'));
$rules->add($rules->existsIn(['turno_id'], 'Turnos'));
return $rules;
}
}
"tarifas": [
{
"nome": "T1",
"dataInicial": "2017-01-10",
"dataFinal": "2018-01-10",
"dias": [
{
"id": 1,
"_joinData": []
},
{
"id": 2,
"_joinData": []
},
{
"id": 3,
"_joinData": []
},
{
"id": 4,
"_joinData": []
},
{
"id": 5,
"_joinData": []
}
],
"TarifasAreas": [
{
"area_id": 3,
"TarifasAreasTurnos": [
{
"turno_id": 4,
"valor": 20
}
]
}
]
}
]
public function salvaTarifasContrato($idContrato, $dadosTarifas){
$tarifas = $this->newEntities(
$dadosTarifas,
['associated' => ['TarifasAreas', 'TarifasAreas.TarifasAreasTurnos']]
);
debug($tarifas); die();
}
{
"message": "Cannot marshal data for \"TarifasAreas\" association. It is not associated with \"Tarifas\".",
"url": "/project/api/contratos",
"code": 500
}
// TarifasTable.php
$this->hasMany('TarifasAreas');