Laravel 关系

2025年3月17日 | 阅读11分钟

在 Laravel 中,一个**Eloquent 关系**是一个非常重要的特性,它允许您以一种非常简单的格式关联表。

一对一关系

一对一关系提供不同表列之间的一对一关系。 例如,每个用户都与单个帖子关联,或者可能与多个帖子关联,但在这种关系中,我们将检索用户的单个帖子。 为了定义关系,我们需要首先在 User 模型中定义 **post()** 方法。 在 post() 方法中,我们需要实现 **hasOne()** 方法,该方法返回结果。

让我们通过一个例子来理解一对一关系。

  • 首先,我们在名为 **posts** 的现有表中添加新列 (user_id)。 在这里,user_id 是外键。
Laravel Relationship
  • 使用以下命令将上述更改迁移到数据库中
    php artisan migrate.
  • 迁移后,**posts** 表的结构如下图所示
Laravel Relationship

上图显示 **user_id** 列已成功添加。

  • 打开 **User.php** 文件,在 **User.php** 文件中添加以下代码。

在上面的代码中,我们实现了包含单个参数(即相关模型的名称)的 **hasOne()** 方法。 默认情况下,Post 将 user_id 视为外键。 **post()** 方法搜索 posts 表,因为我们提到了命名空间 '**App/Post**' 并查找列 **user_id**。 我们可以通过提供外键作为第二个参数来覆盖此约定。 它可以被重写为

return $this->hasOne('App\Post',foreign_key)

  • 现在,我们将在 **web.php** 文件中添加路由。

上面的代码正在查找 ID 号为 1 的用户,然后实现该帖子以查找 user_id 等于 1 的用户的帖子。

输出

Laravel Relationship

逆关系

逆向关系是指一对一关系的逆向。 在上面,我们检索了属于特定用户的帖子。 现在,我们根据帖子检索用户信息。 让我们通过一个例子来理解这一点。

  • 首先,我们在 **web.php** 文件中创建路由。
  • 打开我们之前创建的 **Post.php** 文件(模型)。

输出

Laravel Relationship

一对多关系

Laravel 还提供了一对多关系。

  • 首先,我们定义一个查找单个用户所有帖子的路由。
  • 在 **User.php(model)** 文件中添加以下代码。

输出

Laravel Relationship

多对多关系

多对多关系比一对一关系和一对多关系更复杂。 为了定义多对多关系,我们需要创建一个透视表。 枢轴表基本上是一个将两个表关联起来的查找表。 例如,一个用户可能具有不同的角色,其中角色可以由其他用户共享,例如,许多用户可以具有“**管理员**”的角色。 为了定义用户和角色之间的关系,我们需要创建三个表:用户、角色和 role_user。 在我们的数据库中,user 表已经创建;我们需要创建两个表,即 roles 表和透视表 (roles_user)。

  • 首先,我们创建 **Role** 模型。 我们使用以下命令创建模型
    php artisan make:model Role -m
Laravel Relationship

上图显示 roles 表已创建。 **create_roles_table.php** 已在 **database/migration** 目录中创建。 该文件的结构如下所示

在上面的代码中,我们添加了名为“name”的新列。 'name' 列定义了用户角色的名称。

  • 现在,我们有两个表,即 roles 表和 users 表。 为了关联这两个表,我们需要创建透视表 **roles_user** 表。
Laravel Relationship

上图显示 **roles_user** 表已创建。 create_roles_user_table 的结构如下所示

在上面的代码中,我们添加了两个新列,user_id 和 role_id。

  • 使用下面给出的命令迁移上述所有更改
    php artisan migrate
Laravel Relationship
  • 下面的屏幕显示了所有三个表,即 roles、roles_user 和 users 都已创建。
Laravel Relationship

roles 表中可用的数据

Laravel Relationship

users 表中可用的数据

Laravel Relationship

roles_user 表中可用的数据

Laravel Relationship
  • 现在,我们定义路由。

web.php

  • 我们在 **User.php** 文件中添加以下代码,该代码关联了这两个表。

在上面的代码中,**belongsToMany()** 方法包含两个参数,“**App\Role**”,这是使用 Role 模型的命名空间,'roles_user' 是关联两个表的透视表的名称。 belongsToMany() 方法也可以写成

belongsToMany('App\Role','roles_user','user_id','role_id');

上面的行包含另外两个参数 user_id 和 role_id。 user_id 是 users 表的外键,role_id 是 roles 表的外键。

输出

Laravel Relationship
Laravel Relationship

访问中间/透视表

在多对多关系中,我们创建了透视表或中间表。 现在,我们将看到如何检索此透视表。

在上面的模型中,我们正在检索 ID 等于 1 的用户。 然后,使用 **foreach** 循环,我们正在检索角色模型并分配给透视属性。

Laravel Relationship

如果我们要从透视表中检索特定的列,

web.php

输出

Laravel Relationship

Has Many Through(通过)

“has many through”关系提供了一种方便的方式来访问远端或中间关系。 例如,我们有三个表,用户、帖子和国家/地区表。 现在,我们希望通过 User 模型找到属于该国家/地区的帖子。

