php - wherepivot - Laravel Eloquent clasificación por columna de tabla de relación
wherepivot laravel (2)
Traté de clasificar los productos de la tabla shop_products
por la columna shop_products_options
tabla shop_products_options
:
$products = Shop/Product::with([''options'' => function ($query) {
$query->orderBy(''pinned'', ''desc'');
}])->paginate(5);
Establecí la relación en el modelo Tienda / Producto:
public function options()
{
return $this->hasOne(''Shop/Options'');
}
Pero los productos no están clasificados. Recibo una consulta que solo funciona con la tabla shop_products_options
.
SELECT * FROM `shop_products_options` WHERE `shop_products_options`.`product_id` in (''8'', ''9'', ''10'', ''11'', ''12'') ORDER BY `pinned` DESC
¿Como arreglarlo?
La carga ansiosa utiliza consultas separadas, por lo que necesita unirse para esto:
$products = Shop/Product::join(''shop_products_options as po'', ''po.product_id'', ''='', ''products.id'')
->orderBy(''po.pinned'', ''desc'')
->select(''products.*'') // just to avoid fetching anything from joined table
->with(''options'') // if you need options data anyway
->paginate(5);
SELECT
cláusula SELECT
está allí para no agregar columnas unidas a su modelo de Product
.
editar: según el comentario de @alexw: aún puede incluir columnas de tablas unidas si las necesita. Puede agregarlos para select
o llamar addSelect/selectRaw
etc.
No puede ordenar por columna de tabla relacionada sin la tabla relacionada de unión manual. La respuesta de Jarek es correcta, pero esto podría ser muy incómodo:
1. El primer problema es que debe preocuparse por seleccionar.
->select(''products.*'')
razón: sin select () id de shop_products_options se puede seleccionar e hidratar en el modelo del Producto.
2. El segundo problema es que debes preocuparte por groupBy.
->groupBy(''products .id'');
razón: si la relación es HasOne y hay más de una shop_products_options para el producto, la consulta devolverá más filas para los productos.
3. El tercer problema es que debe cambiar todas las cláusulas where where de:
->where(''date'', $date)
a
->where(''products .date'', $date)
razón: los productos y shop_products_options pueden tener el atributo "date" y en ese caso sin seleccionar el atributo con la tabla "ambiguous column" se generará un error.
4. El cuarto problema es que estás usando nombres de tablas (no modelos) y esto también es malo e incómodo.
->where(''products.date'', $date)
5. El quinto problema es que debe preocuparse por las eliminaciones suaves para las tablas unidas. Si shop_products_options usa el rasgo de SoftDeletes, debe agregar:
->where(''shop_products_options .deleted_at'', ''='', null)
Todos los problemas anteriores son muy frustrantes y unir tablas con elocuentes puede presentarle muchos problemas al código. Creé un paquete que se encarga de todos los problemas anteriores y puede ordenar por atributo de relación de manera elegante, para su caso sería:
$products = Shop/Product::orderByJoin(''options.pinned'', ''desc'')->paginate(5);
Para obtener más información, consulte https://github.com/fico7489/laravel-eloquent-join