Laravel,如何忽略访问器

Posted

技术标签:

【中文标题】Laravel,如何忽略访问器【英文标题】:Laravel, how to ignore an accessor 【发布时间】:2015-03-16 21:25:07 【问题描述】:

我有一个带有自定义访问器的模型,所以我得到了那个自定义属性,

    class Order extends GSModel

        $appends = ['orderContents'];

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

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

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

但是这样做,它也会返回OrderContents.. 有没有办法不获取该字段?

谢谢!

【问题讨论】:

您的意思是当您将orderContents 转换为JSON/数组时不想要它? 是的,这就够了 【参考方案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(); 追加回来了。

【讨论】:

【参考方案2】:

对于 Laravel

有一个内置的getOriginal 方法可以在没有访问器的情况下从模型中获取原始值。见:6.x

$myModel->getOriginal('foo');

对于 Laravel 7.x 和 8.x,

您应该使用getRawOriginal 内置方法从模型中检索原始值。见:8.x

$myModel->getRawOriginal('foo');

7.x & 8.x 中的getOriginal 方法将通过访问器返回属性值。

【讨论】:

【参考方案3】:

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

$this->attributes['name']

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

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

在 Laravel 8 中为我工作

【讨论】:

【参考方案4】:

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

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

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

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

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

【讨论】:

现在可以这样做了:$openOrders->each->setAppends([]); 是的,添加了@JordiPuigdellívol 受保护的 $appends = ['full_name']; public function getFullNameAttribute() return User::where('user_id',$this->id)->value('full_name');在这种情况下,每次模态实例命中时,append 方法都会自动触发需要删除的 sql 查询。公共函数作用域DisableDynamicAccessors() $this->setAppends([]); 这里 setappends 不起作用【参考方案5】:

令人失望的是这里的人给了你虚假信息。实际上有一个内置的方法可以实现这一点,直接写入Illuminate\Database\Eloquent\Model 类,称为Model::getOriginal

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

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

【讨论】:

并在选择中获得多个赞? 这太棒了,我一直在寻找什么...谢谢【参考方案6】:

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

将此添加到您的模型中:

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']);

【讨论】:

我认为这是一个很好的解决方案,我知道它避免了查询以获取正确的元素?因为我的 orderContents 是 belongsToMany 关系 是的,只要您不将其加载到其他地方,就不会获取该关系。我不太喜欢这个解决方案,因为它涉及在模型上设置静态标志。例如,如果您要使用Order:: 进行第二个查询,您将不得不担心withoutAppends 的状态并可能将其设置回false。但是你......它完成了工作。

以上是关于Laravel,如何忽略访问器的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 查询构建器:如何访问 JSON 键/值对

Laravel模型访问器 & 修改器

在 laravel 5.3 中使用带有访问器的强制转换

BlazeDS 忽略 POJO 反序列化的公共访问器

Laravel - 大量使用 Blade 渲染视图的访问器(修改器)

php Laravel mutator和日期格式的访问器