Zend_Db_Select用于更新/删除查询

时间:2011-11-22 07:39:16

标签: php mapping zend-framework

在为我们的应用程序处理映射结构时,我们在代码一致性方面遇到了一些麻烦。虽然很容易使用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);
    }
}

使用这个课程一切正常,但它让我们想知道我们是否可能遗漏了一些东西。是否存在没有默认更新/删除类的原因,就像选择那样,并且会使用这个类给别人带来麻烦吗?

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

Ilians

2 个答案:

答案 0 :(得分:2)

如果您确定将来不会让它进化太多,那么这个课程很好。我假设您的方法是受益于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));
}

编辑:在where部分中包含多个子句会使其更加复杂,您希望的灵活程度取决于您的特定应用。例如,几个“ANDed”子句的可能解决方案可能如下:

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

希望有所帮助,

答案 1 :(得分:1)

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

然而,话虽如此,我认为扩展Zend_Db_Select并根据你的需要调整它是没有错的(就像其他任何你最初没做的事情一样)