Shawn Dellysse Tue Feb 15 13:03:52 -0500 2011

Subject: Not having luck with advanced validation.

I have a users table that contains a field "encrypted_password", and a form that contains a password and a password_confirmation field. Example:

$_POST['user'] = array(
...
'password' => '...',
'password_confirmation' => '...',
...
);

$user = new User($_POST['user']);

In my User model, I want to be able to md5 the password before saving it only when both the password and its confirmation are equal and not empty. I tried using a setter, but it seems like it's not even getting run. Should I be using a before_save callback? If so, how does that factor into the validation.

Also, is it possible to make $user->is_valid() to be false when password and password_confirmation are not equal?

Running phpar nightly Feb14.


Shawn Dellysse Thu Feb 17 23:54:08 -0500 2011

nevermind, figured it out myself.

What I was looking for was validates_confirmation_of, which didn't exist in phpar. I wrote it, you can get my fork with the changes from http://github.com/sdellysse/php-activerecord. I submitted a pull request also.

examples for those having similar issues:
class User extends ActiveRecord\Model {
static $before_validation = array(
'encrypt_password_if_changed',
);
static $validates_confirmation_of = array(
array('password'),
);
static $validates_presence_of = array(
array('ecrypted_password'),
);
public function encrypt_password_if_changed() {
if(isset($this->password)) {
$this->encrypted_password = User::pw_encryption_scheme($this->password);
}
}

public function set_password($p) {
$this->password = $p;
}
public function set_password_confirmation($p) {
$this->password_confirmation = $p;
}
Devi Mandiri Sat Feb 19 05:23:33 -0500 2011
Shawn Dellysse Sat Feb 19 23:22:27 -0500 2011

While using validate() works, why would you use that instead of the patch I submitted? Rails's ActiveRecord implementation has this feature available, and since this is a port of that to PHP, why not make this functionality available out of the box? Also, I can tell that it was meant to be there originally but got put on the backburner as the error message was already in place before I started working on it.

Devi Mandiri Sat Feb 19 23:29:09 -0500 2011
why would you use that instead of the patch I submitted?

Because my goal is different with yours.
I'm focusing on "wrapper" for Kohana Framework instead patching php-activerecord.

That's the beauty of open source right ?

Shawn Dellysse Sat Feb 19 23:51:39 -0500 2011

Devi Mandiri wrote:

[...]

Because my goal is different with yours. I'm focusing on "wrapper" for Kohana Framework instead patching php-activerecord.

That's the beauty of open source right ?

True, that it is. I now understand; here's to hoping my pull request gets accepted, as I'm not a fan of patching a library either... I'm using that code for a project, and I'd like to keep library modifications to minimum for the next person to work on what I've built.

Benjamin P Sat Feb 26 12:52:22 -0500 2011

Shawn Dellysse wrote:

here's to hoping my pull request gets accepted

Don't worry, if I'd be kla, I would accept it immediately (it behaves as in Rails, it may be useful for the general audience, it's documented, and heck, it works!). The fact that he didn't respond only means he's busy with other stuff right now.

@Devi: can you tell me more why attribute_is_dirty() doesn't work for you? It was committed not long ago, if I remember well I even wrote some unit tests for it.

Devi Mandiri Sat Feb 26 13:08:15 -0500 2011

Still checking my box, attribute_is_dirty() always return false, don't know why.

Taylor Otwell Sat Mar 12 21:31:20 -0500 2011

Shawn,

This looks pretty cool! One question though. It looks like you would have to set a "password_confirmation" property on your model for this to work. If that is the case, how do you keep password_confirmation from being stored in your database?

Thanks,
Taylor

Shawn Dellysse Mon Mar 14 10:19:08 -0400 2011

Taylor,

What I do is in the actual database, I have a property called `encrypted_password`. In the PHP Model, I place the code I wrote above. Notice the functions prefixed with `set_`. These create attributes in the Model, but not in the database. When the `before_validation` callback is ran, it checks to see if the virtual attribute `password` is set, and if so, make the encrypted password from that.

Did I explain this well enough for you? My writing skills are not the greatest.

(1-9/9)