Laravel数据库中的关系

本文概述

  • 一对一关系
  • 逆关系
  • 一对多关系
  • 多对多关系
  • 访问中间/数据透视表
  • 有很多通过
  • 多态关系
Eloquent的关系是Laravel中非常重要的功能, 它使你能够以非常简单的格式关联表。
一对一关系 一对一关系提供了不同表的列之间的一对一关系。例如, 每个用户都与一个帖子或多个帖子相关联, 但是在这种关系中, 我们将检索用户的单个帖子。要定义关系, 我们首先需要在User模型中定义post()方法。在post()方法中, 我们需要实现可返回结果的hasOne()方法。
让我们通过一个例子来理解一对一的关系。
  • 首先, 我们在名为posts的现有表中添加新列(user_id)。在此, user_id是外键。
Laravel数据库中的关系

文章图片
  • 使用以下命令迁移数据库中的以上更改:php artisan migration。
  • 迁移后, 以下屏幕快照显示了posts表的结构:
Laravel数据库中的关系

文章图片
上面的屏幕快照显示成功添加了user_id列。
  • 打开User.php文件, 并在User.php文件中添加以下代码。
public function post() { return $this-> hasOne('App\Post'); }

在上面的代码中, 我们实现了hasOne()方法, 该方法包含单个参数, 即相关模型的名称。默认情况下, Post将user_id视为外键。正如我们提到的名称空间“ App / Post”一样, post()方法搜索posts表, 并查找user_id列。我们可以通过提供外键作为第二个参数来覆盖此约定。可以将其重写为:
返回$ this-> hasOne(’ App \ Post’ , foreign_key)
  • 现在, 我们将路由添加到web.php文件中。
< ?php use App\User; Route::get('/user', function() { return User::find(1)-> post; } );

上面的代码是查找ID号为1的用户, 然后实现帖子以查找user_id等于1的用户的帖子。
输出量
Laravel数据库中的关系

文章图片
逆关系 逆关系是指一对一关系的逆关系。在上面, 我们检索了属于特定用户的帖子。现在, 我们根据帖子检索用户信息。让我们通过一个例子来理解这一点。
  • 首先, 我们在web.php文件中创建路由。
< ?php use App\Post; Route::get('/post/user', function() { return Post::find(1)-> user-> name; });

  • 打开我们之前创建的Post.php文件(模型)。
< ?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Post extends Model { use SoftDeletes; protected $table='posts'; protected $primaryKey='id'; protected $fillable= [ 'title', 'body' ]; protected $dates=['deleted_at']; public function user() { return $this-> belongsTo('App\User'); }}

输出量
Laravel数据库中的关系

文章图片
一对多关系 Laravel还提供一对多关系。
  • 首先, 我们定义查找单个用户所有帖子的路线。
Route::get('/posts', function(){ $user=User::find(1); foreach($user-> posts as $post){ echo $post-> title."< br> "; } });

  • 在User.php(model)文件中添加以下代码。
public function posts() { return $this-> hasMany('App\Post', 'user_id'); }

输出量
Laravel数据库中的关系

文章图片
多对多关系 多对多关系比一对一关系和一对多关系更为复杂。要定义多对多关系, 我们需要创建一个数据透视表。数据透视表基本上是一个将两个表关联起来的查找表。例如, 一个用户可能具有不同的角色, 这些角色可以由其他用户共享, 就像许多用户可以具有“管理员”角色一样。要定义用户和角色之间的关系, 我们需要创建三个表, 用户, 角色和role_user。在我们的数据库中, 用户表已经创建;我们需要创建两个表, 即角色表和数据透视表(roles_user)。
  • 首先, 我们创建角色模型。我们使用以下命令创建模型:php artisan make:model Role -m
Laravel数据库中的关系

文章图片
上面的屏幕显示角色表已创建。 create_roles_table.php已在数据库/迁移目录中创建。该文件的结构如下:
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateRolesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('roles', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> string('name'); $table-> timestamps(); }); }/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('roles'); } }

在上面的代码中, 我们添加了名为“ name”的新列。 “名称”列定义用户角色的名称。
  • 现在, 我们有两个表, 角色表和用户表。为了关联这两个表, 我们需要创建数据透视表角色_用户表。
Laravel数据库中的关系

文章图片
上面的屏幕显示Roles_user表已创建。下面给出了create_roles_user_table的结构:
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateRolesUserTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('roles_user', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> integer('user_id'); $table-> integer('role_id'); $table-> timestamps(); }); }/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('roles_user'); } }

在上面的代码中, 我们添加了两个新列, user_id和role_id。
  • 使用以下命令迁移所有上述更改:php artisan migration
Laravel数据库中的关系

文章图片
  • 以下屏幕显示了所有三个表, 即角色, roles_user和用户已创建。
Laravel数据库中的关系

文章图片
角色表中可用的数据:
Laravel数据库中的关系

文章图片
用户表中可用的数据:
Laravel数据库中的关系

文章图片
role_user表中可用的数据:
Laravel数据库中的关系

文章图片
  • 现在, 我们定义路线。
