Laravel Magazine
whereLike(), whereStartsWith(), and whereEndsWith(): Cleaner String Matching in Eloquent

whereLike(), whereStartsWith(), and whereEndsWith(): Cleaner String Matching in Eloquent

Eric Van Johnson ·

Every Laravel codebase has at least one of these somewhere in a search filter:

User::where('email', 'LIKE', "%{$term}%")->get();

It works, but it's easy to get wrong. Forget to escape a literal % or _ in the user's input and your search does something weird. Mix up whether the wildcard goes on one side or both and you've silently changed "starts with" into "contains." And if you've ever moved a query from MySQL to Postgres, you've probably hit the case-sensitivity difference between LIKE and ILIKE the hard way.

The query builder has cleaner names for all three common cases now, and they're worth switching to.

whereLike()

For a plain "contains" search:

User::whereLike('email', "%{$term}%")->get();

That alone doesn't look much different from the raw version, but the real value shows up with case sensitivity. Pass a third argument to control it explicitly instead of depending on which database driver happens to be running:

User::whereLike('email', "%{$term}%", caseSensitive: false)->get();

That third parameter is the whole point. It's a portable way to say "case insensitive search" that behaves the same whether you're on MySQL, Postgres, or SQLite, instead of you remembering that Postgres needs ILIKE and MySQL's collation might already be case-insensitive by default and SQLite does something else entirely.

whereStartsWith() and whereEndsWith()

These two save you from manually placing the % wildcard, and more importantly, they save you from the bug where you place it wrong.

// "Find every product SKU that starts with ART-"
Product::whereStartsWith('sku', 'ART-')->get();

// "Find every uploaded file that ends in .pdf"
Upload::whereEndsWith('filename', '.pdf')->get();

Compare that to the raw version most of us would write by hand:

Product::where('sku', 'LIKE', 'ART-%')->get();
Upload::where('filename', 'LIKE', '%.pdf')->get();

Functionally identical, but the named methods are self-documenting. Six months from now, whoever reads whereStartsWith('sku', 'ART-') doesn't need to mentally parse which side the wildcard is on to understand the intent.

They compose with orWhere and negation like anything else

Because these are just methods on the same query builder, they chain and negate exactly the way you'd expect:

Order::query()
    ->whereStartsWith('reference', 'PHPARCH-')
    ->orWhereStartsWith('reference', 'LEGACY-')
    ->get();

// negated
Order::whereNotLike('notes', "%cancelled%")->get();

That whereNotLike() counterpart exists too, along with orWhereLike(), orWhereStartsWith(), and orWhereEndsWith(), so you're not stuck combining where() and orWhere() manually once you need the inverse or an "or" branch.

A word of caution on indexes

None of this changes the underlying SQL performance characteristics. A leading wildcard, whereLike('email', "%{$term}%") or whereEndsWith(...), still can't use a standard B-tree index efficiently on most databases, because the database can't know where a match might start. whereStartsWith() is the one that can still benefit from an index, since a LIKE 'ART-%' pattern lets the database do a range scan.

If you're building search over a large table, this is your reminder that "search box that filters everything" eventually needs a real search index (MySQL full-text, Postgres tsvector, or a dedicated engine like Meilisearch via Laravel Scout) rather than a LIKE query with a bigger % on the front. But for admin filters, small tables, and anything under a few hundred thousand rows, these three methods make your intent obvious and keep your query builder code portable across database engines, which is a solid trade for a one-word method rename.

Stay Updated

Subscribe to our newsletter

Get latest news, tutorials, community articles and podcast episodes delivered to your inbox.

Weekly articles
We send a new issue of the newsletter every week on Friday.
No spam
We'll never share your email address and you can opt out at any time.