You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel查询构建器关联:多态关联下查询主题类产品

Hey there! Let's walk through common polymorphic relationship operations using Laravel's query builder, based on your database setup. First, I spotted a tiny typo in your original code: your products table uses commentable_type as the polymorphic type field, but your query references productable_type—let's fix that first, then dive into more useful operations.

Corrected Base Query (Get All Theme-Associated Products)

This is the fixed version of your initial code to fetch products linked to Themes:

$themeProducts = DB::table('products')
    ->orderBy('id', 'asc')
    ->where('commentable_type', Theme::class)
    ->get();

1. Join to Fetch Associated Theme Data

If you want to pull in data from the themes table alongside your products (like the composer_package value), use a conditional join to enforce the polymorphic type match:

$themeProductsWithDetails = DB::table('products')
    ->join('themes', function ($join) {
        $join->on('products.commentable_id', '=', 'themes.id')
             ->where('products.commentable_type', Theme::class);
    })
    ->select('products.*', 'themes.composer_package as theme_composer_package')
    ->orderBy('products.id', 'asc')
    ->get();

The join closure ensures we only match products that are actually linked to a Theme, not just any random ID match.

2. Filter Products by a Theme's Field

Suppose you need products linked to a specific Theme (e.g., one with a particular composer_package). Use whereExists to create a subquery that checks the associated Theme's data:

$specificThemeProducts = DB::table('products')
    ->where('commentable_type', Theme::class)
    ->whereExists(function ($query) {
        $query->select(DB::raw(1))
              ->from('themes')
              ->whereColumn('themes.id', 'products.commentable_id')
              ->where('themes.composer_package', '=', 'vendor/laravel-bootstrap-theme');
    })
    ->orderBy('products.id', 'asc')
    ->get();

Alternatively, you could use a join here too—whereExists is great for avoiding duplicate product rows (though in your case, IDs are unique, so either approach works).

3. Get Products for Multiple Polymorphic Types

If you ever need to fetch products linked to both Themes and Plugins, use whereIn on the commentable_type field:

$multiTypeProducts = DB::table('products')
    ->whereIn('commentable_type', [Theme::class, Plugin::class])
    ->orderBy('id', 'asc')
    ->get();

4. Count Products per Theme

To generate a report of how many products each Theme has associated with it, use a left join and grouping:

$themeProductCounts = DB::table('themes')
    ->leftJoin('products', function ($join) {
        $join->on('themes.id', '=', 'products.commentable_id')
             ->where('products.commentable_type', Theme::class);
    })
    ->select('themes.id', 'themes.composer_package', DB::raw('count(products.id) as product_count'))
    ->groupBy('themes.id', 'themes.composer_package')
    ->get();

The left join ensures even Themes with no products show up with a count of 0.

Quick Note: Eloquent Alternative

While you asked for query builder operations, if you're using Laravel's Eloquent models, defining the polymorphic relationships will make these tasks even cleaner. For example:

  • In your Product model:
    public function commentable()
    {
        return $this->morphTo();
    }
    
  • In your Theme model:
    public function products()
    {
        return $this->morphMany(Product::class, 'commentable');
    }
    

Then you could fetch Theme products with:

$themeProducts = Theme::with('products')->get();

内容的提问来源于stack exchange,提问作者user7301337

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:58:00