Какой лучший способ уменьшить количество запросов, когда у класса DAO есть методы, которые используют тот же результат? - PullRequest
0 голосов
/ 17 января 2012

У меня есть вспомогательный класс DAO (я не знаю, в порядке ли он) для получения категорий из БД MySQL, структура в основном такая:

<?php

require_once '../include/PDOConnectionFactory.php';

class CategoryDAO extends PDOConnectionFactory
{
    /**
     *
     * @var PDO $conn 
     */
    private $conn;

    public function __construct()
    {
        $this->conn = PDOConnectionFactory::getConnection();
    }
}
?>

Этот класс имеет эти методы (некоторые затем):

getMaxLevel()
getAllCategories()
getAllCategoriesOfLevel($level)
haveChildCategory($categoryName)
getIdCategory($categoryName)
getCategoryName($idCategory)

Редактировать : Тело метода getAllCategories () аналогично приведенному ниже, и почти все методы этого класса вызывают его getAllCategories ():

public function method()
    {
        try {
            $stmt = $this->conn->prepare("SELECT * FROM category");
            $stmt->execute();
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            echo $e->getMessage();
        }

        return $result;
    }

Я не знаю, какой лучший подход для уменьшения избыточности запросов, я думаю в следующих:

  1. Экземпляр объекта класса, вызовите getAllCategories () и вызовите другие методы, передаваярезультат по параметру.
  2. Иметь частное свойство с результатом getAllCategories (), заполнять при создании объектов с помощью __construct ().

Но в этих случаях я вижу этот недостаток:

  1. Не рекомендуется использовать ООП.
  2. Объект может устареть после БД ОБНОВЛЕНИЕ или ВСТАВКА.

Если моя проблемаконцептуально в ООП, пожалуйста, дайте мне знать.

Ответы [ 2 ]

0 голосов
/ 18 января 2012

Этот ответ зависит от текущей структуры запроса, где нет условий

class CategoriaDAO extends PDOConnectionFactory
{
    /*DB Connection, static member since you only need one connection*/
    private static $dbConnection;

    /*Sql result set, static since there is not conditonal and only a single table used*/
    private static $resultSet;

    private static function getConnection()
    {
            /*Connect to mysql db, set CategoriaDAO::dbConnection; */
    }

    private static function populateResultSet()
    {
            /*Run query and populate resultSet - either as sql result or parse to array - your call*/
    }
    /**
     *
     * @var PDO $conn 
     */
    private $conn;

    public function __construct()
    {
                /*Get sql connection if one hasn't already been established*/
                if(!CategoriaDAO::dbConnection)
                        $this->conn = PDOConnectionFactory::getConnection();
    }
}

Мысленный процесс, стоящий за этим, заключается в том, что, поскольку результаты всегда будут одинаковыми (игнорировать, обновлять, вставлять, удалять на данный момент), нет необходимости хранить копию результатов в каждом объекте.

Как вы указали, обновления таблицы выбивают сохраненный набор результатов из синхронизации с объектом; это то место, где я хотел бы немного отследить и сказать, что если набор результатов для данного объекта должен быть только актуальным на момент создания, тогда используйте обычные члены объекта.

Также стоит рассмотреть как независимо, так и в сочетании с предыдущим комментарием, будет ли запрос изменяться, и если он это сделает, он требует создания элементов объекта. Если запрос не изменяется, тогда не о чем беспокоиться - кроме предыдущего пункта. Если это действительно так, ваши варианты более или менее рассматриваются в следующих примерах.

class Foo{
    private $someMember;

    /*
        $params = Associative array of fields and values
    */
    private static buildAndRunQuery($params)
    {
        /*Build sql query based on the given params Array()*/
    }
    public __construct($someMemebrValue)
    {
        $this->someMember = $someMemberValue;
        Foo::buildAndRunQuery(Array("fieldName" => $this->someMember));
    }
}

В этом примере вы все еще используете статический метод для генерации запроса, но вы передаете нестатические элементы для процесса / На данный момент (см. Комментарий об актуальных объектах на момент создания) вы можете либо сохраните результаты в статическом члене, либо передайте их обратно в функцию __construct () и сохраните в экземпляре объекта.

Тогда существует вероятность того, что используемый вами запрос несколько сложнее, чем простой запрос определенных полей, так что создание многомерного массива для передачи статической функции будет более хлопотным, чем оно того стоит. В этом случае вы можете разделить buildAndRunQuery () на метод buildQuery () - instance и статический метод runQuery (), например.

class Foo{

    private $someMember;

    /*
        $params = Associative array of fields and values
    */
    private static runQuery($query)
    {
        /*Build sql query based on the given params Array()*/
    }

    private function buildQuery()
    {
        /*Construct your query here and either return calling method or store in instance member*/
         /*Either*/
            return <Constructed query>;
        /*Or*/
           $this->query = <Constructed query>;
    }

    public __construct($someMemebrValue)
    {
        $this->someMember = $someMemberValue;
        /*As per buildQuery() comment either:*/
            Foo::runQuery($this->buildQuery());
        /*Or*/
            Foo::runQuery($this->query);
    }
}

В этом случае есть несколько опций для обработки сгенерированного запроса до вызова Foo :: runQuery ().

Конечно, всегда есть вероятность, что вы не захотите создавать и запускать запрос синхронно или даже в конструкторе.

В заключение я лично считаю, что для методов, которые взаимодействуют со службами, независимыми от самого объекта, такими как Sql или, возможно, сфокусированный DOMDocument, или аналогичными объектными взаимодействиями, лучше всего использовать статические методы, когда они оба актуальны и не в конечном итоге обрезают Ваш нос, чтобы прорезать ваше лицо (ненужно сложный и т. д.). Конечно, все это необходимо учитывать для каждого класса.

0 голосов
/ 18 января 2012

Ваш DAO звучит как очень плохая идея с точки зрения эффективности. Лично я не нахожу объекты доступа к данным, которые бы обеспечивали какую-либо реальную ценность. Когда вы потянете название категории, не вытащив при этом ее идентификатор? Вам лучше будет запрашивать целые строки за раз и писать несколько специализированных запросов для выполнения других ваших функций.

...