Attempt to read property "new_password" on array - php

I'm having a problem executing a method that changes the password of the user logged into the system, because it is not recognizing array column to change password. The error is Attempt to read property "new_password" on array.
dd($validations)
array:3 [▼ // app/Http/Controllers/ChangePasswordController.php:22
"current_password" => "12345."
"new_password" => "67890."
"confirm_new_password" => "67890."
]
method
public function updatePassword(ChangePasswordRequest $request)
{
$user = Auth::user()->name;
$validations = $request->validated();
User::find(Auth::user()->id)->update(['password'=> Hash::make($validations->new_password)]);
return redirect('change_password')->with('success-update-password',"$user changed your password with sucess.");
}

User::whereId(Auth::user()->id)->update(['password'=> Hash::make($validations['new_password'])]);

Related

Error message: Creating default object from empty value

Facing this error message but not sure what is wrong with it? Tried the solutions at StackOverflow and other forums but didn't work either.
The error is at line $review->title=$request->title;
public function updateReview(Request $request)
{
// dd($request->all());
$review = Review::find($request->id);
$review->id=$request->id;
$review->title=$request->title;
$review->review=$request->review;
$review->rating=$request->rating;
$review->save();
return redirect('/');
}
A dd($request->all()); returns the following:
array:5 [▼
"id" => "3"
"title" => "User 3 has updated title"
"review" => "User 4 just updated review"
"rating" => "5"
"_token" => "pGFVAzHNg7HmXbkMXylxcM6biqaGnwFmsxjsrTgl"
]
And these are my routes:
Route::get('/edit_review/{id}', 'App\Http\Controllers\UserController#editReview');
Route::post('/update', 'App\Http\Controllers\UserController#updateReview')->middleware('user');
You're getting this error Warning: Creating default object from empty value because $review->title returns false.
find() takes an id and returns a single model. If no matching model exist, it returns null.
You can use findOrFail() instead of find(), if the record not matched then findOrFail() will throw a 404 error :
$review = Review::findOrFail($request->id);
I think you've missed to define a parameter on your function, that passes with your route, probaby its {id} :
public function updateReview(Request $request, $id)
{
$review = Review::findOrFail($id);
//...
}

How to create a custom password field for Laravel Auth

I need to login users registered in the table Igrejas that have the fields responsavel_cpf and responsavel_senha, but Laravel in the function validateCredentials expects the name 'password'.
public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];
}
I tried to login using attempt without success:
$userdata = array(
'responsavel_cpf' => Input::get('email'),
'responsavel_senha' => Input::get('password')
);
if (Auth::guard('igrejas')->attempt($userdata)) {
return Redirect::to('dashboard_paroquia');
} else {
return Redirect::to('login');
}
What do I do to replace the default fields email and password with responsavel_cpf and responsavel_senha?
You can override the password column in your user model like so:
// User.php
public function getAuthPassword()
{
return $this->custom_pw_field;
}
However, if you actually want to pass an array that does not explicitly contain password to Auth::guard('xxx')->attempt($credentials) (for which there is no reason!), you'll probably have to override and add the Illuminate\Auth\EloquentUserProvider manually which seems a lot of work.
So I would suggest to just use the following:
Auth::guard('xxx')->attempt([
'email' => $request->post('email'),
'password' => $request->post('password')
]);
The password key should then validate against the custom_pw_field that you defined.
Explanation
By looking at the source of Illuminate\Auth\EloquentUserProvider and checking the function public function retrieveByCredentials(array $credentials), you can see what it does:
Find the first record in the auth table that matches all the conditions in the $credentials array except for password (so just email in the example above). So you could add for instance another key like is_webmaster like $authGuard->attempt(['email' => $request->post('email'), 'is_webmaster' => 1]) which would then retrieve the first user record that has these properties.
After this record is retrieved, the hash from its password column is then checked against your input.

Store data using modal and pass $id variable

