name change application app laravel laravel-4 eloquent eager-loading

laravel - change - config('' app name '')



Elocuente carga ansiosa Ordenar por (7)

tl; dr

Student::with(''exam'')->get()->sortByDesc(''exam.result'');

Esto ordenará los resultados de la consulta después de una carga ansiosa utilizando métodos de recopilación y no mediante una ORDER BY MySQL ORDER BY .

Explicación

Cuando está ansioso de cargar, no puede usar un ORDER BY en las relaciones cargadas porque se solicitarán y ensamblarán como resultado de una segunda consulta. Como puede ver en la documentación de Laravel, la carga ansiosa ocurre en 2 consultas.

Si desea utilizar ORDER BY MySQL, debe unirse a las tablas relacionadas.

Como solución alternativa, puede ejecutar su consulta y ordenar la colección resultante con sortBy , sortByDesc o incluso sort . Esta solución tiene ventajas y desventajas sobre la solución de combinación:

Ventajas:

  • Mantiene la funcionalidad Eloquent.
  • Código más corto e intuitivo.

Desventajas:

  • La clasificación será hecha por PHP en lugar del motor de la base de datos.
  • Puede ordenar solo por una sola columna, a menos que proporcione un cierre personalizado para las funciones del clasificador .
  • Si solo necesita una parte de los resultados ordenados de una consulta (por ejemplo, ORDER BY con LIMIT ), debe buscarlo todo , ordenarlo y luego filtrar el resultado ordenado, de lo contrario terminará solo con la parte filtrada ordenada (ordenando no considerará los elementos filtrados). Entonces, esta solución solo es aceptable cuando se trabaja en todo el conjunto de datos de todos modos o la sobrecarga no es un problema.

Tengo un problema con la consulta elocuente. Estoy usando la carga ansiosa (relación uno a uno) para obtener '' estudiante '' con el '' examen '', usando el código a continuación.

Student::with(''exam'')->orderBy(''exam.result'', ''DESC'')->get()

Y quiero ordenar las filas recibidas por la columna '' resultado '' en '' examen ''. estoy usando

->orderBy(''exam.result'', ''DESC'')

Pero no está funcionando. Alguna idea de como hacerlo ?


Esto funcionó para mí:

$query = Student::select([''id'',''name'']); $query->has(''exam'')->with([''exam'' => function ($query) { return $query->orderBy(''result'',''ASC''); }]); return $query->get();


Existe una forma alternativa de lograr el resultado que desea tener sin utilizar uniones. Puede hacer lo siguiente para ordenar a los estudiantes según el resultado de su examen. (Laravel 5.1):

$students = Student::with(''exam'')->get(); $students = $students->sortByDesc(function ($student, $key) { return $student->exam->result; });


Podría usar / Illuminate / Database / Eloquent / Relations / Relation y alcances de búsqueda para agregar una relación de columna lejana, escribí un rasgo para esto, se pierde HasOne o HasMany pero teniendo BelongsTo y BelongsToMany podría adaptarse fácilmente

También el método podría ser mejorado para soportar más que la profundidad 1 para la relación de múltiples cadenas, hice espacio para eso

