I took an initial pass at this and the model generator properly generated relations. I then went to perform a complex query (via CDbCriteria) that relied on these relations. Because I wasn't defining a primary key on one of the tables, a call to CDataProvider::getData() wasn't working. First, here's my ddl:
CREATE OR REPLACE FUNCTION check_email(email text) RETURNS bool
LANGUAGE plperlu
AS $$
use Email::Address;
my @addresses = Email::Address->parse($_[0]);
return scalar(@addresses) > 0 ? 1 : 0;
$$;
DROP TABLE IF EXISTS ham_users CASCADE;
CREATE TABLE ham_users(
userid BIGSERIAL NOT NULL PRIMARY KEY
,email VARCHAR(128) NOT NULL UNIQUE
,username VARCHAR(64) NOT NULL UNIQUE
,CONSTRAINT proper_email CHECK(check_email(email))
);
DROP TABLE IF EXISTS ham_authentication;
DROP TYPE IF EXISTS authentication_type;
CREATE TYPE authentication_type AS ENUM('password','facebook');
CREATE TABLE ham_authentication(
userid BIGINT NOT NULL REFERENCES ham_users(userid)
,type authentication_type NOT NULL
,data VARCHAR(128)
,PRIMARY KEY(userid,type)
);
DROP TABLE IF EXISTS ham_user_attributes;
CREATE TABLE ham_user_attributes(
id BIGSERIAL NOT NULL PRIMARY KEY
,userid BIGINT NOT NULL REFERENCES ham_users(userid)
,key VARCHAR(128) NOT NULL
,value TEXT
);
CREATE INDEX idx_ham_id_key ON ham_user_attributes(userid,key);I originally didn't specify a primary key on the ham_user_attributes table. It may be significant that I originally called the "userid" column "id"; the ham_user_attributes table didn't have a primary key, only the separately-created index.
In the original ddl, the gii model generator properly defined authentication and userAttribute relations in models/User.php.
I'm new to gii; I don't think this is the correct way to perform this query, but it should work. I'm trying to perform authentication for the login form (in components/UserIdentity.php). So I need to select users with a specified username and get their (hashed) password from ham_authentication along with a salt from ham_user_attributes. Here's my flawed attempt from UserIdentity::authenticate():
$username = strtolower($this->username);
$criteria = new CDbCriteria();
$criteria->with = array('userAttributes','authentications');
$criteria->addCondition('LOWER(username)=:username');
$criteria->addCondition('"userAttributes".key=:attribute_key');
$criteria->addCondition('"authentications".type='
.':authentication_type');
$criteria->params = array(':username' => $username
,':attribute_key' => self::SALT
,':authentication_type' => 'password');
$criteria->together = true;
$provider = new CActiveDataProvider(
'Users',array('criteria' => $criteria)
);
$data = $provider->getData();
I think the better way to do this would be to use User::model() to get a user with the specified username and then query the salt and password separately. Be that as it may, this didn't work because the ham_user_attributes table didn't have a primary key. The call to getData() resulted in a warning about using an undefined value somewhere deep in the innards of yii. So I refactored the ddl to rename the id column on the ham_users table to "userid" and added a primary key to ham_user_attributes.
When I say it's not generating relations, to be clear, here is that method from models/Users.php:
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
);
}
I may need to adjust it indeed. As I mentioned, I am specifying the table prefix as "ham_" in config/main.php. It was working in one iteration and then changes described resulted in the above. I've also tried the Giix Model Generator, but that had the same result.
This seems like a bug. Thanks -
-Matt

Help












