澳门新葡萄京娱乐网站-澳门新葡萄京888官网-所有平台

热门关键词: 澳门新葡萄京娱乐网站,澳门新葡萄京888官网

模型关联基础教程详解_php实例_脚本之家,目录别

作者: 编程知识  发布:2019-12-22
$userCoupons = UserCoupons::with(['coupon' => function{ return $query->select('id', 'group_id', 'cover', 'group_number', 'group_cover')->where([ 'group_id' => $groupId, ]);}])// 更多查询省略...

在 Laravel 中定义模型关联是每个 Laravel 开发者可能已经做过不止一次的事情。但是在试图实现关联时可能会遇到各种问题。因为 Laravel 有各种各样的关联,你应该选择哪一个?当涉及到查询模型时,我们如何充分利用模型关联的功能?

现在是2017年2月5日,从开始接触Laravel也有小一年来了,这篇文章将记录我使用Laravel的一些新得。新的想法也将随时更新到这篇文章中。

数据结构是三张表用户优惠券表、优惠券表,组优惠券表

Laravel 的模型关联可能会让人糊涂。如果你不完全理解 Laravel 的关联在这一点上是如何工作的,别担心,读完这篇文章后,你会更好地理解它。

1.目录别名

这里我本意想用模型关联查出用户优惠券中属于给定组gourpId的所有数据。

我们应该使用哪个模型关联?

1.1说明

在ShenCom他们有一点做的很好,就是把框架外的扩展全部放在了一个独立的目录里面,没有去破坏Laravel框架本身的结构,让框架保持了原来的特性,又增加了新的功能。

图片 1

1-目录别名.png

但有些结果不是我想要的:

要回答这个问题,首先你要知道有哪些可用的选项。Laravel 有 3 种不同的关联类型。

1.2用法

array ["user_id"]=> int ["corp_id"]=> int ["coupon_id"]=> int ["obtain_time"]=> int ["receive_time"]=> int ["status"]=> int ["expires_time"]=> int ["is_selling"]=> int ["from_id"]=> int ["sell_type"]=> int ["sell_time"]=> int ["sell_user_id"]=> int ["is_compose"]=> int ["group_cover"]=> string "" ["is_delete"]=> int ["score"]=> int ["created_at"]=> NULL ["updated_at"]=> NULL ["coupon"]=> NULL // 注意返回了coupons为空的数据}

一对一 一对多 多对多

1.2.1添加主服务文件

在 appProvidersAppServiceProvider的boot方法中添加
App::register("YaZhouYaZhouServiceProvider");

记录中有的coupon有记录,有的为空。想想也是,with只是用sql的in()实现的所谓预加载。无论怎样主user_coupons的数据都是会列出的。

我们将逐个探讨不同的关联类型并解释一下应该什么时候使用它们。

1.2.2起别名

compser.json里面增加一个autoload选项。
执行命令composer dump-autpload

它会有两条sql查询,第一条查主数据,第二条查关联,这里第二条sql如下:

一对一

2.模型(Model)的定义

select `id`, `group_id`, `cover`, `group_number`, `group_cover` from `youquan_coupons` where `youquan_coupons`.`id` in (1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14) and  and `youquan_coupons`.`deleted_at` is null

一对一关联是目前存在的最基本的关联。这种关联意味着 A 模型只能链接到 B 模型,相反也是如此。举个例子,一个 User 模型和一个 Passport 模型会成为一对一的关联。一个用户只能拥有一张通行证,同样,一张通行证也只属于一个用户。

2.1简单示例

namespace YzModels;

use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentSoftDeletes;

class Test extends Model{
    use SoftDeletes;

    protected   $primaryKey  =   "id";  
    protected   $table       =   "test";
    protected   $guarded     =   ["id"];
    public      $timestamps  =   false;
}

如果第二条为空,主记录的关联字段就是NULL。

让我们看看如何在代码中定义这种关联。

2.2代码说明

