laravel-ardent / ardent

Self-validating, secure and smart models for Laravel's Eloquent ORM
BSD 3-Clause "New" or "Revised" License
1.39k stars 211 forks source link

Using password_confirmation when manually assigning value #47

Closed misaizdaleka closed 11 years ago

misaizdaleka commented 11 years ago

I have something like this:

if (!empty($data['password'])){ $this->password = Hash::make($data['password']); $this->password_confirmation = Hash::make($data['password_confirmation']);
} $this->save();

When saving, I am always getting an error "The password confirmation does not match." I am using "confirmed" rule for the password field. Any ideas?

Thanks

misaizdaleka commented 11 years ago

P. S: I went through this issue too, but it didn't help https://github.com/laravelbook/ardent/issues/21 P. P. S. I don't have password_confirmation column in the db, of course.

jrahmy commented 11 years ago

Not sure if it's related, but I don't see why you're hashing both values at all? You'll get 2 different hashes (even with the same value).

misaizdaleka commented 11 years ago

Great point, but it's still not working, even without the hash:

if (!empty($data['password'])){ $this->password = $data['password']; $this->password_confirmation = $data['password_confirmation']; } $this->save();

misaizdaleka commented 11 years ago

Btw, these are my rules: array(5) { ["first_name"]=> string(8) "required" ["last_name"]=> string(8) "required" ["email"]=> string(14) "email|required" ["password"]=> string(18) "required|confirmed" ["password_confirmation"]=> string(8) "required" }

jrahmy commented 11 years ago

And you've tried var_dump()ing both values before calling save() to make sure they're identical? How is $data being set? Input::all()?

misaizdaleka commented 11 years ago

Yes, I have, they are identical without hashing. I'm doing this:

if (!$data) $data = Input::all();

misaizdaleka commented 11 years ago

Anyway, is my workflow ok? I am assigning password value (which is a column in the db), I am assigning password_confirmation value (which is not a column in the db) and then I'm running save.

Also, in this worklfow, if I don't do hashing (because values need to be compared), how do I later hash the password, after validation passes? Maybe use model event - http://four.laravel.com/docs/eloquent#model-events

jrahmy commented 11 years ago

Workflow looks fine to me.

As for hashing, I would do it in your afterSave() method for that model. Ardent also has an auto-hash feature and I'm sure you could also use model events. Whatever makes the most sense to you.

As for your original problem I just know that both attributes need to be set identically when save() is called for it to pass. Are you using any special Ardent features like autohydration? I notice you're calling $this, are you putting this code in a method for your model or what's the context?

misaizdaleka commented 11 years ago

I am not using autohydration. Yes, this is a part of a model's method. The thing is that I had several models before this one, and they all worked fine with the similar method (but neither of them had password confirmation).

Maybe I'll try with regular validation and see how it goes there.

Thanks for your help, Jeremy!

misaizdaleka commented 11 years ago

I solved it!!! Finally!

What I didn't add to my model was this:

public $autoPurgeRedundantAttributes = true;

I didn't know that it was obligatory for password_confirmation. Because of that, Laravel was trying to save a non-existent password_confirmation field into the db and I was actually getting an exception for that.

jrahmy commented 11 years ago

Glad you got it sorted :)

markalanevans commented 11 years ago

@misaizdaleka How do you update a record in the users table for example if the password has validation rules of required|confirmed and password_confirmed : required

When updating the user model, i get validation errors because i don't have a password_confirmed field...

$user = new User::where("email", '=', 'me@me.com')->get();
$user->email = 'you@me.com';
$user->save()

Fails because i don't have a password field.

How do you specify that these rules should only apply for fields on insert, not on update....

misaizdaleka commented 11 years ago

This is what I did - I created an additional function (I called it feed()), which handles ardent rules. So, I call feed() and inside, along with fetching the data from Input::all(), I also check if $this->id exists (I am checking if the row is new or is being updated). If it exists, then I am going to remove some rules (in your case, you can remove password_confirmed), and if it doesn't exist, I am going to add some rules.

So, the rules are being applied "dynamically" so to speak. Hope this helps.

markalanevans commented 11 years ago

Where did you call feed()?

misaizdaleka commented 11 years ago

I call feed instead of save. So my feed looks like this: // this is inside of a model public function feed($input) { do some logic with ardent validation rules

assign values to the model from $input
$this->save();
}
markalanevans commented 11 years ago

Ok. gotcha. Thanks!

rikinadhyapak commented 10 years ago

The field under validation must have a matching field of foo_confirmation. For example, if the field under validation is password, a matching password_confirmation field must be present in the input.