ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 数据库和表 我们将学习Nette框架中数据库“表”层的基础知识。 Nette\Database\Table层帮助您更容易地以更优化的方式获取数据库数据。 主要的态度是只从一个表中提取数据,并立即提取它们。 将数据提取到ActiveRow实例中。 来自由关系连接的其他表的数据由另一个查询传递 - 这由数据库\表层本身维护。 ~~~ 让我们来看看常见的用例。 你需要获取书籍和作者数据。 它是普通的1:N关系。 常用的实现通过一个具有表连接的SQL查询提取数据。 第二种可能性是单独获取数据,运行一个查询以获取图书,然后通过另一个查询(例如在您的foreach循环中)为每本图书获取作者。 这可以很容易地优化为只运行两个查询,一个用于书籍,另一个用于所需的作者 - 这只是Nette \ Database \ Table的工作方式。 ~~~ Database\Table层提供了Selection实例,作为一个数据库表中的数据选择。 选择实例可帮助您过滤所需的数据并将其作为ActiveRow实例提取。 创建选择很容易,只需在数据库上下文中调用table()方法。 看看如何在Nette \ Database一章中获取或创建上下文实例。 ~~~ $selection = $context->table('book'); // db表名称是 "book" ~~~ 选择工具Traversable接口:你可以只是迭代实例来获取所有的书。 行作为ActiveRow实例提取; 您可以从其属性中读取行数据。 ~~~ $books = $context->table('book'); foreach ($books as $book) { echo $book->title; echo $book->author_id; } ~~~ 只有一个特定的行由Selection :: get()方法完成。 它是“过滤”方法,它直接返回一个ActiveRow实例。 ~~~ $book = $context->table('book')->get(2); // 返回ID为2的书 echo $book->title; echo $book->author_id; ~~~ ## 使用关系 正如我们在章节介绍中提到的,Database\Table层为您维护表关系。 有两种可能性如何和在哪里可以与关系工作。 1、过滤选择获取的行。 在介绍中,我们说明了一次只从一个数据库表中选择数据的基本原理。 但是,Selection实例可以执行表连接以筛选所选行。 例如,您只需要选择写入超过2本书的作者。 有关详细概述,请参阅数据库:选择一章。 2、获取获取的ActiveRows的相关数据。 我们拒绝同时从多个表中获取数据。 可悲的是,打印author_id不够好。 我们需要获得完整的作者数据库行,理想情况下作为ActiveRow提取。 获得这种类型的关系由ActiveRow维护。 有关详细信息,请参阅数据库:ActiveRow章节。 在提供的示例中,我们将使用下面的数据库模式。 有常见的OneHasMany和ManyHasMany关系。 OneHasMany关系加倍,一本书必须有一个作者,可以有一个翻译(translator_id可能是一个NULL)。 有以下数据库结构的例子 ![](https://box.kancloud.cn/099c37476dbe9bad6cfb2f56eea314d9_334x355.png) 在下面的示例中,我们获取了提取的书籍的相关数据。 在作者属性(书ActiveRow实例)中有另一个ActiveRow实例,它表示书的作者。 获取book_tag实例是由related()方法完成的,它返回这个实例的集合。 在循环中,我们从book_tag实例中可用的另一个ActiveRow实例获取标记名称。 有关获取相关数据的详细概述,请参阅数据库:ActiveRow章节。 ~~~ $books = $context->table('book'); foreach ($books as $book) { echo 'title: ' . $book->title; echo 'written by: ' . $book->author->name; echo 'tags: '; foreach ($book->related('book_tag') as $bookTag) { echo $bookTag->tag->name . ', '; } } ~~~ 你会很高兴数据库层的工作效率。 上面的示例执行常量查询,请参阅以下4个查询: ~~~ SELECT * FROM `book` SELECT * FROM `author` WHERE (`author`.`id` IN (11, 12)) SELECT * FROM `book_tag` WHERE (`book_tag`.`book_id` IN (1, 4, 2, 3)) SELECT * FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23)) ~~~ 如果您使用缓存(默认值),则不会不必要地查询列。 第一次查询后,缓存将存储使用的列名称,Nette \ Database将仅运行具有所需列的查询: ~~~ SELECT `id`, `title`, `author_id` FROM `book` SELECT `id`, `name` FROM `author` WHERE (`author`.`id` IN (11, 12)) SELECT `book_id`, `tag_id` FROM `book_tag` WHERE (`book_tag`.`book_id` IN (1, 4, 2, 3)) SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23)) ~~~