How to configure a tree in a good way using Cakephp3? - database

I'm working on a project which needs a tree to structure categories.
The problem is i can't find how to join the tables like it should be between my models, or maybe it's related to the controller itself.
When i fill the form and post it, only the table Categories is written, nothing happens in Categorylangs.
I'm pretty sure it's a little mistake or something simple i misunderstood here.. thanks
public function add()
{
$category = $this->Categories->newEntity();
$category->categorylangs = $this->Categories->Categorylangs->newEntity();
if ($this->request->is(['patch', 'post', 'put'])) {
$category = $this->Categories->patchEntity($category, $this->request->getData());
debug($category);
die();
if ($this->Categories->save($category)) {
$this->Flash->success(__('The category has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The category could not be saved. Please, try again.'));
}
$this->set(compact('category'));
}
class CategoriesTable extends Table
$this->setTable('categories');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Tree');
$this->hasMany('ChildCategories', [
'className' => 'Categories',
'foreignKey' => 'parent_id'
]);
$this->hasMany('Categorylangs', [
'foreignKey' => 'category_id'
]);
// $this->hasMany('Privatequestions', [
// 'foreignKey' => 'category_id'
// ]);
// $this->hasMany('Publicquestions', [
// 'foreignKey' => 'category_id'
// ]);
// $this->hasMany('Userpros', [
// 'foreignKey' => 'category_id'
// ]);
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->nonNegativeInteger('id')
->allowEmptyString('id', 'create');
$validator
->boolean('active')
->requirePresence('active', 'create')
->allowEmptyString('active', false);
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)
{
return $rules;
}
}
class CategorylangsTable extends Table
{
{
parent::initialize($config);
$this->setTable('categorylangs');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
'joinType' => 'INNER'
]);
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->nonNegativeInteger('id')
->allowEmptyString('id', 'create');
$validator
->scalar('label')
->maxLength('label', 350)
->requirePresence('label', 'create')
->allowEmptyString('label', false);
$validator
->scalar('slug')
->maxLength('slug', 450)
->requirePresence('slug', 'create')
->allowEmptyString('slug', false);
$validator
->scalar('description')
->requirePresence('description', 'create')
->allowEmptyString('description', false);
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(['category_id'], 'Categories'));
$rules->add($rules->existsIn(['language_id'], 'Languages'));
return $rules;
}
}
The view with the form to fill the 2 tables:
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Categories'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="categories form large-9 medium-8 columns content">
<?= $this->Form->create($category) ?>
<fieldset>
<legend><?= __('Add Category') ?></legend>
<?php
echo $this->Form->control('parent_id', ['options' => $parentCategories, 'empty' => __('root')]);
echo $this->Form->control('categorylangs.label');
echo $this->Form->control('categorylangs.description');
echo $this->Form->control('categorylangs.language_id');
echo $this->Form->control('active');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
Here is a debug from Categoriescontroller.php, showing the data are not transmitted like they should be but i cant figure how to fix it...
/src/Controller/Admin/CategoriesController.php (line 60)
object(App\Model\Entity\Category) {
'categorylangs' => [],
'active' => false,
'[new]' => true,
'[accessible]' => [
'parent_id' => true,
'lft' => true,
'rght' => true,
'active' => true,
'parent_category' => true,
'child_categories' => true,
'categorylangs' => true,
'privatequestions' => true,
'publicquestions' => true,
'userpros' => true
],
'[dirty]' => [
'categorylangs' => true,
'active' => true
],
'[original]' => [
'categorylangs' => object(App\Model\Entity\Categorylang) {
'[new]' => true,
'[accessible]' => [
'label' => true,
'slug' => true,
'description' => true,
'category_id' => true,
'language_id' => true,
'category' => true,
'language' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Categorylangs'
}
],
'[virtual]' => [],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Categories'
}

Categorylangs is a hasMany relation, not hasOne, so your field names should be like categorylangs.0.label, not categorylangs.label. You need for it to generate an array of entities, even if the array has only a single entity in it.
And $category->categorylangs = $this->Categories->Categorylangs->newEntity(); is meaningless here, the value of categorylangs will be overwritten by the patchEntity call.

Related

Cakephp 4 : How to save hasone data

I have two database table 1) users 2) profiles
profiles has a field called bank_ac
I am trying to save it from user model.
I have created form input like
<?= $this->Form->create($user) ?>
<?= $this->Form->control('profile.bank_ac'); ?>
<?= $this->Form->end() ?>
User model I have added associative like
$this->hasOne('Profiles');
After debug getting data like
[
'name' => 'Jone',
'email' => 'abcd#yahoo.com',
'profile' => [
'bank_ac' => '1212212'
]
]
after debug patch entity
object(App\Model\Entity\User) {
'name' => 'Jone',
'email' => 'abcd#yahoo.com',
'[new]' => true,
'[accessible]' => [
'name' => true,
'email' => true,
'created' => true,
'modified' => true
],
'[dirty]' => [
'name' => true,
'email' => true,
'profile' => true
],
'[original]' => [],
'[virtual]' => [],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Users'
}
In UsersController/add I have applied code like
public function add(){
$user = $this->Users->newEmptyEntity();
$user = $this->Users->patchEntity($user, $this->request->getData());
$this->Users->save($user, ['associated' => ['Profiles']]);
}
Profile data not saving , also not getting any error. How can I save this associative data ?
Looking at your entity debug result, the profile field is missing from the accessibility config, hence disallowing its use in mass assignment (patching).
Add it to your User::$_accessible property, and it should work:
protected $_accessible = [
// ...
'profile' => true,
];
See also
Cookbook > Database Access & ORM > Entities > Mass Assignment

