Skip to content

Commit 73a1a98

Browse files
List un hydrated (#22)
* Add list un hydrated feature * Add list un hydrated feature * Add list un hydrated feature * Add list un hydrated feature * Add list un hydrated feature * Add list un hydrated feature avoid L 10 builder:paginate bug --------- Co-authored-by: Admin <>
1 parent e19c2dd commit 73a1a98

File tree

4 files changed

+122
-5
lines changed

4 files changed

+122
-5
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ OBS
293293

294294
Set `$returnNullOnInvalidColumnAttributeAccess = false;` in model if you want exception instead of null on accessing invalid model attributes or invalid relations (It also needs error_reporting = E_ALL in php ini file).
295295

296+
Set `LIST_UN_HYDRATED_WHEN_POSSIBLE = true` in model if you want to skip eloquent hydration for list db query results; note that setting this to true will not append the primary_key_identifier on response.
297+
296298
Set LIVE_MODE=false in your .env file for non prod environments.
297299

298300
Use Request::getFiltered macro to sanitize data retrieved from request

src/Eloquent/CustomRelations/Builders/CleverEloquentBuilder.php

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@
22

33
namespace MacropaySolutions\LaravelCrudWizard\Eloquent\CustomRelations\Builders;
44

5+
use Illuminate\Contracts\Pagination\CursorPaginator;
6+
use Illuminate\Contracts\Pagination\Paginator;
57
use Illuminate\Database\Eloquent\Builder;
68
use Illuminate\Database\Eloquent\Model;
79
use Illuminate\Database\Eloquent\RelationNotFoundException;
810
use Illuminate\Database\Eloquent\Relations\BelongsTo;
911
use Illuminate\Database\Eloquent\Relations\MorphTo;
1012
use Illuminate\Database\Eloquent\Relations\Relation;
13+
use Illuminate\Pagination\Cursor;
14+
use Illuminate\Pagination\LengthAwarePaginator;
15+
use Illuminate\Support\Collection;
1116
use MacropaySolutions\LaravelCrudWizard\Models\BaseModel;
1217

1318
/**
1419
* @method Model createHydrated(array $attributes = [])
1520
*/
1621
class CleverEloquentBuilder extends Builder
1722
{
23+
protected bool $getUnHydrated = false;
24+
1825
/**
1926
* @inheritDoc
2027
*/
@@ -41,6 +48,73 @@ public function getRelation($name): Relation
4148
return $relation;
4249
}
4350

51+
/**
52+
* @throws \Throwable
53+
*/
54+
public function getUnHydrated(array|string $columns = ['*']): Collection
55+
{
56+
return $this->toBase()->get($columns);
57+
}
58+
59+
/**
60+
* @throws \Throwable
61+
*/
62+
public function paginateUnHydrated(
63+
int|null|\Closure $perPage = null,
64+
array|string $columns = ['*'],
65+
string $pageName = 'page',
66+
int|null $page = null,
67+
int|null|\Closure $total = null,
68+
): LengthAwarePaginator {
69+
$this->getUnHydrated = true;
70+
$result = $total !== null ?
71+
$this->paginate($perPage, $columns, $pageName, $page, $total) :
72+
$this->paginate($perPage, $columns, $pageName, $page);
73+
$this->getUnHydrated = false;
74+
75+
return $result;
76+
}
77+
78+
/**
79+
* @throws \Throwable
80+
*/
81+
public function simplePaginateUnHydrated(
82+
int|null $perPage = null,
83+
array $columns = ['*'],
84+
string $pageName = 'page',
85+
int|null $page = null
86+
): Paginator {
87+
$this->getUnHydrated = true;
88+
$result = $this->simplePaginate($perPage, $columns, $pageName, $page);
89+
$this->getUnHydrated = false;
90+
91+
return $result;
92+
}
93+
94+
/**
95+
* @throws \Throwable
96+
*/
97+
public function cursorPaginateUnHydrated(
98+
int|null $perPage = null,
99+
array|string $columns = ['*'],
100+
string $cursorName = 'cursor',
101+
Cursor|string|null $cursor = null
102+
): CursorPaginator {
103+
$this->getUnHydrated = true;
104+
$result = $this->cursorPaginate($perPage, $columns, $cursorName, $cursor);
105+
$this->getUnHydrated = false;
106+
107+
return $result;
108+
}
109+
110+
/**
111+
* @inheritdoc
112+
*/
113+
public function get($columns = ['*']): \Illuminate\Database\Eloquent\Collection|array|Collection
114+
{
115+
return $this->getUnHydrated ? $this->getUnHydrated($columns) : parent::get($columns);
116+
}
117+
44118
/**
45119
* @inheritDoc
46120
*/
@@ -100,4 +174,4 @@ public function with($relations, $callback = null): static
100174

101175
return $this;
102176
}
103-
}
177+
}