I want to pass the variable id from (the url is /xxxx/{{id}} ) to store
I have a modal box which opens a form. This info is then stored using the controller shown below:
I tried adding $id to pass through the controller (the url is /xxxx/{{id}} )
OpenHome Controller
public function store(Request $request,$id)
$option = new Option;
$option->time = $request->input('time');
$option->date = $request->input('date');
$option->save();
return view('option.create');
ERROR: Type error: Too few arguments to function
App\Http\Controllers\option::store(), 1 passed and exactly 2 expected
dd($request->all());
array:3 [▼
"_token" => "7O23EkldYOYj1d7Fc2xNflcPWMY67ytGTkrymy9g"
"time" => "00:12"
"date" => "12-05-1996"
]
In your question you imply an update of an existing record, but in your code it implies the creation of a new option.
If you wanted to update an option with the $id = 1 you need to have the following route.
Route::put('/options/{id}', 'OptionController#update');
Inside your controller.
public function update(Request $request, $id)
{
$option = Option::find($id);
$option->update([
'time' => $request->input('time'),
'date' => $request->input('date'),
]);
// Redirect to display the list of options.
return redirect('/options');
}
However if you just wanted to pass an additional variable to the store method for use inside the store method, make sure the Route only has single set of {} around the variable.
Route::post('/option/{variable}', 'OptionController#store');
public function store(Request $request, $variable)
{
// User the $variable passed as a route parameter.
}

rules() function in Laravel Request doesn't create unique slugs

I'm trying to make simple unique slugs. The slugs are saved correctly in database, so the function is working. I have problems with making them unique.
I have this rule in TagCreateRequest.php
public function rules()
{
$rules = [
'tag' => 'required|min:3',
'tag_slug' => 'required|alpha_dash|unique:tag,tag_slug,'
];
$rule = 'unique:tag';
$segments = $this->segments();
$id = intval(end($segments));
if ($id != 0) {
$rule .= ',tag_slug,' . $id;
}
$rules['tag_slug'][] = $rule;
return $rules;
}
and this in my store function in the controller
public function store(TagCreateRequest $request)
{
$tag = new Tag();
foreach (array_keys($this->fields) as $field) {
$tag->$field = $request->get($field);
}
$tag->save();
return redirect()->route('tags');
}
The error is about trying to add duplicate value
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'unique slug' for key 'tags_tag_unique'
Can someone help me to fix this issue?
You can access the id field magically. ID must be the same route parameter used in your route.
If you use id parameter like as Route::put('post/{id}/update') then you can magically access the id parameter inside your form request. Otherwise, if you call the parameter of {post} Route::put('post/{post}/update'), in your form request you must be call $this->post instead of $this->id, ok?
Please try it:
public function rules()
{
$rules = [
'tag' => 'required|min:3'
];
$slugRule = 'required|alpha_dash|unique:tag_slug';
if (! empty($this->id)) {
$slugRule = 'required|alpha_dash|unique:tag_slug,'.$this->id;
}
$rules['tag_slug'] = $slugRule;
return $rules;
}
This FormRequest will work fine on the store() and update() methods if you inject him in both methods.
See it:
// Your store route
Route::post('/post/store', ['as' => 'post.store', 'uses' => 'YourController#store']);
// YourController store method
public function store(NameSpaced\FormRequest $request)
{
// ...
}
// Your update route
Route::post('/post/{id}/update', ['as' => 'post.update', 'uses' => 'YourController#store']);
// YourController update method
public function update(NameSpaced\FormRequest $request)
{
// ...
}
$rules = [
'tag' => 'required|min:3',
'tag_slug' => 'required|alpha_dash|unique:[table name],[column name]'
];
Try this the first is table name and the second is column name that you wanted to unique, write without adding square braces. or you just pass table name like this,
$rules = [
'tag' => 'required|min:3',
'tag_slug' => 'required|alpha_dash|unique:[table name]'
];
laravel auto checks for the column.
I hope it helps.
I would suggest that you automatically generate a new slug whenever you are creating a tag. I got myself in same issues that you have listed here, so i decided on automatically generating whenever i am creating a new item. I used laravel-sluggable. It automatically generates unique slugs.
As per your question, i have defined a unique slug rule in one of my demo apps like this:
public function rules()
{
return [
'name' => 'required|string|max:255',
'slug' => 'required|string|max:255|unique:categories,slug,'.$this->segment(3),
];
}
Please note that $this->segment(3) refers to the id of the model being updated in the backend pages, it can be different in your application.

Validate user when email and password are in seperate tables cakephp

