Last active
September 15, 2020 01:48
-
-
Save crynobone/474d2b167ccdbf37d863a2f0e0dbae00 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | |
use Illuminate\Database\Query\Builder as QueryBuilder; | |
use Illuminate\Database\Query\JoinClause; | |
use Illuminate\Queue\SerializableClosure; | |
use Illuminate\Support\Arr; | |
use Illuminate\Support\Facades\DB; | |
trait SerializesQuery | |
{ | |
/** | |
* Serialize from Eloquent Query Builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder|array $eloquentBuilder | |
* @return array | |
*/ | |
public function serializeEloquentBuilder($eloquentBuilder): array | |
{ | |
if (is_array($eloquentBuilder)) { | |
return $eloquentBuilder; | |
} | |
return [ | |
'model' => [ | |
'class' => get_class($eloquentBuilder->getModel()), | |
'eager' => collect($eloquentBuilder->getEagerLoads())->map(function ($callback) { | |
return serialize(new SerializableClosure($callback)); | |
})->all(), | |
], | |
'builder' => $this->serializeQueryBuilder($eloquentBuilder->getQuery()), | |
]; | |
} | |
/** | |
* Unserialize to Eloquent Query Builder. | |
* | |
* @param array|\Illuminate\Database\Eloquent\Builder $payload | |
* @return \Illuminate\Database\Eloquent\Builder | |
*/ | |
public function unserializeEloquentBuilder($payload): EloquentBuilder | |
{ | |
if ($payload instanceof EloquentBuilder) { | |
return $payload; | |
} | |
return (new EloquentBuilder($this->unserializeQueryBuilder($payload['builder']))) | |
->setModel(new $payload['model']['class']()) | |
->setEagerLoads( | |
collect($payload['model']['eager'])->map(function ($callback) { | |
return unserialize($callback); | |
})->all() | |
); | |
} | |
/** | |
* Serialize to basic Query Builder. | |
* | |
* @param \Illuminate\Database\Query\Builder $queryBuilder | |
* @return array | |
*/ | |
public function serializeQueryBuilder(QueryBuilder $queryBuilder): array | |
{ | |
return array_filter([ | |
'columns' => $queryBuilder->columns, | |
'wheres' => collect($queryBuilder->wheres)->map(function ($where) { | |
if (isset($where['query'])) { | |
$where['query'] = $this->serializeQueryBuilder($where['query']); | |
} | |
return $where; | |
})->all(), | |
'bindings' => $queryBuilder->bindings, | |
'distinct' => $queryBuilder->distinct, | |
'from' => $queryBuilder->from, | |
'joins' => collect($queryBuilder->joins)->map(function ($join) { | |
return $this->serializeJoinClause($join); | |
})->all(), | |
'groups' => $queryBuilder->groups, | |
'orders' => $queryBuilder->orders, | |
]); | |
} | |
/** | |
* Unserialize to basic Query Builder. | |
* | |
* @param iterable $builder | |
* @return \Illuminate\Database\Query\Builder | |
*/ | |
public function unserializeQueryBuilder(array $builder): QueryBuilder | |
{ | |
$queryBuilder = DB::query(); | |
collect($builder)->transform(function ($value, $type) { | |
if ($type === 'wheres') { | |
foreach ($value as $index => $where) { | |
if (isset($where['query']) && is_array($where['query'])) { | |
$value[$index]['query'] = $this->unserializeQueryBuilder($where['query']); | |
} | |
} | |
} | |
if ($type === 'joins') { | |
$value = $this->unserializeJoinClause($value); | |
} | |
return $value; | |
})->each(function ($value, $type) use ($queryBuilder) { | |
$queryBuilder->{$type} = $value; | |
}); | |
return $queryBuilder; | |
} | |
/** | |
* Serialize to Join Clause Query Builder. | |
* | |
* @param \Illuminate\Database\Query\Builder $queryBuilder | |
* @return array | |
*/ | |
public function serializeJoinClause(JoinClause $queryBuilder): array | |
{ | |
return array_merge($this->serializeQueryBuilder($queryBuilder), [ | |
'type' => $queryBuilder->type, | |
'table' => $queryBuilder->table, | |
]); | |
} | |
/** | |
* Unserialize to Join Clause Query Builder. | |
* | |
* @param iterable $joins | |
* @return iterable | |
*/ | |
public function unserializeJoinClause(array $joins): array | |
{ | |
$results = []; | |
foreach ($joins as $join) { | |
$type = $join['type']; | |
$table = $join['table']; | |
$result[] = new JoinClause( | |
$this->unserializeQueryBuilder(Arr::except($join, ['type', 'table'])), $type, $table | |
); | |
} | |
return $results; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment