假设我有两种模式:
class Book
{
public $book_id;
public $book_author_id;
public $title;
}
class Author
{
public $author_id;
public $author_name;
}
我习惯写这样的东西:
$DB->query("SELECT book_id, title, author_name
FROM book
LEFT JOIN author
ON book_author_id = author_id
");
我们假设,我对此关联的单独查询不感兴趣。我该怎么办?以下是我听过的一些事情:
我正在处理的应用程序涉及数十个表,并且在过程代码中进行了高度优化(例如,几乎没有任何SELECT *)。我正在重构以使其更易于维护(我也是最初的创建者),但我想在不需要破坏文件结构和数据库调用的情况下灵活地使用连接。
我可能涉及的一个问题与包括其他模型有关:
class Author
{
public $author_id;
public $author_name;
/* @var Book */ //<--don't really fully understand this but I've seen something like it somewhere
public (array) $authors_books;
}
我仍然在寻找答案,但如果您可以按我的方式发送链接,那将不胜感激。
答案 0 :(得分:3)
你所谓的“模特”实际上是domain objects。他们应该负责处理域业务逻辑,而与存储无关。
与存储相关的逻辑和交互应由单独的对象组处理。最明智的解决方案之一是使用data mappers。每个映射器都可以处理多个表和复杂的SQL。
对于您的查询,此类查询的结果将包含适用于传递给域对象集合的信息。
顺便说一下,那个查询很没用。你忘了每本书都有多位作者。举个例子this book - 它有4个不同的作者。要使此查询有用,您必须基于GROUP_CONCAT()
或author_id
执行book_id
。
实现此类JOIN
语句时,数据库响应很可能是一个集合:
$mapper = $factory->buildMapper('BookCollection');
$collection = $factory->buildCollection('Book');
$collection->setSomeCondition('foobar');
$mapper->fetch( $collection );
foreach ( $collection as $item )
{
$item->setSomething('marker');
}
$mapper->store( $collection );
P.S。您的代码示例似乎漏掉了抽象。让其他结构直接访问对象的变量是一种不好的做法。
P.P.S。您对MVC模型部分的理解似乎与how i see it完全不同。
答案 1 :(得分:2)
数据库连接是关系数据库的人工制品,您无需对其进行建模。您需要对数据 以及的行为进行建模,例如:您的getBooks()
个实例中可能有Author
方法,getByAuthor()
类中可能有静态Book
方法(通常,$author->getBooks()
应该实现为{Book::getByAuthor($this)
1}},因此您的Author
类不应该关注Book
的实现细节。自动实例化所有相关数据并不总是一个好主意(例如,给定Book
实例为所有书籍实例化Author
实例,正如您似乎正在考虑使用$author_books
属性,因为这可能很容易降级为“将整个数据库加载到每个请求的内存”场景。
答案 2 :(得分:1)