A form takes in an email and pw
<?= $this->Form->create() ?>
<?= $this->Form->control('email') ?>
<?= $this->Form->control('password') ?>
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>
The email is stored as an ID in Users, and Password is in password table
Address is the attribute in Emails table that stores the actual email address
Password is where pw is stores
The authenticate component takes in address - which
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
//here we define what is compared to be authenticated
'username' => 'address',
'password' => 'password'
]
]...
The login function is like normal:
public function login()
{
if ($this->request->is('post')) {
//PUT IN STUFF HERE
$user = $this->Auth->identify();
if ($user) {
$user->last_login = Time::now();//dont put this above uif statement, will automatically create a default object
$this->Auth->setUser($user);
$this->Flash->success('You have been successfully logged in.');
$this->log("Login success", 'debug');
//redirect after login
return $this->redirect($this->Auth->redirectUrl('/users/index'));
}
$this->Flash->error('Your username or password is incorrect.');
$this->log("Login FAILURE", 'debug');
}
}`
How i see it, we either compare email id's or get the form to look directly at the Associated classes 'address' attribute. How does one point the authentication to the attribute in another table like that
Thanks
You have to create Custom Authentication Objects for that
On load component
$this->loadComponent('Auth', [
'authenticate' => [
'CustomForm' => [
'fields' => [
'username' => 'address',// Field in your emails table
'password' => 'password',// Field in your users table
'myAssoc'=>'Users'// Custom Filed to get association
],
'userModel' => 'Emails'
]...
Create a file CustomFormAuthenticate.php in /src/Auth/ folder
<?php
namespace App\Auth;
use Cake\Auth\FormAuthenticate;
use Cake\Utility\Inflector;
class CustomFormAuthenticate extends FormAuthenticate
{
public function _findUser($username, $password = null)
{
$result = $this->_query($username);
$myAssoc = false;
if (!empty($this->_config['fields']['myAssoc'])) {
$myAssoc = $this->_config['fields']['myAssoc'];
$result->contain([$myAssoc]);
}
$result = $result->first();
if (empty($result)) {
return false;
}
if ($password !== null) {
$hasher = $this->passwordHasher();
if($myAssoc !== false){
$hashedPassword = $result->{Inflector::underscore(Inflector::singularize($myAssoc))}[$this->_config['fields']['password']];
} else {
$hashedPassword = $result->get($this->_config['fields']['password']);
}
if (!$hasher->check($password, $hashedPassword)) {
return false;
}
$this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
$result->unsetProperty($this->_config['fields']['password']);
}
debug($result);
return $result->toArray();
}
}
Make sure you have association of model Users with Email in your EmailTable.php
$this->hasOne('Users', [
'foreignKey' => 'email_id'
]);
In your login page
<?= $this->Form->create() ?>
<?= $this->Form->control('address') ?> // Field in your email table
<?= $this->Form->control('password') ?>// Field in your users table
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>
I have tested it and its working for me.
I would suggest a less intrusive way, that is, using a custom finder that contains/joins the users table, and sets the password field on the main query using an alias, or on the main entity as a virtual field, that way the built-in authenticator retrieves the data it needs, which is all that matters for the authenticator.
For example in your EmailsTable class, add a finder like this, which selects the proper value for the password field:
public function findAuth(\Cake\ORM\Query $query, array $options)
{
return
$this
->find()
->select([
'Emails.id',
'Emails.address', // you may want to alias this one too
'password' => 'Users.password'
])
->leftJoinWith('Users')
->where([
// the options is always named `username`, this is
// not affected by the `fields` configuration
'Emails.address' => $options['username']
]);
}
With such a finder, all you then need to do is to configure the fields, userModel, and finder options for the auth component, like:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
// set the field to `email`, just like in your form
'username' => 'email'
],
'userModel' => 'Emails',
'finder' => 'auth'
]
// ...
]
]);
This example assumes that Emails is associated with Users via a belongsTo or hasOne association, using the join strategy.
Also note that the username field is set to email just like in your example form, you could as well set both to address (or anything you like actually), it will not affect the finders query, as it creates a new query, and uses the username value that was extracted from the request data via the configured field (the extracted value will always be passed in the username key of the $options array, unless the finder configuration would be an array that already has a key named username).
See also
Cookbook > Controllers > Components > Authentication > Customizing Find Query

Categories