在为我们的应用程序处理映射结构时,我们在代码一致性方面遇到了一些麻烦。虽然很容易使用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
答案 0 :(得分: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
部分中包含多个子句会使其更加复杂,您希望的灵活程度取决于您的特定应用。例如,几个“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_Adapter
和Zend_Db_Table
或通用Zend_Db_Table_Row
中使用Zend_Db_Statement
或代理方法。
然而,话虽如此,我认为扩展Zend_Db_Select
并根据你的需要调整它是没有错的(就像其他任何你最初没做的事情一样)