php-activerecord
php-activerecord copied to clipboard
validates_uniqueness_of activerecord exception : Base table or view not found
I am trying out php active record, it's a great ORM, however I am at a standstill.
I have looked around google, blogs, phpactiverecord documentation as well as statckoverflow for days but have not been able to come across a suitable solution to this problem.
I am able to carry out the basic CRUD (insert,fetch, modify and delete) operations however as soon as i validate an object property using a static $validates_uniqueness_of filter, i get
Fatal error: Uncaught exception 'ActiveRecord\DatabaseException'
With message
exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test_ar.models' doesn't exist' in C:\wamp\www\test_AR\AR\lib\Connection.php on line 325
Here is the code i used in full.
set_model_directory('model'); $cfg->set_connections( array( 'development' => 'mysql://root:asdf@localhost/test_ar', 'test' => 'mysql://username:password@localhost/test_database_name', 'production' => 'mysql://username:password@localhost/production_database_name' ) ); }); /* class user extends ActiveRecord\Model { static $validates_presence_of = array(array('username', 'message' => 'Please supply a username')); //this works just fine static $validates_uniqueness_of = array(array('username'));//this line causes the PDO exception } */ $user = new user(); user::create((array('username'=>'mike','password'=>'test','created'=>time()))); $user::create(array('username'=>'mike')); //cannot even reach this line because of the exeption References i have tried/looked at https://github.com/kla/php-activerecord/issues/274 (though i don't really understand what's going on there) http://www.phpactiverecord.org/projects/main/wiki/Validations#validates_uniqueness_of http:// blog.felho.hu/what-is-new-in-php-53-part-2-late-static-binding.html as well as many others. Platform and php version I am using php 5.3.4 and using nightly build (May 8 2013) I have almost failed to get my head around this. Please advise on how to correct this.
I believe your creation syntax is a bit off, you may want something like this
//create a user in the database but not assigned to a variable
//also this may create an error if you refresh the page as it will have already created a user named mike
User::create((array('username'=>'mike','password'=>'test','created'=>time())));
//create a new user assigned to a variable
//this will have an invalid model as there is already a user called mike
$user = new User(array('username'=>'mike'));
$user->is_valid(); // this should be false
@willpower232 Thanks though changing the creation syntax hasn't really fixed the error. Here is the detailed error.
The error implies that it is looking for a table called "models" in your database which is a bit curious. I have added a uniqueness constraint to my site and it is erroring in the exact same way. I daresay this may actually be a bug unless we have both failed in the same way somehow...
Regrettably, I am not a developer of this repo so have not the power of fixing it, I hope someone else is paying attention somewhere...
Which verison of php are you using? Or how do you validate uniqueness.
Other wise Then it looks like checking for uniqueness I guess is not common practice. Because similar errors are almost no where to be found on the net.
Perhaps for now we'll will have to use the find('all',array('conditions'=>"username LIKE '%somestring%'") as a dirty work around?
As a less dirty work around... in your user model you can add this until the bug is sorted out.
public function validate()
{
if(static::exists(array('conditions'=>"username = ?",$username))
$this->errors->add('username','must be unique');
}
Edit: It'd probably be useful to check "$this->is_new_record()" in the validation function ;p.
Validating uniqueness actually slipped my mind in this instance which is mighty silly of me :-P
Thanks for the work around, will use that.
The error comes from this line in the validates_uniqueness_of function Validations.php apparently
// Retrieve connection from model for quote_name method
$connection = $this->klass->getMethod('connection')->invoke(null);
One more point, the syntax for the exists function does not work for me unless I do this
if (static::exists(array("email" => $this->email)))
$this->errors->add('email', 'must be unique');
Makes sense, I think the proper syntax for my example would've been:
static::exists(array('conditions'=>array("username = ?",$username)));
static::exists(array('conditions'=>array('username'=>$username)));
Glad you have a work around, but this definitely looks to be a proper bug.
One more work around tweak, the work around will return true if you are save() 'ing a model (because you have already created the record) so you need an extra check to make sure that the attributes in question are dirty. For me that looks something like this:
$dirty = $this->dirty_attributes();
if (array_key_exists('email', $dirty) && static::exists(array("email" => $this->email)))
$this->errors->add('email', 'must be unique');
Edit: argh! editor fail!
It is indeed a convenient work around. However checking for dirty attributes will generate a warning if the table is initially empty. (No rows). array_key_exists('email',$dirty) //expects an array. but this wont be the case if the table is empty. (for some reason ;p) so alternatively one could use
if ($this->is_new_record() && static::exists(array('conditions' => array('email' => $this->email)))) {
$this->errors->add('username', 'This email is already taken'); //this will work fine even when the table is empty
}
For extra bonus points, the dirty attributes array simply contains fields that have been set by your code. Ergo if you have re applied the same value to your model, it will be classed as dirty even though it has not changed. This means the work around gets a little more complicated
$dirty = $this->dirty_attributes();
if (array_key_exists('email', $dirty)) {
try {
$currently = User::find($this->id);
}
catch (Exception $e) {
$currently = false;
}
if ((
(is_object($currently) && $currently->email != $this->email)
|| !is_object($currently)
) && static::exists(array("email" => $this->email)))
$this->errors->add('email', 'must be unique');
}
Obviously this will become even more complicated if you validate the uniqueness of multiple fields.
Also note the use of try catch to account for isaootikas most excellent observation.
Edit: missed out a bit in the opening sentence :-p
Does anyone have an example of this with the multi column unique? I've put together a stackoverflow for this since its still an issue. I made sure to give this thread credit. http://stackoverflow.com/questions/43705005/phpactiverecord-validates-uniqueness-of-not-working/43705326#43705326
On that same stackoverflow post above I created an answer that you can easily drop in your models as a trait. Let me know if you guys see any errors or improvemnts. It supports multi-column uniques :)