繁体   English   中英

当类DAO具有使用相同结果的方法时,减少查询数量的最佳方法是什么?

[英]What the best way to reduce the number of queries when the Class DAO have methods that use the same result?

我有一个帮助类DAO(我不知道是否可以这样做),用于从MySQL DB获取Categories,该结构基本上是这样的:

<?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. 最好不要使用OOP。
  2. DB UPDATE或INSERT之后,该对象可能已过时。

如果我的问题在OOP中是概念性的,请告诉我。

从效率的角度来看,您的DAO听起来真是个坏主意。 就我个人而言,我找不到提供任何真正价值的数据访问对象。 什么时候拉类别名称而不拉类别ID? 您最好一次查询整行,然后编写一些专门的查询来执行其他功能。

该响应取决于当前的查询结构,其中没有条件

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()-实例方法和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或类似的对象交互),最好在相关且不最终使您不知所措的情况下使用静态方法。讨厌你的脸(不必要地复杂等)。 当然,所有这些都需要在每个班级的基础上加以考虑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM