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?
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With