Правила ассоциации CakePHP HABTM - PullRequest
0 голосов
/ 20 декабря 2010

Если я хочу создать категорию и иметь возможность привязывать товары к ней по тегам, мне это может понравиться так:

  • Создайте таблицы категорий и товаров.
  • Создайте тегитаблица с такими тегами, как: рубин, серьги, белое золото
  • Создайте таблицу category_tags и product_tags для их сопоставления
  • Установите категорию и продукт в теги hasAndBelongsToMany
  • Установите теги для категорий hasAndBelongsToMany и hasABelongsToMany

Теперь скажите, у меня есть 2 продукта, один с тегами: Ruby и Серьги , а другой с тегами: Рубин и Браслет

Скажите, что я хочу создать Рубиновые серьги категории.

Я мог бы добавить Рубин и Серьги Теги к категории.Но при обычной ассоциации моделей HABTM оба продукта будут возвращены, потому что, хотя только 1 имеет тег earrings, они оба имеют тег ruby.

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

Кроме того, как это сделать еще дальше, как я могу добавить -tags в категорию, в которой товары НЕ ДОЛЖНЫ иметь эти теги для возврата?

1 Ответ

0 голосов
/ 21 декабря 2010

Сценарий ниже решил мою проблему, сгенерировав запрос следующим образом:

PHP

$data = $this->Designer->find(
    'first', 
    array(
        'conditions' => array(
            'Designer.slug' => $name, 
            'Designer.available' => 1
        )
    )
);

$inc_tag_ids = array();
$exc_tag_ids = array();
foreach($data["Tag"] as $tag)
{
    if( $tag['DesignersTag']['include'] )
    {
        $inc_tag_ids[] = $tag['id'];
    }
    else
    {
        $exc_tag_ids[] = $tag['id'];
    }
}

$ins = ' ';

if( count($inc_tag_ids) )
{
    $inc_tag_id_str = '"' . implode('","',$inc_tag_ids) . '"';
    $ins .= 'AND tags.id IN ('.$inc_tag_id_str.')';
}   

if( count($exc_tag_ids) )
{
    $exc_tag_id_str = '"' . implode('","',$exc_tag_ids) . '"';
    $ins .= '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 ('.$exc_tag_id_str.')
    )';
}   

$prod_qry = '
    SELECT *, COUNT(DISTINCT tags.name) AS uniques 
    FROM products, products_tags, tags 
    WHERE products.id = products_tags.product_id 
    AND tags.id = products_tags.tag_id 
    '.$ins.'
    GROUP BY products.id
    HAVING uniques = '.count($inc_tag_ids).' 
';

echo $prod_qry;

$data["matching_products"] = $this->Designer->Tag->query($prod_qry);

SQL

SELECT * , COUNT( DISTINCT tags.name ) AS uniques
FROM products, products_tags, tags
WHERE products.id = products_tags.product_id
AND tags.id = products_tags.tag_id
AND tags.id
IN (
"8"
)
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 (
"7"
)
)
GROUP BY products.id
HAVING uniques =1

Однако я чувствую, что это неКстати, CakePHP предназначен для обработки, я думаю, что, возможно, это то, что должно обрабатываться в модели, а не в контроллере.Но я не уверен, как это сделать.

...