Laravel 模型关联基础教程详解
在 Laravel 中定义模型关联是每个 Laravel 开发者可能已经做过不止一次的事情。但是在试图实现关联时可能会遇到各种问题。因为 Laravel 有各种各样的关联,你应该选择哪一个?当涉及到查询模型时,我们如何充分利用模型关联的功能?
Laravel 的模型关联可能会让人糊涂。如果你不完全理解 Laravel 的关联在这一点上是如何工作的,别担心,读完这篇文章后,你会更好地理解它。
我们应该使用哪个模型关联?
要回答这个问题,首先你要知道有哪些可用的选项。Laravel 有 3 种不同的关联类型。
- 一对一
- 一对多
- 多对多
我们将逐个探讨不同的关联类型并解释一下应该什么时候使用它们。
一对一
一对一关联是目前存在的最基本的关联。这种关联意味着 A 模型只能链接到 B 模型,相反也是如此。举个例子,一个 User 模型和一个 Passport 模型会成为一对一的关联。一个用户只能拥有一张通行证,同样,一张通行证也只属于一个用户。
让我们看看如何在代码中定义这种关联。
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
public function passport() {
return $this- hasOne(AppPassport::class);
}
}
在 User 模型中我们创建了一个 passport 方法。我们通过 hasOne 方法告诉 Laravel User 模型有一个 Passport 。
注意: 所有用于定义关联的方法都有可选的额外参数,你可以在这些参数中定义本地键和外键。默认情况下,Laravel会假设你在用户模型中定义了 passport_id ,因为你试图创建与 passport 模型的关联。创建迁移文件时也请注意这一点!
在 Passport 模型中,我们需要定义逆向的关联。我们要让 Passport 模型知道它属于 User 模型。我们可以使用 belongsTo 方法来实现这一点。
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Passport extends Model
{
public function user() {
return $this- belongsTo(AppUser::class);
}
}
一对多
你可以在 Laravel 中定义的下一个关联是一对多关联。 这种类型的关联意味着一个类型A的模型可以链接到多个类型B的模型。但是类型B的模型只属于一个类型A的模型。
例如,User 模型和 Invoice 模型之间的关联是一对多关联。 用户可以拥有多个账单,但账单仅属于一个用户。
在代码中是这样写的:
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
public function invoices() {
return $this- hasMany(AppInvoice::class);
}
}
它看起来就像我们之前用于定义一对一关联的代码,对吧?
我们现在要做的就是让 Invoice 模型知道它属于 User 模型。 让我们定义一对多关联的反向对应关联吧。
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Invoice extends Model
{
public function user() {
return $this- belongsTo(AppUser::class);
}
}
多对多
最后要定义的关联是多对多关联。 这种类型的关联意味着类型A的一个模型可以链接到类型B的多个模型,反之亦然。
例如,Invoice 模型和 Product 模型之间的关联将是多对多关联。 账单可以包含多个产品,而产品可以属于多个账单。
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Invoice extends Model
{
public function products() {
return $this- belongsToMany(AppProduct::class);
}
}
你可以像这样定义这种关联的反向关系:
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Product extends Model
{
public function invoices() {
return $this- belongsToMany(AppInvoice::class);
}
}
多对多关联实现起来稍微困难一些,因为它们需要数据库中的中间表。 你可以通过创建迁移文件在 Laravel 中创建此中间表。
远程关联
远程一对一
has one through 关联通过单个中间关联模型实现。 如果每个供应商都有一个用户,并且每个用户与一个用户历史记录相关联,那么供应商可以通过用户访问用户的历史记录。
这就是定义这种关联所需的数据库表:
suppliers:
- idproducts:
- id
- supplier_idproduct_history:
- id
- product_id
即使 product_history 表不包含 supplier_id 列,供应商也可以通过使用 「has one through」 关系访问 product_history 记录。
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Supplier extends Model
{
public function productHistory() {
return $this- hasOneThrough(AppHistory::class, AppProduct::class);
}
}
传递给 hasOneThrough 方法的第一个参数是希望访问模型的名称。 第二个参数是中间模型的名称。
远程一对多
「has many through」 关联相当于 「has one through」 关联,只是对于多个记录的。 让我们使用前面的示例,但我们改变一件事:产品现在可以有多个历史条目而不是一个。 数据库表保持不变。
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Supplier extends Model
{
public function productHistory() {
return $this- hasManyThrough(AppHistory::class, AppProduct::class);
}
}
这样,供应商模型可以访问产品的历史记录条目。
查询关联
查询一个关联非常简单。因为我们定义了 Passport 的一对一关联和 Invoice 的一对多关联,所以我们可以在 User 模型中使用它们。在 User 模型的每个实例上,我们都可以得到对应的 Passport 和 Invoice。
<?php
$user = AppUser::find(1);
// 查询 passport 关联
$user- passport- expiration_date;
// 查询 invoice 关联
foreach($user- invoices as $invoice) {
$invoice- total_amount;
}
也可以查询关联的反向关联。 如果您有账单,则可以获得该账单的用户。
<?php
$invoice = AppInvoice::find(1);
// Get the user
$invoice- user- first_name;
查询多对多关联的工作方式与其他关联完全相同。 此外,多对多关联有一个pivot 属性。 此属性表示中间表,可以像任何其他模型一样使用。
举个例子,假设连接的表有 created_at 字段,我们就可以使用 pivot 来获取 created_at 字段。
<?php
$invoice = AppInvoice::find(1);
// 获取 product 的 `created_at` 字段
foreach($invoice- products as $product) {
$product- pivot- created_at;
}
查询 has one through 和 has many through 的工作方式与其他关联完全相同。
添加约束
可以在查询时向关系添加约束。看看下面的示例:
<?php
$user- passport()- where('active', 1)- orderBy('expiration_date');
检查关联是否存在
有时候你希望检查模型中是否有添加某些关联, Laravel有一些方法可以帮助你用来检查:
<?php
// 找到拥有护照的所有用户
$users = AppUser::has('passport')- get();
// 找到没拥有护照的所有用户
$users = AppUser::doesntHave('passport')- get();
// 找到拥有 5 个及以上产品的发票
$invoices = AppInvoice::has('products', ' =', 5)- get();
希望这篇文章能让你对Laravel的模型关联有更好的理解。谢谢你的阅读!也希望大家多多支持ZaLou.Cn。
- 初学java之大数处理
- hdu---1024Max Sum Plus Plus(动态规划)
- Go语言异步服务器框架原理和实现
- nyoj------布线问题(kruscal+求最小值)
- nyoj-----127星际之门(一)
- nyoj------20吝啬的国度
- HDUOJ-------2493Timer(数学 2008北京现场赛H题)
- go sync.Mutex 设计思想与演化过程 (一)
- HDUOJ--------A simple stone game(尼姆博弈扩展)(2008北京现场赛A题)
- HDUOJ----2485 Destroying the bus stations(2008北京现场赛A题)
- Go语言实践:从新手入门到上线真实的小型服务所遇到的那些坑
- Node.js真的无所不能?那些不适用的应用领域分析
- hdu-----2491Priest John's Busiest Day(2008 北京现场赛G)
- nyoj------79拦截导弹
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- sql server 字符串替换函数REPLACE
- sql server 更新两个表的某个字段
- HTML 引用Css样式的四种方式
- Java也可以像python般range出连续集合
- c# dev控件 gridcontrol 数据跟随鼠标滚轮滚动也可以编辑
- Apollo(阿波罗)配置中心Java客户端使用指南使用指南
- DevExpress.LookUpEdit控件实现自动搜索定位功能 兼使用方法(looUpEdit可编辑)
- dev GridControl直接打印 纵向合并单元格
- Dooring可视化之从零实现动态表单设计器
- 我不是最后一个知道MDC的吧?
- 实战编写 wireshark 插件解析私有协议
- 安卓 APP 三代加壳方案的研究报告
- 将博客主题替换成 Clean Blog
- Go 数据存储篇(一):基于内存存储实现数据增删改查功能
- 创建联系表单页面并通过 Ajax 提交表单请求数据