update multi tables in cakephp - php

I'm trying to know what's the wrong with this function , which i need to update only one field in table or the all fields in multi assocatied tables .
The multi update is working fine , but when i going to update only the first column it's not working fine with me
public function edit($id) {
$contractor = $this->Contractors->get($id);
$associated = ['ContractorsAttachments' ];
// Used to get the all attachments associated with Contractors
$ContractorsAttachments = $this->Contractors->ContractorsAttachments->find()->where(['contractor_id' => $id])->all();
if ($this->request->is(['patch', 'post', 'put'])) {
$contractor = $this->Contractors->patchEntity($contractor, $this->request->data );
if ($this->Contractors->save($contractor)) {
$this->Flash->success(__('The Contractors has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The Contractors could not be saved. Please, try again.'));
}
$this->set(compact('contractor','ContractorsAttachments'));
$this->set('_serialize', ['contractor']);
$this->render('add');
}

You can get associated model data using contain.
Use Saving With Associations
After the tweaks your code will be like this
$contractor = $this->Contractors->get($id, ['contain'=>'ContractorsAttachments']);
if ($this->request->is(['patch', 'post', 'put'])) {
$contractor = $this->Contractors->patchEntity($contractor, $this->request->data );
if ($this->Contractors->save($contractor,['associated' => ['ContractorsAttachments']])) {
$this->Flash->success(__('The Contractors has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The Contractors could not be saved. Please, try again.'));
}
Also verify that you Contractors Model has the association defined like this
$this->hasMany('ContractorsAttachments', [
'foreignKey' => 'contractor_id'
]);
Hope this will help :)

Related

Cakephp 4 - Authentication Plugin how to fetch current user name?

I'm using CMS Authentication plugin
I fetch current user name like this but when I update user profile the current user name doesn't get reflected I need to logout first
$user = $this->request->getAttribute('identity');
$name = $user->first_name ?? '';
How to # CakePHP 4.x
update identity object with: $this->Authentication->setIdentity($user);
Full example:
public function editMe()
{
// fetch current identity data
$user = $this->Authentication->getIdentity()->getOriginalData();
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->getRequest()->getData());
if ($this->Users->save($user)) {
$this->Authentication->setIdentity($user); // ----- > update identity data
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'me']);
}
$this->Flash->error(__('The user could not be saved. Please try again.'));
}
$this->set(compact('user'));
}

CakePHP Redirecting to the View page after adding a new record

