2011-11-22 154 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,並調整它的需求(就這樣沒有做你想要開始什麼任何其他組件)