Laravel范围有两个关系

时间:2015-06-09 19:49:12

标签: php laravel eloquent

我有一个主表,“help_pages”存储文章或视频的ID。还有另外两个表:“文章”和“视频”。

在下面的示例中,为了我的应用程序,$ portalType是“经销商”或“全局”。只要我没有未发布的视频标记,一切都很顺利。现在我无法通过发布的两篇文章和视频过滤范围功能。

这是在我的模型/ HelpPage.php中:

public function scopeByPortalType($query, $portalType) {
    return $query->where('portal_type', '=', $portalType)
    ->leftjoin('articles', 'content_id', '=', 'articles.id')
    ->where('articles.published', '=', '1');
}

我希望我能做的只是添加第二个

->leftJoin('videos', 'content_id', '=', videos.id')
->where('videos.published', '=', '0');

但这会返回太多行。我尝试为文章和视频创建一个带有UNION的临时表:

        CREATE TEMPORARY TABLE IF NOT EXISTS tmp_assets AS 
            (SELECT id, 'Article' AS content_type FROM articles WHERE published = 1)
        UNION
            (SELECT id, 'Video' AS content_type FROM videos WHERE published = 1)

然后加入,但没有骰子。这可能比我做的要小,但我现在迷路了!

Laravel版本4.2

2 个答案:

答案 0 :(得分:0)

嗯,它并不完美,但是我做了我需要做的事情:

public function scopeByPortalType($query, $portalType) {
    $q = $query
        ->whereRaw("
        (id IN (SELECT help_pages.id FROM help_pages INNER JOIN articles ON content_id=articles.id WHERE articles.published='1' AND content_type='Article')
        OR
        id IN (SELECT help_pages.id FROM help_pages INNER JOIN videos ON content_id=videos.id WHERE videos.published='1' AND content_type='Video'))")
        ->where('portal_type', '=', $portalType);
    return $q;
}

我希望我能找到一种方法来使用实际的Eloquent来做到这一点,但每一步都让我陷入了一个死胡同的兔子洞。这很有效!

答案 1 :(得分:0)

执行此操作的雄辩方法是建立关系,以便您可以利用预先加载。

关系:http://laravel.com/docs/4.2/eloquent#relationships

渴望加载:http://laravel.com/docs/4.2/eloquent#eager-loading

设置关系:

class HelpPage extends Eloquent {

    public function articles()
    {
        return $this->hasMany('Article');
    }


    public function videos()
    {
        return $this->hasMany('Video');
    }

}

然后你就可以利用这样的热切加载:

$help_pages = HelpPage::with(array('articles' => function($query)
{
    $query->where('published', '=', 1);

},
'videos' => function($query)
{
    $query->where('published', '=', 1);

}
))->get();

然后,您可以在实际查询中使用whereHas和orWhereHas,而不是上面的示例。