CakePHP4 Edit doesnt update record - php

Version: 4.2.9
My edit view is populating my inputs with the data, but when I change them and click on save, its not saving but giving me "user has been saved" message.
UsersController.php edit function
public function edit($id = null)
{
$user = $this->Users->get($id, [
'contain' => ['Userdata'],
]);
if ($this->request->is(['post', 'put'])) {
$user = $this->Users->get($id, [
'contain' => ['Userdata'],
]);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact('user'));
}
my edit.php
<div class="users form large-9 medium-8 columns content">
<?php echo $this->Form->create($user) ?>
<fieldset>
<legend><?= __('Edit User') ?></legend>
<?php
echo $this->Form->control('userdata.Email');
echo $this->Form->control('userdata.UserName');
echo $this->Form->control('PasswordHashed', ['type' => 'password']);
?>
</fieldset>
<?= $this->Form->button(__('save')) ?>
<?= $this->Form->end() ?>
</div>

Your update code is not complete, you have omitted the patchEntity method.
public function edit($id = null)
{
// call query only once
$user = $this->Users->get($id, [
'contain' => ['Userdata'],
]);
// Call the debug method just to test and understand your data
// debug($user);
// debug($this->getRequest()->getData()); // debug posted data
if ($this->request->is(['post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->getRequest()->getData());
// debug patched data debug($user); exit;
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact('user'));
}

Related

how to append the username in url instead of user_id in cakephp 3

I want my url like this format http://localhost/blog/users/username instead of this http://localhost/blog/users/view/6
I have this code in Users view index.ctp
<?php foreach ($users as $user): ?>
<?= $this->Html->link(__('View Profile'), ['action' => 'view', $user['user']['slug']]) ?>
<?php endforeach; ?>
routes.php
<?php
$routes->connect('/user/*', array('controller' => 'users', 'action' => 'view'));
?>
//public function view($id = null)
public function view($username)
{
$users = $this->Users->get($username, [
'contain' => ['Subjects'] // i have relation
]);
$this->set('users', $users);
$this->set('_serialize', ['user']);
}
I tried this link but it not solved my problem
public function edit($id = null)
{
//$logged_user_id=$this->request->Session()->read('Auth.user.id');
$logged_user_id=$this->Auth->user('id');
if($logged_user_id==$id){
$user = $this->Users->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success(__('User profile successfuly updated.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
} else {
$this->Flash->error(__('You are not allowed to do this.'));
return $this->redirect(['action' => 'index']);
}
}
In index.ctp
<?php foreach ($users as $user): ?>
<?= $this->Html->link(__('View Profile'), ['action' => 'view', $user->username]) ?>
<?php endforeach; ?>
Please change $user->username as per your structure.
You don't have to do anything in your routs.php
the username will receive as an argument of the function view
function view($username){
//Your code
}
The get function uses the model's primary key field. It might be possible to change your primary key to username, but I suspect that will cause you other problems. Instead, try this:
$users = $this->Users->find('first')
->where(['username' => $username])
->contain(['Subjects']);
Also, is there a reason that your variable here is plural ($users)? You should only be getting a single user from this, right?

how to prevent other users to edit my profile in cakephp3

I have simple program using cakephp3, when I try to directly put this into browser:
http://localhost/sample/users/edit/82
it directly goes to login page. Then after the login, my code still can edit the profile even that profile is not the current user login.
Below is my edit code
public function edit($id = null)
{
$user = $this->Users->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->data);
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.'));
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
edit.ctp
<div class="actions columns large-2 medium-3">
<h3><?= __('Actions') ?></h3>
<ul class="side-nav">
<li><?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', $user->id],
['confirm' => __('Are you sure you want to delete # {0}?',
$user->id)]
)
?></li>
<li><?= $this->Html->link(__('List Users'), ['action' => 'index']) ?>
</li>
</ul>
<div class="users form large-10 medium-9 columns">
<?= $this->Form->create($user) ?>
<fieldset>
<legend><?= __('Edit User') ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
You have to check the existing user is trying to update his/her profile. You can do something like this.
All this on top of your edit method
public function edit($id = null)
{
$logged_user_id=$this->Auth->user('id');
if($logged_user_id==$id){
$user = $this->Users->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->data);
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.'));
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
} else {
$this->Flash->error(__('You are not allowed to do this.'));
}
}
In my case and like ndm say, i don't use session, that's what i do (hope it helps):
public function edit($id = null)
{
if(!is_null($this->Auth->user())): // if the user is logged
if(is_null($id)) { $id = $this->Auth->user('id'); }
if($this->Auth->user()['group_id']<>1): // in my case group 1 is for the administrator group, i let them edit profile
$id = $this->Auth->user('id'); // in this case, if the user is not an administrator, id will always be his "user id"
endif;
endif;
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'edit', $id]);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}

update multi tables in cakephp

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 :)

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