让我们通过一个例子来理解。

  • country 表在数据库中不可用。 我们首先使用数据库迁移创建 country 模型。
Laravel Relationship
  • 在 country 表中添加“**name**”列。
  • 使用下面给出的命令迁移上述更改
    php artisan migrate
  • 现在,我们在 users 表中添加新列“country_id”。 使用下面给出的命令
    php artisan make:migration add_new_column_column_id -table=users;
  • 执行上述命令后,将在 database/migrations 目录中创建 **add_new_column_column_id** 文件。

在上面的代码中,我们在 users 表中添加了一个新列。

要将上述更改迁移到数据库中,

php artisan migrate

  • 打开 **country.php(model)** 文件。 我们将使用 country 模型提取特定国家/地区的帖子。
    country.php
  • 现在,我们添加了提取特定国家/地区帖子的路由。

输出

Laravel Relationship

多态关系

一对多(多态)

多态关系类似于一对多关系。 当单个模型属于单个关联中的多个类型的模型时,称为一对一多态关系。 例如,如果我们有三个表,帖子、用户和照片表,其中照片表表示与用户和帖子表的多态关系。

让我们通过一个例子来理解这种关系。

  • 我们已经在前面的主题中创建了用户和帖子表。 现在,我们创建一个照片表。
Laravel Relationship

打开在 migrations 文件夹中创建的 **create_photos_table.php** 文件。

在上面的代码中,我们添加了三列,路径、**imageable_id** 和 **imageable_type**。 路径确定图像的路径,**imageable_id** 是用户或帖子的 id 值,而 imageable_type 是模型的类名。

  • 我们将从之前创建的帖子表中删除 **user_id** 列。
  • 查看数据库表。

帖子表中可用的数据

Laravel Relationship

用户表中可用的数据

Laravel Relationship

照片表中可用的数据

Laravel Relationship
  • 打开 **Photo** 模型文件。
  • 在 User 模型文件中添加以下代码。
  • 在 Post 模型文件中添加以下代码。
  • 现在,我们将为用户和帖子创建路由。

输出

Laravel Relationship
Laravel Relationship

一对多(多态)关系的逆向

在本主题中,我们将执行一对多多态关系的逆运算。 到目前为止,我们找到了用户和帖子的图像,现在我们找到了图像的所有者。

让我们通过一个例子来理解。

我们需要在 web.php 文件中创建路由。

在上面的代码中,**Photo::findOrFail($id)** 方法确定是否存在给定 **id** 的照片。 如果存在,则它通过语句“**$photo->imageable**”返回图像的详细信息。

输出

Laravel Relationship

上面的输出显示了图像的详细信息。

多对多多态关系

在多对多多态关系中,目标模型由各种模型共享的唯一记录组成。 例如,标签表在视频和帖子表之间共享多态关系。 标签表由视频和帖子表共享的标签的唯一列表组成。

让我们通过一个例子来理解。

  • 首先,我们创建带有数据库迁移的模型,分别命名为 **Audio、Tag** 和 **Taggable**。
Laravel Relationship
  • 创建模型后,我们将编辑它们的迁移文件。

打开名为“**create_audio_table**”的 Audio 表的迁移文件。

在上面的代码中,我们使用命令 **$table->string('name');** 在 audio 表中创建了名称列。

打开名为“**create_tag_table**”的 Tag 模型的迁移文件。

在上面的代码中,我们使用命令 **$table->string('name');** 在 tags 表中创建了名称列。

打开名为“**create_taggables_table**”的 **Taggable** 模型的迁移文件。

在上面的代码中,我们在 **taggables** 表中添加了三个新列,即 tag_id、taggable_id 和 taggable_type。 tag_id 代表标签表的 ID,taggable id 代表模型表的 ID,taggable type 代表类的名称。

  • 为了迁移上述更改,我们使用下面给出的命令
    php artisan migrate
  • 查看数据库表

audio 表中可用的数据

Laravel Relationship

帖子表中可用的数据

Laravel Relationship

标签表中可用的数据

Laravel Relationship

taggables 表中可用的数据

Laravel Relationship
  • 现在我们在模型上定义关系。

Audio.php

Post.php

  • 现在我们定义路由。

输出

当访问帖子的路由时,输出将是

Laravel Relationship

当访问音频的路由时,输出将是

Laravel Relationship

多对多(多态)关系的逆向

在多对多多态关系中,我们找到了属于帖子和音频模型的标签。 但是,在多对多(多态)关系的逆向中,我们将找到属于特定标签的所有帖子和音频。

让我们通过一个例子来理解。

  • 首先,我们在 Tag 模型中定义方法。

Tag.php

在上面的代码中,我们定义了两种方法,**posts()** 和 **audios()**。 在 posts() 方法中,我们检索属于指定标签的所有帖子。 在 audios() 方法中,我们检索属于指定标签的所有音频。

  • 现在,我们定义路由。

输出

Laravel Relationship
Laravel Relationship
下一主题Laravel Tinker