【问题标题】:Laravel: Pass Parameter to Relationship Function?Laravel:将参数传递给关系函数?
【发布时间】:2014-04-11 15:04:37
【问题描述】:

是否可以通过某种方式将参数传递给关系函数?

我目前有以下:

public function achievements()
{
     return $this->belongsToMany('Achievable', 'user_achievements')->withPivot('value', 'unlocked_at')->orderBy('pivot_unlocked_at', 'desc');
}

问题在于,在某些情况下,它不会获取 unlocked_at 列并返回错误。

我尝试过类似的操作:

public function achievements($orderBy = true)
{
$result = $this->belongsToMany (...)
if($orderBy) return $result->orderBy(...)
return $result;
}

并将其称为:

$member->achievements(false)->(...)

但这不起作用。有没有办法将参数传递给该函数或任何方法来检查 pivot_unlocked_at 是否正在使用?

【问题讨论】:

  • 你应该按照你说的去做。您确实需要记住,如果您将关系函数称为方法而不是属性,则它们的行为会有所不同。如果您将它们用作属性,您将获得一个结果集(集合),但如果您将它们作为方法调用,您将获得一个查询构建器。如果您想将参数传递给它们,显然必须将它们作为方法调用,因此请确保在调用代码中使用 ->get()$member->achievements(true)->get()->(...) 将等效于 $member->achievements->(...)
  • awsm @alexrussell。让我头疼....
  • 很高兴我 2014 年的建议仍然适用 :)

标签: php laravel


【解决方案1】:

我所做的只是向我的模型添加新属性,然后将我的条件添加到该属性,只需这样做。

Class Foo extends Eloquent {
    protected $strSlug;

    public function Relations(){
         return $this->belongsTo('Relation','relation_id')->whereSlug($this->strSlug);
    }
 }

 Class FooController extends BaseController {
     private $objFoo;


     public function __construct(Foo $foo){
         $this->objFoo = $foo
     }

     public function getPage($strSlug){
        $this->objFoo->strSlug = $strSlug;
        $arrData = Foo::with('Relations')->get();
        //some other stuff,page render,etc....
     }
 }

【讨论】:

    【解决方案2】:

    您可以简单地创建一个范围,然后在必要时将其添加到构建器实例中。

    例子:

    用户.php

    public function achievements()
    {
        return $this->hasMany(Achievement::class);
    }
    

    成就.php

    public function scopeOrdered(Builder $builder)
    {
        return $builder->orderBy(conditions);
    }
    

    那么当使用时:

    //returns unordered collection
    $user->achievements()->get();
    
    //returns ordered collection
    $user->achievements()->ordered()->get();
    

    您可以在Eloquent documentation 阅读有关范围的更多信息。

    【讨论】:

    • 我可以在这里传递ordered()函数的参数吗?
    • 是的,你可以。 ``` public function scopeOrdered(Builder $builder, string $orderBy) { return $builder->orderBy($orderBy); } ```
    【解决方案3】:

    您可以做的更简单、更安全:

    当你调用带双亲的关系函数时,Laravel 将只返回查询,你需要添加 get() 或 first() 来检索结果

    public function achievements($orderBy = true)
    {
    if($orderBy) 
        $this->belongsToMany(...)->orderBy(...)->get();
    else
        return $this->belongsToMany(...)->get();
    }
    

    然后你可以这样称呼它:

    $member->achievements(false);
    

    适用于最新版本的 Laravel。

    【讨论】:

    • 执行此操作时请注意,此方法不再表现得像关系。您不能将其与其他条件链接。我建议为该方法使用不同的名称以明确这一点,例如getAchievements()
    【解决方案4】:

    必须解决这个问题,就像在 Laravel 5.3 上一样,其他解决方案都不适合我。如下:

    实例化一个模型:

    $foo = new Foo();

    设置新属性

    $foo->setAttribute('orderBy',true);

    然后在查询数据的时候使用setModel方法

    Foo::setModel($foo)->where(...)

    这将让你从关系方法中访问属性

    public function achievements()
    {
    if($this->orderBy) 
        $this->belongsToMany(...)->orderBy(...)->get();
    else
        return $this->belongsToMany(...)->get();
    }
    

    【讨论】:

    • 那里有问题。你不能将它与 ->with 函数一起使用,当你尝试时,你会得到 Null。所以它只能在单个模型上使用,不能批量使用。所以会有多个查询而不是几个
    • @AidOnline01 仅仅因为它不适用于您的场景,并不意味着它不正确。这对我的使用非常有用,我相信它会解决 OP 的问题。不值得你投反对票,因为它可以帮助别人;-)
    • 我之前说过,这不是关系函数,而是属性函数,最好是getAchievementsAttribute。您不能使用 with 函数查询它,因此 Model::with('achievements')->get() 将失败。就是说我相信这并不能回答作者的问题
    猜你喜欢
    • 1970-01-01
    • 2016-04-26
    • 2013-01-27
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    相关资源
    最近更新 更多