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

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'));
}

Related

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]);
?

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.x updating user data

I have written a basic login script and now need to update the data stored in the auth component and then save it to the database, this is what i have so far;
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
$this->Auth->user()->last_activity = date("Y-m-d");
$this->Users->save($this->Auth->user());
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Email or password is incorrect, please try again.'));
}
}
I've tried a few different variations but can't get any to work. Any ideas?
Updating data in cakephp3 is slightly different than cakephp2, Try something like this:
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
$userData = $this->Users->get($user['id']);
$userData->last_activity = date("Y-m-d");
if($this->Users->save($userData)){
$user['last_activity'] = $userData->last_activity; // to update auth component
}
// echo $this->Auth->user('last_activity');
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Email or password is incorrect, please try again.'));
}
}
Another way of updating record in cakephp3 is:
$query = $this->Users->query();
$query->update()
->set(['last_activity ' => date('Y-m-d')])
->where(['id' => $user['id']])
->execute();
But I don't recommend this one as callbacks are not fired.
In Cake3, you can take advantage of the afterIdentify event.
In AppController::initialize, add a listener for the event:
\Cake\Event\EventManager::instance()->on('Auth.afterIdentify', [$this, 'afterIdentify']);
Add AppController::afterIdentify function to handle the event:
public function afterIdentify(CakeEvent $cakeEvent, $data, $auth) {
$users_table = TableRegistry::get('Users');
$user = $users_table->get($data['id']);
$user->last_activity = new Cake\I18n\FrozenTime();
// If you ever need to do password rehashing, here's where it goes
if ($this->Auth->authenticationProvider()->needsPasswordRehash()) {
$user->password = $this->request->data('password');
}
$users_table->save($user);
}
Now, the data returned by the Auth->user() call should always be up-to-date without any extra effort on your part.

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.

CakePHP: sending latest user id to admin's create_employee view

I am trying to send the latest user's id from UsersController to AdminController whose add_employee() action creates a new employee. My users and employees table are separate and what I want to do is when Admin creates a new user its entry go into users table. Then he opens create employee form and the latest user id will be assigned to the new employee the admin is creating. So when admin will open create new employee form the latest user id will be shown in the form.
My UsersController has this code for sending latest user it to AdminsController:
public function get_latest_user_id()
{
$content = $this->User->query("SELECT id FROM users ORDER BY id DESC LIMIT 0,1");
$this->set('latest_user', $content);
}
AdminsController page's add_employee contains this code:
public function add_employee()
{
$this->loadModel('Employee');
$this->set('latest_user', $this->requestAction('/Users/get_latest_user_id'));
if ($this->request->is('post'))
{
$this->Employee->create();
if ($this->Employee->save($this->request->data))
{
$this->Session->setFlash(__('The employee profile has been saved.'));
return $this->redirect(array('action' => 'list_of_employees'));
}
else
{
$this->Session->setFlash(__('The employee profile could not be saved. Please, try again.'));
}
}
}
So UserController's get_latest_user_id function sends latest user id to add_employee function of AdminController. There latest_user is set to latest user id so that when add_employee view is called it is there. But it is not showing. So I want to know that am i doing it right? Please help and thanks.
In add_employee.ctp I am displaying it like this:
echo $latest_user['User']['id'];
Move get_latest_user_id to the User model
public function get_latest_user_id()
{
$user = $this->query("SELECT id FROM users ORDER BY id DESC LIMIT 1");
if (empty($user)) {
return 0;
}
// return only the Id
return $user[0]['users']['id'];
}
In the controller:
public function add_employee()
{
$this->loadModel('Employee');
$this->loadModel('User');
$this->set('latest_user', $this->User->get_latest_user_id());
if ($this->request->is('post'))
{
// ....
}
}
cornelb is right that you should move the method to your User model. Although a more Cake-ish approach would be to use a find('first'), rather than doing a direct query():
// app/Model/User.php
public function getLatest() {
// Get the latest user
$user = $this->find('first', array(
'fields' => array('id'), // Only interested in id? Use this.
'order' => array('User.id' => 'DESC')
));
if (!empty($user)) {
return $user['User']['id'];
} else {
// Nothing was returned, this is very awkward
throw new NotFoundException(__('No users found!'));
}
}
And in your controller:
// app/Controller/AdminsController.php
public function add_employee() {
$this->loadModel('User');
$this->set('latestUser', $this->User->getLatest());
// ...
}

Categories