I have a CakePHP lead management website, and when you make a new lead, I want it to redirect you to the view page for that lead, but I can't figure it out.
Here is my current add controller.
/**
* Add method
*
* #return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add()
{
$lead = $this->Leads->newEmptyEntity();
if ($this->request->is('post')) {
$lead = $this->Leads->patchEntity($lead, $this->request->getData());
if ($this->Leads->save($lead)) {
$this->Flash->success(__('The lead has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The lead could not be saved. Please, try again.'));
}
}
$this->set(compact('lead'));
$this->set('user', $user);
}
The line that I am conserned about is return $this->redirect(['action' => 'index']);.
For the edit controller, I was able to do return $this->redirect(['action' => 'view', $id]); but that doesn't work here, and I can't figure it out.
Any help would be appreciated. If it matters, IDs are just a sequential counter in MySQL.
Try this:
/**
* Add method
*
* #return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add()
{
$lead = $this->Leads->newEmptyEntity();
if ($this->request->is('post')) {
$lead = $this->Leads->patchEntity($lead, $this->request->getData());
if ($savedLead = $this->Leads->save($lead)) {
$this->Flash->success(__('The lead has been saved.'));
return $this->redirect(['action' => 'view', $savedLead->id]);
} else {
$this->Flash->error(__('The lead could not be saved. Please, try again.'));
}
}
$this->set(compact('lead'));
$this->set('user', $user);
}
Here, you need to set a variable containing the result of recording you saved (savedLead in your case). This variable will contain the id of the newly saved recording, and you can pass it to your view method.
Whats the problem with
return $this->redirect(['action' => 'view', $lead->id]);
?

delete all associated child rows when delete the parent row in cakephp 3

I'm new at cake php framework , and i want to delete the row from database and it's associated rows from the child table too .
Now , I can only delete the parent row but without it's child rows ,
How can i delete all the rows associated .
and here's my function for the parent :
public function delete($id = null) {
$contractor = $this->Contractors->get($id);
if ($this->Contractors->delete($contractor)) {
$this->Flash->success(__('The contractor has been deleted.'));
}
else {
$this->Flash->error(__('The contractor could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
and here's the function for the child
public function deleteSub($id = null) {
// $this->request->allowMethod(['post', 'delete']);
$contractorAttachments = $this->Contractors->ContractorsAttachments->get($id);
if($contractorAttachments->Contractors->ContractorsAttachments->delete($contractorAttachments))
{
$this->Flash->success(__('The contractor Attacments has been deleted.'));
}
else {
$this->Flash->error(__('The contractor Attacments could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
But i need to delete the child rows indidiual or delete all the parent row and all the associated child rows .
Can anyone help me with that ?

CakePHP 3 - Conditionally creating newEntity for associated table

I have these three tables:
Bookings (hasOne Sessions)
Sessions (hasOne Files) with foreign key booking_id linking to Bookings
Files (belongsTo Sessions) with foreign key session_id linking to Sessions
In the BookingsController, I have two functions:
New (functions the same as the add function)
Confirm (functions like the edit function)
When a user first submits a new Booking data entry, while a newEntity is created and saved for Bookings and Sessions, no newEntity is created and saved for Files. However, when a Booking/Session is being updated and confirmed, that is when a newEntity in Files is created the very first time. Since the Confirm function can be used many times, I use a conditional if statement to determine if an associated Files entry exists or not - if one exists, a newEntity for Files is created, patched and then saved. If not, it is just patched and saved.
In my Confirm function:
public function confirm($id = null)
{
$booking = $this->Bookings->get($id,[
'contain' => ['Sessions']
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$booking = $this->Bookings->patchEntity($booking, $this->request->data,[
'contain' => ['Sessions']
]);
$fileTable = TableRegistry::get('Files');
$findFiles = $fileTable->find()->where([
'session_id' => $session['id']
])->first();
if($findFiles == null){
$findFiles = $fileTable->newEntity();
$findFiles = $fileTable->patchEntity($findFiles, $data);
$findFiles->session_id = $booking['session']['id'];
if($fileTable->save($findFiles)){
} else {
}
} else {
$findFiles = $filesTable->patchEntity($findFiles, $data);
if($filesTable->save($findFiles)){
} else {
}
}
if ($this->Bookings->save($booking)) {
$this->Flash->success(__('The booking has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The booking could not be saved. Please, try again.'));
}
$this->set(compact('booking'));
$this->set('_serialize', ['booking']);
}
}
However, when trying to use the Confirm function, I get a integrity constraint violation regarding the booking_id foreign key in the Sessions table. I've pinpointed that by removing all the conditional saving code regarding the Files table, the function works fine, however that means neither a newEntity for Files is created when needed.
The easier method is I think just including Files in the New function, but because some bookings could be cancelled, there could potentially be a lot of empty Files data entries.
Update: Including Model and Confirm function's View and form input.
Below is the View of the Confirm function in BookingsController:
<?= $this->Form->create($booking) ?>
<fieldset>
<legend><?= __('Confirm Booking') ?></legend>
<?php
echo $this->Form->input('session.startdate', ['class'=>'form-control']);
echo $this->Form->input('session.enddate', ['class'=>'form-control']);
echo $this->Form->input('session.no_people', ['class'=>'form-control']);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
And the Models for the individual tables.
Bookings:
public function initialize(array $config)
{
parent::initialize($config);
$this->table('bookings');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasOne('Sessions', [
'foreignKey' => 'booking_id'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
return $validator;
}
Sessions:
public function initialize(array $config)
{
parent::initialize($config);
$this->table('sessions');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Bookings', [
'foreignKey' => 'booking_id',
'joinType' => 'INNER'
]);
$this->hasOne('Templates', [
'foreignKey' => 'session_id'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->date('startdate')
->requirePresence('startdate', 'create')
->notEmpty('startdate');
$validator
->date('enddate')
->requirePresence('enddate', 'create')
->notEmpty('enddate');
$validator
->integer('no_people')
->requirePresence('no_people', 'create')
->notEmpty('no_people');
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['booking_id'], 'Bookings'));
return $rules;
}
Files:
public function initialize(array $config)
{
parent::initialize($config);
$this->table('files');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Sessions', [
'foreignKey' => 'session_id',
'joinType' => 'INNER'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->allowEmpty('link');
$validator
->allowEmpty('name');
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['session_id'], 'Sessions'));
return $rules;
}
The foreign key session_id was a required attribute (this was why Files couldn't ever save). I've changed up the function to the following:
public function confirm($id = null)
{
$booking = $this->Bookings->get($id,[
'contain' => ['Sessions', 'Sessions.Files']
]);
if ($this->request->is(['patch', 'post', 'put'])) {
if($booking->session->file == null){ //checks for existing Files array
$template = $this->Bookings->Sessions->Files->newEntity(); //creates new Files entity if one doesn't exist for the associated session
$template->session_id = $booking->session->id; //fills in the foreign key with the currently active session primary key.
if($this->Bookings->Sessions->Templates->save($template)){ //saves the File entity
} else {
}
}
$booking = $this->Bookings->patchEntity($booking, $this->request->data,[
'contain' => ['Sessions', 'Sessions.Files']
]);
$fileTable = TableRegistry::get('Files');
$file = $fileTable->find('all',[
'contain' => ['Sessions'],
'conditions' => ['Sessions.booking_id' => $booking->id, 'Files.session_id' => $booking->session->id]
])->first();
if($file->session_id != $data['session']['id']){ //checks for any changes in session_id
$file->engineer_id = $data['session']['id']; //changes value to match if there isn't a match
$fileTable->save($template);
}
if ($this->Bookings->save($booking)) {
$this->Flash->success(__('The booking has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The booking could not be saved. Please, try again.'));
}
$this->set(compact('booking'));
$this->set('_serialize', ['booking']);
}
}
Something like this should work. Cake will change the query to an UPDATE if an id exists else uses an INSERT.
public function confirm($id = null)
{
$booking = $this->Bookings->get($id, [
'contain' => ['Sessions' => ['Files']]
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$booking = $this->Bookings->patchEntity($booking, $this->request->data, [
'associated' => ['Sessions' => ['associated' => ['Files']]]
]);
if ($this->Bookings->save($booking)) {
$this->Flash->success(__('The booking has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The booking could not be saved. Please, try again.'));
}
$this->set(compact('booking'));
$this->set('_serialize', ['booking']);
}
}

Create multiple forms on one page for different models in cakephp 3.x

I have 2 models: User and UserInfo with relation 1-1 (One user have
one userinfo).
User(id) is primary key for User and UserInfo(user_id)
is both foreign key and primary key for UserInfo.
2 models have the same attribute: email, password.
I want to insert 'user_id', 'email', 'password' to UserInfo when add
new User.
But it seems can insert to UserInfo although User is successful saved.
I think it stop when ($this->User->UserInfos->save($userinfo)) run.
Anybody can help?
--Here is my code---
///**
* Add method
*
* #return void Redirects on successful add, renders view otherwise.
*/
public function add() {
$user = $this->Users->newEntity();
$userinfo = $this->Users->UserInfos->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
$userinfo = $this->Users->UserInfos->patchEntity($userinfo, [
'user_id' => $user['User']['id'],
'email' => $user['User']['email'],
'password' => $user['User']['password'],
]);
if ($this->User->UserInfos->save($userinfo)) {
$this->Flash->success(__('The userinfo has been saved.'));
}
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$this->set(compact('user', 'userinfo'));
$this->set('_serialize', ['user', 'userinfo']);
}
//Code in add.php
<?= $this->Form->create($user) ?>
<fieldset>
<legend><?= __('Add User') ?></legend>
<?php
echo $this->Form->radio('user_type',
[
['value' => '0', 'text' => 'Personal'],
['value' => '1', 'text' => 'Company'],
]);
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->hidden('status', ['value' => '0']);
echo $this->Form->hidden('authority', ['value' => '0']);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
I think you may take the Bookmarker Tutorial as a reference because in the tutorial, new Tags are created while new Bookmarks is created. You can consider this as an idea of your UserInfo creation.
Well I am new to CakePHP too but have this idea for your case.
In your controller, controller\UserController, the action add() creates User entity:
public function add() {
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->User->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']); // same controller's index action, or you can set others
}
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
In your model, model\Table\UserTable.php, create a function called afterSave() which creates UserInfo after User entity is saved
$this->UserInfo->newEntity();
So inside newEntity(), you actually set some data which User doesn't have and UserInfo has, besides user_id (user_id should be set if you have already set up the associations of them)
I strongly recommend to follow all basic tutorials.
Remarks: I suggest you define model's name clearly as CakePHP conventions should be an important topic for CakePHP's developer. So for the above codes/filenames I typed, could be wrong if they don't match your case exactly. e.g. Users / Users / UsersInfo / UserInfo etc.

Categories