【问题标题】:Zend_Db_Select for update/delete query'sZend_Db_Select 用于更新/删除查询
【发布时间】:2011-11-22 17:14:07
【问题描述】:

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

使用这个类一切正常,但它让我们想知道我们是否可能遗漏了什么。有没有像 select 那样没有默认更新/删除类的原因,并且在其他地方使用这个类会给我们带来麻烦?

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

伊利安人

【问题讨论】:

    标签: php mapping zend-framework


    【解决方案1】:

    如果您确定将来不会使其发展太多,则该课程很好。我假设您的方法是从 Zend_Db_Select 类中的自动引用中受益。然而,以我的拙见,如果您需要修改或扩展它,它有一些设计缺陷可能会导致可扩展性问题:

    • 它正在接收一些随后被丢弃的数据(实体对象,使用“from”子句)。
    • 它直接操作select 查询的SQL 输出,依赖它可能很危险。如果格式发生变化,并且如果您需要在 where 子句中包含更多元素,您的代码可能会变得非常“混乱”以适应这些变化。

    我的方法是直接在代码中使用where 子句,并在必要时引用它们。对我来说,它看起来并不特别干净。类似于以下内容:

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

    最终,您甚至可以将其抽象为一个方法或类,以避免将$db-&gt;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'));
    

    希望对你有帮助,

    【讨论】:

    • 感谢您的回复,您对报价的看法是正确的。我试图自动引用所有内容,这样程序员就不必费心引用所有内容(即使他忘记了也是安全的)。但是,myDelete 函数如何处理 where 中的多个值?喜欢:“删除其中 id = 3 或地址 = 'test' AND 语言!= 'EN'
    • 根据 WHERE 子句的复杂程度,您需要或多或少地调整代码。我已经编辑了我的答案,只使用“AND”和字段相等,只是为了展示一个简单的例子。
    • 我之前尝试过类似的方法,但发现自己陷入了类似数组键的问题。像这种情况: array( 'id' => 3, 'id' => 4 ) 像这样使用它来启用大于可能性 array( 'id = ?'=>3, 'id = ?'=>4 )
    • 正如我所说,我认为您需要缩小问题范围,仅包含您将在哪里获得的“可能”值,否则您可能会使解决方案过于复杂。如果您需要处理标识符采用多个可能值的情况,您可以这样做:array('id' => array('3', '4'))。但同样,复杂性将取决于您的应用程序中可能的“位置”情况的范围。
    【解决方案2】:

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

    不过,话虽如此,我认为扩展 Zend_Db_Select 并根据您的需要调整它并没有错(就像任何其他最初不满足您需求的组件一样)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-01
      • 2014-11-07
      • 2012-09-01
      • 2013-04-18
      • 1970-01-01
      • 1970-01-01
      • 2019-07-16
      相关资源
      最近更新 更多