Как сообщить модели, как найти связанные с ней модели?

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

У меня есть модель дизайнера, и я хочу получить связанные продукты для каждого дизайнера, когда получаю информацию из модели дизайнера.

Ассоциация непростая, поэтому торт не сделает это за меня волшебным образом, поэтому мне нужно определить это самостоятельно. Я следил за учебниками, и я думаю, что я близок, но не уверен, как связать все это вместе.

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

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

Вот запрос, части строки, которые выглядят как {$__cakeID__$}, нужно заменить на designer_id:

SELECT *, COUNT(DISTINCT tags.name) AS uniques 
FROM products, products_tags, tags, designers, designers_tags 
WHERE products.id = products_tags.product_id 
AND tags.id = products_tags.tag_id 
AND tags.id IN (
    SELECT t.id
    FROM tags t
    LEFT JOIN designers_tags dt ON dt.tag_id = t.id
    LEFT JOIN designers d ON d.id = dt.designer_id
    WHERE d.id ={$__cakeID__$}
    AND dt.include =1
)
AND products.id NOT IN ( 
    SELECT products.id 
    FROM products, products_tags, tags 
    WHERE products.id = products_tags.product_id 
    AND tags.id = products_tags.tag_id 
    AND tags.id IN (
        SELECT t.id
        FROM tags t
        LEFT JOIN designers_tags dt ON dt.tag_id = t.id
        LEFT JOIN designers d ON d.id = dt.designer_id
        WHERE d.id ={$__cakeID__$}
        AND dt.include =0
    ) 
)
AND designers.id = designers_tags.designer_id
AND designers_tags.tag_id = tags.id
GROUP BY products.id 
HAVING uniques = (
    SELECT COUNT(d.id) AS tag_count 
    FROM tags t
    LEFT JOIN designers_tags dt 
        ON dt.tag_id = t.id
    LEFT JOIN designers d 
        ON d.id = dt.designer_id
    WHERE d.id = {$__cakeID__$} 
    AND dt.include =1
    GROUP BY d.id
)

Также вот дизайнерская модель:

class Designer extends AppModel 
{    
    var $name = 'Designer';

    var $actsAs = array('Sluggable' => array('separator' => '-', 'overwrite' => false, 'label' => 'name')); 

    var $hasAndBelongsToMany = 'Tag';

    var $hasOne = 'AlternateName';

    var $hasMany = 'Vote';
}

Что мне нужно сделать, чтобы модель Designer использовала этот запрос для автоматического поиска связанных продуктов?


person JD Isaacks    schedule 22.12.2010    source источник
comment
Это адский запрос. Вы уверены, что Кейк не сможет справиться с ассоциацией вместо вас? Не могли бы вы описать связь и/или точно описать, что вы хотите вернуть из базы данных?   -  person Stephen    schedule 22.12.2010
comment
@Stephen, дизайнерские теги HABTM, теги продукта HABTM. Включены продукты, которые имеют все теги конструктора. Также в таблице Designers_tags есть логическое поле с именем include, если оно ложно, то никакие продукты с этими тегами НЕ должны быть включены. Таким образом, я могу создать категорию и выбрать, какие теги должны или не должны быть у продуктов, чтобы быть включенными в категорию. Есть смысл?   -  person JD Isaacks    schedule 22.12.2010
comment
Почти понял: Вам нужны только те товары, у которых точно такие же теги, как у Конструктора? Или вам нужны все продукты с тегом любой, который также есть у конструктора?   -  person Stephen    schedule 22.12.2010
comment
@Stephen, продукты могут содержать больше, но дизайнер должен содержать ВСЕ.   -  person JD Isaacks    schedule 22.12.2010


Ответы (1)


Этот запрос должен работать с использованием специального соединения и поведения Containable:

// this assumes you are in the DesignersController
$this->Designer->Tag->find('all', array(
    'joins' => array(
        array(
            'table' => 'designers_tags',
            'alias' => 'FilterDesignersTag',
            'type' => 'INNER',
            'conditions' => array(
                'FilterDesignersTag.tag_id = Tag.id'
            )
        )
    ),
    'contain' => array('Designer', 'Product'),
    'conditions' => array(
        'FilterDesignersTag.designer_id' => $designer_id,
        'FilterDesignersTag.include' => 1
    )
));

Данные вернутся, ориентируясь на теги, но вы получите то, что вам нужно. Кроме того, вам нужно убедиться, что вы определили отношения HABTM во всех трех моделях, Designer, Product и Tag (тег должен иметь две ассоциации HABTM).

Кроме того, вам нужно будет добавить var $actsAs = array('Containable'); к вашим моделям.

ИЗМЕНИТЬ

Если вы не можете найти решение CakePHP и в конечном итоге вам нужно использовать необработанный запрос, CakePHP может сделать это с моделью метод запроса. Поймите, что вы отказываетесь от некоторых функций при использовании этого метода. Также обратите внимание на этот совет из кулинарной книги:

Если вы когда-либо использовали этот метод в своем приложении, обязательно ознакомьтесь с библиотекой CakePHP Sanitize, которая помогает очищать предоставленные пользователем данные от атак внедрения и межсайтового скриптинга.

person Stephen    schedule 22.12.2010
comment
Ваш последний комментарий делает мой ответ недействительным... Но вы можете опираться на это. - person Stephen; 22.12.2010
comment
спасибо за ваш ответ, я могу попробовать поиграть с вашим решением и посмотреть, что я могу из него сделать, хотя одно. Как бы я сказал, чтобы он не включал продукты, которые имеют какой-либо из тегов include=0? Могу ли я добавить что-то вроде 'FilterDesignersTag.include !=' => 0 в массив условий? Спасибо! - person JD Isaacks; 22.12.2010
comment
Я говорю, чтобы он включал только те, у которых есть FilterDesignersTag.include = 1. Посмотрите на окончательные условия. - person Stephen; 22.12.2010