связь таблиц через Active Record

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

связь таблиц через Active Record

Сообщение RuZk »

Я только начал осваивать yii.
Есть 2 таблицы User (id, username,password,email,role) и Profile(id, name,surname ...)
Нужно, что бы администратор имел возможность добавлять нового пользователя и при этом заполнять его профиль
Я попробовал сделать так: создал 2 модели (User,Profile), после заполнения формы добавления нового пользователя,
переадресовывает на страницу редактирования профиля. Нужно, что бы в действии admin контроллера выводились данные из профиля, а так же отображалось, создан ли профиль вообще.

Я понимаю, что можно просто сделать запрос к базе, но интересно сделать это именно через Active Record. В модели User отношения описаны так

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

return array(
     'profile'=> array(self::HAS_ONE,'Profile','id'),
); 
А в модели Profile

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

return array(
     'user'=> array(self::HAS_ONE,'User','id'),
); 
Как мне сделать выборку данных из таблицы профиля и вообще нужна ли мне модель Profile или проще руками работать с данными из той таблицы.
Последний раз редактировалось RuZk 2010.06.14, 18:49, всего редактировалось 1 раз.
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц

Сообщение RuZk »

всё, разобрался
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц

Сообщение RuZk »

с выборкой я вроде разобрался, а вот с сохранением таблиц не очень
у меня есть форма (модель group) а так же таблица в бд, которая связывает user и group (teacher, в ней параметры user_id, group_id).
В форме выбирается из списка 1 из юзеров.
Можно ли что бы автоматически, через AR создавалась запись в таблице связке (номер группы привязывался к id юзера) или нужно вручную делать запрос?
Я описал отношения между 3 моделями (user, teacher и group).
В group

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

'teacher'=>array(self::HAS_ONE,'Teacher','group_id'),
 
в teacher

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

 'group'=>array(self::HAS_MANY,'Group','id'),
            'user'=>array(self::HAS_ONE,'User','id',
                'condition'=>'role=3',
 ), 
в user

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

'teacher'=>array(self::HAS_MANY,'Teacher','user_id'), 
помогите разобраться

+1 вопрос, если например у меня есть таблица с описанием группы и таблица с юзерами, а так же таблица, какой юзер к какой группе принадлежит, Как это связать через AR, если я работаю с моделью категории?
Bartholomew
Сообщения: 110
Зарегистрирован: 2010.02.05, 01:58
Откуда: Нижний Новгород
Контактная информация:

Re: связь таблиц через Active Record

Сообщение Bartholomew »

По поводу сохранения: используйте метод afterSave, в котором нужно описать создание записи для связанной таблицы:
http://yiiframework.ru/doc/cookbook/ru/ ... lated.data

По поводу последнего вопроса - не очень понятно, что имеется ввиду.
Если речь идет об этом:
В документации очень не хватает примеров задания различных отношений AR, например как связать 2 таблицы посредством третей (я пока так и не понял, возможно ли это вообще сделать (viewtopic.php?f=3&t=1089 дополнительный вопрос в 3 посте))
...то это выглядит следующим образом (на примере связи Блог—Тэги Блога):
Имеем три таблицы (blog, blog_tags и blog_tags_link) и две модели (Blog и BlogTags).
В таблице blog_tags_link два поля — post_id и tag_id, — они являются внешними ключами к соотв. таблицам.
В модели Blog описывается эта свзяь:

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

public function relations()
{
    return array(
        'tags'=>array(self::MANY_MANY, 'BlogTags', 'blog_tags_link(post_id, tag_id)'),
    );
} 
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц через Active Record

Сообщение RuZk »

Проблема в том, что мне нужно связать таблицу user (id, username, ...) и таблицу group (id, status, name, ...) Я пробовал сделать это через таблицу teacher (user_id, group_id). В модели group отношения описаны так:

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

'teacher'=>array(self::MANY_MANY,'User','ej_teacher(group_id,user_id)'), 
yii делает такой sql запрос

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