web.php
Route::get('/roles/{id}', function($id){ $user=User::find($id); foreach($user-> role as $role) { return $role-> name; } });

  • 我们在与两个表相关的User.php文件中添加以下代码。
public function role() { return $this-> belongsToMany('App\Role', 'roles_user'); }

在上面的代码中, belongsToMany()方法包含两个参数:“ App \ Role”(使用角色模型的命名空间), “ roles_user”是关联两个表的数据透视表的名称。 EmiratesToMany()方法也可以写成:
ownersToMany(’ App \ Role’ , ‘ roles_user’ , ‘ user_id’ , ‘ role_id’ );
上一行包含另外两个参数, user_id和role_id。 user_id是用户表的外键, 而role_id是角色表的外键。
输出量
Laravel数据库中的关系

文章图片
Laravel数据库中的关系

文章图片
访问中间/数据透视表 在多对多关系中, 我们创建数据透视表或中间表。现在, 我们将看到如何检索此数据透视表。
< ?php Use App\User; Route::get('/pivot', function(){ $user=User::find(1); foreach($user-> role as $role) { return $role-> pivot; } });

在上述模型中, 我们检索ID等于1的用户。然后, 使用foreach循环, 检索角色模型并在ivot属性中分配。
Laravel数据库中的关系

文章图片
如果我们要从数据透视表中检索特定列,
public function role() { return $this-> belongsToMany('App\Role', 'roles_user')-> withPivot('created_at'); }

web.php
Route::get('/pivot', function(){ $user=User::find(1); foreach($user-> role as $role) { return $role-> pivot-> created_at; } });

输出量
Laravel数据库中的关系

文章图片
有很多通过 “具有很多通过”关系提供了访问遥远或中间关系的便捷方法。例如, 我们有三个表, 用户, 帖子和国家/地区表。现在, 我们要通过用户模型查找属于该国家的帖子。
让我们通过一个例子来理解。
  • 国家/地区表在数据库中不可用。我们首先通过数据库迁移创建国家模型。
Laravel数据库中的关系

文章图片
  • 在国家/地区表中添加“名称”列。
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateCountriesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('countries', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> string('name'); $table-> timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('countries'); } }

  • 使用以下命令迁移上述更改:php artisan migration
  • 现在, 我们在用户表中添加新列“ country_id”。使用下面给出的命令:php artisan make:migration add_new_column_column_id -table = users;
  • 执行上述命令后, 将在database / migrations目录中创建add_new_column_column_id文件。
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddNewColumnColumnId extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { $table-> integer('country_id')-> unsigned; }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table-> dropColumn('country_id'); }); } }

在上面的代码中, 我们在users表中添加了一个新列。
要迁移数据库中的上述更改,
PHP的工匠迁移
  • 打开country.php(model)文件。我们将使用国家/地区模型拉出特定国家/地区的职位。 country.php
< ?php namespace App; use Illuminate\Database\Eloquent\Model; class country extends Model { public function posts(){ return $this-> hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id'); } }

  • 现在, 我们添加了提取特定国家/地区帖子的路线。
Route::get('/user/country', function() {$country=country::find(1); foreach($country-> posts as $post) { return $post-> title; } });

输出量
Laravel数据库中的关系

文章图片
多态关系 一对多(多态)
多态关系类似于一对多关系。当单个模型在单个关联上属于一种以上类型的模型时, 称为一对一多态关系。例如, 如果我们有三个表, posts, users和photo表, 其中photo表代表与users和posts表的多态关系。
让我们通过一个例子来理解这种关系。
  • 在上一个主题中, 我们已经创建了users和posts表。现在, 我们创建一个照片表。
Laravel数据库中的关系

文章图片
打开在migrations文件夹中创建的create_photos_table.php文件。
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePhotosTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('photos', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> string('path'); $table-> integer('imageable_id'); $table-> string('imageable_type'); $table-> timestamps(); }); }/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('photos'); } }

在上面的代码中, 我们添加了三列:path, imageable_id和imageable_type。路径确定图像的路径, imageable_id是用户或帖子的id值, 而imageable_type是模型的类名。
  • 我们将从先前创建的posts表中删除user_id列。
  • 查看数据库表。
帖子表中可用的数据
Laravel数据库中的关系

文章图片
用户表中可用的数据:
Laravel数据库中的关系

文章图片
照片表中的可用数据:
Laravel数据库中的关系

文章图片
  • 打开照片模型文件。
