php - wheredate - with() laravel



Elocuente en donde con unir múltiples tablas (1)

Tengo 4 tablas, elementos, listas, catitem_item y item_listing.

los artículos y el listado es una relación de muchos a muchos. los artículos y catitems son también muchas a muchas relaciones.

catitems contiene una lista de categorías de artículos. listados es como la ubicación donde se encuentran los artículos. El ejemplo que enumera la tienda A puede tener la silla del artículo y la silla del artículo tienen categorías catitem múltiples.

Mi objetivo es obtener los artículos que figuran en la lista de categorías como categoría 1 Y 2 Y 3 ( $cats ) y con la información de la lista donde se encuentra este elemento. Entonces, si hay 6 listados de silla, devolverá 6 resultados de silla.

Esta es la consulta que tengo hasta ahora.

$items = DB::table('items')
                ->join('catitem_item', 'catitem_item.item_id', '=', 'items.id')
                ->join('item_listing', 'item_listing.item_id', '=', 'items.id')
                ->join('listings', 'item_listing.listing_id', '=', 'listings.id')
                ->whereIn('catitem_item.catitem_id', $cats)
                //->groupBy('items.id')
                //->having(DB::raw('count(*)'), '=', count($cats))
                ->select('items.id', 'items.name', 'items.price', 'items.slug', 'item_listing.listing_id', 'listings.name as listing_name', 'listings.slug as listing_slug')
                ->get();

Tenga en cuenta que, por la forma en que está tratando de hacerlo, es posible que obtenga varias filas por artículo (una por lista relacionada). Una mejor manera sería tener una variedad de listados por artículo.

Si usa modelos elocuentes y ha configurado las relaciones correctamente, podría intentar lo siguiente:

$cats = [1, 2, 3];

$query = Item::with('listings');
foreach ($cats as $cat) {
    $query->whereHas('catitems', function($q) use($cat) {
        $q->where('id', $cat);
    });
}
$items = $query->get();

Ahora cada artículo debe tener una propiedad de listings . Por ejemplo, para el primer elemento, puede acceder a los listados de la siguiente manera:

$item1 = $items[0];
$listings1 = $item1->listings;

Tenga en cuenta que whereHas() probablemente creará una subconsulta EXISTS correlacionada para cada entrada en la matriz $cats . Si eso es lento, puede usar una consulta JOIN como:

$items = Item::with('listings')
    ->join('catitem_item', 'catitem_item.item_id', '=', 'items.id')
    ->whereIn('catitem_item.catitem_id', $cats)
    ->groupBy('items.id')
    ->having(DB::raw('count(*)'), '=', count($cats))
    ->select('items.*')
    ->get();

Si no usa elocuente, también puede hacer la "carga ansiosa" usted mismo.

$items = DB::table('items')
    ->join('catitem_item', 'catitem_item.item_id', '=', 'items.id')
    ->whereIn('catitem_item.catitem_id', $cats)
    ->groupBy('items.id')
    ->having(DB::raw('count(*)'), '=', count($cats))
    ->select('items.*')
    ->get()
    ->keyBy('id');

foreach ($items as $item) {
    $item->listings = [];
}

$itemIds = $items->pluck('id');
$listings = DB::table('listings')
    ->join('item_listing', 'item_listing.listing_id', '=', 'listings.id')
    ->whereIn('item_listing.item_id', $itemIds)
    ->groupBy('listings.id')
    ->select('listings.*', DB::raw('group_concat(item_listing.item_id) as item_ids'))
    ->get();

foreach ($listings as $listing) {
    $itemIds = explode(',', $listing->item_ids);
    foreach ($itemIds as $itemId) {
        $items[$itemId]->listings[] = $listing;
    }
    $listing->forget('item_ids');
}




laravel-eloquent