如何在ORM查询中混合使用OR和AND

时间:2010-06-30 19:01:30

标签: php mysql orm kohana

我正在使用kohana 2.3开发一个网站,但我遇到了一个特定的ORM查询问题。基本上我正在做的是以下查询

SELECT *
   FROM 'records'
   WHERE ('ServRepSupervisor' = name AND 'Followup_read' = 0) OR ('ServRepSupervisor' = name AND `read` = 0)

当我尝试这样的ORM查询时......

$unread = ORM::factory('record')
   ->where(array('ServRepSupervisor' => Auth::instance()->get_user()->name, 'Followup_read' => 0))
   ->orwhere(array('ServRepSupervisor' => Auth::instance()->get_user()->name, 'read' => 0))
   ->find_all();

我最终得到的查询是

SELECT `records`.*
   FROM (`records`)
   WHERE `ServRepSupervisor` = 'name' AND `Followup_read` = 0
   OR `ServRepSupervisor` = 'name'
   OR `read` = 0

如何重新编写ORM查询以产生预期结果?

编辑:我设法让它发挥作用,但它似乎不是一个非常优雅的解决方案。

$unread = ORM::factory('record')
   ->where('(\'ServRepSupervisor\' = \'' . Auth::instance()->get_user()->name . '\' AND \'Followup_read\' = 0) OR (\'ServRepSupervisor\' = \'' . Auth::instance()->get_user()->name . '\' AND \'read\' = 0)')
   ->find_all();

这会返回我想要的数据集,但它只是丑陋的代码。必须有更好的方法来做到这一点。

3 个答案:

答案 0 :(得分:1)

经过一些研究,我找到了一个补丁,用于改变KO2 ORM以获得open_paren()和close_paren(),但KO2中orwhere的默认行为不允许进行所需的操作,因此parens不会帮助我。我已经辞职了,因为我的时间限制,我使用的详细where()方法对我来说是最好的选择。我稍微改变了查询以适应我的mysql实例中的一些特性。

这是有效的,也是该项目的最终查询。

$unread = ORM::factory('record')
   ->where('(ServRepSupervisor = \'' . Auth::instance()->get_user()->name . '\' AND Followup_read = 0) OR (ServRepSupervisor = \'' . Auth::instance()->get_user()->name . '\' AND records.read = 0)')
   ->find_all();

答案 1 :(得分:0)

ko3有像->where_open()->where_close()这样的方法,ko2没有

这是最好的解决方案

ps:我会缓存用户btw

$current_user = Auth::instance()->get_user();

答案 2 :(得分:0)

使用Kohana 2时,您可以执行以下操作:

system/libraries/ORM.php:223内的文件__call()中将'or_open_paren'添加到数组中

if (in_array($method, array('open_paren', 'close_paren', 'enable_cache', 'disable_cache'))) {

或者如果该文件尚未修补,则更改case 0:如下所示:

case 0:
    if (in_array($method, array('open_paren', 'or_open_paren', 'close_paren', 'enable_cache', 'disable_cache'))) {
        $this->db->$method();
    } else {
        return $this->db->$method();
    }
break;

将以下代码添加到system/libraries/Database.php

public function open_paren()
{
    $this->where[] = $this->get_where_count() ? 'AND (' : '(';
    return $this;
}
public function or_open_paren()
{
    $this->where[] = $this->get_where_count() ? 'OR (' : '(';
    return $this;
}
public function close_paren()
{
    $this->where[] = ')';
    return $this;
}
protected function get_where_count()
{
    $lastWhen = end($this->where);
    if ( $lastWhen === false )
        return 0;
    $lastWhen = trim( str_replace( array('AND ', 'OR '), '', $lastWhen ) );
    return $lastWhen === '(' ? 0 : count($this->where);
}

,并在同一文件中将count($this->where)的所有实例替换为$this->get_where_count(),但新方法get_where_count()(显然)和方法delete($table, $where)(总共11个)除外替换)。