2011-11-22 99 views
1

在处理我们的应用程序的映射结构时,我们遇到了代码一致性问题。虽然使用Zend_Db_Select类很容易地进行选择查询(使用如下函数:$ select-> from('table') - > where('id = ?, 1),但它不适用于更新/删除查询。并不像Zend_Db_Update或Zend_Db_Delete那样构建更新和删除查询,就像构建select一样,为了解决这个问题,我们扩展了Zend_Db_Select类,如下代码所示:代码显示了扩展Zend_Db_Select类的自定义类在底部的一些小例子代码来显示如何使用它。Zend_Db_Select更新/删除查询

<?php 
class Unica_Model_Statement extends Zend_Db_Select 
{ 
    public function __construct($oMapper) 
    { 
     parent::__construct($oMapper->getAdapter()); 
     $this->from($oMapper->getTableName()); 
    } 


    /** 
    * @desc Make a string that can be used for updates and delete 
    *  From the string "SELECT `column` FROM `tabelnaam` WHERE `id` = 1" only the part "`id = `" is returned. 
    * @return string 
    */ 
    public function toAltString() 
    { 
     $sQuery = $this->assemble();  // Get the full query string 
     $sFrom = $this->_renderFrom(''); // Get the FROM part of the string 

     // Get the text after the FROM (and therefore not using the "SELECT `colname`" part) 
     $sString = strstr($sQuery,$sFrom); 

     // Delete the FROM itself from the query (therefore deleting the "FROM `tabelnaam`" part) 
     $sString = str_replace($sFrom, '', $sString); 

     // Delete the word "WHERE" from the string. 
     $sString = str_replace('WHERE', '', $sString); 

     return $sString; 
    } 
} 

################################################ 
# Below code is just to demonstrate the usage. # 
################################################ 

class Default_IndexController extends Zend_Controller_Action 
{ 
    public function indexAction() 
    { 
     $person = new Unica_Model_Person_Entity(); 
     $statement = new Unica_Model_Statement($person->getMapper()); 
     $statement->where('id = ?' , 1); 
     $person->getMapper()->delete($statement); 
    } 
} 

class Unica_Model_Person_Mapper 
{ 
    public function delete($statement) 
    { 
     $where = $statement->toAltString(); 
     $this->getAdapter()->delete($this->_tableName,$where); 
    } 
} 

一切工作正常使用这个类,但是它让我们知道,如果我们也许失去了一些东西。是否有一个原因有没有默认的更新/删除类似的选择和将使用这个类给我们在其他地方的麻烦?

建议将不胜感激。 由于提前,

Ilians

回答

2

类是好的,如果你确定你不会在将来演变太多。我假设你的方法是从Zend_Db_Select类中的自动引用中受益。在我的愚见,但是,它有一些设计缺陷,如果你需要修改或者扩展它可能导致可扩展的烦恼:

  • 它接收一些数据,是继丢弃(实体对象,用“来自“条款)。
  • 它直接操纵select查询的SQL输出,这可能是危险的依靠。如果格式发生变化,并且如果您需要在where子句中包含更多元素,则代码可能变得非常“浑浊”以适应变化。

我的方法只是直接在代码中使用where子句,并在必要时引用它们。它对我来说看起来并不那么干净。像下面这样:

$db->delete('tablename', 'id = ' . $db->quote('1')); 

最终,你甚至可以将它抽象成一个方法或类,以避免对所有的地方蔓延$db->quote()通话,这样的事情:

private function myDelete($tableName, $fieldName, $fieldValue) 
{ 
    $this->db->delete($tableName, $fieldName . ' = ' . $db->quote($fieldValue)); 
} 

编辑:在where部分中包含多个子句会使其更加复杂一点,您想要的灵活程度取决于您的特定应用程序。例如,对于一些“相与”条款可能的解决方案可能是以下几点:

private function myDelete($tableName, array $fields) 
{ 
    $whereClauses = array(); 
    foreach ($fields as $fieldName => $fieldValue) { 
     $whereClauses[] = $fieldName . ' = ' . $db->quote($fieldValue); 
    } 
    $this->db->delete($tableName, implode(' AND ', $whereClauses)); 
} 

$this->myDelete('tablename', array('id' => '1', 'name' => 'john')); 

希望帮助,

+0

感谢您的答复,你是正确的报价。我试图自动引用所有内容,以便程序员不必费尽心思地引用所有内容(即使他忘记了它也是安全的)。但是,myDelete函数将如何与where中的多个值一起工作?就像:“DELETE WHERE id = 3 OR adress ='test'AND language!='EN' – Ilians

+0

根据WHERE子句的复杂程度,您需要或多或少地调整代码。只使用“AND”和场平等,只是为了展示一个简单的例子。 – dinopmi

+0

我之前尝试过类似的方法,但是发现自己陷入了类似数组键的问题,就像 array( 'id'=> 3, 'ID'=> 4 ) 使用像这样虽然使比posibilities 阵列( 更大的 'ID =?'=> 3, 'ID =?'=> 4 ) – Ilians

1

我不知道背后Zend_Db_Select没有提供CUD方法精确推理。显而易见的解释是,选择意味着您应该使用它:动态查询构建。要插入,更新和删除您将在Zend_Db_TableZend_Db_Table_Row或通用Zend_Db_Statement中使用Zend_Db_Adapter或代理方法。

然而,随着中说,我认为没有什么不妥延伸Zend_Db_Select,并调整它的需求(就这样没有做你想要开始什么任何其他组件)