src/Http/Controllers/ResourceControllerTrait.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,28 @@ protected function getPaginator(
435435
): LengthAwarePaginator | Paginator | CursorPaginator {
436436
$model = $builder instanceof Relation ? $builder->getRelated() : $builder->getModel();
437437
$limit = \max(1, (int)($allRequest['limit'] ?? $model->getPerPage()));
438+
$listUnHydrated = false;
439+
440+
if ($model::LIST_UN_HYDRATED_WHEN_POSSIBLE) {
441+
/** @var BaseModel $first */
442+
$first = $model->exists ? $model : ($model::query()->first() ?? $model);
443+
$listUnHydrated = $builder->getEagerLoads() === []
444+
&& \array_diff_key(
445+
$first->attributesToArray(),
446+
['primary_key_identifier' => null]
447+
) === $first->getRawOriginal();
448+
}
438449

439450
if (isset($allRequest['cursor'])) {
451+
if ($listUnHydrated) {
452+
return $builder->cursorPaginateUnHydrated(
453+
$limit,
454+
['*'],
455+
'cursor',
456+
$allRequest['cursor']
457+
);
458+
}
459+
440460
return $builder->cursorPaginate(
441461
$limit,
442462
['*'],
@@ -445,6 +465,24 @@ protected function getPaginator(
445465
);
446466
}
447467

468+
if ($listUnHydrated) {
469+
if ($this->simplePaginate) {
470+
return $builder->simplePaginateUnHydrated(
471+
$limit,
472+
['*'],
473+
'page',
474+
\max((int)($allRequest['page'] ?? 1), 1)
475+
);
476+
}
477+
478+
return $builder->paginateUnHydrated(
479+
$limit,
480+
['*'],
481+
'page',
482+
\max((int)($allRequest['page'] ?? 1), 1)
483+
);
484+
}
485+
448486
return $builder->{$this->simplePaginate ? 'simplePaginate' : 'paginate'}(
449487
$limit,
450488
['*'],

src/Models/BaseModel.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ abstract class BaseModel extends Model
2828
public const CREATED_AT_FORMAT = 'Y-m-d H:i:s';
2929
public const UPDATED_AT_FORMAT = 'Y-m-d H:i:s';
3030
public const COMPOSITE_PK_SEPARATOR = '_';
31+
/**
32+
* Setting this to true will not append the primary_key_identifier on response
33+
*/
34+
public const LIST_UN_HYDRATED_WHEN_POSSIBLE = false;
3135
public $timestamps = false;
3236
public static $snakeAttributes = false;
3337
public BaseModelAttributes $a;
@@ -110,8 +114,7 @@ public function getIndexRequiredOnFilteringAttribute(): array
110114
*/
111115
public function getPrimaryKeyIdentifierAttribute(): string
112116
{
113-
return \implode(
114-
$this::COMPOSITE_PK_SEPARATOR, \array_map(
117+
return \implode($this::COMPOSITE_PK_SEPARATOR, \array_map(
115118
fn (mixed $value): string => (string)(\is_array($value) ? \last($value) : $value),
116119
$this->getPrimaryKeyFilter()
117120
));
@@ -242,7 +245,7 @@ function () use ($driver): array {
242245
Carbon::now()->addDay(),
243246
$callback
244247
));
245-
} catch (\Throwable $e) {
248+
} catch (\Throwable) {
246249
return \collect($callback());
247250
}
248251
}
@@ -364,7 +367,7 @@ public function getAttributeValue($key): mixed
364367
if (!$this->hasGetMutator($key) && !$this->hasAttributeGetMutator($key)) {
365368
try {
366369
return $this->attributes[$key];
367-
} catch (\Throwable $e) {
370+
} catch (\Throwable) {
368371
throw new \Exception('Undefined attribute: ' . $key . ' in model: ' . static::class);
369372
}
370373
}

0 commit comments

Comments
 (0)