You don't have to use Eloquent/Query Builder, you can just do a DB::select()
SQL Query To Eloquent Relationship
// category-product_variant pivot table
Schema::create('category_product_variant', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')->constrained('categories');
$table->foreignId('product_variant_id')->constrained('product_variants');
$table->timestamps();
$table->softDeletes();
// unique constraints
$table->unique(['category_id', 'product_variant_id'], 'category_product_variant_unique');
});
// category model
class Category extends Model
{
public function products()
{
// return $this->hasMany(Product::class); <-- only gets products directly connected to the category
// WHAT TO DO HERE
}
}
// raw sql
select * from `products`
where `category_id` = 6
or exists (
select * from `product_variants`
where `products`.`id` = `product_variants`.`product_id`
and exists (
select * from `categories`
inner join `category_product_variant`
on `categories`.`id` = `category_product_variant`.`category_id`
where `product_variants`.`id` = `category_product_variant`.`product_variant_id`
and `categories`.`id` = 6
and `categories`.`deleted_at` is null
)
and `product_variants`.`deleted_at` is null
)
and `products`.`deleted_at` is null
i have the following models: Product, ProductVariant and Category. a Product belongs to a Category via category_id, it also has many ProductVariants via product_id on the product_variants table. a ProductVariant may have categories attached to it stored in a m2m pivot table category_product_variant. the raw sql above produces the desired results or data. i want to get all products in a category even if it's only the variant that's associated with it. for example a book. the book has the books category and one of its variants is connected to the audiobooks category. i want the book to show when i look for products in the audiobooks category.
public function products()
{
$categoryId = $this->id;
return Product::where('category_id', $categoryId)
->orWhere(function ($query) use ($categoryId) {
$query->whereExists(function ($subquery) use ($categoryId) {
$subquery->select(DB::raw(1))
->from('product_variants')
->whereColumn('products.id', 'product_variants.product_id')
->whereExists(function ($subquery2) use ($categoryId) {
$subquery2->select(DB::raw(1))
->from('categories')
->join('category_product_variant', 'categories.id', '=', 'category_product_variant.category_id')
->whereColumn('product_variants.id', 'category_product_variant.product_variant_id')
->where('categories.id', $categoryId)
->whereNull('categories.deleted_at');
})
->whereNull('product_variants.deleted_at');
});
})
->whereNull('products.deleted_at');
}
this returns this error: App\Models\Category::products must return a relationship instance.
Please or to participate in this conversation.