AR relations нельзя строить не по PK?

Вопрос:

Есть 2 таблицы (записи структуры условные, но, надеюсь, понятные):


1. Article

id (PK), header_id, body_id


2. Content

id (PK), type(header, body), content

Таблица Article связана с Content "по-хитрому", если учесть, что id для header и body никогда не пересекутся, то Content фактически содержит 2 записи для 1 записи Article.

В контексте Yii для модели Article я бы описал эти связи так:


'content_header' => array(self::HAS_ONE, 'Content', 'id')

'content_body' => array(self::HAS_ONE, 'Content', 'id')

Но вот незадача, AR подразумевает, что я должен связать для этих отношений именно PK с указанным полем, получается, что я не могу (или не знаю как) указать, что по ‘content_header’ я хочу связать именно header_id с id, а не id с id … Неужели все так плохо и эти связи никак не описать?

P.S. Чтобы сосредоточиться именно на проблеме связки в AR, считаем, что структура БД неизменяемая, есть возможность манипулировать только PHP кодом. :)

Да, про параметр ‘on’ в relations я знаю, но он не спасает ситуацию, так как отношение вида


'content_header' => array(self::HAS_ONE, 'Content', 'id', 'on' => 'header_id = id')

даст ошибку SQL, так как в ON запроса окажется


id = id AND header_id = id

to vladm

У вас проблема с проектированием этих таблиц, а вероятнее всего с знанием основ реляционных СУБД. То что вы хотите сделать неправильно на уровне проектирования. Но исходя из спортивных условий задачи(возможность манипулировать только PHP кодом) сделайте так:




'content_header' => array(self::BELONGS_TO, 'Content', 'header_id')

'content_body' => array(self::BELONGS_TO, 'Content', 'body_id')



и будет работать как вы хотите. Но я бы всетаки подумал о другой структуре таблиц без "хитрых" связок, а так как положено.

За прямой ответ искреннее спасибо, действительно работает, этого вполне достаточно. По поводу "кривизны" структуры, я специально не заострял внимание на этом, это и так видно невооруженным глазом, но решение было необходимо именно без изменения структуры средствами AR.

Действительно, прочитайте материала по проектированию. Все равно в будущем пригодится.

Просто код переписать в будущем - это пол дела. А изменить всю структуру и заставить приложение под неё работать - это большой геморой.

Уважаемый теоретик, прежде чем тыкать носом в материал по проектированию, внимательно читайте условие задачи! В ней четко сказано, что структуру базы менять нельзя, только код, потому Вы либо даете решение задачи, либо проходите мимо! Я же не спрашивал где мне почитать о том, как базу правильно проектировать, и совета на будущее не просил, только четкое решение задачи, которое уже было предоставлено выше.

P.S. В библии говорится: "Не верь глазам своим", очень правильно говорится, я бы на Вашем месте 100 раз подумал, прежде чем судить о уровне оппонента, а уж тем более прежде чем делать подобные наставления, так как не всегда в жизни вещи являются такими, какими Вы их видите.

Смешно. Заказчику вы также говорите?

Он вам говорит "Сайт что вы сделали - херовый!", а вы ему "Не верь глазам своим. Через время ты привыкнешь и он станет лучше".

Что за бред?

А тут проблема не в связке AR, а в логике проектирования базы. Зачем закрывать глаза на свои косяки, не понимаю.

Логика проектирования базы? Ну-ну, вы еще скажите что автоинкрементный ID в качестве PK это главный принцип проектирования любой базы. :) Почему-то разработчики того же MySQL, к примеру, не считают проблемой дать возможность построить связь FK по любому полю, лишь бы типы полей совпадали и по нему был индекс, в котором это поле стоит первым (ссылку на мануал дать?).

Бред это Ваши ответы, совершенно не относящиеся к сути вопроса. Научитесь читать и понимать поставленные задачи прежде, чем давать ответы и рекомендации.

Вам никто не говорил, что есть какая-то проблема, вам четко задали вопрос и добавили условия, от которых отходить нельзя.

Или заказчику вы тоже говорите, пойди почитай теорию прежде чем ставить мне задачу таким образом? В данном случае я “заказчик” (топикастер, постановщик задачи), если хотите, а вы то как раз “исполнитель”, (отвечающий в моем топике, решающий задачу). :)

И еще раз повторюсь, научитесь читать то, что вам пишут, а не то что вы хотите видеть, это замечание касательно “не верь глазам своим”. Не думайте, что все вокруг намного глупее и нуждаются в ваших наставнических советах, вашего совета как раз никто и не спрашивал, по крайней мере ни в этом топике. :)

P.S. Надеюсь ваша самооценка повысится еще больше благодаря тому, что смогли показать мне “мои косяки”, на которые я упорно закрываю глаза. :) Да и, уважаемый, проходите таки мимо, вам явно не сюда. :)

обсуждайте ваши личные отношения в личных сообщениях

@vladm: Не обращайтесь с такой интонацией и отношением к людям, которые тратят свое время безвозмездно и пытаются помочь вам решить вашу проблему. Это как минимум невежливо.

@rosko: Вы меня конечно извините, но Вы внимательно читали топик? К человеку, который "потратил свое время безвозмездно и попытался помочь мне решить мою проблему" я обратился более чем вежливо и поблагодарил его за ответ, но к людям, которые тратят свое личное время в пустую дабы поднять собственную самооценку за счет других я буду обращаться именно так и не иначе. Право же, неужели один я тут считаю, что после того как тему раскрыли, сунуться с советом "Действительно, прочитайте материала по проектированию. Все равно в будущем пригодится.", по меньшей мере хамство и неуважение к задающему вопрос?

Какой то вы сильно хамовитый :)

Наверно трудно вам в жизни приходятся с таким длинным языком.

Народ! Хватит!

Кстати почти аналогичная проблема, база уже есть, перепроектировать ее нельзя, строил ее не я.

Надо сверху навернуть функционал

есть

TableA

ID(PK)

field

<…>

TableB

ID(PK)

field

<…>

надо сделать релейшн по полям field в обеих таблицах, т.е. on TableA.field = TableB.field

возможно?

Весело тут у Вас.