在我们的示例域中,每篇博文“有一”条归总记录。这是“一对一”关系的一种,在这儿,每条归总(外地)记录从属于一篇博文。下面我们给模型建立这种关系,代码如下:
<?php
class Acme_Model_Blogs extends Acme_Sql_Model
{
    protected function _setup()
    {
        $this->_hasOne('summary');
    }
}
                    ![]()  | 单数形式 VS. 复数形式 | 
|---|---|
| 
                        
                         模型系统假定所有的数据表(同样地,所有的模型类)以复数形式命名。为了便于直观命名,“有一”关系的名字被假定为单数形式,并且当查找关联目录项时转变为复数形式再查找。当然,你也可以使用下面描述的关系定义键改变这种默认行为。  | 
上面的代码在每条博客记录上创建了一个“虚假的”属性$summary,该属性从模型目录summaries条目中执行延迟的数据查询。也就是说,每次你请求$blog_record->summary时,模型系统将会从数据库获取相关的归总记录并且放到$summary属性中。下面给出延迟加载SQL的一个示例:
SELECT summary.*
FROM summaries AS summary
WHERE summary.blog_id = {$blog_record->id}
LIMIT 1
                    ![]()  | 延迟加载 VS. 贪婪加载 | 
|---|---|
| 
                        
                         小心可怕的N+1问题。如果你获取一个包含10条博客记录的记录集并且遍历它们,每次打印出  | 
在“有一”关系中,外键存在于外地模型/表中。在我们的示例域中,这意味着和blog有关的外键在summaries表中,并且映射表blogs的主键。
![]()  | 外键命名 | 
|---|---|
| 
                        
                         每个模型定义自己被当作外地模型使用时所期望的外键名。接着本地模型会向外地模型请求它(外地模型)期望的外键名。 默认情况下,模型使用其关联表名的单数形式,后跟表主键名的组合作为外键名。例如,如果模型/表名是“authors”,表主键是“id”,那么authors模型将默认把它的外键名定义为“author_id”。你可以在外地模型的setup方法中添加代码  | 
当外地数据在数据库中不存在时,且当你试着访问不存在的关系记录时,Solar模型系统会在主记录对象中为你创建一个新的记录对象。显然,有些时候这些自动产生的记录并不是我们想要的。在这种情况下,我们可以定义hasOneOrNull关系。在这种关系中,如果你请求的外地数据不存在,那么关系属性得到的是一个null对象,而不是一个新的记录对象,而且如果你要访问它,你需要自己判断该记录对象是否存在。
尽管Solar模型系统预先假设了数据表和外键的命名规则,但是这些假设都不是硬编码的。你可以在调用_hasOne()方法时给它传递一个键-值数组来重新定义这种外部关系的方方面面。
<?php
        $this->_hasOne('name', array(
            'option' => 'value',
            // ...
        ));
                    - string 
foreign_name - 
                                
正常情况下,模型系统期望外地模型以关系名称的复数形式存在于模型目录中。例如,本地的
_hasOne('foreign')意味着外地模型名为‘foreigns’,并且关联了某些模型类。使用
foreign_name选项可以为外地模型设置一个不同的目录名。这允许你把关系名命为“foo”(也即记录的外键属性),却使用“bar”模型为其做相关的工作。foreign_class选项优先于foreign_name选项。 - string 
foreign_key - 
                                
正常情况下,模型系统期望外地表中的外键名和本地模型中
foreign_col属性定义的值一致。使用
foreign_key选项可以在外地表中设置一个不同的字段名。(如果设置了native_col或foreign_col选项,那么foreign_key选项将被忽略。) - array 
cols - 
                                
为关系记录获取这些字段。
 - array 
conditions - 
                                
获取关系记录时,对外地表附加的条件。这些在获取数据时,将被适当地使用为WHERE或是JOIN ON条件。(例如,延迟获取 VS. 贪婪获取)
 - array 
order - 
                                
获取关系记录时附加的ORDER从句。
 
![]()  | Note | 
|---|---|
| 
                         以下是一些不太常见,但更高级和更细密的选项定义关系:  | 
- string 
foreign_class - 
                                
外地模型的类名。默认是关系名在父类栈中匹配到的第一个类。
 - string 
foreign_alias - 
                                
外地表的别名。默认是关系名。
 - string 
foreign_col - 
                                
外地表中参与联合的字段名,与本地表中的一些字段进行匹配。这形成了关系条件的外地部分。
 - string 
native_col - 
                                
本地表中参与联合的字段名,与外部表中的一些字段进行匹配。这形成了关系条件的本地部分。
 - string 
native_by - 
                                
贪婪获取时用于连接本地记录的策略:‘wherein’,这意味着“WHERE IN (...)”(即“在”)本地ID的一个列表中;或者“select”,这意味着一个子查询。
 - int 
wherein_max - 
                                
选择
native-by策略时,使用‘wherein’最多在本地结果中产生这么多记录;之后,再使用‘select’策略。 - string 
merge - 
                                
指定为合并加入的外地记录的策略:‘server’是指数据库将通过单个SELECT语句把结果合并到本地获取的数据中(仅适合“对一”关系);然而,‘client‘是指使用PHP来处理它,在关系中使用一个额外的SELECT语句(“对多”关系总是如此,“对一”关系是可选的),之后在PHP循环中合并这些记录。
 
![[Note]](images/note.png)
![[Warning]](images/warning.png)

