如果我有两个表,比如blog_category和blog,每个"blog"只能属于一个特定的类别,因此基于一个名为"blog_categary_id"的键可以建立1-1的关系。
现在在我的代码中,我会做一些类似的事情:
//Loop through categories such as
foreach($categories as $cat):
//then for each category create an array of all its posts
$posts = $cat->getPosts(); // This would be another DB call to get all posts for the cat
//do stuff with posts
endforeach;
现在,在我看来,根据$categories的大小,就DB调用而言,这可能会非常昂贵。这仍然是最好的解决方案吗?或者,我可以在代码中做一些事情,首先检索所有类别,然后检索所有博客,并通过id将它们映射到相应的类别吗?理论上,这只需要对DB进行2次调用,现在从大小上看,调用2(博客)的结果集肯定会更大,但实际的DB调用会同样昂贵吗?
我通常会选择第一个选项,但我只是想知道是否有更好的方法来解决这个问题,或者PHP中的额外处理在性能方面更有可能更昂贵?特别是从MVC的角度来看,如果模型返回类别,但它也应该返回该类别的相应博客,我不确定如何最好地构建它,根据我的理解,模型不应该返回视图所需的所有数据吗?
还是我最好在第一个查询中使用内部联接选择所有类别和博客,并创建我需要的输出?也许通过使用多维数组?
感谢
您可以使用一个简单的SQL查询来获取所有类别和帖子,如下所示:
SELECT *
FROM posts p
JOIN categories c ON c.id = p.blog_category_id
ORDER BY c.category_name ASC,
p.posted_date DESC
然后,当您循环返回的记录时,将当前类别id分配给一个变量,您可以使用该变量与下一个记录类别进行比较。如果类别不同,则在打印记录之前打印类别标题。需要注意的是,要做到这一点,你需要先按类别排序帖子,然后再发布,以便同一类别中的所有帖子都在一起。
例如:
$category_id = null;
foreach($posts as $post) {
if($post['blog_category_id'] != $category_id) {
$category_id = $post['blog_category_id'];
echo '<h2>' . $post['category_name'] . '</h2>';
}
echo '<h3>' . $post['post_title'] . '</h3>';
echo $post['blog_content'];
}
注意:由于您还没有发布这两个表的架构,我不得不编写与我希望在这样的代码中看到的类似的列名。因此,如果不对此进行一些调整,上面的代码将无法与您的代码一起使用。
最佳解决方案取决于您将如何处理数据。
延迟加载
在需要的时候加载数据。例如,当你有20个类别,而你只加载其中2个类别的帖子时,这是一个很好的解决方案。然而,如果你需要为所有人加载帖子,那就根本没有效率。。。它被称为n+1查询(这真的很糟糕)。
热切加载
另一方面,如果你必须访问几乎所有的帖子,你应该进行一次热切的加载。
-- Load all your data in a query
SELECT *
FROM categories c
INNER JOIN posts p ON c.id = p.category_id;
// Basic example in JSON of how to format your result
{
'cat1': ['post1', 'post2'],
'cat2': ['post5', 'post4', 'post5'],
...
}
该怎么办
在你的情况下,我会说一个热切的加载,因为你把所有东西都加载在一个循环中。但是,如果你不能访问大部分数据,你应该重新设计你的模型,以执行延迟加载,这样,当视图试图访问特定类别的帖子时,加载特定类别帖子的SQL查询实际上是执行的。
你觉得怎么样?