From d2f75c5c87fa3f9079ad5878cdbde3cdb2b0e4e9 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Fri, 13 Nov 2026 15:33:48 +0000 Subject: [PATCH 1/2] Work the pattern for a like where out once, not for every item --- src/Query/Builder.php | 6 ++++- tests/Data/Entries/EntryQueryBuilderTest.php | 24 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Query/Builder.php b/src/Query/Builder.php index 77c7302016a..3de28660066 100644 --- a/src/Query/Builder.php +++ b/src/Query/Builder.php @@ -28,6 +28,7 @@ abstract class Builder implements Contract protected $offset = 0; protected $wheres = []; protected $with = []; + private $likePatterns = []; protected $orderBys = []; protected $operators = [ '=' => 'Equals', @@ -816,7 +817,10 @@ protected function filterTestLike($item, $like) $item = json_encode($item); } - $pattern = Pattern::sqlLikeToRegex($like); + // What's being looked for is the same for every item, so its pattern is only worked out for the first. + $pattern = is_string($like) + ? $this->likePatterns[$like] ??= Pattern::sqlLikeToRegex($like) + : Pattern::sqlLikeToRegex($like); return preg_match('/'.$pattern.'/imu', (string) $item); } diff --git a/tests/Data/Entries/EntryQueryBuilderTest.php b/tests/Data/Entries/EntryQueryBuilderTest.php index a31ec9b505d..72d4dad7dac 100644 --- a/tests/Data/Entries/EntryQueryBuilderTest.php +++ b/tests/Data/Entries/EntryQueryBuilderTest.php @@ -1700,6 +1700,30 @@ public function sorting_by_unsafe_method_does_not_invoke_it() $this->assertCount($count, Entry::all()); } + + #[Test] + public function the_pattern_for_a_like_is_worked_out_once_for_all_the_entries_it_is_tested_against() + { + $this->createDummyCollectionAndEntries(); + + \Statamic\Facades\Pattern::partialMock()->shouldReceive('sqlLikeToRegex')->with('%post 1%')->once()->passthru(); + + $this->assertEquals(['Post 1'], Entry::query()->where('title', 'like', '%post 1%')->get()->map->title->all()); + } + + #[Test] + public function each_like_in_a_query_looks_for_its_own_thing() + { + $this->createDummyCollectionAndEntries(); + + $entries = Entry::query() + ->where('title', 'like', 'post%') + ->where('title', 'not like', '%2') + ->where(fn ($query) => $query->where('title', 'like', '%1')->orWhere('title', 'like', '%3')) + ->get(); + + $this->assertEquals(['Post 1', 'Post 3'], $entries->map->title->all()); + } } class CustomScope extends Scope From 20278ac459c0964e682dc15f8bb846219e054f43 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Fri, 13 Nov 2026 17:06:39 +0000 Subject: [PATCH 2/2] Make the like patterns property protected like its neighbours --- src/Query/Builder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Query/Builder.php b/src/Query/Builder.php index 3de28660066..2f0b32e8fd3 100644 --- a/src/Query/Builder.php +++ b/src/Query/Builder.php @@ -28,7 +28,6 @@ abstract class Builder implements Contract protected $offset = 0; protected $wheres = []; protected $with = []; - private $likePatterns = []; protected $orderBys = []; protected $operators = [ '=' => 'Equals', @@ -43,6 +42,7 @@ abstract class Builder implements Contract '>=' => 'GreaterThanOrEqualTo', '<=' => 'LessThanOrEqualTo', ]; + protected $likePatterns = []; public function __call($method, $args) {