Override CActiveRecord Primary Key

I’m hoping someone can help.

I have a table with an ID column, which MySQL defines as the primary key, but also with a varchar column which contains a unique value for each row, example: UserID, UserName… both are unique.

All other tables I have contain the UserName, therefore I would like to set UserName as the primary key. I’ve tried creating a primaryKey function in the model, returning ‘UserName’, and I’ve tried creating an init() function for the model, with $this->setPrimaryKey(‘UserName’); however, generated queries still are created with WHERE (user.UserID=:ypl0).

Can someone tell me how to override the primary key, so queries will be generated with WHERE (user.UserName = …

Thanks!!

I am not sure if I understand what you want. You have a table with userId and username and the id is an auto incremented integer I guess. All other tables referencing a user record don’t use the id column as foreign key but the username itself? Well, if you want to reference a user by its username and not the id then you should define the username as primary key in your DATABASE first (otherwise you lose all benefits of referential integrity). Then you should override the primaryKey method as you stated like this


public function primaryKey()

{

    return 'username';

}

You just have to take care that your relations use the username and not the id value now

Greetings,

Hannes

Thank You, but the problem is, I don’t have control of the DATABASE table… so I cannot change it’s structure. Is there a way in the model of overriding this?

Yes, as I said above: Overriding the primaryKey() method is enough. But remember to change the relations method in the other models referencing a User so that they are using ‘username’ and not id as the foreign key

Makes sense, but… The referencing model has the relation set based on UserName, the model has the PrimaryKey set to UserName, as you suggested. But the resulting query is showing "WHERE UserID = "…

I think I found the reason in line 2266 of CActiveRecord http://code.google.com/p/yii/source/browse/tags/1.1.10/framework/db/ar/CActiveRecord.php#2266

I checks for a pk field in the database via CDbSchema and if none is defined it uses the models primaryKey method, otherwise it uses the database field defined as pk which makes sense in 99% of all cases to not mess things up. So it seems that as long as you define the id field as primary key in your database it will use that one

I think I found a way: Tri suggested this method here http://www.yiiframework.com/forum/index.php/topic/17708-overriding-primarykey/page__view__findpost__p__88188

It looks weird but at least it seems to work. Sorry for misleading you at first :)

Thanks again… I saw that post, but still not working. I think the init() is too late in the process, as it gets assigned in the __construct()…

I’ve looked at overriding CActiveRecordMetaData, but it seems to be pretty extensive.

Thanks again

I’ve been trying to do this exact same thing with some legacy databases where I cannot change the schema definitions. Did you ever find a workaround?