CakePHP HABTM 关联规则

发布于 2024-10-08 16:00:52 字数 697 浏览 6 评论 0原文

如果我想创建一个类别并能够通过标签将产品链接到它,我可以这样:

  • 创建类别和产品 表。
  • 创建一个标签表,其中包含以下标签: 红宝石、耳环、白金
  • 创建一个 category_tagsproduct_tags 表来映射它们
  • 将类别和产品设置为 hasAndBelongsToMany 标签
  • 将标签设置为 hasAndBelongsToMany 产品和 hasAndBelongsToMany 类别

现在假设我有 2 个产品,其中一个带有标签:Ruby耳环,另一个带有标签:Ruby手镯假设

我想创建一个红宝石耳环类别。

我可以将 RubyEarrings 标签添加到该类别中。但在正常的 HABTM 模型关联下,这两种产品都将被退回,因为尽管只有 1 个具有 earrings 标签,但它们都具有 ruby 标签。

如何使其仅匹配具有与该类别所有相同标签的产品(产品可以具有更多标签,但必须具有相应类别具有的所有标签)才能返回?

另外,更进一步,我如何将 -tags 添加到产品不得具有这些要返回的标签的类别中?

If I want to create a category and be able to link products to it by tags I can like so:

  • Create the category and product
    tables.
  • Create a tags table with tags like:
    Ruby, Earrings, White-Gold
  • Create a category_tags and
    product_tags table to map them
  • Set category and product to
    hasAndBelongsToMany tags
  • Set tags to
    hasAndBelongsToMany products and hasAndBelongsToMany categories

Now say I have 2 products one with tags: Ruby and Earrings and another with tags: Ruby and Bracelet

Say I want to create a Ruby Earrings category.

I could add the Ruby and Earrings tags to the category. But under normal HABTM Model associations both products will be returned because even though only 1 has an earrings tag they both have a ruby tag.

How can I make it only match products that have ALL of the same tags as the category (products can have more tags but must have all the tags the corresponding category has) in order be returned?

Also, taking that even further, how could I add -tags to a category that the products must NOT have these tags to be returned?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

-黛色若梦 2024-10-15 16:00:52

下面的脚本通过生成如下查询解决了我的问题:

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 的处理方式,我认为也许这应该在模型中处理,而不是在控制器中处理。但我不知道该怎么做。

The script below solved my issue by generating a query like so:

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

However I feel like this is not the way CakePHP is inteded to be treated, I think maybe this is something that should be handled in the model not in the controller. But I am not sure how to do that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文