Проблема организации связей в AR. Совета бы!

Здравствуйте, надеюсь на ваши советы и помощь.

Есть три таблицы в БД - скриншот ER-модели

rghost.ru/36871096/image.png

product - некий товар. Например, шапка или книга.

option - некая опция при заказе товара. Например, цвет, или размер.

product_option_value - непосредственно отношение опции к товару. Например, есть цвета данной шапки: красный, белый.

Таким образом, product и option связаны связью MANY2MANY через product_option_value.

Разумеется, встаёт тривиальная задача: получить все товары с их опциями и значениями опций. Вот тут-то я и туплю. Думаю, что связь задавать нужно через through, но не получается задать связь между option и product_option_value.

Самое разумное, к чему я пришёл:




class Product extends CActiveRecord

{

...

	public function relations()

	{

		return array(

			'purchase' => array(self::BELONGS_TO, 'Purchase', 'purchase_id'),

			'values' => array(self::HAS_MANY, 'ProductOptionValue', 'product_id'),

            'options' => array(self::HAS_MANY, 'Option', array('option_id'=>'id'),'through'=>'values'),

		);

	}

...

}




class Option extends CActiveRecord

{

...

	public function relations()

	{


return array(

            'valueses' => array(

    self::HAS_MANY,

    'ProductOptionValue',

    'option_id',

    'joinType'=>'INNER JOIN',

    'on'=>'`valueses`.product_id = `products`.product_id'),

		);

	}

...

}



И затем в контроллере загружать "products.options.valueses". Но не работает правильно. Получается каша.

Есть какие-то идеи?

если у тебя в БД все связи правильно установлены, то GII с генерирует тебе 3 модели со связями.

Абсолютно согласен, недавно столкнулся с подобной проблемой, учусь на стандартном мануале создания блога, нужно кроме постов добавить категории, а каждый пост определить в свою категорию …

так вот, несколько дней смотрел как баран на ворота, пока не понял, что главное для работы с AR правильно построить таблицы и связи на уровне создания базы и её таблиц, а уже после создания таблиц Gii замечательно построит нужные relations сам

использую mysql

поначалу не получалось сразу же при создании базы задать foreign key по которому я бы хотел вязать таблицы,

в phpmyadmin оказалось есть такая хорошая штука как "дизайнер", в котором методом научного тыка можно построить связи между таблицами, по логике вещей нужно вязать поля, которые нам необходимы, НО для решения моей задачи я просто связал ключевые поля двух таблиц, после этого советую обратиться к логам проекта (если Вы этого еще не сделали, то раскомментируйте логирование в main.php) тогда внизу страницы Вам будет доступен подробный лог того, что происходит пошагово

пример:

trace system.db.CDbCommand

Querying SQL: SHOW COLUMNS FROM tbl_post

in C:\xampp\htdocs\new\protected\controllers\PostController.php (130)

in C:\xampp\htdocs\new\index.php (13)

в этом трейсе я вижу, что контроллер хочет обратиться к таблице с постами

trace system.db.ar.CActiveRecord

lazy loading Post.category

in C:\xampp\htdocs\new\protected\views\post\_view.php (32)

in C:\xampp\htdocs\new\protected\views\post\index.php (17)

in C:\xampp\htdocs\new\protected\controllers\PostController.php (133)

а вот и тот результат, который мне был нужен: явно видно lazy loading как в мануале …ленивая(отложенная) загрузка таблицы category, иными словами из модели пост я получаю возможность работать с таблицей category посредством relations

и напоследок, так как я связал primary keys двух таблиц, конкретной связи поля к полю я не получил, но а зачем мне это ? у меня есть модель $data из которой я могу напрямую обращаться к полям первой или второй таблицы таким образом:

$data->status - получение значения статуса выбранного поля таблицы post

$data->category->name - получение значения имени категории выбранного поля из таблицы category

разница лишь в том, что при запросе к связанной таблице нужно указать её имя (обращение на один ярус больше выходит)

заранее простите за мой французский только перехожу с процедурного php к OOP PHP + framework потому любая критика приветствуется

Подскажи те пожалуйста ребят !

есть две таблицы




delimiter $$


CREATE TABLE `i_user` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `login` varchar(45) NOT NULL,

  `password` varchar(45) NOT NULL,

  `email` varchar(45) DEFAULT NULL,

  `fname` varchar(45) DEFAULT NULL,

  `lname` varchar(45) DEFAULT NULL,

  `sname` varchar(45) DEFAULT NULL,

  `birthday` date DEFAULT NULL,

  `group_id` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`),

  UNIQUE KEY `login_UNIQUE` (`login`),

  UNIQUE KEY `email_UNIQUE` (`email`),

  KEY `role` (`group_id`),

  CONSTRAINT `role` FOREIGN KEY (`group_id`) REFERENCES `i_group` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION

) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8$$






delimiter $$


CREATE TABLE `i_group` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `title` varchar(45) DEFAULT NULL,

  `description` text,

  `weight` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8$$



есть два Класса User и Group

в классе User перегружен метож relations


public function relations(){

		return array(

			'role'=>array(self::HAS_MANY,'Group',"group_id")

		);

	}

Попытка обратиться к полям group не удается пробовал так :


User::model()->findByPk($this->id)->title

Пишет нет поля title

Пробовал так


User::model()->findByPk($this->id)->width('role');

:(

тоже потом нет метода title

может ты имел ввиду такую связь…

есть таблица [Продуктов], и таблица [Цветов] и соответственно промежуточная таблица [Продукты_цвета]

в модели таблицы продуктов есть связь




public function relations()

{

	return array(

             ...

             'colors' => array(self::MANY_MANY, 'Colors', 'product_color(idproduct,idcolor)'),

	);

}



ну и собственно получать данные можно




$product = Product::model()->findByPk($id);

foreach($product->colors as $color)

{

    echo $color->name;

}



Спасибо! с двумя таблицами дошло! а вот когда просто одна на другю (как в моем примере выше ) не понятно :(

в твоем примере должно быть так.




$user = User::model()->findByPk($id);

foreach($user->role as $role)

    echo $role->title;



foreach - потому что, у тебя связь HAS_MANY, это значит у тебя может быть несколько групп у пользователя

Тьфу я идиот! Спасибо!

Если бы Вы не показали бы на:

я бы так и бился бы головой о стенку :(

у меня ж BELONGS_TO

Спасибо Большое!