Controller doesn't get hasOne relationship data - Cakephp

I have a problem with related tables in CakePHP. I can't get the related table data include in the form.
I have two Entities. One of them is "Users" and the other one is "Subjects". Every User has a subject. Table "Subject" has foreign key idUser from Users table.
I added in UsersTable:
$this->hasOne('Subjects');
And I added in SubjectsTable:
$this->belongsTo('Users', [
'foreignKey' => 'idUser',
'joinType' => 'INNER'
]);
In the view (signup), I have this:
<div class="form-group">
<?php echo $this->Form->control('Subject.name',['label' => 'Asignatura','placeholder' => 'Ingrese asignatura','class' => 'form-control']) ?>
</div>
In the controller, I have this:
$user = $this->Users->patchEntity($user, $this->request->getData(),['associated' => 'Subjects']);
When I debug $user, I am getting this result:
\src\Controller\UsersController.php (line 113)
object(App\Model\Entity\User) {
'id' => '11111111',
'name' => 'Leo',
'firstlastname' => 'Messi',
'secondlastname' => 'Cuccittini',
'email' => 'leo.messi#gmail.com',
'password' => '$2y$10$E02nd/w89BDvgCyz36bQdeBbujOLrSdON1e6CD25aDYCP2VeLkNNm',
'role' => '2',
'[new]' => true,
'[accessible]' => [
'id' => true,
'name' => true,
'firstlastname' => true,
'secondlastname' => true,
'email' => true,
'password' => true,
'role' => true
],
'[dirty]' => [
'id' => true,
'name' => true,
'firstlastname' => true,
'secondlastname' => true,
'email' => true,
'password' => true,
'role' => true
],
'[original]' => [],
'[virtual]' => [],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Users'
}
So, I am not getting in the controller the data from Subject.
Any help, please.
Model
$this->hasOne('Subjects', [
'foreignKey' => 'userId'
]);
Controller:
$user = $this->User->get($id, ['contain' => ['Subjects']);
Entity/User.php
protected $_accessible = [
'subjects' => true
// ...
];
Form
https://book.cakephp.org/3.0/en/views/helpers/form.html#associated-form-inputs
Change: Subject.name to user.subject.name
<?php echo $this->Form->control('user.subject.name',['label' => 'Asignatura','placeholder' => 'Ingrese asignatura','class' => 'form-control']) ?>

saving belongsToMany association with same keys but different _joinData

I have a belongsToMany relationship between two tables which is configured using a through table.
class UsersTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Groups', [
'through' => 'GroupsUsers',
]);
}
}
class GroupsTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Users', [
'through' => 'GroupsUsers',
]);
}
}
class GroupsUsersTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Groups');
$this->belongsTo('Users');
}
}
I can make associations between users and groups, but not I can't figure out how to make multiple associates between the same user and groups, but with different _joinData.
This is how the join table is built:
$table = $this->table('groups_users');
$table->addColumn('user_id', 'integer');
$table->addColumn('group_id', 'integer');
$table->addColumn('role', 'string');
$table->create();
When I add or edit a group by adding users to it, the $data in beforeMarshal() is
object(ArrayObject) {
name => 'test group'
users => [
(int) 0 => [
'id' => (int) 1,
'_joinData' => [
'role' => 'writer'
]
],
(int) 1 => [
'id' => (int) 1,
'_joinData' => [
'role' => 'editor'
]
]
]
}
after patching the entity in the controller with
$entity = $this->Groups->patchEntity(
$entity,
$data,
['associated' => ['Users._joinData']]
);
I get the following $entity in beforeSave()
object(App\Model\Entity\Group) {
'id' => (int) 1,
'name' => 'test group',
'users' => [
(int) 0 => object(App\Model\Entity\User) {
'id' => (int) 1,
'username' => 'testuser',
'_joinData' => object(Cake\ORM\Entity) {
'role' => 'writer',
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'role' => true
],
'[original]' => [],
'[virtual]' => [],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'GroupsUsers'
},
'[new]' => false,
'[accessible]' => [
'username' => true,
'groups' => true,
'_joinData' => true
],
'[dirty]' => [
'_joinData' => true
],
'[original]' => [
'_joinData' => [
'role' => 'writer'
]
],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Users'
}
],
'[new]' => false,
'[accessible]' => [
'name' => true,
'users' => true
],
'[dirty]' => [
'users' => true,
'modified' => true
],
'[original]' => [
'modified' => object(Cake\I18n\FrozenTime) {
'time' => '2019-05-15T14:41:49+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
}
],
'[hasErrors]' => false,
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Groups'
}
So it looks like the Marshaller is removing the second "duplicate" user from the group, even though the _joinData is different. The default saveStrategy is replace, but manually changing it to append doesn't add the second association either.
How can I add the same user to the same group with different _joinData using the same join table.
The marshaller uses the primary key to identify records, and the collection of existing entities will then only hold one user entity instance, so even though the marshaller will add the different join data sets, it will set it on one and the same entity... long story short, the marshaller isn't (yet) capable of doing what you're trying to do. You may want to open an issue over at GitHub if there isn't one already.
For now you'll have to save the records separately, for example like this (untested, but you get the idea):
$group = $this->Groups->patchEntity($entity, $data, [
'fieldList' => ['name']
]);
$users = [];
foreach ($data['users'] as $userData) {
$user = $this->Groups->Users->newEntity();
$users[] = $this->Groups->Users->patchEntity($user, $userData);
}
$result = $this->Groups->getConnection()->transactional(function () use ($group, $users) {
if (!$this->Groups->save($group, ['atomic' => false])) {
return false;
}
if (!$this->Groups->Users->link($group, $users, ['atomic' => false])) {
return false;
}
return true;
});

