简体   繁体   English

Laravel雄辩的模型继承

[英]Laravel Eloquent Model inheritance

I'm a new bit who is trying to build an app using Laravel 5.5, and the Eloquent model. 我是新手,他正尝试使用Laravel 5.5和Eloquent模型构建应用程序。

I have two classes: (1) Customer and (2) VIPCustomer which extends Customer. 我有两类:(1) 客户和(2)扩展客户的VIPCustomer

You may immediately tell VIPCustomer contains all attributes that a customer has, and other extra attributes. 您可能会立即告诉VIPCustomer包含客户拥有的所有属性以及其他额外属性。

Just to be clear, a customer may not be a VIP, and a VIP must be a customer; 要明确一点,客户可能不是VIP,而VIP必须是客户。 The customer may immediately opt-in to be a VIP the first time he shops. 客户在第一次购物时可以立即选择成为VIP。

Therefore, I am attempting to do something like this in the database: 因此,我正在尝试在数据库中执行以下操作:

Customer: 顾客:

+------------------------+
|id|name|gender|join_date|
+------------------------+

VIPCustomer: VIPCustomer:

+----------------------------------+
|customer_id|valid_until|type|point|
+----------------------------------+
(customer_id is a foriegn key referencing Customer.id)

And accordingly, in the model php file: 因此,在模型php文件中:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{

}

.

namespace App;

use Illuminate\Database\Eloquent\Model;

class VIPCustomer extends Customer
{
    public $incrementing = false;
}

And that's it? 就是这样吗? I saw there are others saying I should using polymorphic relationship but I don't understand what it means. 我看到还有其他人说我应该使用多态关系,但是我不明白这意味着什么。

In addition, is it possible to do instantiate a new VIP Customer something like this? 此外,是否可以像这样实例化新的VIP客户?

$customer = new VIPCustomer;
$customer->name   = 'Alice';
$customer->gender = 'F';
$customer->type   = 'gold';
$customer->point  =  0;
$customer->save();

On top of that, say when the VIP membership ends, is it possible to preserve that person as Customer ? 最重要的是,假设VIP会员资格结束后,可以将该人保留为客户吗? Because I'm afraid deleting that person will delete him from both Customer and VIPCustomer tables. 因为恐怕删除该人会将其从“客户”和“ VIPCustomer”表中删除。

Thank you very much in advance. 提前非常感谢您。

Your current VIPCustomer class looks like a class that holds a VIP data, not a subject (a customer). 您当前的VIPCustomer类看起来像是持有VIP数据的类,而不是主题(客户)。 Then so, I would rename it as VIPCustomerData here and make a new VIPCustomer to inherit Customer class instead. 然后,在这里,我将其重命名为VIPCustomerData并创建一个新的VIPCustomer来继承Customer类。

class Customer extends Model
{
    protected $table = 'customers';
}

Make sure you define the table name to avoid it being guessed by inheritance. 确保定义表名,以避免被继承猜测。 Then tell VIPCustomer to has a relation to VIPCustomerData . 然后告诉VIPCustomer到有关系VIPCustomerData

class VIPCustomer extends Customer
{
    public function vipData()
    {
        return $this->hasOne(VIPCustomerData::class, 'customer_id', 'id');
    }
}

Now, the problem is whenever you're going to retrieve VIP customers like VIPCustomer::get() , you'll get whole customers instead. 现在,问题在于,每当您要检索VIP客户(如VIPCustomer::get() ,您就会获得整个客户。 So, applying global scope is needed. 因此,需要应用全局范围。

class VIPCustomer extends Customer
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('weareviptypeofcustomer', function ($q) {
            $q->has('vipData'); // only customers with vip data
        });
    }

    public function vipData()
    {
        return $this->hasOne(VIPCustomerData::class, 'customer_id', 'id');
    }
}

To create a new Customer as VIP, of course 2 queries is needed to insert here. 要创建新客户作为VIP,当然需要在此处插入2个查询。 Example, 例,

$vipCustomer = new VIPCustomer;
$vipCustomer->name   = 'Alice';
$vipCustomer->gender = 'F';
$vipCustomer->save();

$vipCustomerData = new VIPCustomerData;
$vipCustomerData->type   = 'gold';
$vipCustomerData->point  =  0;

$vipCustomer->vipData()->save($vipCustomerData);

Example of updating point. 更新点示例。

$vipCustomerData = $vipCustomer->vipData; // or $vipCustomer->vipData()->first();
$vipCustomerData->point  =  10;
$vipCustomerData->save();

Example of removing VIP status from customer. 从客户删除VIP状态的示例。 Of course just delete VIPCustomerData from its table. 当然,只需从其表中删除VIPCustomerData。

$vipCustomer->vipData()->delete();

However, it's better to maintain these subjects as one class if there is no special column to treat each subject differently. 但是,如果没有专门的栏目将每个主题区别对待,最好将这些主题保持为一类。

class Customer extends Model
{
    protected $table = 'customers';

    protected $with = ['vipData']; // always eager load related 'vipData'

    protected $appends = ['is_vip']; // append 'is_vip' accessor

    public function vipData()
    {
        return $this->hasOne(static::class, 'customer_id', 'id');
    }

    public function getIsVipAttribute()
    {
        return (bool) $this->vipData;
    }
}

$customers = Customer::all();

foreach($customers as $customer) {
    if ($customer->is_vip) {
        // is VIP
    } else {

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM