Zend_Db_Select для обновления / удаления запроса - PullRequest
1 голос
/ 22 ноября 2011

Работая над структурой отображения для наших приложений, мы столкнулись с некоторыми проблемами в отношении согласованности кода.Хотя легко сделать запрос на выборку с помощью класса 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, и будет ли использование этого класса доставлять нам неприятности в других местах?

Советы приветствуются. Заранее спасибо,

Ilians

Ответы [ 2 ]

2 голосов
/ 22 ноября 2011

С классом все в порядке, если вы уверены, что не собираетесь развивать его слишком сильно в будущем.Я предполагаю, что ваш подход заключается в том, чтобы воспользоваться автоматическим цитированием в классе Zend_Db_Select.Однако, по моему скромному мнению, у него есть некоторые конструктивные ошибки, которые могут привести к проблемам с расширяемостью, если вам нужно изменить или расширить его:

  • Он получает некоторые данные, которые впоследствии отбрасываются (объект сущности, чтобыиспользуйте предложение "from").
  • Он напрямую управляет выводом SQL запроса select, что может быть опасным.Если формат изменяется, а также если вам нужно включить больше элементов в предложение 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 голос
/ 22 ноября 2011

Я не знаю точных причин, по которым Zend_Db_Select не предлагает методы CUD. Очевидное объяснение состоит в том, что Select означает, что вы должны использовать его только для динамического построения запросов. Для вставки, обновления и удаления вы должны либо использовать Zend_Db_Adapter, либо прокси-методы для него в Zend_Db_Table и Zend_Db_Table_Row, либо общий Zend_Db_Statement.

.

Однако, с учетом сказанного, я думаю, что нет ничего плохого в расширении Zend_Db_Select и настройке его в соответствии с вашими потребностями (как и в любом другом компоненте, который изначально не выполняет то, что вы хотите)

...