@@ -29,11 +29,11 @@ public function addConstraints(): void
29
29
}
30
30
$ query = $ this ->getBaseQuery ();
31
31
32
- $ query -> when ( $ this ->isString , function ( $ q ) {
33
- $ q -> whereJsonContains ( $ this -> ownerKey , ( string ) $ this -> getParentKey ());
34
- }, function ( $ q ) {
35
- $ q -> whereJsonContains ( $ this ->ownerKey , $ this -> getParentKey () );
36
- });
32
+ $ parentKey = $ this ->getParentKey ();
33
+ if ( $ parentKey !== null ) {
34
+ $ searchValue = $ this -> isString ? ( string ) $ parentKey : $ parentKey ;
35
+ $ this -> addJsonContainsConstraint ( $ query , $ this ->ownerKey , $ searchValue );
36
+ }
37
37
38
38
$ query ->whereNotNull ($ this ->ownerKey );
39
39
}
@@ -44,15 +44,37 @@ public function addConstraints(): void
44
44
public function addEagerConstraints (array $ models ): void
45
45
{
46
46
$ ids = $ this ->getEagerModelKeys ($ models );
47
- $ this ->query ->where (function ($ q ) use ($ ids ) {
48
- foreach ($ ids as $ id ) {
49
- $ q ->when ($ this ->isString , function ($ q ) use ($ id ) {
50
- $ q ->orWhereJsonContains ($ this ->ownerKey , (string ) $ id );
51
- }, function ($ q ) use ($ id ) {
52
- $ q ->orWhereJsonContains ($ this ->ownerKey , $ id );
53
- });
54
- }
55
- });
47
+
48
+ if ($ this ->isString ) {
49
+ // For strings, simple OR with quoted values
50
+ $ this ->query ->where (function ($ q ) use ($ ids ) {
51
+ foreach ($ ids as $ id ) {
52
+ $ q ->orWhere ($ this ->ownerKey , 'LIKE ' , '%" ' . $ id . '"% ' );
53
+ }
54
+ });
55
+ } else {
56
+ // For integers, use pattern matching with OR logic
57
+ $ this ->query ->where (function ($ q ) use ($ ids ) {
58
+ foreach ($ ids as $ id ) {
59
+ $ q ->orWhere (function ($ subQuery ) use ($ id ) {
60
+ $ patterns = [
61
+ '%[ ' . $ id . ',% ' ,
62
+ '%, ' . $ id . ',% ' ,
63
+ '%, ' . $ id . ']% ' ,
64
+ '%[ ' . $ id . ']% '
65
+ ];
66
+
67
+ foreach ($ patterns as $ i => $ pattern ) {
68
+ if ($ i === 0 ) {
69
+ $ subQuery ->where ($ this ->ownerKey , 'LIKE ' , $ pattern );
70
+ } else {
71
+ $ subQuery ->orWhere ($ this ->ownerKey , 'LIKE ' , $ pattern );
72
+ }
73
+ }
74
+ });
75
+ }
76
+ });
77
+ }
56
78
}
57
79
58
80
/**
@@ -85,4 +107,49 @@ public function getResults(): mixed
85
107
{
86
108
return $ this ->query ->get ();
87
109
}
110
+
111
+ /**
112
+ * Add JSON contains constraint in a database-agnostic way.
113
+ * Uses pattern matching that works across all database engines and Laravel versions.
114
+ */
115
+ protected function addJsonContainsConstraint ($ query , string $ column , $ value , string $ boolean = 'and ' ): void
116
+ {
117
+ // Use pattern matching for all databases to ensure compatibility
118
+ // with prefer-lowest dependency resolution in CI environments
119
+ if ($ this ->isString ) {
120
+ // For strings, search for quoted value: "value"
121
+ $ method = $ boolean === 'or ' ? 'orWhere ' : 'where ' ;
122
+ $ query ->$ method ($ column , 'LIKE ' , '%" ' . $ value . '"% ' );
123
+ } else {
124
+ // For integers, use precise pattern matching for unquoted numbers
125
+ $ patterns = [
126
+ '%[ ' . $ value . ',% ' , // [1,
127
+ '%, ' . $ value . ',% ' , // ,1,
128
+ '%, ' . $ value . ']% ' , // ,1]
129
+ '%[ ' . $ value . ']% ' // [1]
130
+ ];
131
+
132
+ if ($ boolean === 'or ' ) {
133
+ $ query ->orWhere (function ($ subQuery ) use ($ column , $ patterns ) {
134
+ foreach ($ patterns as $ i => $ pattern ) {
135
+ if ($ i === 0 ) {
136
+ $ subQuery ->where ($ column , 'LIKE ' , $ pattern );
137
+ } else {
138
+ $ subQuery ->orWhere ($ column , 'LIKE ' , $ pattern );
139
+ }
140
+ }
141
+ });
142
+ } else {
143
+ $ query ->where (function ($ subQuery ) use ($ column , $ patterns ) {
144
+ foreach ($ patterns as $ i => $ pattern ) {
145
+ if ($ i === 0 ) {
146
+ $ subQuery ->where ($ column , 'LIKE ' , $ pattern );
147
+ } else {
148
+ $ subQuery ->orWhere ($ column , 'LIKE ' , $ pattern );
149
+ }
150
+ }
151
+ });
152
+ }
153
+ }
154
+ }
88
155
}
0 commit comments