Laravel,如何忽略访问器

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

我有一个带有自定义访问器的模型,因此我获得了该自定义属性,

    class Order extends GSModel{

        $appends = ['orderContents'];

        public function getOrderContentsAttribute()
        {
            return $this->contents()->get();
        } 
 }

但是现在,在一种情况下,我只需要获取一些字段,而不需要这个

OrderContents

$openOrders         = Order::open()->has('contents')->get(['id','date','tableName']);

但是这样做,它也会给我返回

OrderContents
.. 有没有办法不获得该字段?

谢谢!

php laravel laravel-4 eloquent
8个回答
47
投票

令人失望的是这里的人给了你虚假信息。事实上,有一个内置方法可以实现此目的,直接写入

Illuminate\Database\Eloquent\Model
类,称为
Model::getOriginal

要检索

foo
属性,忽略
Model::getFooAttribute
中定义的访问器,只需调用
$myModel->getOriginal('foo');
。该方法定义在Illuminate\Database\Eloquent\Model的第
3087
行。

请记住,此方法获取模型上的原始值。这意味着,如果您对该模型实例上的属性进行任何修改,上述解决方案将不会反映这些修改。只要您只是检索该值,就应该没有问题。


35
投票

没有办法一次性完成,所以这就是你需要的:

$openOrders = Order::open()->has('contents')->get(['id','date','tableName']);

$openOrders->each(function ($order) {
  $order->setAppends([]);
});

或者,您可以在最后一步使用 Laravel 的 Higher Order Messaging

$openOrders->each->setAppends([]);

16
投票

对于 Laravel <= 6.x,

有一个内置的

getOriginal
方法可以从模型中获取原始值而无需访问器。请参阅:6.x

$myModel->getOriginal('foo');

对于 Laravel 7.x 和 8.x 和 9.x,

您应该使用

getRawOriginal
内置方法从模型中检索原始值。请参阅:9.x

$myModel->getRawOriginal('foo');

7.x & 8.x & 9.x 中的

getOriginal
方法将通过访问器返回属性值。


13
投票

好吧,我并不是说这是一个很好的解决方案,但它确实有效,并且您可以使用循环......

将此添加到您的模型中:

public static $withoutAppends = false;

protected function getArrayableAppends()
{
    if(self::$withoutAppends){
        return [];
    }
    return parent::getArrayableAppends();
}

然后当您想要禁用

$appends
属性时:

Order::$withoutAppends = true;
$openOrders = Order::open()->has('contents')->get(['id','date','tableName']);

3
投票

从模型类中获取未突变值的更一致和可靠的方法是从 attribute 属性中检索它,如下所示:

$this->attributes['name']

但请注意,属性是受保护的属性,因此您无法从模型类外部执行此操作。在这种情况下,你可以使用

$model->getAttributes()['name']

在 Laravel 8 中为我工作


1
投票

将此添加到您的模型中:

public function newInstance($attributes = [], $exists = false): self
{
    $model = parent::newInstance($attributes, $exists);
    $model->setAppends($this->appends);

    return $model;
}

public static function withoutAppends(): Builder
{
    $model = (new static);
    $model->setAppends([]);

    return $model->newQuery();
}

暂时禁用

$appends

$openOrders = Order::withoutAppends()->open()->has('contents')->get(['id','date','tableName']);

如果您运行辅助查询,例如

$orders = Order::get();
附件又回来了。


0
投票

假设您只需要加载关系时的自定义属性值,并且contents()是一个关系,您可以执行以下操作:

public function getOrderContentsAttribute()
{
  if ($this->relationLoaded('contents')) {
    return $this->contents()->get();
  } else {
    return [];
  }
}

然后,为了访问该属性,您可以使用查询范围来添加关系,或者在查询模型时使用

Order::with('contents')


0
投票

您可以使用 Laravel 在运行时追加

首先为值定义一个访问器

function getTotalPointsAttribute(){
  return $this->users->sum->getTotalPoints();
}

然后,如果您想检索多个模型,请像这样使用它:

$users->each->append(['total_points']);

// or if you want to override the entire array
// of appended properties for a given models
$users->each->setAppends(['total_points']);

或者如果您只想检索单个模型,只需执行以下操作:

$user->total_points;

// append(['total_points']) and setAppends(['total_points']) is also usable;
© www.soinside.com 2019 - 2024. All rights reserved.