CodeIgniter Active Record与常规查询

时间:2013-01-25 13:55:13

标签: database codeigniter activerecord

目前我使用CodeIgniter进行常规查询,即:

$sql = "
    SELECT *
    FROM my_table
    WHERE item_id > 1
";    
$q = $this->db->query($sql);

我已经开始研究ActiveRecord,它确实看起来不错,并且无论使用哪个数据库驱动程序都具有构建查询的优势 - 但是,我通常严格按照每个项目使用一个数据库类型,所以这是对我来说并没有什么好处。

我发现常规查询(正如我在我的示例中所示)在我看来更易读,更容易维护,因此我目前正在考虑保持常规查询。

除了上面提到的原因,我应该选择哪个,以及出于什么原因?

谢谢

7 个答案:

答案 0 :(得分:8)

对我来说,我更喜欢运行常规查询,CI的活动记录消耗大量内存。因为它会将所有结果加载到内存中。如果你明白我的意思。至于复杂性,最好采用常规查询而不是CI的主动记录sytax。

答案 1 :(得分:7)

我倾向于更喜欢ActiveRecord。我发现它更具可读性,并且它使得构建动态查询变得更加容易,因为您不必将明显地连接原始SQL块。这意味着我可以向我的查询构建器添加各种条件,而不用大惊小怪,并提供一些非常容易阅读的内容。

ActiveRecord的CodeIgniter实现有一些非常适合的东西(并且让我想念Doctrine)并且我使用直接SQL,但它不会经常发生。

答案 2 :(得分:5)

对于简单的问题,你厌倦了编写SELECT blah blah,你可以使用活动记录稍微改变你的风格,因为在编写常规查询时,很可能会产生syntex错误。活动记录是为此目的而设计的,除非您是专家,否则您不需要编写使用语法,其中出错的可能性很高。活动记录也提供逃避设施。您不熟悉它们(简单)可读的活动记录。看一下这个例子

$array  =   array(
        'user.username',
        'user.email',
        'user.password',
        'other.blah',
        'other.blah'
);
$where  =   array(
        'active'    =>  1,
        'other'     =>  'blahblah'
);  

return $this->db
        ->select($array)
        ->from('user')
        ->join('other','other.user_id = user.id','left')
        ->where($where)
        ->get()
        ->result();    

答案 3 :(得分:5)

差不多两年后,我发现了这个问题。我的一些同事已经回答了几个优点或缺点,我只想根据个人经验添加一个观点:

正如一些人所说,我也混合使用有效记录一些时间和纯直sql用于非常复杂的查询,原因是当你需要一个接收大量os参数的方法并相应地更改查询时,使用它非常简单。例如,我有一个接收名为'options'的参数数组的方法:

if(!empty($options['login']))
{
    $this->db->where('tl.login', $options['login']);
}
if(!empty($options['ip']))
{
    $this->db->where('tl.ip', $options['ip']);
}
if(!empty($options['sucesso']))
{
    $this->db->where('tl.sucesso', $options['sucesso']);
}

if(isset($options['usuarios_existentes']) && $options['usuarios_existentes'])
{
    $this->db->join('usuario u', 'tl.login = u.login');
}
else
{
    $this->db->join('usuario u', 'tl.login = u.login', 'LEFT');
}

if(!empty($options['limit']))
{
    $this->db->limit($options['limit']);
}
else
{
    $this->db->limit(50);
}

return $this->db->select('tl.id_tentativa_login, tl.login, DATE_FORMAT(tl.data, "%d/%m/%Y %H:%i:%s") as data, tl.ip, tl.sucesso', FALSE)
                ->from('logs.tentativa_login tl')
                ->order_by('tl.data', 'DESC')
                ->get()->result();

当然这只是一个简单的例子,但是我已经构建了数百个可以改变通用'get'方法的行和条件的方法,而且活动记录使它非常好并且非常易读,因为你不需要编写代码在它的中间正确格式化查询。

你甚至可以有连接和其他有条件的东西。所以你可以使用通用的集中式方法,这样可以避免重写大部分代码并复制它的一部分(对于维护来说很糟糕),它不仅可读,但它可以快速查询您的查询,因为只加载您需要的内容:

if(!empty($opcoes['com_maquina']))
{
    if(strtoupper($opcoes['com_maquina'])=='SIM')
    {
        $this->db->join('maquina m', 'm.id_local = l.id_local');
    }
    elseif(strtoupper($opcoes['com_maquina'])=='NAO')
    {
        $this->db->join('maquina m', 'm.id_local = l.id_local', 'LEFT');
        $this->db->where('m.id_maquina IS NULL');
    }
}

activerecord的另一个好处是它在语句中接受纯SQL,比如子查询和其他东西,所以你可以随意使用它。

我说的是优点,但很明显,纯SQL总是会更快地执行,并且不会有调用函数的开销。但说实话,在大多数情况下,php解析器会这么快就会以一种富有表现力的方式影响最终结果,如果你必须制作大量的手动条件,你的代码可能和activerecord一样慢解析器无论如何。

请注意,有时activerecord查询将无法按预期方式工作,因为它尝试以编程方式执行的逻辑方式构建查询,因此在使用“OR”语句时要小心,例如,大多数时候你必须隔离它(和):

$this->db->where('(m.ultimo_status < DATE_ADD(NOW(), INTERVAL -2 HOUR) OR m.ultimo_status IS NULL)');

如果你没有添加(),OR statament将影响整个where子句。 因此,一旦你习惯了activerecord,它可以帮助很多并且仍然可以快速和可读的查询。

答案 4 :(得分:4)

嗯,我的主要原因是它快速而安全。因为它会自动转义值等。但是当谈到复杂查询时,我建议使用普通的查询字符串。

(不是谈论联接等等因为codeigniter支持它非常好并且可读)更像是数据库查询,或者通过rownumber选择(如下所示)

$query = $this->db->query('SELECT * FROM
  (SELECT  @row := @row + 1 as row, t.*
   FROM `default_red_albums` t, (SELECT @row := 0) r) AS view
WHERE `row` IN(' . $in . ')');

return $query->result();

答案 5 :(得分:2)

ActiveRecord并不总是按您希望的顺序生成查询,这可能会导致不可预测的结果。例如,这个模型:

        $this->db->select('page, content');
        $this->db->from('table');
        $array = array('title' => $searchq, 'content' => $searchq);
        $this->db->or_like($array, 'both'); 
        $this->db->where('showsearch', 'Yes'); 
        return $this->db->count_all_results();

生成此查询:

        SELECT COUNT(*) AS `numrows`
        FROM (`table`)
        WHERE `showsearch` =  'Yes'
        AND  `title`  LIKE '%term%'
        OR  `content`  LIKE '%term%'

但是我希望在查询结束时检查showsearch,这就是我把它放在首位的原因。但ActiveRecord将其移动到查询的中间,我得到的结果不准确。

答案 6 :(得分:2)

使用对象模型进行查询有很大好处。虽然您可以执行字符串解析和连接以在多个函数上构建查询,但这非常耗时并且极易出错。使用对象模型,您可以传递引用并继续构建查询或在执行之前将其传递给预处理器。

一个人为的例子可能是自动为带有creation_date字段的表的所有查询添加日期过滤器。

CI还允许您将原始SQL与对象模型相当好地混合。基本上,您构造一个自定义查询,返回结果以水合对象。