CakePHP2.3:构建复杂的条件Model-> find()选项

时间:2013-07-14 03:07:03

标签: mysql cakephp cakephp-2.0

我对MySQL或数据库一般都不熟悉,所以这里是我的数据模型(table {cols}]),以使我的问题连贯一致:

Domains{id, name} 注意:此处的“域名”不涉及网络域名

Subdomains{id, domain_id, name}

Items{id, subdomain_id, name}

SubdomainsItems{id, subdomain_id, item_id} 没有domain_id列!

我的Items Controller有一个函数fetchWithin($domains, $subdomains),最终应该执行两个复杂的find()之一。这是我无法解决的复杂问题。

以编程方式我可以做到这一点,但我确信更好的方法是通过聪明的连接等。唉,目前这是方法:

如果$domains为空,请仅执行步骤2和3,否则:

  1. foreach($domains as $d):获取Subdomains的所有行Subdomain.domain_id = Domains.id$subdomains
  2. foreach($subdomains as $s):go SubdomainsItems所有行SubdomainsItems.subdomain_id = Subdomains.id $item_ids
  3. foreach($items_ids as $i):获取Items所有行Items.id = SubdomainsItemsitems_id
  4. 这是有效的,但我认为这可以避免关系数据库的强大功能,我想了解这个应该如何完成(即根据Cakephp约定或简单地通过任何MySQL)声明会实现这一点)。

    非常感谢帮助,我尝试来学习SQL的更复杂的方面,但它恰好在我的脑海中。 :S

1 个答案:

答案 0 :(得分:1)

了解必要的查询

使用问题中描述的结构,必要的查询形式为:

SELECT
    *
FROM
    items
LEFT JOIN
    subdomains ON (
        items.subdomain_id = subdomains.id
    )
LEFT JOIN
    domains ON (
        subdomains.domain_id = domains.id
    )
WHERE
    domains.name = "foo"
    AND
    subdomains.name IN ('some', 'list', 'of', 'subdomains');

与问题中的逻辑相比,这将所有三个表连接在一起并允许按域名或子域名(或涉及任何或所有三个表的任何其他标准)查找所有项目;一般来说,如果你想在数据库中查找数据并使用多个查询来获取数据 - 那么有一种更有效的方法。

实施查找呼叫

使用Cake创建此类查询的方法有很多种。最简单的可能是使用the join key并明确指定连接:

function fetchWithin($domains = null, $subdomains = null) {
    $params = array(
        'joins' =>  array(
            array('table' => 'subdomains',
                'alias' => 'Subdomain',
                'type' => 'LEFT',
                'conditions' => array(
                    'Subdomain.id = Item.subdomain_id',
                )
            ),
            array('table' => 'domains',
                'alias' => 'Domain',
                'type' => 'LEFT',
                'conditions' => array(
                    'Domain.id = Subdomain.domain_id',
                )
            )
        )
    );

    if ($domains) { // single value or an array
        $params['conditions']['Domain.name'] = $domains;
    }

    if ($subdomains) { // single value or an array
        $params['conditions']['Subdomain.name'] = $subdomains;
    }

    return $this->find('all', $params);
}