Tengo dos modelos principales en mi proyecto Laravel. ProductMaster es donde están los datos principales del producto y Product es el modelo que contiene la variación de cada producto y el precio para cada cliente. No tengo permitido cambiar este modelo, en caso de que se lo pregunte.
Mi pregunta es cómo hacer una consulta elocuente para obtener los datos de ProductMaster con Productos filtrados por cliente (y otros parámetros también). Intenté whereHas pero no funcionó.
Estos son mis modelos:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class ProductMaster extends Model { protected $table = 'product_masters'; protected $primaryKey = 'id'; protected $fillable = ['code','title']; public function products(){ return $this->hasMany(Product::class,'master_id'); } } namespace App\Models; use Illuminate\Database\Eloquent\Model; use App\Models\ProductMaster; class Product extends Model { protected $table = 'products'; protected $primaryKey = 'id'; protected $fillable = ['sku', 'stock', 'brand', 'size', 'priceList', 'master_id', 'client']; public function productMaster(){ return $this->belongsTo(ProductMaster::class,'master_id'); } }Y esta es la consulta que traté de hacer:
//QUERY WITH FILTERS $products = ProductMaster::whereHas('products', function($query) use($filterBrand, $filterCats, $filterSizes, $clientCode) { $query->where('client', $clientCode); $query->whereIn('brand', $filterBrand); $query->whereIn('size', $filterSizes); }) ->where('title', 'LIKE', '%' . $request->find . '%') ->orderby($order[0], $order[1]) ->paginate(6) ->withQueryString();Esta consulta funciona pero no obtengo exactamente lo que necesito. Esto me da todos los ProductMaster que tienen productos con esos parámetros, pero en la colección $products pone TODOS los productos que tienen ese master_id y no solo los productos que tienen esos parámetros.
Este es el sql:
select * from `product_masters` where exists (select * from `products` where `product_masters`.`id` = `products`.`master_id` and `client` = ? and `products`.`brand` in (?) and `category` in (?) and `client` = ?) and `title` LIKE ? order by `title` ascAquí hay algunos datos de muestra: SQL Fiddle
¿Alguien puede ayudarme? Gracias.
Si desea filtrar los productos para cargar ansiosos y también filtrar para cargar solo los maestros de productos que tienen esos productos, su consulta debería ser así:
$products = ProductMaster:: with([ 'products' => fn($query) => $query ->where('client', $clientCode) ->whereIn('brand', $filterBrand) ->whereIn('size', $filterSizes) ]) ->whereHas('products', fn($query) => $query ->where('client', $clientCode) ->whereIn('brand', $filterBrand) ->whereIn('size', $filterSizes) ) ->where('title', 'LIKE', '%' . $request->find . '%') ->orderby($order[0], $order[1]) ->paginate(6) ->withQueryString();Incluso podría pasar esa consulta en las funciones with y whereHas a una función privada dentro de su controlador para mantener el clon más limpio.
¿Podría probar esto y decirme si funciona o no? Y también creo que te perdiste el filtrado de categorías en una de las cláusulas whereIn.
$q = ProductMaster::with('products')->where(function($query) use ($filterBrand, $filterCats, $filterSizes, $clientCode) { $query->whereHas('products', function($query) use ($filterBrand, $filterCats, $filterSizes, $clientCode) { $query->where('client', $clientCode); $query->whereIn('brand', $filterBrand); $query->whereIn('size', $filterSizes); $query->whereIn('category', $filterCats); }); }); $products = $q->where('title', 'LIKE', '%' . $request->find . '%') ->orderby($order[0], $order[1]) ->paginate(6) ->withQueryString();