protected $table
指定当前模型对应的数据表名。
protected $primaryKey
指定当前数据表的主键,默认id。
public $timestamps
默认情况下,Eloquent期望created_at和updated_at已经存在于数据表中,如果你不想要这些Laravel自动管理的列,在模型类中设置$timestamps属性为false。
protected $guarded/$fillale
在使用create方法保存一个新的模型时,所有的Eloquent模型都通过批量赋值(Mass Assignment)进行保护,需要指定模型的fillableguarded属性。在fillable里面的都是可以被赋值的(白名单),在guarded里面的都是不可以被赋值的(黑名单),fillable和guarded二选一。
use SoftDeletes
软删除,要求数据表中以一个字段“deleted_at”。被软删除的记录并没有被真正的删除,只是在“deleted_at”字段记录了操作时间。
Model::withTrashed()->...,同时获取被软删除的记录。
Model::onlyTrashed()->...,只获取被软删除的记录。
$record->restore();,恢复被软删除的记录。
$record->forceDelete(),强制删除。
$record-> history() -> forceDelete(),强制删除所有关模型。

后来看到了Laravel关联的模型的has是基于存在的关联查询,下面我们用whereHas

hasOne; }}

2.3扩展

这里我们思想是把判断有没有优惠券数据也放在第一次查询逻辑中,所以才能实现筛选空记录。

在 User 模型中我们创建了一个 passport 方法。我们通过 hasOne 方法告诉 Laravel User 模型有一个 Passport 。

查询作用域

作用域允许你定义一个查询条件的通用集合,这样就可以在应用中方便地复用。详情参见,Laravel5.1中文文档。

加上whereHas()后的代码如下

注意:所有用于定义关联的方法都有可选的额外参数,你可以在这些参数中定义本地键和外键。默认情况下,Laravel会假设你在用户模型中定义了 passport_id ,因为你试图创建与 passport 模型的关联。创建迁移文件时也请注意这一点!

3.模型关系

$userCoupons = UserCoupons::whereHas('coupon', function{ return $query->select('id', 'group_id', 'cover', 'group_number', 'group_cover')->where([ 'group_id' => $groupId, ]); })->with(['coupon' => function{ return $query->select('id', 'group_id', 'cover', 'group_number', 'group_cover'); }])-> // ...

select * from `youquan_user_coupons` where exists (select `id`, `group_id`, `cover`, `group_number`, `group_cover` from `youquan_coupons` where `youquan_user_coupons`.`coupon_id` = `youquan_coupons`.`id` and  and `youquan_coupons`.`deleted_at` is null) and (`status` = 1 and `user_id` = 1)

在 Passport 模型中,我们需要定义逆向的关联。我们要让 Passport 模型知道它属于 User 模型。我们可以使用 belongsTo 方法来实现这一点。

3.1一对一关系

这里实际上是用exists()筛选存在的记录。然后走下一步的with()查询,因为此时都筛选一遍了,所以with可以去掉条件。

belongsTo; }}
3.1.1关系的定义
namespace YzTestModels;

use IlluminateDatabaseEloquentModel;

class User extends Model{
    //  获取关联到用户的手机
    public function phone(){
        return $this->hasOne("YzTestModelsPhone");
        // 这种写法默认Phone模型中有一个user_id外键,默认与当前模型的id关联

        // return $this->hasOne("YzTestModelsPhone", "user_id");
        // 指定Phone模型中的外键,默认与当前模型的id关联

        // return $this->hasOne("YzTestModelsPhone", "user_id", "id");
        // 指定phone模型的外键,同时指定当前模型的关联键,推荐使用
    }
}

显然区分这两个的作用很重要,尤其是在列表中,不用特意去筛选为空的数据,而且好做分页。

一对多

3.1.2定义关系的相对关联
namespace YzTestModels;

use IlluminateDatabaseEloquentModel;

class Phone extends Model{
    public function user(){
        // 找到电话所属的用户
        return $this->belongsTo("YzTestModelsUser");
        // 默认通过当前表的user_id去匹配user表的id

        // return $this->belongsTo("YzTestModelsUser", "user_id");
        // 指定当前表的关联字段,去与主表的id字段进行匹配

        // return $this->belongsTo("YzTestModelsUser", "user_id", "id");
        // 指定当前表的user_id与User表的id进行匹配,推荐使用
    }
}

