2011-03-27 119 views
0

我正在将原始PHP代码迁移到CakePHP并且存在一些问题。由于我在查询ORM转换时遇到很大问题,我暂时使用原始SQL。一切都很好,但我遇到了难看的代码,并不知道如何使它变得美丽。我制作了DealersController并添加了function advanced($condition = null)(它将通过参数1-15和69从AJAX中调用)。功能看起来像:在控制器中添加CakePHP查询

switch ($condition) { 
    case '1': 
    $cond_query = ' AND ((d.email = \'\' OR d.email IS NULL))'; 
    break; 
    case '2': 
    $cond_query = ' AND (d.id IN (SELECT dealer_id FROM dealer_logo)'; 
    break; 
    // There are many cases, some long, some like these two 
} 

if($user_group == 'group_1') { 
    $query = 'LONG QUERY WITH 6+ TABLES JOINING' . $cond_query; 
} elseif ($user_group == 'group_2'){ 
    $query = 'A LITLE BIT DIFFERENT LONG QUERY WITH 6+ TABLES JOINING' . $cond_query; 
} else { 
    $query = 'A LITLE MORE BIT DIFFERENT LONG QUERY WITH 10+ TABLES JOINING' . $cond_query; 
} 

// THERE IS $this->Dealer->query($query); and so on 

所以..当你看到代码看起来很丑。我有两个变种:

1)退出查询添加并为每个条件制作模型方法,然后这些条件分离到函数。但是这不是DRY,因为主要的3个大问题几乎是一样的,如果我需要改变一个东西 - 我将需要改变16个以上的查询。 2)使小的可重用模型方法/查询从DB小块数据中获得,然后不使用原始SQL,而是使用方法。这会很好,但表现会很低,我需要尽可能高。

请给我建议。谢谢!

回答

0

如果”关心CakePHP如何为每个连接的表进行数据库查询,您可能会发现Linkable行为可以帮助您减少查询的数量(连接是一个表上的简单关联)。

否则,我发现在模型级创建简单的数据库查询方法以获取较小的信息,然后再将它们组合起来是一种好方法。它允许你清楚地描述你的代码(通过内联文档)。如果您可以迁移到使用CakePHP的find方法而不是原始查询,那么您将使用conditions数组语法。所以你可以通过一种方法解决你的问题,就是在你的Model类上有公共函数,这些函数将适当的条件附加到输入的条件数组中。例如:

class SomeModel extends AppModel { 
    ... 
    public function addEmailCondition(&$conditions) { 
     $conditions['OR'] = array(
      'alias.email_address' => null, 
      'alias.email_address =' => '' 
     ); 
    } 
} 

你会调用这些函数来建立一个大的conditions数组,然后你可以用它来检索您从您的控制器需要的数据(或从模型中,如果要包含所有的模型层)。请注意,在上面的示例中,conditions数组正在通过引用传递,因此可以对其进行编辑。还要注意,数组中现有的任何'OR'条件都将被这个函数覆盖:如果要将新条件与现有条件合并,您的真正解决方案必须更加明智。

不要担心'假设'性能问题 - 如果您尝试过查询并且速度太慢,那么您可以担心如何提高性能。但对于初学者来说,尽可能干净地编写代码。

您还可能想要考虑将function advanced()调用拆分为多个按其condition查询的相似性分组的控制器操作。

最后,如果您还没有将其检出,请参阅本书的关于从模型中检索数据的条目。可能有一些你以前从未见过的技巧:http://book.cakephp.org/view/1017/Retrieving-Your-Data

+0

所以..首先感谢Linkable - 我读到它并认为它非常有帮助! – Orbitum 2011-03-28 10:55:24

+0

第二个 - 你提供一个函数在模型'find_big_query()'和一个小的函数'add_something_tofunction_find_big_query()'?也许在模型公共变量'additional_query_string'并添加控制器添加?什么是“最好的方式?” – Orbitum 2011-03-28 10:58:42

+0

对于如何在不了解数据库模式的情况下如何分解查询,我无法做出正确的建议;你能否更具体一些? – tokes 2011-03-29 20:44:48

0

如果查询的底座部分是一样的,你可以有一个函数生成查询部分,然后用其他的小功能,附加不同的地方条件等

+0

所以你认为这是一个好方法? “最好的办法”? – Orbitum 2011-03-28 10:52:53

+0

不,我认为最好的办法是摆脱查询和使用Cake函数,但如果你没有时间,那么至少可以划分代码:) – 2011-03-28 13:30:35

+0

所以...那么最好的方法是是要使用Linkable(在需要的地方)并且使用model-> find()方法而不是查询,并且在每个switch :: case中调用此方法?这将是最好的方式? – Orbitum 2011-03-28 14:54:05