SELECT `teacher`.`id` AS `t1_c0`, `teacher`.`username` AS `t1_c1`, 
`teacher`.`password` AS `t1_c2`, `teacher`.`salt` AS `t1_c3`, `teacher`.`email` AS `t1_c4`, 
`teacher`.`role` AS `t1_c5` FROM `ej_user` `teacher` INNER JOIN `ej_teacher` `teacher_teacher` ON 
(`teacher_teacher`.`group_id`=:ypl0) AND (`teacher`.`id`=`teacher_teacher`.`user_id`) 
Но ничего не возвращает, если в phpmyadmin выполнить этот запрос и вместо :ypl0 подставить число, то возвращаются нужные данные.
Видимо yii не может сопоставить group_id и id (в таблице group).
Как можно решить эту проблему?
Аватара пользователя
yii
Сообщения: 122
Зарегистрирован: 2010.04.29, 10:40

Re: связь таблиц через Active Record

Сообщение yii »

RuZk, схему таблиц можно глянуть? так будет проще понять что имеем и что нужно сделать
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц через Active Record

Сообщение RuZk »

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

CREATE TABLE `ej_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `course` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  `start_time` date NOT NULL,
  `end_time` date NOT NULL,
  PRIMARY KEY (`id`)
) 
CREATE TABLE `ej_teacher` (
  `user_id` int(11) NOT NULL,
  `group_id` int(11) NOT NULL
)

CREATE TABLE `ej_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(128) NOT NULL,
  `password` varchar(128) NOT NULL,
  `salt` varchar(128) NOT NULL,
  `email` varchar(128) NOT NULL,
  `role` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) 
Аватара пользователя
yii
Сообщения: 122
Зарегистрирован: 2010.04.29, 10:40

Re: связь таблиц через Active Record

Сообщение yii »

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

$criteria=new CDbCriteria;
$criteria->with = array('teacher.group'); //teacher - это связь в User.php: 'teacher'=>array(self::HAS_MANY, 'Teacher', 'user_id'); а group - связь в Teacher.php c моделью Group 
$users_and_group = User::model()->findAll($criteria); 
Как-то так, если я правильно понял :)
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц через Active Record

Сообщение RuZk »

yii писал(а):

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

$criteria=new CDbCriteria;
$criteria->with = array('teacher.group'); //teacher - это связь в User.php: 'teacher'=>array(self::HAS_MANY, 'Teacher', 'user_id'); а group - связь в Teacher.php c моделью Group 
$users_and_group = User::model()->findAll($criteria); 
Как-то так, если я правильно понял :)
yii выдаёт ошибку

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

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'teacher.' in 'on clause' 
отношения group в Teacher.php c моделью Group выглядит так

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

'group'=>array(self::HAS_MANY,'Group','id'), 
В остальном всё так же.
На самом деле мне нужно в точности наоборот, что бы я мог из модели Group получить данные юзера.
Что я делаю не так?
isergey
Сообщения: 83
Зарегистрирован: 2010.01.16, 21:05

Re: связь таблиц через Active Record

Сообщение isergey »

Блин, когда уже задокументируют эту фишечку...
Ваша ошибка говорит на то, что при соединении yii обозвал teacher иначе. Смотрите логи запросов в БД и уже в критерии пишите название новой таблицы (некое путешествие в кишки фреймворка, которое не факт, что будет работать в следующих версиях ;))
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц через Active Record

Сообщение RuZk »

а можно поподробнее :oops: yii сгенерировал вот такой sql

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

SELECT `t`.`id` AS `t0_c0`, `t`.`username` AS `t0_c1`, `t`.`password` AS `t0_c2`, `t`.`salt` AS `t0_c3`, `t`.`email` AS `t0_c4`, `t`.`role` AS `t0_c5`, `teacher`.`user_id` AS `t1_c0`, `teacher`.`group_id` AS `t1_c1`, `group`.`id` AS `t2_c0`, `group`.`course` AS `t2_c1`, `group`.`status` AS `t2_c2`, `group`.`start_time` AS `t2_c3`, `group`.`end_time` AS `t2_c4` FROM `ej_user` `t` LEFT OUTER JOIN `ej_teacher` `teacher` ON (`teacher`.`user_id`=`t`.`id`) LEFT OUTER JOIN `ej_group` `group` ON (`group`.`id`=`teacher`.``) 
что мне нужно написать в критериях?
isergey
Сообщения: 83
Зарегистрирован: 2010.01.16, 21:05

Re: связь таблиц через Active Record

Сообщение isergey »