总结

你可以在 Laravel 中定义的下一个关联是一对多关联。 这种类型的关联意味着一个类型A的模型可以链接到多个类型B的模型。但是类型B的模型只属于一个类型A的模型。

3.1.3一对一关系的使用

$phone = User::find(1)->phone;

以上所述是小编给大家介绍的Laravel关联模型中过滤结果为空的结果集,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

例如,User 模型和 Invoice 模型之间的关联是一对多关联。 用户可以拥有多个账单,但账单仅属于一个用户。

3.2 一对多关系

hasMany; }}
3.2.1关系的定义
namespace YzTestModels;

use IlluminateDatabaseEloquentModel;

class Post extends Model{
    /*博客数据*/

    public function comments(){
        // 获取博客的评论
        return $this->hasMany("YzTestModelsComment");

        // $this->hasMany("YzTestModelsComment", "post_id");
        // $this->hasMany("YzTestModelsComment", "post_id", "id");
    }
}

它看起来就像我们之前用于定义一对一关联的代码,对吧?

3.2.2定义关系的相对关联
namespace YzTestModels;

use IlluminateDatabaseEloquentModel;

class Comment extends Model{
    /*博客的评论*/

    public function post(){
        return $this->belongsTo("YzTestModelsPost");

        // return $this->belongsTo("YzTestModelsPost", "post_id");
        // return $this->belongsTo("YzTestModelsPost", "post_id", "id");
    }
}

我们现在要做的就是让 Invoice 模型知道它属于 User 模型。 让我们定义一对多关联的反向对应关联吧。

3.2.3一对多关系的使用
$comments = AppPost::find(1)->comments;
$comments = AppPost::find(1)->comments()->where('title', 'foo')->first();

$comment = AppComment::find(1);
echo $comment->post->title;
belongsTo; }}

3.3多对多关系

实现多对多关系需要一个中间表。比如,一个用户(user)拥有多种角色(role),那么我们就需要一个中间表(user_role)。

多对多

3.3.1关系的定义
public function roles(){
        return $this->belongsToMany("YzTestModelRole");
        // 省略写法,要求中间表的名字为role_user,且中间表包含role_id和user_id两个字段

        // return $this->belongsToMany("YzTestModelsRole", "user_role");
        // 半完整写法

        // return $this->belongsToMany("YzTestModelsRole", "user_role", "user_id", "role_id");
        // 完整写法
    }

最后要定义的关联是多对多关联。 这种类型的关联意味着类型A的一个模型可以链接到类型B的多个模型,反之亦然。

3.3.2定义关系的相对关联
namespace YzTestModels;

use IlluminateDatabaseEloquentModel;

class Role extends Model
{
    // 用户角色

    public function users()
    {
        // 找到属于当前角色的用户
        return $this->belongsToMany("YzTestModelsUser");

        // return $this->belongsToMany("YzTestModelsUser", "user_role");
        // return $this->belongsToMany("YzTestModelsUser", "user_role", "role_id", "user_id");
    }
}

例如,Invoice 模型和 Product 模型之间的关联将是多对多关联。 账单可以包含多个产品,而产品可以属于多个账单。

3.3.3多对多关系的使用
$user = AppUser::find(1);
foreach ($user->roles as $role) {
    //
}

$roles = AppUser::find(1)->roles()->orderBy('name')->get();
belongsToMany; }}

3.4插入关联模型

你可以像这样定义这种关联的反向关系:

3.4.1插入一个关联模型
$comment = new AppComment(['message' => 'A new comment.']);
$post = AppPost::find(1);
$comment = $post->comments()->save($comment);
belongsToMany; }}
3.4.2插入多个关联模型
$post = AppPost::find(1);
$post->comments()->saveMany([
    new AppComment(['message' => 'A new comment.']),
    new AppComment(['message' => 'Another comment.']),
]);