<?php /** * User: matteo.orefice * Date: 16/05/2017 * Time: 10:54 */ use Illuminate/Database/Eloquent/Relations/BelongsToMany; use Illuminate/Database/Eloquent/Relations/BelongsTo; use Illuminate/Support/Facades/DB; use Illuminate/Database/Eloquent/Builder; trait WithFarColumnsTrait { public function scopeWithFarColumns(Builder $query , $relationPath , $columns , $tableAliasPrefix = null) { $relationPath = array_wrap($relationPath); $tableAliasPrefix = $tableAliasPrefix ?: WithFarColumnsTrait::randomStringAlpha(3); $currentModel = $this; $subQueries = []; $relationIndex = 0; foreach ($relationPath as $relationName) { if (method_exists($currentModel , $relationName)) { $relation = $currentModel->$relationName(); } else { throw new BadMethodCallException("Relationship $relationName does not exist, cannot join."); } $currentTable = $currentModel->getTable(); if ($relationIndex == 0) { $query->addSelect($currentTable . ''.*''); } $relatedModel = $relation->getRelated(); /** * @var string */ $relatedTable = $relatedModel->getTable(); if ($relation instanceof BelongsTo) { foreach ($columns as $alias => $column) { $tableAlias = $tableAliasPrefix . $relationIndex; $tableAndAlias = $relatedTable . '' AS '' . $tableAlias; /** * Al momento gestisce soltanto la prima relazione * todo: navigare le far relationships e creare delle join composte */ if (!isset($subQueries[$alias])) { $subQueries[$alias] = $currentQuery = DB::query() ->from($tableAndAlias) ->whereColumn( $relation->getQualifiedForeignKey() , // ''child-table.fk-column'' ''='' , $tableAlias . ''.'' . $relation->getOwnerKey() // ''parent-table.id-column'' ) ->select($tableAlias . ''.'' . $column); // se la colonna ha una chiave stringa e'' un alias /** * todo: in caso di relazioni multiple aggiungere solo per la piu lontana */ if (is_string($alias)) { $query->selectSub($currentQuery , $alias); } else { throw new /InvalidArgumentException(''Columns must be an associative array''); } } else { throw new /Exception(''Multiple relation chain not implemented yet''); } } // end foreach <COLUMNs> } // endif else if ($relation instanceof BelongsToMany) { foreach ($columns as $alias => $column) { $tableAlias = $tableAliasPrefix . $relationIndex; $tableAndAlias = $relatedTable . '' AS '' . $tableAlias; if (!isset($subQueries[$alias])) { $pivotTable = $relation->getTable(); $subQueries[$alias] = $currentQuery = DB::query() ->from($tableAndAlias) ->select($tableAlias . ''.'' . $column) // final table vs pivot table ->join( $pivotTable , // tabelle pivot $relation->getQualifiedRelatedKeyName() , // pivot.fk_related_id ''='' , $tableAlias . ''.'' . $relatedModel->getKeyName() // related_with_alias.id ) ->whereColumn( $relation->getQualifiedForeignKeyName() , ''='' , $relation->getParent()->getQualifiedKeyName() ); if (is_string($alias)) { $query->selectSub($currentQuery , $alias); } else { throw new /InvalidArgumentException(''Columns must be an associative array''); } } else { throw new /Exception(''Multiple relation chain not implemented yet''); } } // end foreach <COLUMNs> } else { throw new /InvalidArgumentException( sprintf("Relation $relationName of type %s is not supported" , get_class($relation)) ); } $currentModel = $relatedModel; $relationIndex++; } // end foreach <RELATIONs> } /** * @param $length * @return string */ public static function randomStringAlpha($length) { $pool = array_merge(range(''a'', ''z''),range(''A'', ''Z'')); $key = ''''; for($i=0; $i < $length; $i++) { $key .= $pool[mt_rand(0, count($pool) - 1)]; } return $key; } }


Prueba esto:

Student::with(array(''exam'' => function($query) { $query->orderBy(''result'', ''DESC''); })) ->get();


Si SIEMPRE quiere que se ordene según el resultado del examen, puede agregar la llamada a sortBy directamente en la función de relación en el modelo.

public function exam() { return this->hasMany(Exam::class)->orderBy(''result''); }

(El mérito de esta respuesta es amistoso: la respondió aquí: cómo ordenar una subconsulta elocuente )


Si necesita ordenar su colección de estudiantes por la columna de resultados, tendrá que unirse a las tablas.

Student::with(''exam'') ->join(''exam'', ''students.id'', ''='', ''exam.student_id'') ->orderBy(''exam.result'', ''DESC'') ->get()

En este caso, suponiendo que tiene una columna student_id y su tabla de exámenes se denominan exam .