cakephp 3 multi level associated save - cakephp

I have a Users model which has a hasOne relationship to an Employees model. When I save a user I also add a record in the Employees table with the user_id. This works fine.
The Employee can be associated to belongsToMany Courses through CoursesEmployees table. This saves ok when I only save the Employees.
My problem is I want to save all 3 three but the Courses do not get saved.
Save user -> save employee with new user_id -> save courses chosen for new employee with employee_id in courses_employees
EmployeesTable.php
public function initialize(array $config)
{
$this->table('employees');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
]);
$this->belongsTo('Hotels', [
'foreignKey' => 'hotel_id',
'joinType' => 'INNER'
]);
$this->belongsToMany('Courses', [
'foreignKey' => 'employee_id',
'targetForeignKey' => 'course_id',
'joinTable' => 'courses_employees'
]);
}
users add.ctp:
<?= $this->Form->create($user) ?>
<fieldset>
<legend><?= __('Add User') ?></legend>
<?php
echo $this->Form->input('role_id', ['options' => $roles, 'empty' => true]);
echo $this->Form->input('email');
echo $this->Form->input('active');
echo $this->Form->input('activation_key');
echo $this->Form->input('password');
echo $this->Form->input('employee.name');
echo $this->Form->input('employee.email');
echo $this->Form->input('employee.surname');
echo $this->Form->input('employee.employee_num');
echo $this->Form->input('employee.courses._ids', ['options' => $courses]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
Here is the post data sent to the add method for save. With this the user and employee get saved correctly but no recored in the courses_employees.
If I save the employee form the employee controller the courses_employees get add ok so I know the associations are setup ok.
[
'role_id' => '1',
'email' => 'asdasd#asdasd.com',
'active' => '11111111111',
'activation_key' => '1',
'password' => 'asdasdadasdasdasda',
'employee' => [
'name' => 'asdasdasdasd',
'email' => 'asdasdasd2dasd.com',
'surname' => 'asdasdads',
'employee_num' => 'asdasdadasdas',
'courses' => [
'_ids' => [
(int) 0 => '2'
]
]
]
]
UserController.php
public function add()
{
$this->loadModel('Courses');
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data, [
'associated' => ['Employees', 'Courses']
]);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$roles = $this->Users->Roles->find('list', ['limit' => 200]);
$courses = $this->Courses->find('list', ['limit' => 200]);
$this->set(compact('user', 'roles', 'courses'));
$this->set('_serialize', ['user']);
}

I have found the solution. I have read the cookbook again and I noted in one of the examples snippets 'associated' => ['Tags', 'Comments.Users']
I have applied this to my controller and it now works. It is saving on all levels.
$user = $this->Users->patchEntity($user, $this->request->data, [
'associated' => ['Employees', 'Employees.Courses']
]);

Related

cakephp $this- auth- identify() return false

please i really need help i tried almost everything on forums
The method $this->Auth->identify(); always return false
the length fo password in database is varchar(255)
my cakephp version is 3.6.8
candidatcontroller
public function login()
{
if ($this->request->is('post'))
{
$candidat = $this->Auth->identify();
if ($candidat)
{
$this->Auth->setUser($candidat);
return $this->redirect(['Controller'=>'Candidat','action'=>'index']);
}
$this->Flash->error(__('The candidat could not be saved Please try again.'));
}
}
appcontroller
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler', [
'enableBeforeRedirect' => false,
]);
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authError' => 'Vous croyez vraiment que vous pouvez faire cela?',
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email','password' => 'password']
]
],
'loginAction' => [
'controller' => 'candidat',
'action' => 'login',
],
'storage' => 'Session'
]);
}
login
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('login') ?></legend>
<?php
echo $this->Form->control('Email_cand',['label'=>'Email']);
echo $this->Form->control('password',['label'=>'mot de passe']);
?>
</fieldset>
<?= $this->Form->button(__('connecter')) ?>
<?= $this->Form->end() ?>

Cakephp 3: showing two values on form drop-down from associated table

