Reputation: 484
I used this old code, and start refactor it with use of laravel/scout
.
This code is a simply search function thet search in posts and pages too, and show result mixed paginate.
Old code:
public function search($term) {
$post = Post::where('title', 'LIKE', $term);
$page = Page::where('content', 'LIKE', $term);
$result = $page->union($post)->orderBy('created_at')->paginate();
return $result;
}
New Code not working:
public function search($term) {
$post = Post::search($term);
$page = Page::search($term);
$result = $page->union($post)->orderBy('created_at')->paginate();
return $result;
}
get error: Method Laravel\Scout\Builder::union does not exist.
What is the best syntax for this problem?
Upvotes: 4
Views: 4461
Reputation: 12835
Since Scout\Builder
doesn't support union
. And it would be non trivial to implement union
functionality for all possible search engines supported by Scout.
However, Scout\Builder
provides a query() function to customise the eloquent results query.
This provides kind of an escape hatch, where by scout can be leveraged on one model (out of the two)
public function search($term)
{
$postQuery = Post::query()
->where('some_column', 'like', $term . "%");
$results = Page::search($term)
->query(
fn($query) => $query->union($postQuery)
->orderBy('created_at', 'desc')
)
->paginate();
}
Laravel Scout - Customizing the Eloquent Results Query
If using Algolia as search engine, there's Algolia Scout Extended which supports search with multiple models.
Another approach to search multiple models with Scout and get paginated results would be:
Model::search('query')->get();
)Define a macro for Illuminate\Support\Collection
in the boot
method of a Service Provider (for eg in App\Providers\AppServiceProvider
)
<?php
namespace App\Providers;
use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\LengthAwarePaginator;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$total ? $this : $this->forPage($page, $perPage)->values(),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
});
}
}
Then in the controller
public function search($term) {
$post = Post::where('title', 'LIKE', $term)->get();
$page = Page::where('content', 'LIKE', $term)->get();
$result = $page->concat($post)->sortBy('created_at')->paginate(5);
return $result;
}
Upvotes: 3