From 06a4b807446c705412c1cfac1917da23812c83f1 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Mon, 5 Jul 2021 17:35:38 +0200 Subject: [PATCH] Reverse aliases for column ordering with cursor pagination --- .../Database/Concerns/BuildsQueries.php | 31 ++++++++++++++++++- src/Illuminate/Pagination/Cursor.php | 2 +- tests/Database/DatabaseQueryBuilderTest.php | 2 +- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 6b91a673676a..19d3271cb484 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -4,6 +4,7 @@ use Illuminate\Container\Container; use Illuminate\Database\MultipleRecordsFoundException; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\RecordsNotFoundException; use Illuminate\Pagination\CursorPaginator; use Illuminate\Pagination\LengthAwarePaginator; @@ -305,7 +306,9 @@ protected function paginateUsingCursor($perPage, $columns = ['*'], $cursorName = $builder->where(function (self $builder) use ($addCursorConditions, $cursor, $orders, $i) { ['column' => $column, 'direction' => $direction] = $orders[$i]; - $builder->where($column, $direction === 'asc' ? '>' : '<', $cursor->parameter($column)); + $original = $this->reverseColumnAliasingForCursorPagination($this, $column); + + $builder->where($original, $direction === 'asc' ? '>' : '<', $cursor->parameter($column)); if ($i < $orders->count() - 1) { $builder->orWhere(function (self $builder) use ($addCursorConditions, $column, $i) { @@ -327,6 +330,32 @@ protected function paginateUsingCursor($perPage, $columns = ['*'], $cursorName = ]); } + /** + * Reverse any aliases columns for column ordering. + * + * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder + * @param string $parameter + * @return string + */ + protected function reverseColumnAliasingForCursorPagination($builder, string $parameter) + { + $columns = $builder instanceof Builder ? $builder->getQuery()->columns : $builder->columns; + + if (! is_null($columns)) { + foreach ($columns as $column) { + if (stripos($column, ' as ') !== false) { + [$original, $alias] = explode(' as ', $column); + + if ($parameter === $alias) { + return $original; + } + } + } + } + + return $parameter; + } + /** * Create a new length-aware paginator instance. * diff --git a/src/Illuminate/Pagination/Cursor.php b/src/Illuminate/Pagination/Cursor.php index e8edf6526bc8..89a744464113 100644 --- a/src/Illuminate/Pagination/Cursor.php +++ b/src/Illuminate/Pagination/Cursor.php @@ -12,7 +12,7 @@ class Cursor implements Arrayable * * @var array */ - protected $parameters; + public $parameters; /** * Determine whether the cursor points to the next or previous set of items. diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 6a511b9232e1..8f07c34c9ffb 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -4271,7 +4271,7 @@ protected function getMySqlBuilderWithProcessor() } /** - * @return m\MockInterface|Builder + * @return \Mockery\MockInterface|\Illuminate\Database\Query\Builder */ protected function getMockQueryBuilder() {