I have three tables:
BudgetRevenues - belongs to AnnualOperatingBudgets
AnnualOperatingBudgets has an Azinstitutions
In my add form for Budget Revenues the first selection is for Budget Year & Institution.
public function add()
{
$budgetRevenue = $this->BudgetRevenues->newEntity();
$associated = [ 'RevenueTitles', 'AnnualOperatingBudgets', 'AnnualOperatingBudgets.Azinstitutions'];
if ($this->request->is('post')) {
$budgetRevenue = $this->BudgetRevenues->patchEntity($budgetRevenue, $this->request->getData(), ['associated' => $associated]);
if ($this->BudgetRevenues->save($budgetRevenue)) {
$this->Flash->success(__('The budget revenue has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The budget revenue could not be saved. Please, try again.'));
}
$annualOperatingBudgets = $this->BudgetRevenues->AnnualOperatingBudgets->find('list', ['keyField' => 'id', 'valueField' => ['budget_year', 'azinstitutions_id']]);
$revenueTitles = $this->BudgetRevenues->RevenueTitles->find('list', ['keyField' => 'id', 'valueField' => 'revenue_title']);
$this->set(compact('budgetRevenue', 'revenueTitles', 'annualOperatingBudgets', 'AnnualOperatingBudgets.Azinstitutions'));
}
In my code I can call the budget year (a field in AnnualOperatingBudgets) and the azinstitution_id. But I would like it to show the name of the institution. That is in the azinstitutions table linked by the azinstitution_id in the AnnualOperatingBudgets table.
Right now the form shows 2015;1
I would like it to show 2015 ASU
my add.ctp looks like this:
<div class="budgetRevenues form large-9 medium-8 columns content">
<?= $this->Form->create($budgetRevenue) ?>
<fieldset>
<legend><?= __('Add Budget Revenue') ?></legend>
<?php
echo $this->Form->control('annual_operating_budget_id', ['label' => 'Budget Year & Institution'], ['options' => $annualOperatingBudgets ]);
echo $this->Form->control('revenue');
echo $this->Form->control('revenue_title_id', ['options' => $revenueTitles]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
you can do with a calculated field
$query = $this->BudgetRevenues->AnnualOperatingBudgets->find();
$annualOperatingBudgets = $query
->find('list', [
'keyField' => 'id',
'valueField' => 'full_year'
])
->select([
'id',
'full_year' => $query->func()->concat([
'budget_year' => 'identifier',
' - ',
'Azinstitutions.name' => 'identifier'
])
])
->contain(['Azinstitutions']);
Another solution is using a virtual property in your entity
in your AnnualOperatingBudget Entity create a virtual property
// AnnualOperatingBudget.php
public function _getFullYear()
{
return $this->budget_year.' - '.$this->azinstitution->name;
// You should add a check to ensure
// that $this->azinstitution actually exists
}
//controller
$annualOperatingBudgets = $this->BudgetRevenues->AnnualOperatingBudgets
->find('list', ['keyField' => 'id', 'valueField' => 'full_year'])
->contain(['Azinstitutions]);

How to save associated joinData in cakephp 3.x

I have Problems and Fields in a many-to-many relationship. The join table fields_problems has a field named fieldvalue I am trying to have a form that will insert a problem record and also multiple records into fields_problems.
/src/Model/Table/ProblemsTable.php
class ProblemsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->table('problems');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Fields', [
'foreignKey' => 'problem_id',
'targetForeignKey' => 'field_id',
'joinTable' => 'fields_problems'
]);
}
...
/src/Model/Table/FieldsTable.php
class FieldsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->table('fields');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Problems', [
'foreignKey' => 'field_id',
'targetForeignKey' => 'problem_id',
'joinTable' => 'fields_problems'
]);
}
...
/src/Model/Table/FieldsProblemsTable.php
class FieldsProblemsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->table('fields_problems');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Fields', [
'foreignKey' => 'field_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Problems', [
'foreignKey' => 'problem_id',
'joinType' => 'INNER'
]);
}
...
And I want to Add a new problem, link it to fields, and add values to the fieldvalue field in the join table.
So I have this /src/Template/Problems/add.ctp
<div class="problems form large-10 medium-9 columns">
<?= $this->Form->create($problem) ?>
<fieldset>
<legend><?= __('Add Problem') ?></legend>
<?php
echo $this->Form->input("Problems.id");
echo $this->Form->input('Problems.summary');
echo $this->Form->input('Problems.Fields.0._ids', [
'type' => 'select',
'multiple' => false,
'options' => $fields,
]);
echo $this->Form->input('Problems.Fields.0._joinData.fieldvalue');
echo $this->Form->input('Problems.Fields.1._ids', [
'type' => 'select',
'multiple' => false,
'options' => $fields,
]);
echo $this->Form->input('Problems.Fields.1._joinData.fieldvalue');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
And this add() in /src/Controller/ProblemsController.php
public function add()
{
$problem = $this->Problems->newEntity();
if ($this->request->is('post')) {
$problem = $this->Problems->patchEntity($problem, $this->request->data, ['associated'=>['Fields._joinData']] );
//$problem->dirty('fields',true);
if ($this->Problems->save($problem)) {
$this->Flash->success(__('The problem has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The problem could not be saved. Please, try again.'));
}
}
$fields = $this->Problems->Fields->find('list', ['limit' => 200]);
$this->set(compact('problem', 'fields'));
$this->set('_serialize', ['problem']);
}
When I fill out and submit the app form, the Problem record is saved, but the association is not, nothing gets inserted into fields_problems.
What am I doing wrong that is preventing the associated joinData from being saved?
Despite the cookbook (http://book.cakephp.org/3.0/en/views/helpers/form.html) saying to use the special _ids key, don't!
Changing "_ids" to "id" fixed the form and now it functions properly saving the data into the jointable.
Here is the example from the cookbook that I built my app with
echo $this->Form->input('tags.0.id');
echo $this->Form->input('tags._ids', [
'type' => 'select',
'multiple' => true,
'options' => $tagList,
]);
Here is how it should be
echo $this->Form->input('tags.0.id', [
'type' => 'select',
'multiple' => false,
'options' => $tagList,
]);

complex multiple associations save in cakephp 3

I am saving an Employee which is associated with a hasMany relationship with Courses through EmployeesCourses table. This all works fine, the employee gets added and the new employee_id and the course_id get created into EmployeesCourses table.
I am now trying to add a record into the users table for the employee and the new user_id gets saved with the employee as it gets created. All other recored still get saved but I do not get anytime for the users table and no id in Employee.user_id
EmployeesController.php
public function add()
{
$employee = $this->Employees->newEntity();
if ($this->request->is('post')) {
$employee = $this->Employees->patchEntity($employee, $this->request->data, [
'associated' => ['Users', 'Courses']
]);
if ($this->Employees->save($employee)) {
$this->Flash->success(__('The employee has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The employee could not be saved. Please, try again.'));
}
}
$businesses = $this->Employees->Businesses->find('list', ['limit' => 200]);
$courses = $this->Employees->Courses->find('list', ['limit' => 200]);
$this->set(compact('employee', 'users', 'businesses', 'courses'));
$this->set('_serialize', ['employee']);
}
employees add.ctp
<?= $this->Form->create($employee) ?>
<fieldset>
<legend><?= __('Add Employee') ?></legend>
<?php
echo $this->Form->input('user.email');
echo $this->Form->input('user.new_password', ['value' => '', 'type' => 'password']);
echo $this->Form->input('user.confirm_password', ['value' => '', 'type' => 'password']);
echo $this->Form->input('business_id', ['options' => $hotels]);
echo $this->Form->input('name');
echo $this->Form->input('email');
echo $this->Form->input('surname');
echo $this->Form->input('employee_num');
echo $this->Form->input('courses._ids', ['options' => $courses]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
Employees Model
public function initialize(array $config)
{
$this->table('employees');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
]);
$this->belongsTo('Businesses', [
'foreignKey' => 'hotel_id',
'joinType' => 'INNER'
]);
$this->belongsToMany('Courses', [
'foreignKey' => 'employee_id',
'targetForeignKey' => 'course_id',
'joinTable' => 'courses_employees'
]);
}
Users model
public function initialize(array $config)
{
$this->table('users');
$this->displayField('email');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Roles', [
'foreignKey' => 'role_id'
]);
$this->hasOne('Employees', [
'foreignKey' => 'user_id'
]);
$this->hasOne('Businesses', [
'foreignKey' => 'user_id'
]);
}