< ?php namespace App; use Illuminate\Database\Eloquent\Model; class photo extends Model { // public function imageable() { return $this-> morphTo(); }}

  • 在用户模型文件中添加以下代码。
public function photos() { return $this-> morphMany('App\Photo', 'imageable'); }

  • 将以下代码添加到Post模型文件中。
public function photos() { return $this-> morphMany('App\Photo', 'imageable'); }

  • 现在, 我们将为用户和帖子创建路线。
// Route for the users. Route::get('/user/photo', function(){ $user=User::find(1); foreach($user-> photos as $photo) { return $photo; } }); // Route defined for the posts. Route::get('/post/photo', function(){ $post=Post::find(1); foreach($post-> photos as $photo) { return $photo; }});

输出量
Laravel数据库中的关系

文章图片
Laravel数据库中的关系

文章图片
一对多(多态)关系的逆
在本主题中, 我们将执行一对多多态关系的逆运算。到现在为止, 我们已经找到了用户和帖子的图像, 现在我们找到了图像的所有者。
让我们通过一个例子来理解。
我们需要在web.php文件中创建路由。
Route::get('/photo/{id}', function($id) { $photo=Photo::findOrFail($id); return $photo-> imageable; });

在上面的代码中, Photo :: findOrFail($ id)方法确定给定id的照片是否存在。如果存在, 则它通过语句’ $ photo-> imageable’ 返回图像的详细信息。
输出量
Laravel数据库中的关系

文章图片
上面的输出显示了图像的细节。
多对多态关系
在多对多多态关系中, 目标模型由在各种模型之间共享的唯一记录组成。例如, 标签表共享视频和帖子表之间的多态关系。标签表由表, 视频和帖子表共享的唯一标签列表组成。
让我们通过一个例子来理解。
  • 首先, 我们使用数据库迁移创建模型, 这些模型分别命名为Audio, Tag和Taggable。
Laravel数据库中的关系

文章图片
  • 创建模型后, 我们将编辑其迁移的文件。
打开名为“ create_audio_table”的音频表的迁移文件。
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateAudioTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('audio', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> string('name'); $table-> timestamps(); }); }/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('audio'); } }

在上面的代码中, 我们使用命令$ table-> string(’ name’ ); 在音频表中创建了name列。
打开名为“ create_tag_table”的Tag模型的迁移文件。
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTagsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('tags', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> string('name'); $table-> timestamps(); }); }/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('tags'); } }

在上面的代码中, 我们使用命令$ table-> string(’ name’ ); 在标签表中创建了name列。
打开名为“ create_taggables_table”的Taggable模型的迁移文件。
< ?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTaggablesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('taggables', function (Blueprint $table) { $table-> bigIncrements('id'); $table-> integer('tag_id'); $table-> integer('taggable_id'); $table-> string('taggable_type'); $table-> timestamps(); }); }/** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('taggables'); }}

在上面的代码中, 我们在taggables表中添加了三个新列, 即tag_id, taggable_id和taggable_type。 tag_id代表标签表的ID, taggable id代表模型表的ID, taggable type代表类的名称。
  • 要迁移上述更改, 我们使用下面给出的命令:php artisan migration
  • 查看数据库表:
音频表中可用的数据:
Laravel数据库中的关系

文章图片
帖子表中可用的数据:
Laravel数据库中的关系

文章图片
标签表中可用的数据:
Laravel数据库中的关系

文章图片
可标记表中可用的数据:
Laravel数据库中的关系

文章图片
  • 现在, 我们在模型上定义关系。
Audio.php
< ?php namespace App; use Illuminate\Database\Eloquent\Model; class Audio extends Model { // get all the tags from the audio. public function tags() { return $this-> morphToMany('App\Tag', 'taggable'); } }

Post.php
namespace App; use App\Photo; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Post extends Model { // get all the tags from this post. public function tags() { return $this-> morphToMany('App\Tag', 'taggable'); } }

  • 现在我们定义路线。
use App\Post; use App\Audio; // Route for getting the tags from the Post model. Route::get('/post/tags', function() { $post=Post::find(1); foreach($post-> tags as $tag) { return $tag-> name; }}); //Route for getting the tags from the Audio model. Route::get('/audio/tags', function() { $audio=Audio::find(1); foreach($audio-> tags as $tag) { return $tag-> name; }});

输出量
访问帖子的路线时, 输出为:
Laravel数据库中的关系

文章图片
访问音频路由时, 输出为:
Laravel数据库中的关系

文章图片
多对多(多态)关系的逆
在多对多多态关系中, 我们发现了属于帖子和音频模型的标签。但是, 在多对多的逆关系中(多态), 我们将找出属于特定标签的所有帖子和音频。
让我们通过一个例子来理解。
  • 首先, 我们在标签模型中定义方法。
Tag.php
< ?php namespace App; use Illuminate\Database\Eloquent\Model; class Tag extends Model { // get all the posts from the tag. public function posts() { return $this-> morphedByMany('App\Post', 'taggable'); } // get all the audios from the tag. public function audios() { return $this-> morphedByMany('App\Audio', 'taggable'); } }

在上面的代码中, 我们定义了两个方法, posts()和audios()。在posts()方法中, 我们检索属于指定标签的所有帖子。在audios()方法中, 我们将检索属于指定标签的所有音频。
  • 现在, 我们定义路线。
use App\Tag; // Route for getting all the posts of a tag. Route::get('/tag/post/{id}', function($id){ $tag=Tag::find($id); foreach($tag-> posts as $post) { return $post-> title; } }); // Route for getting all the audios of a tag. Route::get('/tag/audio/{id}', function($id){ $tag=Tag::find($id); foreach($tag-> audios as $audio) { return $audio-> name; } });

【Laravel数据库中的关系】输出量
Laravel数据库中的关系

文章图片
Laravel数据库中的关系

文章图片

    推荐阅读