Стало быть таблица ej_user в контексте этого запроса называется как t. Теперь если вы хотите обратится к ней в критерии писать нужно t вместо ej_user (например t.id = лололо)
andrew_yii
Сообщения: 15
Зарегистрирован: 2010.06.21, 13:52

Re: связь таблиц через Active Record

Сообщение andrew_yii »

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

CREATE TABLE IF NOT EXISTS `file` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `path` varchar(100) DEFAULT NULL,
  `size` int(10) unsigned DEFAULT NULL,
  `type` varchar(10) DEFAULT NULL,
  `width` int(10) DEFAULT NULL,
  `height` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `id` (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


CREATE TABLE IF NOT EXISTS `foto` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `descr` text,
  `thumb_id` int(10) unsigned NOT NULL,
  `original_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id` (`id`),
  KEY `thumb_id` (`thumb_id`),
  KEY `original_id` (`original_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 
Здравствуйте! Пожалуйста, подскажите, как правильно написать связь таблиц через Active Record
Т.е. select s.*, f.* from foto s left join file f on f.id = s.thumb_id Спасибо
Аватара пользователя
kosenka
Сообщения: 677
Зарегистрирован: 2009.09.26, 12:41
Откуда: москва
Контактная информация:

Re: связь таблиц через Active Record

Сообщение kosenka »

andrew_yii писал(а):Здравствуйте! Пожалуйста, подскажите, как правильно написать связь таблиц через Active Record
Т.е. select s.*, f.* from foto s left join file f on f.id = s.thumb_id Спасибо
в модели foto:

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

    public function relations()
    {
                return array(
                        'files'=>array(self::HAS_MANY,'files','thumb_id'),//HAS_MANY - если у фоток много превьюшек или HAS_ONE - если у фотки одна превьюшка
                );
    }
 
в контроллере foto:

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

                        $result=Foto::model()->with('files')->findAll();
 
как-то так...
andrew_yii
Сообщения: 15
Зарегистрирован: 2010.06.21, 13:52

Re: связь таблиц через Active Record

Сообщение andrew_yii »

на странице выдается ошибка : The relation "files" in active record class "Foto" is specified with an invalid foreign key "thumb_id". There is no such column in the table "{{file}}".
в модели Foto.php

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

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(
            'files'=>array(self::HAS_ONE,'File','thumb_id'),
        );
    } 
в контроллере FotoController.php

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

$result=Foto::model()->with('files')->findAll();
echo $result; 
Не пойму где ошибка
Аватара пользователя
kosenka
Сообщения: 677
Зарегистрирован: 2009.09.26, 12:41
Откуда: москва
Контактная информация:

Re: связь таблиц через Active Record

Сообщение kosenka »

'files'=>array(self::HAS_ONE,'File','thumb_id'), - а таблица точно называется File ? может она с маленькой буквы?

и есть ли поле thumb_id в таблице file ?
andrew_yii
Сообщения: 15
Зарегистрирован: 2010.06.21, 13:52

Re: связь таблиц через Active Record

Сообщение andrew_yii »

таблица kuzpolymer_file
есть поле thumb_id
Жду
Аватара пользователя
kosenka
Сообщения: 677
Зарегистрирован: 2009.09.26, 12:41
Откуда: москва
Контактная информация:

Re: связь таблиц через Active Record

Сообщение kosenka »

Прошу прощения, но "ждать" вы будете долго. Соизвольте прочесть документацию и попробуйте разобраться сами, направление я вам дал.
RuZk
Сообщения: 18
Зарегистрирован: 2010.06.13, 12:53

Re: связь таблиц через Active Record

Сообщение RuZk »

проявилось очень странное поведение, база всё та же, отношения заданы так

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

'teacher'=>array(self::MANY_MANY,'User','ej_teacher(group_id,user_id)'), 
вот кусок кода

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

$data=Group::Model()->findAll();
        foreach($data as $a){
            echo $a->teacher->id;
        } 
ничего не выдаёт,
но если распечать через print_r($a->teacher), то нужные данные там есть

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

            [_attributes:private] => Array
                (
                    [id] => 4
                    [username] => Вася
                    [password] => 4561ed798db7d7c424fa84b6834868cb
                    [salt] => 
                    [email] => admin@admi.ri
                    [role] => 3
                )
 
в чём проблема?
Ответить