Skip to content

Commit 0e0a122

Browse files
authored
Add simplePaginate() and migrate to protected properties and methods (#11)
1 parent 033d4e7 commit 0e0a122

File tree

7 files changed

+125
-26
lines changed

7 files changed

+125
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ vendor
55
coverage
66
.phpunit.result.cache
77
.phpunit.result.cache
8+
.idea

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All notable changes to `laravel-cross-eloquent-search` will be documented in this file
44

5+
## 1.8.0 - 2020-12-23
6+
7+
- Support for simple pagination (credit to @mewejo).
8+
59
## 1.7.0 - 2020-12-16
610

711
- Added a `count` method.

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ Search::add(Post::class, 'title')
119119
->get('build');
120120
```
121121

122+
You may also use [simple pagination](https://laravel.com/docs/master/pagination#simple-pagination). This will return an instance of `\Illuminate\Contracts\Pagination\Paginator`, which is not length aware:
123+
124+
```php
125+
Search::add(Post::class, 'title')
126+
->add(Video::class, 'title')
127+
128+
->simplePaginate()
129+
// or
130+
->simplePaginate($perPage = 15, $pageName = 'page', $page = 1)
131+
132+
->get('build');
133+
```
134+
122135
### Constraints and scoped queries
123136

124137
Instead of the class name, you can also pass an instance of the [Eloquent query builder](https://laravel.com/docs/master/eloquent#retrieving-models) to the `add` method. This allows you to add constraints to each model.

src/ModelToSearchThrough.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ class ModelToSearchThrough
1212
/**
1313
* Builder to search through.
1414
*/
15-
private Builder $builder;
15+
protected Builder $builder;
1616

1717
/**
1818
* The columns to search through.
1919
*/
20-
private Collection $columns;
20+
protected Collection $columns;
2121

2222
/**
2323
* Order column.
2424
*/
25-
private string $orderByColumn;
25+
protected string $orderByColumn;
2626

2727
/**
2828
* Unique key of this instance.
2929
*/
30-
private int $key;
30+
protected int $key;
3131

3232
/**
3333
* @param \Illuminate\Database\Eloquent\Builder $builder
@@ -82,7 +82,7 @@ public function getQualifiedColumns(): Collection
8282
*
8383
* @return \Illuminate\Database\Eloquent\Model
8484
*/
85-
private function getModel(): Model
85+
protected function getModel(): Model
8686
{
8787
return $this->builder->getModel();
8888
}
@@ -108,7 +108,7 @@ public function getModelKey($suffix = 'key'): string
108108
* @param string $column
109109
* @return string
110110
*/
111-
private function qualifyColumn(string $column): string
111+
protected function qualifyColumn(string $column): string
112112
{
113113
return $this->getModel()->qualifyColumn($column);
114114
}

src/Search.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* @method static \ProtoneMedia\LaravelCrossEloquentSearch\Searcher startWithWildcard()
1313
* @method static \ProtoneMedia\LaravelCrossEloquentSearch\Searcher add($query, $columns, string $orderByColumn = 'updated_at')
1414
* @method static \ProtoneMedia\LaravelCrossEloquentSearch\Searcher paginate($perPage = 15, $pageName = 'page', $page = null)
15+
* @method static \ProtoneMedia\LaravelCrossEloquentSearch\Searcher simplePaginate($perPage = 15, $pageName = 'page', $page = null)
1516
* @method static \Illuminate\Support\Collection parseTerms(string $terms, callable $callback = null)
1617
* @method static \Illuminate\Database\Eloquent\Collection|\Illuminate\Contracts\Pagination\LengthAwarePaginator get(string $terms = null)
1718
*

src/Searcher.php

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,49 +15,54 @@ class Searcher
1515
/**
1616
* Collection of models to search through.
1717
*/
18-
private Collection $modelsToSearchThrough;
18+
protected Collection $modelsToSearchThrough;
1919

2020
/**
2121
* Sort direction.
2222
*/
23-
private string $orderByDirection;
23+
protected string $orderByDirection;
2424

2525
/**
2626
* Start the search term with a wildcard.
2727
*/
28-
private bool $startWithWildcard = false;
28+
protected bool $startWithWildcard = false;
2929

3030
/**
3131
* Allow an empty search query.
3232
*/
33-
private bool $allowEmptySearchQuery = false;
33+
protected bool $allowEmptySearchQuery = false;
3434

3535
/**
3636
* Collection of search terms.
3737
*/
38-
private Collection $terms;
38+
protected Collection $terms;
3939

4040
/**
4141
* The number of items to be shown per page.
4242
*/
43-
private int $perPage = 15;
43+
protected int $perPage = 15;
4444

4545
/**
4646
* The query string variable used to store the page.
4747
*/
48-
private string $pageName = 'page';
48+
protected string $pageName = 'page';
4949

5050
/**
5151
* Parse the search term into multiple terms.
5252
*/
53-
private bool $parseTerm = true;
53+
protected bool $parseTerm = true;
54+
55+
/**
56+
* Use simplePaginate() on Eloquent\Builder vs paginate()
57+
*/
58+
protected bool $simplePaginate = false;
5459

5560
/**
5661
* Current page.
5762
*
5863
* @var int|null
5964
*/
60-
private $page;
65+
protected $page;
6166

6267
/**
6368
* Initialises the instanace with a fresh Collection and default sort.
@@ -170,9 +175,27 @@ public function startWithWildcard(): self
170175
*/
171176
public function paginate($perPage = 15, $pageName = 'page', $page = null): self
172177
{
173-
$this->page = $page ?: Paginator::resolveCurrentPage($pageName);
174-
$this->pageName = $pageName;
175-
$this->perPage = $perPage;
178+
$this->page = $page ?: Paginator::resolveCurrentPage($pageName);
179+
$this->pageName = $pageName;
180+
$this->perPage = $perPage;
181+
$this->simplePaginate = false;
182+
183+
return $this;
184+
}
185+
186+
/**
187+
* Paginate using simple pagination.
188+
*
189+
* @param integer $perPage
190+
* @param string $pageName
191+
* @param int|null $page
192+
* @return self
193+
*/
194+
public function simplePaginate($perPage = 15, $pageName = 'page', $page = null): self
195+
{
196+
$this->paginate($perPage, $pageName, $page);
197+
198+
$this->simplePaginate = true;
176199

177200
return $this;
178201
}
@@ -201,7 +224,7 @@ public function parseTerms(string $terms, callable $callback = null): Collection
201224
* @throws \ProtoneMedia\LaravelCrossEloquentSearch\EmptySearchQueryException
202225
* @return self
203226
*/
204-
private function initializeTerms(string $terms): self
227+
protected function initializeTerms(string $terms): self
205228
{
206229
$terms = $this->parseTerm ? $this->parseTerms($terms) : $terms;
207230

@@ -241,7 +264,7 @@ public function addSearchQueryToBuilder(Builder $builder, ModelToSearchThrough $
241264
* @param \ProtoneMedia\LaravelCrossEloquentSearch\ModelToSearchThrough $currentModel
242265
* @return array
243266
*/
244-
private function makeSelects(ModelToSearchThrough $currentModel): array
267+
protected function makeSelects(ModelToSearchThrough $currentModel): array
245268
{
246269
return $this->modelsToSearchThrough->flatMap(function (ModelToSearchThrough $modelToSearchThrough) use ($currentModel) {
247270
$qualifiedKeyName = $qualifiedOrderByColumnName = 'null';
@@ -264,7 +287,7 @@ private function makeSelects(ModelToSearchThrough $currentModel): array
264287
*
265288
* @return string
266289
*/
267-
private function makeOrderBy(): string
290+
protected function makeOrderBy(): string
268291
{
269292
$modelOrderKeys = $this->modelsToSearchThrough->map->getModelKey('order')->implode(',');
270293

@@ -276,7 +299,7 @@ private function makeOrderBy(): string
276299
*
277300
* @return \Illuminate\Support\Collection
278301
*/
279-
private function buildQueries(): Collection
302+
protected function buildQueries(): Collection
280303
{
281304
return $this->modelsToSearchThrough->map(function (ModelToSearchThrough $modelToSearchThrough) {
282305
return $modelToSearchThrough->getFreshBuilder()
@@ -293,7 +316,7 @@ private function buildQueries(): Collection
293316
*
294317
* @return
295318
*/
296-
private function getCompiledQueryBuilder(): QueryBuilder
319+
protected function getCompiledQueryBuilder(): QueryBuilder
297320
{
298321
$queries = $this->buildQueries();
299322

@@ -312,13 +335,16 @@ private function getCompiledQueryBuilder(): QueryBuilder
312335
*
313336
* @return \Illuminate\Support\Collection|\Illuminate\Contracts\Pagination\LengthAwarePaginator
314337
*/
315-
private function getIdAndOrderAttributes()
338+
protected function getIdAndOrderAttributes()
316339
{
317340
$query = $this->getCompiledQueryBuilder();
318341

342+
// Determine the pagination method to call on Eloquent\Builder
343+
$paginateMethod = $this->simplePaginate ? 'simplePaginate' : 'paginate';
344+
319345
// get all results or limit the results by pagination
320346
return $this->perPage
321-
? $query->paginate($this->perPage, ['*'], $this->pageName, $this->page)
347+
? $query->{$paginateMethod}($this->perPage, ['*'], $this->pageName, $this->page)
322348
: $query->get();
323349

324350
// the collection will be something like:
@@ -345,7 +371,7 @@ private function getIdAndOrderAttributes()
345371
* @param \Illuminate\Support\Collection|\Illuminate\Contracts\Pagination\LengthAwarePaginator $results
346372
* @return \Illuminate\Support\Collection
347373
*/
348-
private function getModelsPerType($results)
374+
protected function getModelsPerType($results)
349375
{
350376
return $this->modelsToSearchThrough
351377
->keyBy->getModelKey()

tests/SearchTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace ProtoneMedia\LaravelCrossEloquentSearch\Tests;
44

55
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
6+
use Illuminate\Pagination\Paginator;
67
use Illuminate\Support\Carbon;
78
use ProtoneMedia\LaravelCrossEloquentSearch\EmptySearchQueryException;
89
use ProtoneMedia\LaravelCrossEloquentSearch\Search;
@@ -258,4 +259,57 @@ public function it_can_eager_load_relations()
258259
$this->assertEquals(10, $results->first()->comments_count);
259260
$this->assertTrue($results->first()->relationLoaded('comments'));
260261
}
262+
263+
/** @test */
264+
public function it_uses_length_aware_paginator_by_default()
265+
{
266+
$search = Search::add(Post::class, 'title', 'published_at')
267+
->add(Video::class, 'title', 'published_at')
268+
->orderByDesc();
269+
270+
$results = $search->paginate()->get('foo');
271+
272+
$this->assertInstanceOf(LengthAwarePaginator::class, $results);
273+
}
274+
275+
/** @test */
276+
public function it_can_use_simple_paginator()
277+
{
278+
$search = Search::new()
279+
->add(Post::class, 'title', 'published_at')
280+
->add(Video::class, 'title', 'published_at')
281+
->orderByDesc();
282+
283+
$results = $search->simplePaginate()->get('foo');
284+
285+
$this->assertInstanceOf(Paginator::class, $results);
286+
}
287+
288+
/** @test */
289+
public function it_can_simple_paginate_the_results()
290+
{
291+
$postA = Post::create(['title' => 'foo', 'published_at' => now()->addDays(1)]);
292+
$postB = Post::create(['title' => 'foo', 'published_at' => now()->addDays(2)]);
293+
$videoA = Video::create(['title' => 'foo', 'published_at' => now()]);
294+
$videoB = Video::create(['title' => 'foo', 'published_at' => now()->addDays(3)]);
295+
296+
$search = Search::new()
297+
->add(Post::class, 'title', 'published_at')
298+
->add(Video::class, 'title', 'published_at')
299+
->orderByDesc();
300+
301+
$resultsPage1 = $search->simplePaginate(2, 'page', 1)->get('foo');
302+
$resultsPage2 = $search->simplePaginate(2, 'page', 2)->get('foo');
303+
304+
$this->assertInstanceOf(Paginator::class, $resultsPage1);
305+
$this->assertInstanceOf(Paginator::class, $resultsPage2);
306+
307+
$this->assertCount(2, $resultsPage1);
308+
309+
$this->assertTrue($resultsPage1->first()->is($videoB));
310+
$this->assertTrue($resultsPage1->last()->is($postB));
311+
312+
$this->assertTrue($resultsPage2->first()->is($postA));
313+
$this->assertTrue($resultsPage2->last()->is($videoA));
314+
}
261315
}

0 commit comments

Comments
 (0)