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

问题描述 投票:0回答:3

我有一个像这样的

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

php laravel laravel-5
3个回答
3
投票

要将

product_id
变成
stuff_id
的别名:

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

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;
}

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

© www.soinside.com 2019 - 2024. All rights reserved.