Zend_Db_Select用于更新/删除查询


Zend_Db_Select for update/delete query's

在处理应用程序的映射结构时,我们遇到了一些关于代码一致性的问题。虽然很容易使用Zend_Db_Select类(使用如下函数:$select->from('table')->where('id=?,1))进行选择查询,但它不适用于更新/删除查询。没有像Zend_Db_Update或Zend_Db_Delete这样的类来构建更新和删除查询,就像构建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);
    }
}

一切工作正常使用这个类,但它让我们怀疑,如果我们可能错过了一些东西。是否有一个原因,没有默认的更新/删除类,就像有选择和使用这个类会给我们的麻烦在其他地方?

建议将不胜感激。提前感谢,

伊利安

如果你确定你不会让它在未来发展太多的话,这个类是很好的。我假设您的方法是受益于Zend_Db_Select类中的自动引用。然而,在我看来,它有一些设计缺陷,如果您需要修改或扩展它,可能会导致可扩展性问题:

  • 它正在接收一些之后被丢弃的数据(实体对象,使用"from"子句)。
  • 它直接操作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));
}

EDIT:在where部分中包含多个子句会使它更复杂,您想要的灵活性将取决于您的特定应用程序。例如,几个" and "子句的可能解决方案如下:

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'));

希望有帮助,

我不知道Zend_Db_Select不提供CUD方法的确切原因。最明显的解释是Select意味着您应该将其用于动态查询构建。要插入、更新和删除,您可以使用Zend_Db_AdapterZend_Db_TableZend_Db_Table_Row或通用Zend_Db_Statement中的代理方法。

然而,话虽如此,我认为扩展Zend_Db_Select并调整它是没有错的(就像任何其他组件不做你想要的最初)