Closed maximesahagian closed 3 years ago
This extension basically applies this Laravel query:
Given a search term is foobar
when searching for user posts by a title.
User::whereHas('posts', function ($query) {
return $query->where('title', 'foobar');
});
so if your User
and Post
models are from different databases and this type of query does not work I can't help much.
Here is my approach to implement multi-connection searching using nova-search-relations.
<?php
declare(strict_types=1);
namespace App\Nova\Search;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Titasgailius\SearchRelations\Contracts\Search;
use Titasgailius\SearchRelations\Searches\ColumnSearch;
class ExternalRelationSearch implements Search
{
public function __construct(
private array $columns,
) {
}
public function apply(Builder $query, string $relation, string $search): Builder
{
/** @var Relation $relationObj */
$relationObj = $query->getModel()->{$relation}();
$relatedModel = $relationObj->getRelated();
list($externalModelKey, $localModelKey) = $this->getRelationKeys($relationObj);
/**
* Load all keys of external model, matching the search criteria
*/
$keys = (new ColumnSearch($this->columns))
->apply(
$relatedModel->select($externalModelKey),
$relation,
$search
)
->get()
->pluck($externalModelKey);
/**
* Set loaded keys as whereIn statement in the search query
*/
return empty($keys) ? $query : $query->orWhereIn($localModelKey, $keys);
}
protected function getRelationKeys(Relation $relation): array
{
// Complete with other relation types if needed
if ($relation instanceof BelongsTo) {
return [$relation->getOwnerKeyName(), $relation->getForeignKeyName()];
}
throw new \InvalidArgumentException(sprintf(
'Relation type %s is not supported in %s:%s. Maybe you need to implement it yourself',
get_class($relation),
get_class($this),
__METHOD__,
));
}
}
In resource file:
public static function searchableRelations(): array
{
return [
'user' => new ExternalRelationSearch(['email']),
];
}
Be careful with this method, because you load all related models matching the search criteria, which can lead to a high memory usage.
Also make sure you set up the connection in the related model class.
@TitasGailius check this out. Maybe it deserves to be contributed :p
@yuoppp thank you! I'm in the exact same boat and your solutions works perfectly
Hello,
This package sounds perfect, but impossible to filter with a different database connection.. (my belongs to model/resource is connected to another database than the resource).
When I search for a belongs to name, an error appears because the package tries to select the model in the same database, but the $connection is well set in the other model..
Is there a way to solve it?
Best.