除了save和saveMany方法外,还可以使用create方法,该方法接收属性数组、创建模型、然后插入数据库。save和create的不同之处在于save接收整个Eloquent模型实例而create接收原生PHP数组。

$post = AppPost::find(1);
$comment = $post->comments()->create([
    'message' => 'A new comment.',
]);

多对多关联实现起来稍微困难一些,因为它们需要数据库中的中间表。 你可以通过创建迁移文件在 Laravel 中创建此中间表。

3.4.3更新关联模型

更新belongsTo关联的时候,可以使用associate方法,该方法会在子模型设置外键。

$account = AppAccount::find(10);
$user->account()->associate($account);
$user->save();

远程关联

3.4.4移除关联模型

移除belongsTo关联的时候,可以使用dissociate方法。该方法在子模型上取消外键和关联。

$user->account()->dissociate();
$user->save();

远程一对一

3.4.5多对多关系的附加
$user = AppUser::find(1);
$user->roles()->attach($roleId);

附加关联关系到模型,还可以以数组形式传递额外被插入数据到中间表:
$user->roles()->attach($roleId, ['expires' => $expires])

has one through 关联通过单个中间关联模型实现。 如果每个供应商都有一个用户,并且每个用户与一个用户历史记录相关联,那么供应商可以通过用户访问用户的历史记录。

3.4.6多对多关系的移除
// 从指定用户中移除角色...
$user->roles()->detach($roleId);
// 从指定用户移除所有角色...
$user->roles()->detach();

为了方便,attach和detach还接收数组形式的ID作为输入。

$user = AppUser::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);

这就是定义这种关联所需的数据库表:

3.4.7触发父级时间戳

当一个模型属于另外一个时,例如Comment属于Post,子模型更新时父模型的时间戳也被更新将很有用,例如,当Comment模型被更新时,你可能想要”触发“创建其所属模型Post的updated_at时间戳。Eloquent使得这项操作变得简单,只需要添加包含关联关系名称的touches属性到子模型中即可。

suppliers:- idproducts:- id- supplier_idproduct_history:- id- product_id

即使 product_history 表不包含 supplier_id 列,供应商也可以通过使用 「has one through」 关系访问 product_history 记录。

hasOneThrough(AppHistory::class, AppProduct::class); }}

传递给 hasOneThrough 方法的第一个参数是希望访问模型的名称。 第二个参数是中间模型的名称。

远程一对多

「has many through」 关联相当于 「has one through」 关联,只是对于多个记录的。 让我们使用前面的示例,但我们改变一件事:产品现在可以有多个历史条目而不是一个。 数据库表保持不变。

hasManyThrough(AppHistory::class, AppProduct::class); }}

这样,供应商模型可以访问产品的历史记录条目。

查询关联

查询一个关联非常简单。因为我们定义了 Passport 的一对一关联和 Invoice 的一对多关联,所以我们可以在 User 模型中使用它们。在 User 模型的每个实例上,我们都可以得到对应的 Passport 和 Invoice。

passport->expiration_date;// 查询 invoice 关联foreach($user->invoices as $invoice) { $invoice->total_amount;}

也可以查询关联的反向关联。 如果您有账单,则可以获得该账单的用户。

user->first_name;

查询多对多关联的工作方式与其他关联完全相同。 此外,多对多关联有一个pivot 属性。 此属性表示中间表,可以像任何其他模型一样使用。

举个例子,假设连接的表有 created_at 字段,我们就可以使用 pivot 来获取 created_at 字段。

products as $product) { $product->pivot->created_at;}

查询 has one through 和 has many through 的工作方式与其他关联完全相同。

添加约束

可以在查询时向关系添加约束。看看下面的示例:

passport->orderBy;

检查关联是否存在

有时候你希望检查模型中是否有添加某些关联, Laravel有一些方法可以帮助你用来检查:

get();

希望这篇文章能让你对Laravel的模型关联有更好的理解。谢谢你的阅读!也希望大家多多支持脚本之家。

本文由澳门新葡萄京娱乐网站发布于编程知识,转载请注明出处:模型关联基础教程详解_php实例_脚本之家,目录别

关键词: