这个问题的演变表是:
Tarifas
也是Dias
,但这种关联没有问题,因为这是一个简单的关联。
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();
}
}
AreasTable:
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Areas Model
*
* @property \Cake\ORM\Association\BelongsTo $Clientes
* @property \Cake\ORM\Association\BelongsToMany $Bairros
* @property \Cake\ORM\Association\BelongsToMany $Contratos
* @property \Cake\ORM\Association\BelongsToMany $Tarifas
*
* @method \App\Model\Entity\Area get($primaryKey, $options = [])
* @method \App\Model\Entity\Area newEntity($data = null, array $options = [])
* @method \App\Model\Entity\Area[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\Area|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Area patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\Area[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\Area findOrCreate($search, callable $callback = null)
*/
class AreasTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('areas');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Clientes', [
'foreignKey' => 'cliente_id',
'joinType' => 'INNER'
]);
$this->belongsToMany('Bairros', [
'foreignKey' => 'area_id',
'targetForeignKey' => 'bairro_id',
'joinTable' => 'areas_bairros'
]);
$this->belongsToMany('Contratos', [
'foreignKey' => 'area_id',
'targetForeignKey' => 'contrato_id',
'joinTable' => 'contratos_areas'
]);
$this->belongsToMany('Tarifas', [
'foreignKey' => 'area_id',
'targetForeignKey' => 'tarifa_id',
'joinTable' => 'tarifas_areas'
]);
}
/**
* 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
->allowEmpty('descricaoarea');
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(['cliente_id'], 'Clientes'));
return $rules;
}
}
TarifasAreasTable:
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* TarifasAreas Model
*
* @property \Cake\ORM\Association\BelongsTo $Tarifas
* @property \Cake\ORM\Association\BelongsTo $Areas
* @property \Cake\ORM\Association\BelongsToMany $Turnos
*
* @method \App\Model\Entity\TarifasArea get($primaryKey, $options = [])
* @method \App\Model\Entity\TarifasArea newEntity($data = null, array $options = [])
* @method \App\Model\Entity\TarifasArea[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\TarifasArea|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\TarifasArea patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\TarifasArea[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\TarifasArea findOrCreate($search, callable $callback = null)
*/
class TarifasAreasTable 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');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Tarifas', [
'foreignKey' => 'tarifa_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Areas', [
'foreignKey' => 'area_id',
'joinType' => 'INNER'
]);
$this->belongsToMany('Turnos', [
'foreignKey' => 'tarifas_area_id',
'targetForeignKey' => 'turno_id',
'joinTable' => 'tarifas_areas_turnos'
]);
}
/**
* 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');
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_id'], 'Tarifas'));
$rules->add($rules->existsIn(['area_id'], 'Areas'));
return $rules;
}
}
TarifasAreasTurnosTable:
<?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;
}
}
这是我要保存的数据(它是json的一部分):
"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
}
]
}
]
}
]
所以,在TarifasTable
我编写了这个函数来保存所有tarifas
(但我还在调试):
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
}
那么,我怎么能告诉CakePHP这些表如何相互关联?有没有办法一次性保存这些数据?
答案 0 :(得分:1)
您需要在hasMany
和Tarifas
之间定义TarifasAreas
关系。在表上定义belongsToMany
关系时,它只涉及明确声明的表而不是直通表。
// TarifasTable.php
$this->hasMany('TarifasAreas');
https://book.cakephp.org/3.0/en/orm/associations.html#hasmany-associations
只要TarifasAreas
Tarifas
中的外键为tarifa_id
,这就行了!