multiple select for hasMany association in CakePHP 3

I have two tables seller_businesses and seller_business_categories. and their association is as follows
SellerBusinessesTable.php
$this->hasMany('SellerBusinessCategories', [
'foreignKey' => 'seller_business_id'
]);
SellerBusinessCategories.php
$this->belongsTo('SellerBusinesses', [
'foreignKey' => 'seller_business_id',
'joinType' => 'INNER'
]);
I'm using a single form to save data in both tables
<?= $this->Form->create($sellerBusiness, ['type' => 'file']) ?>
<?= $this->Form->input('company_name') ?>
<?= $this->Form->input('proof', ['type' => 'file']) ?>
<?= $this->Form->input('seller_business_categories._category_ids', ['multiple' => true, 'options' => $categories]) ?>
<?= $this->Form->button('submit', ['type' => 'submit']) ?>
<?= $this->Form->end() ?>
And controller action is
$sellerBusiness = $this->SellerBusinesses->newEntity();
if ($this->request->is('post')) {
$sellerBusiness->seller_id = $this->Auth->user('id');
$sellerBusiness = $this->SellerBusinesses->patchEntity($sellerBusiness, $this->request->data, [
'associated' => [
'SellerBusinessCategories'
]
]);
debug($sellerBusiness);
if ($save_s_b = $this->SellerBusinesses->save($sellerBusiness)) {
debug($save_s_b);
$this->Flash->success(__('The seller business has been saved.'));
return $this->redirect(['controller' => 'SellerBusinesses', 'action' => 'view', $save_s_b->id]);
} else {
$this->Flash->error(__('The seller business could not be saved. Please, try again.'));
}
}
But this is not saving record to seller_business_categories table.
From document Here
// Multiple select element for belongsToMany
echo $this->Form->input('tags._ids', [
'type' => 'select',
'multiple' => true,
'options' => $tagList,
]);
But this is not working. Is there any other way for hasMany
debug($this->request->data); gives
'seller_business_categories' => [
'_category_ids' => [
(int) 0 => '1',
(int) 1 => '2'
]
],
and debug($sellerBusiness); after patchEntity
object(App\Model\Entity\SellerBusiness) {
'seller_id' => (int) 16,
'company_name' => 'My company',
'seller_business_categories' => [
(int) 0 => object(App\Model\Entity\SellerBusinessCategory) {
(int) 0 => '1',
(int) 1 => '2',
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
(int) 0 => true,
(int) 1 => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'SellerBusinessCategories'
}
],
'[new]' => true,
'[accessible]' => [
'*' => true,
],
'[dirty]' => [
'seller_id' => true,
'company_name' => true,
'seller_business_categories' => true,
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'SellerBusinesses'
}
and error
Error: SQLSTATE[HY000]:
General error: 1364 Field 'category_id' doesn't have a default value in seller_business_categories table
SellerBusinessesTable
$this->belongsToMany('Categories');
CategoriesTable
$this->belongsToMany('SellerBusinesses', [
'foreignKey' => 'category_id',
'targetForeignKey' => 'seller_business_id',
'joinTable' => 'categories_seller_businesses'
]);
// Pivot tables must be sorted alphabetically
bin/cake bake migration CreateCategoriesSellerBusinesses seller_business_id:integer category_id:integer created modified
CategoriesSellerBusinessesTable
$this->belongsTo('SellerBusinesses', [
'foreignKey' => 'seller_business_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER'
]);
Add.ctp
<?= $this->Form->create($sellerBusiness, ['type' => 'file']) ?>
...
<?= $this->Form->input('categories', ['type' => 'select', 'options' => $categories, 'multiple' => 'select', 'label' => __('Categories')]) ?>
...
<?= $this->Form->end() ?>
SellerBusinessesController
public function add()
{
$sellerBusiness = $this->SellerBusinesses->newEntity();
if ($this->request->is('post')) {
$sellerBusiness = $this->SellerBusinesses->patchEntity($sellerBusiness, $this->request->data);
$sellerBusiness->seller_id = $this->Auth->user('id');
if(isset($this->request->data['categories']))
{
$sellerBusiness -> categories = $this->SellerBusinesses->Categories->find()->where(['id IN' => $this->request->data['categories']])->all()->toArray();
}
if ($this->SellerBusinesses->save($sellerBusiness)) {
$this->Flash->success(__('The sellerBusiness has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The seller could not be saved. Please, try again.'));
}
}
$categories = $this -> SellerBusinesses-> Categories-> find('treeList');
$this->set(compact('sellerBusiness', 'categories'));
$this->set('_serialize', ['sellerBusiness']);

CakePHP 3.0 Can't save hasMany associated data

I've problem when saving data with hasMany association
This is my table
1) post table: each item has an unique id.
id | title | ...
1 | Aloha | ...
2) images table
id | post_id | image | ...
1 | 1 | abc.jpg | ...
2 | 1 | efg.jpg | ...
My Model (Table)
Posts Model
// PostsTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class PostsTable extends Table {
public function initialize(array $config) {
$this->table('posts');
$this->displayField('title');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('Images', [
'foreignKey' => 'id'
]);
}
}
...
Images Model
// ImagesTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class ImagesTable extends Table {
public function initialize(array $config) {
$this->table('images');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Posts');
}
}
...
My Controller
// PostsController.php
...
public function add() {
$post = $this->Posts->newEntity($this->request->data, [
'associated' => ['Images']
]);
if ($this->request->is('post')) {
if ($this->Posts->save($post, ['associated' => ['Images']])) {
$this->Flash->success('The post has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The post could not be saved. Please, try again.');
}
}
$this->set('post', $post);
}
...
My Template
// add.ctp
<?= $this->Form->create($post); ?>
<?php echo $this->Form->input('title'); ?>
<?php echo $this->Form->input('images.0.image'); ?>
<?php echo $this->Form->input('images.1.image'); ?>
<?php echo $this->Form->input('images.2.image'); ?>
<?= $this->Form->button(__('Submit'), ['class' => 'button-green']) ?>
<?= $this->Form->end() ?>
Input array result Debug
[
'title' => 'Hello',
'images' => [
(int) 0 => [
'image' => 'testa.jpeg'
],
(int) 1 => [
'image' => 'testb.jpeg'
],
(int) 2 => [
'image' => 'testc.jpeg'
]
]
]
(Update)
debug($post)
object(App\Model\Entity\Story) {
'new' => true,
'accessible' => [
'title' => true,
'images' => true
],
'properties' => [
'title' => 'Hello',
'images' => [
(int) 0 => object(App\Model\Entity\Image) {
'new' => true,
'accessible' => [
'post_id' => true,
'image' => true,
'post' => true
],
'properties' => [
'image' => 'testa.jpeg'
],
'dirty' => [
'image' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Images'
},
(int) 1 => object(App\Model\Entity\Image) {
'new' => true,
'accessible' => [
'post_id' => true,
'image' => true,
'post' => true
],
'properties' => [
'image' => 'testb.jpeg'
],
'dirty' => [
'image' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Images'
},
(int) 2 => object(App\Model\Entity\Image) {
'new' => true,
'accessible' => [
'post_id' => true,
'image' => true,
'post' => true
],
'properties' => [
'image' => 'testc.jpeg'
],
'dirty' => [
'image' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Images'
}
]
],
'dirty' => [
'title' => true,
'images' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Stories'
}
I can't figure out what I am doing wrong
Thanks
I haven't looked everything, but I saw there is an error in your association declaration:
$this->hasMany('Images', [
'foreignKey' => 'id'
]);
The docs say:
foreignKey: the name of the foreign key found in the other model. This is especially handy if you need to define multiple hasMany relationships. The default value for this key is the underscored, singular name of the actual model, suffixed with ‘_id’.
So it should be:
$this->hasMany('Images', [
'foreignKey' => 'post_id'
]);
or even:
$this->hasMany('Images');
I've just finished my 3-hour tour with saving hasMany content along with the main model. This struggle seems to be even worse, if considered saving many main model's objects with many associated items.
Foreign key in hasMany relationship is the singular name of the current model (entity) with _id suffix, so it's like:
class MainModel extends Table {
...
public function initialize(array $config) {
...
// remember the "s" at the end of the name
$this->hasMany('VeryWeirdCalleds', [
'className' => 'VeryWeirdCalleds',
'foreignKey' => 'main_model_id',
'propertyName' => 'very_weird_calleds'
]);
...
}
...
}
Then, you set the accessible in the MAIN Entity, so that the MAIN model can save the association based on "very_weird_calleds" index:
class MainModel extends Entity {
protected $_accessible = [
...
'very_weird_calleds' => true,
];
}
And the last (but not least): the Controller save. It's usually the hardest part to overcome, due to the fact, that docs do not clarify the whole process in detail:
class MainModelsController extends AppController {
public function add($data) {
$data = [
[
'name' => 'Hello',
'body' => 'Bla bla',
'very_weird_calleds' => [
[
'name' => 'Very Weird Called'
]
]
]
];
foreach ($data as $record) {
$main = $this->MainModels->newEntity($record);
if(isset($record['images']) && !empty($record['images'])) {
foreach($record['images'] as $record_image) {
$image = $this->MainModels->VeryWeirdCalleds->newEntity();
$image->IMAGE = $record_image['IMAGE'];
$import->very_weird_calleds[] = $image;
}
}
if (!$this->MainModels->save($main)) {
$this->Flash->error('The main model could not be saved. Please, try again.');
}
}
}
Explanation? First of all, we loop through the data, previously prepared as follows:
[ 'main', 'model', 'data', 'association_accessible_property' => [ 'associated_data' ] ] ]
Then we create new entries for associated data, using the same method as for the main model. The last thing, is to add those associated Entities to the main model Entity.
Pay an extreme attention to the names given in this example. The 's'-es and CamelCases are not coincidental.
try this :
<?php echo $this->Form->input('0.Images.image'); ?>
<?php echo $this->Form->input('1.images.image'); ?>
<?php echo $this->Form->input('2.images.image'); ?>
with int before , according with http://book.cakephp.org/3.0/en/views/helpers/form.html#field-naming-conventions

Resources