# 數據庫:ActiveRow
Selection所返回的每一行由ActiveRow實例表示。 此類提供用于訪問已提取列的標準接口。 您可以讀取數據作為屬性或通過數組訪問。 如果列不存在,則拋出MemberAccessException。 您可以檢查列是否由標準isset結構設置。
~~~
echo $book->id;
echo $book['title'];
isset($book->id);
isset($book['title']);
~~~
請注意,即使提取列,但值為NULL,isset也會返回FALSE。
## 關系
主要的Nette\Database\Table原理是分別從不同的表中提取數據。 此行為由Nette\Database本身維護,行的相關數據將同時為所有其他行提取。 我們有兩種簡單的關系類型:“有一個”和“有很多”。
我們將使用DiscoveredConventions,它從你的數據庫中獲取關系。
## 一對一關系
一對一關系是一個常見的用例。 書有一個作者。 書有一個翻譯。 獲取相關行主要由ref()方法完成。 Ref()方法接受兩個參數:目標表名和源連接列。 參見示例:
~~~
$book = $context->table('book')->get(1);
$book->ref('author', 'author_id');
~~~
在上面的示例中,我們從作者表獲取相關作者條目,作者主鍵由book.author_id列搜索。 如果沒有適當的條目,Ref()方法返回ActiveRow實例或NULL。 返回的行是ActiveRow的一個實例,所以我們可以使用與書條目相同的方式。
~~~
$author = $book->ref('author', 'author_id');
$author->name;
$author->born;
// or directly
$book->ref('author', 'author_id')->name;
$book->ref('author', 'author_id')->born;
~~~
書也有一個翻譯,所以得到翻譯名稱是很容易。
~~~
$book->ref('author', 'translator_id')->name
~~~
所有這一切都很好,但它有點麻煩,你不覺得嗎? 數據庫已經包含外鍵定義,為什么不自動使用它們? 讓我們這樣做!
如果我們調用property不存在,ActiveRow嘗試將調用屬性名稱解析為“has one”關系。 獲取此屬性與調用只有一個參數的ref()方法相同。 我們將調用唯一的參數key。 鍵將被解析為特定的外鍵關系。 傳遞的鍵與行列匹配,如果匹配,則在匹配列上定義的外鍵用于從相關目標表獲取數據。 參見示例:
~~~
$book->author->name;
// same as
$book->ref('author')->name;
~~~
ActiveRow實例沒有作者列。 將搜索所有圖書列與鍵匹配。 在這種情況下匹配意味著列名稱必須包含鍵。 因此,在上面的示例中,author_id列包含字符串“author”,因此與“author”鍵匹配。 如果你想得到圖書翻譯,只需要使用例如。 “translator”作為鍵,因為“translator”鍵將匹配translator_id列。 您可以在“加入表達式”章節中找到有關鍵匹配邏輯的更多信息。
~~~
echo $book->title . ": ";
echo $book->author->name;
if ($book->translator) {
echo " (translated by " . $book->translator->name . ")";
}
~~~
如果您要獲取多本圖書,應該使用相同的方法。 Nette \ Database將同時獲取所有提取的圖書的作者和翻譯者。
~~~
$books = $context->table('book');
foreach ($books as $book) {
echo $book->title . ": ";
echo $book->author->name;
if ($book->translator) {
echo " (translated by " . $book->translator->name . ")";
}
}
~~~
代碼將只運行這3個查詢:
~~~
SELECT * FROM `book`;
SELECT * FROM `author` WHERE (`id` IN (1, 2, 3)); -- ids of fetched books from author_id column
SELECT * FROM `author` WHERE (`id` IN (2, 3)); -- ids of fetched books from translator_id column
~~~
## 多對多關系
“多對我”關系只是扭轉了“一對一”關系。 作者寫了很多書。 作者翻譯了很多書。 正如你可以看到的,這種類型的關系是有點困難,因為關系是“命名”(“書面”,“翻譯”)。 ActiveRow實例具有related()方法,它將返回相關條目的數組。 條目也是ActiveRow實例。 參見下面的例子:
~~~
$author = $context->table('author')->get(11);
echo $author->name . " has written:";
foreach ($author->related('book.author_id') as $book) {
echo $book->title;
}
echo "and translated:";
foreach ($author->related('book.translator_id') as $book) {
echo $book->title;
}
~~~
Related()方法接受作為兩個參數傳遞的完整連接描述或作為由點連接的一個參數。 第一個參數是目標表,第二個是目標列。
~~~
$author->related('book.translator_id');
// same as
$author->related('book', 'translator_id');
~~~
您可以使用基于外鍵的Nette \ Database啟發式方法,并且只提供關鍵參數。 鍵將與指向當前表(作者表)的所有外鍵進行匹配。 如果有匹配,Nette \ Database將使用這個外鍵,否則會拋出Nette \ InvalidArgumentException或AmbiguousReferenceKeyException。 您可以在“加入表達式”章節中找到有關鍵匹配邏輯的更多信息。
當然,你可以為所有獲取的作者調用相關的方法,Nette \ Database將再次同時獲取適當的書。
~~~
$authors = $context->table('author');
foreach ($authors as $author) {
echo $author->name . " has written:";
foreach ($author->related('book') as $book) {
$book->title;
}
}
~~~
上面的示例將只運行兩個查詢:
~~~
SELECT * FROM `author`;
SELECT * FROM `book` WHERE (`author_id` IN (1, 2, 3)); -- ids of fetched authors
~~~
- Nette簡介
- 快速開始
- 入門
- 主頁
- 顯示文章詳細頁
- 文章評論
- 創建和編輯帖子
- 權限驗證
- 程序員指南
- MVC應用程序和控制器
- URL路由
- Tracy - PHP調試器
- 調試器擴展
- 增強PHP語言
- HTTP請求和響應
- 數據庫
- 數據庫:ActiveRow
- 數據庫和表
- Sessions
- 用戶授權和權限
- 配置
- 依賴注入
- 獲取依賴關系
- DI容器擴展
- 組件
- 字符串處理
- 數組處理
- HTML元素
- 使用URL
- 表單
- 驗證器
- 模板
- AJAX & Snippets
- 發送電子郵件
- 圖像操作
- 緩存
- 本土化
- Nette Tester - 單元測試
- 與Travis CI的持續集成
- 分頁
- 自動加載
- 文件搜索:Finder
- 原子操作