Using BelongsToMany association in Cakephp 3

I am trying to associate multiple games to a continuity in my database.
I have 3 tables: continuities, continuities_games and games. The continuities_games table has a continuity_id and a game_id. When I try to select the different games in my selection input, it creates a new game entry in the database and then creates a entry into the join table linking it to that new game entry instead of linking it to the originally selected game.
This is the initialize function in my ContinuitiesTable:
public function initialize(array $config){
parent::initialize($config);
$this->belongsToMany('Games');
}
And for my GamesTable:
public function initialize(array $config){
parent::initialize($config);
$this->displayField('name');
$this->addBehavior('Tree');
//Associations
$this->hasMany('Children', [
'className' => 'Games',
'foreignKey' => 'parent_id',
'dependant' => true,
'cascadeCallbacks' => true,
]);
$this->belongsTo('Parent', [
'className' => 'Games',
]);
$this->hasMany('Books');
$this->belongsToMany('Continuities');
}
This is my edit function in the ContinuitiesController:
public function edit($id=null){
$continuity = $this->Continuities->find()->where(['id'=>$id])->contain('Games')->first();
if ($this->request->is(['post', 'put'])) {
debug($this->request->data);
$continuity->start_date = $this->request->data['start_date']['year'].'-'.$this->request->data['start_date']['month'].'-'.$this->request->data['start_date']['day'];
$continuity->end_date = $this->request->data['end_date']['year'].'-'.$this->request->data['end_date']['month'].'-'.$this->request->data['end_date']['day'];
//$continuity->start_date = $this->request->data['start_date'];
//$continuity->end_date = $this->request->data['end_date'];
$continuity->games = $this->request->data['games'];
debug($this->Continuities->newEntity($this->request->data)->toArray());
debug($continuity);
if ($result = $this->Continuities->save($continuity, ['associated'=>['Games']])) {
$this->Flash->success(__('The continuity has been updated.'));
return $this->redirect(['action' => 'view', $continuity->id]);
}
$this->Flash->error(__('Unable to update the continuity.'));
}
$games = $this->Continuities->Games->getGamesList();
$this->set(compact('continuity', 'games'));
}
And finally the edit.ctp form:
<?= $this->Form->create($continuity) ?>
<fieldset>
<legend><?= __('Edit Continuity') ?></legend>
<?= $this->Form->input('start_date') ?>
<?= $this->Form->input('end_date') ?>
<?= $this->Form->input('games', ['multiple'=>true]) ?>
</fieldset>
<?= $this->Form->button(__('Submit')); ?>
<?= $this->Form->end() ?>
Thanks.
There were a few things that needed to be changed to make this work.
First is the Continuities table:
public function initialize(array $config){
parent::initialize($config);
$this->belongsToMany('Games',
[
'targetForeignKey' => 'game_id',
'foreignKey' => 'continuity_id',
'joinTable' => 'continuities_games',
]);
}
Next, the Games table:
public function initialize(array $config){
parent::initialize($config);
$this->belongsToMany('Continuities',
[
'targetForeignKey' => 'continuity_id',
'foreignKey' => 'game_id',
'joinTable' => 'continuities_games',
]);
}
Now, the ContinuitiesController edit() function:
public function edit($id=null){
$continuity = $this->Continuities->find()->where(['id'=>$id])->contain('Games')->first();
if ($this->request->is(['post', 'put'])) {
$this->Continuities->patchEntity($continuity, $this->request->data(), ['associated'=>['Games']]);
if ($result = $this->Continuities->save($continuity, ['associated'=>['Games']])) {
$this->Flash->success(__('The continuity has been updated.'));
return $this->redirect(['action' => 'view', $continuity->id]);
}
$this->Flash->error(__('Unable to update the continuity.'));
}
$games = $this->Continuities->Games->getGamesList();
$this->set(compact('continuity', 'games'));
}
And finally, the edit.ctp
<?= $this->Form->create($continuity) ?>
<fieldset>
<legend><?= __('Edit Continuity') ?></legend>
<?= $this->Form->input('start_date') ?>
<?= $this->Form->input('end_date') ?>
<?= $this->Form->input('games._ids', ['options' => $games, 'multiple'=>true]) ?>
</fieldset>
<?= $this->Form->button(__('Submit')); ?>
<?= $this->Form->end() ?>

Resources