Add whereLike and orWhereLike macros for driver-agnostic case-insensitive searches

- 🔄 Replace `ilike`/`like` conditions with `whereLike` in API controllers and search tools for consistency.
- 🚀 Enhance query usability by ensuring cross-database compatibility (PostgreSQL and SQLite).
This commit is contained in:
HolgerHatGarKeineNode
2026-06-14 01:32:03 +02:00
parent 6239842b15
commit f93190f029
14 changed files with 42 additions and 28 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ class CityController extends Controller
->when(
$request->search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$request->search}%")
->whereLike('name', "%{$request->search}%")
)
->when(
$request->exists('selected'),
@@ -28,8 +28,8 @@ class CountryController extends Controller
->when(
$request->search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$request->search}%")
->orWhere('code', 'ilike', "%{$request->search}%"),
->whereLike('name', "%{$request->search}%")
->orWhereLike('code', "%{$request->search}%"),
)
->when(
$request->exists('selected'),
@@ -50,7 +50,7 @@ class CourseController extends Controller
->when(
$request->search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$request->search}%")
->whereLike('name', "%{$request->search}%")
)
->when(
$request->exists('selected'),
+10 -13
View File
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use JoeDixon\Translation\Language;
use JoeDixon\Translation\Translation;
@@ -21,15 +22,14 @@ class LanguageController extends Controller
->orderBy('name')
->when(
$request->search,
fn(Builder $query)
=> $query
->where('name', 'ilike', "%{$request->search}%")
->orWhere('language', 'ilike', "%{$request->search}%"),
fn (Builder $query) => $query
->whereLike('name', "%{$request->search}%")
->orWhereLike('language', "%{$request->search}%"),
)
->when(
$request->exists('selected'),
fn(Builder $query) => $query->whereIn('language', $request->input('selected', [])),
fn(Builder $query) => $query->limit(10),
fn (Builder $query) => $query->whereIn('language', $request->input('selected', [])),
fn (Builder $query) => $query->limit(10),
)
->get()
->map(function ($language) {
@@ -61,7 +61,7 @@ class LanguageController extends Controller
/**
* Store a newly created resource in storage.
*
* @return \Illuminate\Http\Response
* @return Response
*/
public function store(Request $request)
{
@@ -71,8 +71,7 @@ class LanguageController extends Controller
/**
* Display the specified resource.
*
* @param $language
* @return \Illuminate\Http\Response
* @return Response
*/
public function show(Language $language)
{
@@ -82,8 +81,7 @@ class LanguageController extends Controller
/**
* Update the specified resource in storage.
*
* @param $language
* @return \Illuminate\Http\Response
* @return Response
*/
public function update(Request $request, Language $language)
{
@@ -93,8 +91,7 @@ class LanguageController extends Controller
/**
* Remove the specified resource from storage.
*
* @param $language
* @return \Illuminate\Http\Response
* @return Response
*/
public function destroy(Language $language)
{
@@ -45,7 +45,7 @@ class LecturerController extends Controller
->when(
$request->search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$request->search}%")
->whereLike('name', "%{$request->search}%")
)
->when(
$request->exists('selected'),
@@ -55,9 +55,9 @@ class MeetupController extends Controller
->when(
$request->search,
fn (Builder $query) => $query
->where('name', 'like', "%{$request->search}%")
->whereLike('name', "%{$request->search}%")
->orWhereHas('city',
fn (Builder $query) => $query->where('cities.name', 'ilike', "%{$request->search}%")),
fn (Builder $query) => $query->whereLike('cities.name', "%{$request->search}%")),
)
->when(
$request->exists('selected'),
+1 -1
View File
@@ -42,7 +42,7 @@ class VenueController extends Controller
->when(
$request->search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$request->search}%")
->whereLike('name', "%{$request->search}%")
)
->when(
$request->exists('selected'),
+2 -2
View File
@@ -26,8 +26,8 @@ class ListCountriesTool extends Tool
->when(
$search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$search}%")
->orWhere('code', 'ilike', "%{$search}%"),
->whereLike('name', "%{$search}%")
->orWhereLike('code', "%{$search}%"),
)
->limit(10)
->get()
+1 -1
View File
@@ -27,7 +27,7 @@ class SearchCitiesTool extends Tool
->when(
$search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$search}%")
->whereLike('name', "%{$search}%")
)
->limit(10)
->get();
+1 -1
View File
@@ -29,7 +29,7 @@ class SearchCoursesTool extends Tool
->when(
$search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$search}%")
->whereLike('name', "%{$search}%")
)
->limit(10)
->get()
+1 -1
View File
@@ -26,7 +26,7 @@ class SearchLecturersTool extends Tool
->when(
$search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$search}%")
->whereLike('name', "%{$search}%")
)
->limit(10)
->get()
+1 -1
View File
@@ -27,7 +27,7 @@ class SearchVenuesTool extends Tool
->when(
$search,
fn (Builder $query) => $query
->where('name', 'ilike', "%{$search}%")
->whereLike('name', "%{$search}%")
)
->limit(10)
->get()
+1 -1
View File
@@ -157,7 +157,7 @@ class LibraryItem extends Model implements Feedable, HasMedia, Sortable
->latest('id');
if ($value) {
$query->where('name', 'ilike', "%{$value}%");
$query->whereLike('name', "%{$value}%");
}
return $query->get();
+17
View File
@@ -5,6 +5,7 @@ namespace App\Providers;
use App\Support\Carbon;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\DiagnosingHealth;
use Illuminate\Http\Request;
@@ -39,6 +40,22 @@ class AppServiceProvider extends ServiceProvider
{
$this->configureRateLimiting();
// Case-insensitive Teilstring-Suche DB-portabel halten: PostgreSQL
// kennt `ilike`, SQLite (lokales Dev / Tests) nicht — dort liefert ein
// hartkodiertes `ilike` einen Syntaxfehler. Auf SQLite ist `like`
// ohnehin case-insensitiv (ASCII), sodass das Produktionsverhalten
// (PostgreSQL/ilike) unverändert bleibt. Verwendung in den API-
// Controllern: ->whereLike('name', "%{$search}%").
Builder::macro('whereLike', function (string $column, string $value, string $boolean = 'and') {
$operator = $this->getConnection()->getDriverName() === 'pgsql' ? 'ilike' : 'like';
return $this->where($column, $operator, $value, $boolean);
});
Builder::macro('orWhereLike', function (string $column, string $value) {
return $this->whereLike($column, $value, 'or');
});
Gate::define('viewApiDocs', fn (?Authenticatable $user = null): bool => true);
// OAuth-2.1-Flow des MCP-Servers (Claude.ai Web-Connector).