2

我在 PHP (Kohana) 中使用了一个面向对象的 MVC 框架,并且将一些技术混合在一起来完成工作。问题是我不确定如何在每页调用大量查询的情况下保持清洁。

为了说明我的示例,我假设我正在设计一个类似站点的堆栈溢出:

我有一个问题模型类 ( question_model) 以及一个问题查找器模型类 ( question_finder_model)。

question_model 主要只包含存储问题数据的变量、答案对象数组和一些工厂方法。就像是:

class question_model {
    public $question_id,$question_title,$question_body,$answers = array();    
}

问题查找器包含一个 question_model 对象数组以及一个问题 ID 数组。id 数组由类中的 find 方法填充并由其他方法使用。就像是:

class question_finder_model {
    private $question_ids = array();
    public $questions = array() ;   //

    function public find_questions () {
        // executes some SQL to find a list of projects
        // Create a new question_model object for each question and store in $questions
        // for each of these questions store the id in $questions_ids
    }
    function public get_answer_info () {
       // using all the question ids stored in $question_ids:
       // find information about the answers
     }
}

所以我对我的所有模型都使用这种方法,例如我的用户模型将包含一系列问题对象。

问题是它变得非常难以处理,例如我的问题包含许多答案,每个答案都可以包含许多评论等等。如何在不进行多次查询的情况下填充所有这些对象。我的意思是简单的方法是遍历我的问题对象数组并调用存储在问题类中的函数,该函数获取该对象的答案信息。但是我会在每页调用 10 个或 100 个查询。

如果这有点模糊,我很抱歉,因为这个问题很难表达。任何帮助都将不胜感激,因为我的整个模式都有缺陷。

4

3 回答 3

3

您在这里表达的是天真的 ORMappers 最常见的问题之一。生成多个查询。

您可以在此处阅读对问题的准确描述:ORMs Done right:(DBA 抱怨 #3:隐藏的昂贵操作)

基本上,问题是您需要对以下内容进行多次查询:

foreach ($questions in $site) {
 foreach ($question as $questions) {
    foreach ($answer in $question){
       foreach ($comment in $answer) {
         echo "$site->title, $question->title, $answer->title, $comment->title";
       }
    }
 }

}

它变得非常缓慢,非常快。

您需要做的是使用正确的联接在一个查询中获取所有信息。然后填充你的对象。

在一些文章中寻找建议的实现:Class::ReluctantORM — 强制预取

最后,不要挂断试图让每个案例都正确。关系模型和对象模型“阻抗不匹配”不是一个已解决的问题。所以不要试图自己完美地解决它。毕竟对象关系映射是计算机科学的越南

于 2009-09-26T04:54:29.197 回答
1

它与 PHP 的关系并不比 SQL 大。

要获取问题的答案列表(包括评论),您可以按问题 ID 获取所有答案。然后,将所有答案 id 收集到一个数组中,并获取该数组中具有答案 id 的所有评论。

这是三个查询。您只需要在代码中计算出哪个评论属于哪个答案 - 如果您按答案 id 对评论进行排序等等,这可以更快。

您还可以使用 memcached 将内容缓存到文件或其他文件中,这应该可以很好地加快速度。

当然,从这样的结构构建对象可能比仅按查询更棘手,但这是您只需要做的事情。

于 2009-09-25T21:33:37.450 回答
0

Jani Hartikainen 总结得很好,我想提点别的。

学习 OOP 后,一切都开始看起来像一个对象。

虽然确实可以将所有内容声明为类并视为对象,但您不必这样做。在您的示例中,可能更容易将其视为大量数据操作,而不是处理单个问题/答案/评论对象。

一旦你从那个角度来看它,你可能会想出像 Jani 自己这样的解决方案。

于 2009-09-25T21:56:23.347 回答