在laravel中扩展的模型中定义主键的别名

时间:2018-05-21 08:46:51

标签: laravel laravel-5.4

我有一个像这样的Stuff模型:

class Stuff extends Model
{
    protected $primaryKey = 'stuff_id';
    protected $fillable   = ['stuff_id' , 'title' , 'desc'];
    protected $dates = ['deleted_at'];
}

另一方面,有一个Product模型从Stuff模型扩展而来:

class Product extends Stuff 
{
    protected $fillable   = ['quantity' , 'picture'];
}

正如您所看到的那样Product已从Stuff扩展而Stuff的主键为stuff_id,我想要调用Product个实例的任何地方并且需要打印它的ID应该使用$product->stuff_id,而我希望使用更清晰的名称,如$product->product_id

在数据库上运行查询时,是否有任何方法可以在子模型中定义别名主键,后者在后端解释为stuff_id

3 个答案:

答案 0 :(得分:2)

product_id转换为stuff_id的别名:

...
$product->product_id // resolves to $product->stuff_id
...
public function getProductIdAttribute(): int
{
    return $this->stuff_id;
}
...

答案 1 :(得分:1)

您可以覆盖从该变量读取的函数,而不是使用$primaryKey

Stuff模型中,尝试添加以下内容:

/**
 * Get the primary key for the model.
 *
 * @return string
 */
public function getKeyName(): string
{
    return [
        Stuff::class => 'stuff_id',
        Product::class => 'product_id',
    ][get_class($this)];
}

供参考,默认行为:(Illuminate/Database/Eloquent/Model.php

/**
 * Get the primary key for the model.
 *
 * @return string
 */
public function getKeyName()
{
    return $this->primaryKey;
}

答案 2 :(得分:1)

使用全球范围:

//Say ProductScope.php
namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Schema;

class ProductScope implements Scope
{
    protected $model_name;
    public function __construct($model_name)
    {
        $this->model_name = $model_name;
    }

    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $attr = Schema::getColumnListing($this->model_name);

        $attr_ =  array_map(function ($item){
            return $item === 'stuff_id' ? $item.' as product_id' : $item;
        }, $attr);

        $builder->select($attr_);
    }
}

然后在产品型号中:

use App\Scopes\ProductScope;

class Product extends Stuff
{
    protected $table = 'stuffs';
    protected $primaryKey = 'stuff_id';
    /**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(new ProductScope('stuffs'));
    }
}

这会将stuff_id替换为product_id