php - PHP PDO 一个查询或多个单独查询中的多个结果集
问题描述
我刚刚为一个大学项目完成了一个简单的 PHP 框架,我正在尝试为每个实体创建一个简单的数据访问对象,它封装了所有数据库交互,我不会为此使用 Doctrine 或其他工具,我需要自己做, 它需要简单但健壮,我会尽量让我的问题尽可能清晰。
我想为每个实体创建一个 DAO 类,以便它充当表和实体之间的桥梁。我从 Doctrine 中学到了一些东西,但找不到足够的信息。
由于我每个实体都有一个 Dao 类,显然所有 DB 逻辑都在 Dao 中,实体将具有纯域逻辑,每个 Dao 负责创建实体和对数据层的所有读/写操作
我的主要问题是加载实体关联的最佳和最有效的方法是什么,特别是如果我希望加载完整的关联?
我试图了解这种懒惰和急切的加载如何在实体关联的幕后工作,(不是部分列)
如果我只想要一个列,我可以使用连接,但如果我想要整个实体,我认为这是可能的唯一方法是对数据库进行另一个查询,或者在一个带有行集的执行语句中使用多个查询来获取关联的实体.
如果我有很多关联,如果数据库在不同的机器上怎么办?我想让它尽可能灵活,但我不想要不必要的复杂性,性能上有什么显着差异吗?
特别是如果我从不同的表中获取多个实体,如果我必须发出多个查询,延迟加载和急切加载之间有什么真正的区别吗?由于进行了或多或少相同的查询,
我将使用文章和评论的简单示例 1:many 关系作为示例:
//Article Entity example, Assume each property maps to a column in a database
class Article extends Entity
{
private $id;
private $title;
private $body;
private $comments = [];
//Getters/Setters:
public function get_comments()
{
return $this->comments;
}
}
class Comment extends Entity
{
private $id;
private $title;
private $comment;
private $user_name;
private $created_at;
private $updated_at;
private $edited = false;
//
}
//dao class example:
class ArticleDao extends SQLDao
{
private $one_to_many = [
'comments' => [
//metadata here
],
];
}
现在评论实体/表有不同的列/属性所以如果我想要整个东西它是一个不同的集合所以我猜不可能加入?
假设我想获得一堆文章或一篇文章,并且我想要他们的相关评论,这些评论是评论实体的简单数组/集合,那么最有效的方法是什么?
我觉得我唯一的选择是:
1)创建一个多查询多结果集,我可以一次获取所有内容,我可以使用我的查询生成器,并且 Dao 类可以有一个整洁的包装器,比如:
$article_dao = new Dao();
$article_dao->where('id','=',$id)->with('comments')->get();
//Creates two queries:
SELECT * FROM Articles WHERE id = :id,
SELECT * FROM Comments WHERE Comments.article_id = id,
//use nextrowset:
//Populate entities and initialise objects:
选项2:将dao对象和load方法添加到comments变量中,并创建某种回调,在第一次访问comments属性时调用该方法,下面的代码主要只是一个粗略的版本:
//Base Dao Class method:
public function load_relation($relation, $id):array
{
//Checks if relation exists and is defined
if(!$this->has_relation($relation))
{
return false;
}
/*Initialises the Comment Dao class
and calls the method and passes parent id */
return $this->get_relation($relation)['dao']->get($id);
}
//Base entity class load method:
public function load($prop)
{
Check if the property in the entity has a dao object
if(is_a($this->$prop[0], IDao::class))
{
//Call that method which makes a query to the database
$entities = call_user_func($prop);
}
//Now the array has been populated
$this->$prop = $entities;
//reuturn
return $this->$prop;
}
//Now in the article entity, I could use this:
public function get_comments()
{
return $this->load('comments');
}
还是有更好的选择?
将多个查询与 nextrowset 一起使用而不是一个干净的新查询是否有主要的性能优势?后者似乎更简单,我的代码会更干净
我已经创建了一个基本查询构建器库,我将与 dao 一起使用
也许我错过了重点,我不知道这些 ORM 是如何工作的,但我想创建一个好的平台
任何建议将不胜感激,如果我的问题听起来很复杂,我很抱歉,如果需要,我很乐意尽可能详细地阐述/简化
解决方案
也许这会有所帮助,我 sudo 编码了一堆东西,但希望它能传达这个想法。
class Article extends Entity
{
public $id;
public $title;
public $body;
public $comments = [];
}
class Comment extends Entity
{
public $id;
public $title;
public $comment;
public $user_name;
public $created_at;
public $updated_at;
public $edited = false;
}
class ArticleDao
{
public function get(int $id): Article {
// query for article that has primary key $id
// $object = fetch::class
$object->comments = (new ArticleCommentDao())->findByArticle($id);
return $object;
}
}
class ArticleCommentDao
{
public function findByArticle(int $articleId): array {
// query for comments that have foreign key $articleId
$comments = [];
// foreach result in resultset
// $object = fetch::class
$comments[] = $object;
return $comments;
}
}
推荐阅读
- python - 从 ROS 节点重启计算机
- c# - 尝试在 VST2017 中调试 specflow 场景时发生构建失败错误
- javascript - 在javascript的帮助下从字符串中获取数字
- java - 打模式报警关闭应用
- typo3 - 无法使用通配符或子上下文的 TypoScript applicationContext 条件
- matlab - 参考 MATLAB 中的第二个函数输出
- entity-framework - 如何在包管理器控制台中获取实体框架的可用命令列表
- java - 当我构建项目时,为同一个 .java 文件多次生成的 .class 文件
- c# - 如何在 RichTextBox 的 rtf 代码中获取插入符号的位置?
- c# - 创建帐户时自动 Defender 令牌