作为程序员一定要保持良好的睡眠,才能好编程

laravel中的关联模型使用方法

发布时间:2020-01-29

laravel提供了强大的模型关联,模型关联可以有效的减少表链接查询复杂操作。


laravel中提供了哪些关联?


一对一 hasOne

一对多 hasMany

一对多反向 belongsTo

多对多 belongsToMany

远层一对一 hasOneThrough

远层一对多 hasManyThrough

多态关联 morphMany


1、一对多演示实例

class article extends Model{
    
    public function articleNav(){
        //文章关联模型  一篇文章对应一个栏目
        return $this->belongsTo('App/ArticleNav');
    }
    
    public function comments(){
        //一篇文章对应多篇评论
        return $this->hasMany('App/Comments')->orderBy('createtime','desc');
        return $this->hasMany('App/Comments');
    }
    
    public function addresses()
        {
            return $this->hasMany(UserAddress::class);
        }

}

 

一个用户拥有多个喜欢的物品

class User extends Model{
    public function favoriteProducts()
    {
        return $this->belongsToMany(Product::class, 'user_favorite_products')
            ->withTimestamps()
            ->orderBy('user_favorite_products.created_at', 'desc');
    }
    
    public function cartItems()
    {
        return $this->hasMany(CartItem::class);
    }

}
withPivot() 可以额外添加获取的参数
withTimestamps() 携带时间戳

一个购物车从属于一个用户

class CartItem extends Model
{
    protected $fillable = ['amount'];
    public $timestamps = false;

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    
}






OrderItem.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class OrderItem extends Model
{
    protected $fillable = ['amount', 'price', 'rating', 'review', 'reviewed_at'];
    protected $dates = ['reviewed_at'];
    public $timestamps = false;

    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    public function productSku()
    {
        return $this->belongsTo(ProductSku::class);
    }

    public function order()
    {
        return $this->belongsTo(Order::class);
    }
}



order.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Ramsey\Uuid\Uuid;

class Order extends Model
{
    const REFUND_STATUS_PENDING = 'pending';
    const REFUND_STATUS_APPLIED = 'applied';
    const REFUND_STATUS_PROCESSING = 'processing';
    const REFUND_STATUS_SUCCESS = 'success';
    const REFUND_STATUS_FAILED = 'failed';

    const SHIP_STATUS_PENDING = 'pending';
    const SHIP_STATUS_DELIVERED = 'delivered';
    const SHIP_STATUS_RECEIVED = 'received';

    public static $refundStatusMap = [
        self::REFUND_STATUS_PENDING    => '未退款',
        self::REFUND_STATUS_APPLIED    => '已申请退款',
        self::REFUND_STATUS_PROCESSING => '退款中',
        self::REFUND_STATUS_SUCCESS    => '退款成功',
        self::REFUND_STATUS_FAILED     => '退款失败',
    ];

    public static $shipStatusMap = [
        self::SHIP_STATUS_PENDING   => '未发货',
        self::SHIP_STATUS_DELIVERED => '已发货',
        self::SHIP_STATUS_RECEIVED  => '已收货',
    ];

    protected $fillable = [
        'no',
        'address',
        'total_amount',
        'remark',
        'paid_at',
        'payment_method',
        'payment_no',
        'refund_status',
        'refund_no',
        'closed',
        'reviewed',
        'ship_status',
        'ship_data',
        'extra',
    ];

    protected $casts = [
        'closed'    => 'boolean',
        'reviewed'  => 'boolean',
        'address'   => 'json',
        'ship_data' => 'json',
        'extra'     => 'json',
    ];

    protected $dates = [
        'paid_at',
    ];

    protected static function boot()
    {
        parent::boot();
        // 监听模型创建事件,在写入数据库之前触发
        static::creating(function ($model) {
            // 如果模型的 no 字段为空
            if (!$model->no) {
                // 调用 findAvailableNo 生成订单流水号
                $model->no = static::findAvailableNo();
                // 如果生成失败,则终止创建订单
                if (!$model->no) {
                    return false;
                }
            }
        });
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function items()
    {
        return $this->hasMany(OrderItem::class);
    }

    public function couponCode()
    {
        return $this->belongsTo(CouponCode::class);
    }

    public static function findAvailableNo()
    {
        // 订单流水号前缀
        $prefix = date('YmdHis');
        for ($i = 0; $i < 10; $i++) {
            // 随机生成 6 位的数字
            $no = $prefix.str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            // 判断是否已经存在
            if (!static::query()->where('no', $no)->exists()) {
                return $no;
            }
        }
        \Log::warning('find order no failed');

        return false;
    }
  
}




模型处理中处理属性返回


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Product extends Model
{
    protected $fillable = [
        'title', 'description', 'image', 'on_sale',
        'rating', 'sold_count', 'review_count', 'price'
    ];
    protected $casts = [
        'on_sale' => 'boolean', // on_sale 是一个布尔类型的字段
    ];
    // 与商品SKU关联
    public function skus()
    {
        return $this->hasMany(ProductSku::class);
    }

    public function getImageUrlAttribute()
    {
        // 如果 image 字段本身就已经是完整的 url 就直接返回
        if (Str::startsWith($this->attributes['image'], ['http://', 'https://'])) {
            return $this->attributes['image'];
        }
        return \Storage::disk('public')->url($this->attributes['image']);
    }
}


这里处理了  image 这个字段的属性



分析这条语句做了什么事情:

$items = $event->getOrder()->items()->with(['product'])->get();


1、首先获取到 order 模型

class Order extends Model{

public static $refundStatusMap = [
    self::REFUND_STATUS_PENDING    => '未退款',
    self::REFUND_STATUS_APPLIED    => '已申请退款',
    self::REFUND_STATUS_PROCESSING => '退款中',
    self::REFUND_STATUS_SUCCESS    => '退款成功',
    self::REFUND_STATUS_FAILED     => '退款失败',
];

public static $shipStatusMap = [
    self::SHIP_STATUS_PENDING   => '未发货',
    self::SHIP_STATUS_DELIVERED => '已发货',
    self::SHIP_STATUS_RECEIVED  => '已收货',
];

protected $fillable = [
    'no',
    'address',
    'total_amount',
    'remark',
    'paid_at',
    'payment_method',
    'payment_no',
    'refund_status',
    'refund_no',
    'closed',
    'reviewed',
    'ship_status',
    'ship_data',
    'extra',
];

protected $casts = [
    'closed'    => 'boolean',
    'reviewed'  => 'boolean',
    'address'   => 'json',
    'ship_data' => 'json',
    'extra'     => 'json',
];

protected $dates = [
    'paid_at',
];


public function items()
{
    return $this->hasMany(OrderItem::class);
}

}

2、通过with 找到商品

class OrderItem extends Model
{
    protected $fillable = ['amount', 'price', 'rating', 'review', 'reviewed_at'];
    protected $dates = ['reviewed_at'];
    public $timestamps = false;

    public function product()
    {
        return $this->belongsTo(Product::class);
    }
    public function order()
    {
        return $this->belongsTo(Order::class);
    }
}


然后 通过 get 获取关于这个订单所有的数据



laravel_event.docx