Laravel 有许多通过关系进行解释的示例
推荐阅读
Eloquent Relationships是 Laravel 框架最实用、最强大的功能之一,也是我最喜欢 Laravel 的原因之一。它主要帮助我们以非常简单高效的方式获取和插入数据。
我们知道 Laravel 中有几种关系类型。我们(开发者)最常用的是前四种:一对一、一对多、一对多(反向)/属于、多对多。
我最喜欢多对多和多对多关系。说实话,我最喜欢这两种关系。今天我将用一个简单的例子来解释多对多关系。希望读完这篇文章后,您能彻底理解。
那么,让我们直接进入正题。
假设我们正在创建一家餐厅的菜品/菜单,其中菜品属于类型,类型属于类别。
简单来说,类别包含多个类型,每个类型又包含多个项目。如果我们想要获取所有属于该类别的项目,就需要维护一个category_id包含所有项目的表。而项目主要属于某个类型。基本上,项目与类型直接关联。
所以,在这种情况下,我们应该使用Has Many Through关系。通过这种关系,我们可以通过另一个模型获取数据。就像我们的场景一样,我们可以直接通过Types从Category获取Items。
为了方便您理解,我创建了一个GitHub 代码库。您可以访问该代码库。我在那里给出了两种Has Many Through关系的示例。
我尽量举一个非常简单的例子,以便你们容易理解。那么,我们开始吧。
正如我之前提到的,我们使用类别、类型和项目。
所以我让我的迁移过程非常简单。
这是我的分类迁移代码。我们来看一下。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
}
您可以看到这里我只保留了类别名称。
我们来看一下我的品类模型。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
];
}
这是我的类型迁移文件。我们来看一下。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTypesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('types', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedInteger('category_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('types');
}
}
我只是将其保留category_id为外键。因此,类别与类型相关联。
这是类型模型。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Type extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'category_id'
];
}
你可能会觉得这很简单。
让我们直接跳到我的项目迁移部分。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->longText('description');
$table->unsignedInteger('type_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
所以你可以看到,我把它保留type_id为外键。因此,类型(Type )与项目(Item)关联。我没有category_id在项目迁移中保留任何内容。你需要理解的关键一点是,项目(Item)并不直接与类别(Category)关联。项目(Item)是通过类型(Type)与类别(Category)关联的。这就是为什么它被称为“通过多对多”(Has Many Through)关系。
这是Item的模型。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'description', 'type_id'
];
}
现在我们将建立从类别到项目的“通过”多对多关系。
让我们建立与类别模型的关系。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
];
/**
* Get all of the items for the user.
*/
public function items()
{
return $this->hasManyThrough(Item::class, Type::class);
}
}
以下items关系将按类型获取属于该类别的所有项目。
你也可以像这样使用关系:
return $this->hasManyThrough(
Item::class,
Type::class,
'category_id', // Foreign key on the types table...
'type_id', // Foreign key on the items table...
'id', // Local key on the users table...
'id' // Local key on the categories table...
);
就这样,我们通过“ Has Many Through”建立的关系已经成功了。
我想再举一个例子,帮助你更好地理解这种关系。
设想
假设我们有三个模型。
团队(id,user_id,名称)
用户(id,名称)
目标(id,user_id,目标数)
所以,关系是这样的。
Team hasMany User (在Userteam_id模型中)
用户拥有多个目标(在目标模型user_id内部)
从这种关系可以看出,这里的用户模型是一个中间模型。
我们不能goal_id直接将数据存储到 Team 表中,因为我们已经将数据存储goal_id在 User 表中了。
现在,User 模型与 Team 模型建立了关系。因此,在 User 模型内部,存在team_id……
最后,如果我们需要了解团队创建了多少个目标,我们可以通过用户模型来获取这些信息。
如果你的用例生成了这种类型的场景,那么你需要定义“通过多对多”关系。
希望现在清楚了。