Баг или фича ?

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Баг или фича ?

Сообщение Ekstazi »

Даже не знаю, баг это или фича.
Ситуация такая, есть таблица User:

Код: Выделить всё

CREATE TABLE `User` (
  `Id` int(11) NOT NULL auto_increment,
  `login` varchar(20) NOT NULL default '',
  `pass` varchar(32) default NULL,
  `idReferal` int(11) NOT NULL default '0',
  PRIMARY KEY  (`Id`,`login`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
Id,login - составной первичный ключ

Есть моделька User:

Код: Выделить всё

class User extends CActiveRecord
{
    public static function  model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public function relations()
    {
        return array(
            'referal'=>array(self::BELONGS_TO,'User','idReferal')
        );
    }
    //put your code here
}
 
В таблице User хранятся две записи:

Код: Выделить всё

INSERT INTO `User` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',9);
INSERT INTO `User` VALUES (9,'oa_09c7c3248d87b73f7',NULL,0);
 
Делаю вот так в контроллере:

Код: Выделить всё

User::model()->findByPk(array('Id'=>1,'login'=>'admin'))->referal;
 
И все работает. Как-то странно что он(CActiveFinder) нашел связанную запись если у него есть только кусок от первичного ключа. Вот формируемый sql запрос :

Код: Выделить всё

SELECT `referal`.* FROM `User` `referal` WHERE `referal`.`Id`=:ypl0. Bound with :ypl0='9'
 
В теории, правильно должно быть описано так:

Код: Выделить всё

    public function relations()
    {
        return array(
            'referal'=>array(self::BELONGS_TO,'User','idReferal,extrnlLogin')
        );
    }
 
И с такой записью relations все работает, как и пред. случае, формируется примерно такой sql-запрос:

Код: Выделить всё

SELECT `referal`.* FROM `User` `referal` WHERE (`referal`.`Id`=:ypl0) AND (`referal`.`login`=:ypl1). Bound with :ypl0='9', :ypl1='oa_333333'
 
Момент двусмысленный, даже не знаю на что ориентироваться. По идее CActiveFinder должен проверять соответствие внешнего ключа с первичный, а он просто игнорирует это соответствие. Это нормальное поведение или является багом ? Почему же все таки работает неправильный вариант ?
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: Баг или фича ?

Сообщение Ekstazi »

Вот код CActiveFinder, ответственный за это:

Код: Выделить всё

                if($this->relation instanceof CBelongsToRelation)
                {
                    if(isset($parent->_table->foreignKeys[$fk]))  // FK defined
                        $pk=$parent->_table->foreignKeys[$fk][1];
                    else if(is_array($this->_table->primaryKey)) // composite PK
                        $pk=$this->_table->primaryKey[$i];
                    else
                        $pk=$this->_table->primaryKey;
                    $params[$pk]=$record->$fk;
                }
 
То есть, он смотрит, если у связываемой таблицы составной первичный ключ, то он берет первый внешний ключ сопоставляет с первым стоблцом из первичного ключа подгружаемой таблицы, второй - со вторым столбцом и так далее. Странно что нет проверок на соответствие внешнего ключа первичному.
Ответить