Php 如何从相关模型中附加雄辩的属性而不获取模型';什么内容?

Php 如何从相关模型中附加雄辩的属性而不获取模型';什么内容?,php,mysql,eloquent,Php,Mysql,Eloquent,我有两个能言善辩的模型: EloquentUser 及 它们都与用户id相关 我正在尝试在SharedEvents模型中设置并附加属性,该属性将附加与之共享事件的用户的全名 为了可读性,我只包含类的appends组件 class SharedEvents extends Model { protected $appends = ['fullName']; /** * @return BelongsTo */ public function user() : BelongsTo

我有两个能言善辩的模型:

EloquentUser

它们都与用户id相关

我正在尝试在SharedEvents模型中设置并附加属性,该属性将附加与之共享事件的用户的全名

为了可读性,我只包含类的appends组件

class SharedEvents extends Model {

protected $appends      = ['fullName'];

/**
 * @return BelongsTo
 */
public function user() : BelongsTo {
    return $this->belongsTo('Path\To\EloquentUser', 'shared_with_id', 'user_id');
}

    /**
 * @return mixed
 */
public function getFullNameAttribute(){
    return $this->user->user_full_name;
}
不幸的是,当我运行这个程序时,我得到了全名和整个用户模型,而我只需要全名

有没有办法避免附加用户模型的内容?

你能试试吗

public function user() : BelongsTo {
    return $this->belongsTo('Path\To\EloquentUser', 'shared_with_id', 'user_id')->select('fullName','user_id');
}

在做了一些研究和实验之后,似乎没有办法用雄辩来做到这一点。不幸的是,我最终采用的解决方案是运行一个附加查询

/**
 * This is inefficient, but I could not find a way to get the full name
 * attribute without including all of user.
 *
 * @return string
 */
public function getFullNameAttribute(){
    return EloquentUser::select('user_full_name')
                        ->where('user_id', $this->shared_with_id)
                        ->first()
                        ->user_full_name;
}

这感觉就像你在尝试从你的
ellounter
模型中创建列,在你的
SharedEvent
模型中创建一等公民。你越来越接近了,但是想想…… 在处理关系时,这是一种明确表达的好方法:

假设
user\u full\u name
user
型号上的访问者:

// EloquentUser.php

// This will automatically add your accessor to every query 
// as long as you select the columns the accessor is made 
// up of
protected $appends = ['user_full_name'];

/**
 * User Full Name Accessor

 * @return string
 */
public function getUserFullNameAttribute()
{
    return $this->first_name . ' ' . $this->last_name;
}

// SharedEvent.php

/**
 * A SharedEvent belongs to an Eloquent User

 * @return BelongsTo
 */
public function user() : BelongsTo 
{
    return $this->belongsTo('Path\To\EloquentUser', 'shared_with_id', 'user_id');
}

// Somewhere in your controller or wherever you want to access the data
$sharedEvents = SharedEvent::with(['user' => function ($query) {
    $query->select('user_id', 'first_name', 'last_name');
}])->where(...)->get(['shared_with_id', ...other columns]); // you must select the related column here
这会让你最接近你想要的,但是有几件事你应该知道:

  • 如果
    user\u full\u name
    是一个访问器,则需要选择构成该访问器的所有列(如上所述)
  • 您必须选择相关的键(
    EloquentUser
    中的
    user\u id
    SharedEvent
    中的
    shared\u与\u id
  • $appends
    在这里的
    EloquentUser
    中是必需的,因为您不能在闭包内直接向子查询添加访问者
  • 试着在你的人际关系中把闭包作为第二个参数来使用。这是在加载关系时准确确定要选择哪些列的最佳方法-雄辩使懒惰变得非常容易,只需执行以下操作:

    SharedEvent::with('user')->get();
    
    正如您所看到的,它将在
    SharedEvent
    和您的
    user
    关系上执行
    select*


    在处理使用关系的复杂查询时,我注意到的另一件事是,您可以很快到达一个点,感觉您正在与框架抗争。这通常是考虑使用原始SQL简化OT的一个标志。雄辩是强大的,但只是编程工具带中的另一个工具。请记住,您可以使用其他工具。

    我遇到了相同的问题,我的第一个想法是在获取SharedEvent时显式隐藏(整个)关联模型

    在您的情况下,这看起来像:

    class SharedEvents extends Model {
    
       protected $appends  = ['fullName'];
       protected $hidden   = ['user'];
       ...
    }
    
    实际上,我决定不这样做,因为我返回了许多其他附加的模型,所以我决定附加整个用户,但我测试了它,它工作了

    仅供参考,我不确定这种差异是否是由于较旧版本的Laravel造成的,但Eloquent实际上希望$appends属性在snake case()中:

    请注意,属性名称通常在“snake-case”中引用,即使访问器是使用“camel-case”定义的


    您能告诉我们调用
    getFullNameAttribute()
    accessor的代码吗?因此它会通过查询自动调用。我可以展示它,但这是一个非常漂亮的头发查询。我确实尝试过,但不幸的是得到了相同的结果。回答很好,我自己有时也有同样的感觉。我想在这里的确切场景中,我会坚持为这些情况运行额外的查询。我的API的其余部分依赖于一个laravel集合的结果,除了这个特定字段之外,其他一切都可以正常工作。由于你深思熟虑的分析,我将接受你的回答。谢谢你抽出时间!很高兴我能帮忙。这将仍然是一个雄辩的收集,但也许有一些其他细节我错过了。祝你好运你是对的,这将是一个雄辩的集合,我刚才说我确实依赖API。雄辩的关系不仅仅执行连接。事实上,它们总是执行额外的查询。这是雄辩的一大特点。如果您选择使用雄辩,那么您需要学习如何控制这些查询的效率。看看吧,你会开始对雄辩者在幕后的所作所为有一个很好的理解。
    class SharedEvents extends Model {
    
       protected $appends  = ['fullName'];
       protected $hidden   = ['user'];
       ...
    }