### [](https://octobercms.com/docs/database/relations#one-to-one)一对一
一对一关系是非常基本的关系。例如,`User`模型可能与关联`Phone`。为了定义这种关系,我们向模型`phone`的`$hasOne`属性添加一个条目`User`。
~~~
<?php namespace Acme\Blog\Models;
use Model;
class User extends Model
{
public $hasOne = [
'phone' => 'Acme\Blog\Models\Phone'
];
}
~~~
定义关系后,我们可以使用相同名称的model属性检索相关记录。这些属性是动态的,使您可以像访问模型中的常规属性一样访问它们:
~~~
$phone = User::find(1)->phone;
~~~
模型基于模型名称假定关系的外键。在这种情况下,将`Phone`自动假定模型具有`user_id`外键。如果您希望覆盖此约定,则可以将`key`参数传递给定义:
~~~
public $hasOne = [
'phone' => ['Acme\Blog\Models\Phone', 'key' => 'my_user_id']
];
~~~
此外,该模型还假定外键的值应`id`与父级的列匹配。换句话说,它将在记录的`id`列中查找用户列的值。如果您希望该关系使用以外的值,则可以将参数传递给定义:`user_id``Phone``id``otherKey`
~~~
public $hasOne = [
'phone' => ['Acme\Blog\Models\Phone', 'key' => 'my_user_id', 'otherKey' => 'my_id']
];
~~~
#### 定义关系的逆关系
现在,我们可以从中访问`Phone`模型了`User`。让我们做相反的事情,并在`Phone`模型上定义一个关系,使我们可以访问`User`拥有手机的。我们可以`hasOne`使用`$belongsTo`属性定义关系的逆:
~~~
class Phone extends Model
{
public $belongsTo = [
'user' => 'Acme\Blog\Models\User'
];
}
~~~
在上面的例子中,模型将尝试匹配的`user_id`从`Phone`模型到一个`id`上`User`的模型。它通过检查关系定义的名称并在名称后缀来确定默认的外键名称`_id`。但是,如果`Phone`模型上的外键不是`user_id`,则可以使用`key`定义中的参数传递自定义键名称:
~~~
public $belongsTo = [
'user' => ['Acme\Blog\Models\User', 'key' => 'my_user_id']
];
~~~
如果您的父模型不用`id`作其主键,或者您希望将子模型连接到其他列,则可以将`otherKey`参数传递给指定父表的自定义键的定义:
~~~
public $belongsTo = [
'user' => ['Acme\Blog\Models\User', 'key' => 'my_user_id', 'otherKey' => 'my_id']
];
~~~
#### 默认型号
的`belongsTo`关系,您可以定义如果给定的关系是将要返回默认模式`null`。此模式通常称为[空对象模式](https://en.wikipedia.org/wiki/Null_Object_pattern),可以帮助删除代码中的条件检查。在以下示例中,如果该帖子未附加,则该`user`关系将返回一个空`Acme\Blog\Models\User`模型`user`:
~~~
public $belongsTo = [
'user' => ['Acme\Blog\Models\User', 'default' => true]
];
~~~
要使用属性填充默认模型,可以将数组传递给`default`参数:
~~~
public $belongsTo = [
'user' => [
'Acme\Blog\Models\User',
'default' => ['name' => 'Guest']
]
];
~~~
### [](https://octobercms.com/docs/database/relations#one-to-many)一对多
一对多关系用于定义单个模型拥有任意数量其他模型的关系。例如,博客帖子可能有无限数量的评论。与所有其他关系一样,定义了一对多关系`$hasMany`,在模型的属性中添加了一个条目:
~~~
class Post extends Model
{
public $hasMany = [
'comments' => 'Acme\Blog\Models\Comment'
];
}
~~~
请记住,模型将自动确定模型上正确的外键列`Comment`。按照惯例,它将采用拥有模型的“ snake case”名称,并在其后缀`_id`。因此,对于此示例,我们可以假定`Comment`模型上的外键为`post_id`。
定义关系后,我们可以通过访问`comments`属性来访问评论集合。请记住,由于模型提供了“动态属性”,因此我们可以像在模型上将它们定义为属性一样访问关系:
~~~
$comments = Post::find(1)->comments;
foreach ($comments as $comment) {
//
}
~~~
当然,由于所有关系也都可以用作查询生成器,因此可以通过调用`comments`方法并继续将条件链接到查询上来为注释添加更多约束:
~~~
$comments = Post::find(1)->comments()->where('title', 'foo')->first();
~~~
像该`hasOne`关系一样,您还可以通过分别在定义上传递`key`和`otherKey`参数来覆盖外键和本地键:
~~~
public $hasMany = [
'comments' => ['Acme\Blog\Models\Comment', 'key' => 'my_post_id', 'otherKey' => 'my_id']
];
~~~
#### 定义关系的逆关系
现在我们可以访问帖子的所有评论,让我们定义一个关系以允许评论访问其父帖子。要定义`hasMany`关系的逆关系,请`$belongsTo`在子模型上定义属性:
~~~
class Comment extends Model
{
public $belongsTo = [
'post' => 'Acme\Blog\Models\Post'
];
}
~~~
一旦定义了关系,我们可以通过访问“动态属性”来检索`Post`模型:`Comment``post`
~~~
$comment = Comment::find(1);
echo $comment->post->title;
~~~
在上面的例子中,模型将尝试匹配的`post_id`从`Comment`模型到一个`id`上`Post`的模型。它通过检查关系的名称并为它加后缀来确定默认的外键名称`_id`。但是,如果`Comment`模型上的外键不是`post_id`,则可以使用以下`key`参数传递自定义键名称:
~~~
public $belongsTo = [
'post' => ['Acme\Blog\Models\Post', 'key' => 'my_post_id']
];
~~~
如果您的父模型不用`id`作其主键,或者您希望将子模型连接到其他列,则可以将`otherKey`参数传递给指定父表的自定义键的定义:
~~~
public $belongsTo = [
'post' => ['Acme\Blog\Models\Post', 'key' => 'my_post_id', 'otherKey' => 'my_id']
];
~~~
### [](https://octobercms.com/docs/database/relations#many-to-many)多对多
多对多关系比`hasOne`和`hasMany`关系稍微复杂。这种关系的一个示例是具有多个角色的用户,其中这些角色也由其他用户共享。例如,许多用户可能具有“管理员”角色。要定义这种关系,需要三个数据库表:`users`,`roles`,和`role_user`。该`role_user`表是从相关模型名称的字母顺序得出的,并且包含`user_id`和`role_id`列。
下面的示例显示了用于创建联接表的[数据库表结构](https://octobercms.com/docs/plugin/updates#migration-files)。
~~~
Schema::create('role_user', function($table)
{
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->primary(['user_id', 'role_id']);
});
~~~
定义了多对多关系`$belongsToMany`,在模型类的属性上添加了一个条目。例如,让`roles`我们在`User`模型上定义方法:
~~~
class User extends Model
{
public $belongsToMany = [
'roles' => 'Acme\Blog\Models\Role'
];
}
~~~
定义关系后,您可以使用`roles`dynamic属性访问用户的角色:
~~~
$user = User::find(1);
foreach ($user->roles as $role) {
//
}
~~~
当然,像所有其他关系类型一样,您可以调用该`roles`方法以继续将查询约束链接到该关系上:
~~~
$roles = User::find(1)->roles()->orderBy('name')->get();
~~~
如前所述,为了确定关系的联接表的表名,模型将按字母顺序联接两个相关的模型名。但是,您可以随意重写此约定。您可以通过将`table`参数传递给`belongsToMany`定义来实现:
~~~
public $belongsToMany = [
'roles' => ['Acme\Blog\Models\Role', 'table' => 'acme_blog_role_user']
];
~~~
除了自定义联接表的名称之外,还可以通过将其他参数传递给`belongsToMany`定义来自定义表上键的列名。该`key`参数是要为其定义关系模型的外键名称,而`otherKey`参数是要加入到模型的外键名:
~~~
public $belongsToMany = [
'roles' => [
'Acme\Blog\Models\Role',
'table' => 'acme_blog_role_user',
'key' => 'my_user_id',
'otherKey' => 'my_role_id'
]
];
~~~
#### 定义关系的逆关系
要定义多对多关系的逆关系,只需`$belongsToMany`在相关模型上放置另一个属性即可。继续我们的用户角色示例,让我们`users`在`Role`模型上定义关系:
~~~
class Role extends Model
{
public $belongsToMany = [
'users' => 'Acme\Blog\Models\User'
];
}
~~~
如您所见,该关系的定义与其`User`对应关系完全相同,只是简单地引用了`Acme\Blog\Models\User`模型。由于我们正在重用该`$belongsToMany`属性,因此在定义多对多关系的逆关系时,所有常用的表和键自定义选项均可用。
#### 检索中间表列
如您所知,使用多对多关系需要一个中间联接表。模型提供了一些与该表进行交互的非常有用的方法。例如,假设我们的`User`对象有许多`Role`与之相关的对象。访问此关系后,我们可以使用`pivot`模型上的属性访问中间表:
~~~
$user = User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
~~~
请注意,`Role`我们检索的每个模型都会自动分配一个`pivot`属性。此属性包含表示中间表的模型,并且可以像其他任何模型一样使用。
默认情况下,只有模型关键点会出现在`pivot`对象上。如果数据透视表包含额外的属性,则在定义关系时必须指定它们:
~~~
public $belongsToMany = [
'roles' => [
'Acme\Blog\Models\Role',
'pivot' => ['column1', 'column2']
]
];
~~~
如果希望您的数据透视表具有自动维护`created_at`和`updated_at`时间戳记,请使用`timestamps`关系定义上的参数:
~~~
public $belongsToMany = [
'roles' => ['Acme\Blog\Models\Role', 'timestamps' => true]
];
~~~
这些是`belongsToMany`关系支持的参数:
| 论据 | 描述 |
| --- | --- |
| **table** | 联接表的名称。 |
| **key** | 定义模型的关键列名称(在数据透视表内部)。默认值由型号名称和`_id`后缀组合而成,即`user_id` |
| **parentKey** | 定义模型的键列名称(在定义模型表内部)。默认值:id |
| **otherKey** | 相关模型的关键列名称(在数据透视表内部)。默认值由型号名称和`_id`后缀组合而成,即`role_id` |
| **relatedKey** | 相关模型的关键列名称(在相关模型表内部)。默认值:id |
| **pivot** | 在联接表中找到的一组枢轴列,可通过访问属性`$model->pivot`。 |
| **pivotModel** | 指定访问枢纽关系时要返回的自定义模型类。默认为`October\Rain\Database\Pivot`。 |
| **timestamps** | 如果为true,则联接表应包含`created_at`和`updated_at`列。默认值:false |
### [](https://octobercms.com/docs/database/relations#has-many-through)有很多通过
拥有多次关系为通过中间关系访问远处的关系提供了方便的捷径。例如,一个`Country`模型可能`Post`通过中间`User`模型具有许多模型。在此示例中,您可以轻松地收集给定国家/地区的所有博客文章。让我们看一下定义此关系所需的表:
~~~
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
~~~
尽管`posts`不包含`country_id`列,但该`hasManyThrough`关系可通过访问该国家/地区的帖子`$country->posts`。要执行此查询,模型将检查`country_id`中间`users`表上的。找到匹配的用户标识后,将使用它们来查询`posts`表。
现在我们已经检查了关系的表结构,让我们在`Country`模型上定义它:
~~~
class Country extends Model
{
public $hasManyThrough = [
'posts' => [
'Acme\Blog\Models\Post',
'through' => 'Acme\Blog\Models\User'
],
];
}
~~~
传递给该`$hasManyThrough`关系的第一个参数是我们希望访问的最终模型的名称,而`through`参数是中间模型的名称。
执行关系查询时,将使用典型的外键约定。如果您想自定义关系的钥匙,你可以通过他们的`key`,`otherKey`和`throughKey`参数的`$hasManyThrough`定义。该`key`参数是在中间模型外键的名称,`throughKey`参数是最终的模型外键的名称,而`otherKey`为本地密钥。
~~~
public $hasManyThrough = [
'posts' => [
'Acme\Blog\Models\Post',
'key' => 'my_country_id',
'through' => 'Acme\Blog\Models\User',
'throughKey' => 'my_user_id',
'otherKey' => 'my_id'
],
];
~~~
### [](https://octobercms.com/docs/database/relations#has-one-through)一通
一对一关系通过单个中间关系链接模型。例如,如果每个供应商有一个用户,并且每个用户与一个用户历史记录相关联,则供应商模型可以通过用户访问用户的历史。让我们看一下定义此关系所需的数据库表:
~~~
users
id - integer
supplier_id - integer
suppliers
id - integer
history
id - integer
user_id - integer
~~~
尽管该`history`表不包含`supplier_id`列,但是该`hasOneThrough`关系可以提供对供应商模型的用户历史记录的访问。现在我们已经检查了关系的表结构,让我们在`Supplier`模型上定义它:
~~~
class Supplier extends Model
{
public $hasOneThrough = [
'userHistory' => [
'Acme\Supplies\Model\History',
'through' => 'Acme\Supplies\Model\User'
],
];
}
~~~
传递给该`$hasOneThrough`属性的第一个数组参数是我们希望访问的最终模型的名称,而`through`键是中间模型的名称。
执行关系查询时,将使用典型的外键约定。如果您想自定义关系的钥匙,你可以通过他们的`key`,`otherKey`和`throughKey`参数的`$hasManyThrough`定义。该`key`参数是在中间模型外键的名称,`throughKey`参数是最终的模型外键的名称,而`otherKey`为本地密钥。
~~~
public $hasOneThrough = [
'userHistory' => [
'Acme\Supplies\Model\History',
'key' => 'supplier_id',
'through' => 'Acme\Supplies\Model\User'
'throughKey' => 'user_id',
'otherKey' => 'id'
],
];
~~~
- 基本说明
- 基本操作
- October cms 安装
- 后台控制器路径
- 图标
- 获取安装网上的插件/主题
- 插件构造器使用
- 定时任务
- October后台控制器
- vscode编辑器
- ajax操作
- 使用
- ajax更新组件
- ajax属性API
- JavaScript API
- ajax综合使用
- 主题
- 多语言主题
- 安装市场主题
- 主题程序处理
- 主题
- 页面
- 部件
- 布局
- 内容
- 组件
- 媒体
- 主题表单操作
- 表单使用
- 表单后端程序处理
- 插件
- 自定义插件
- 插件说明
- 插件导航条
- 插件数据库设置
- 插件的设置管理
- 插件的配置文件config
- 组件
- app服务
- app容器
- 扩展行为
- 缓存
- Collection类
- Lazy Collections
- Collection方法
- 助手函数
- 数组助手函数
- 路径助手函数
- 玄乐助手函数
- 其他助手函数
- 错误与记录
- 事件处理
- HTML页面
- 文件与目录操作
- 散列和加密
- 邮件
- 邮件内容
- 邮件发送
- 分页
- 模板解析器
- 动态解析器语法
- 队列消息
- 请求与输入
- 响应
- 视图
- 路由器
- 配置
- 验证操作
- 处理错误消息
- 错误消息与视图
- 可用的验证规则
- 有条件的验证规则
- 验证数组
- 错误消息
- 自定义验证规则
- 模型操作
- 定义模型与其属性
- 检索模型
- 插入与更新
- 删除模型
- 查询范围
- 事件操作
- 关联操作
- 定义关系
- 关系类型
- 多肽关系
- 关系查询
- 渴望加载
- 插入模型
- 数据库操作
- 基本用法
- 数据表结构
- 查询连贯操作
- 结果检索
- select子句
- 插入更新
- where子句
- 排序,分组,限制和偏移
- 文件附件
- Collection操作
- 属性操作
- 系列化json
- 数据库属性
- 数据库行为
- 控制器
- 后台控制器定义
- 后台页面
- 后台组件
- 后台表单
- 表单组件
- 表单视图
- 表单行为
- 后台列表
- 列表行为
- 列表过滤器
- 可用列类型
- 关系行为
- 关系行为类型
- 扩展关系行为
- 列表排序操作
- 导入导出操作
- 用于与权限
- corlate模板修改
- 修改顶部导航
- laravel问题
- 控制器不存在
- 控制器
- 路由组
- laravel笔记
- laravel 安装
- 伪静态配置
- 依赖注入 & 控制器
- 中间件
- 路由文件
- 视图