@@ -272,18 +272,97 @@ protected function getEagerLoads()
272
272
protected function compileRelationSearch ($ query , $ relation , $ column , $ keyword )
273
273
{
274
274
$ myQuery = clone $ this ->query ;
275
- $ relationType = $ myQuery ->getModel ()->{$ relation }();
276
- $ myQuery ->orWhereHas ($ relation , function ($ builder ) use ($ column , $ keyword , $ query , $ relationType ) {
277
- $ builder ->select ($ this ->connection ->raw ('count(1) ' ));
278
- $ this ->compileQuerySearch ($ builder , $ column , $ keyword , '' );
275
+
276
+ /**
277
+ * For compile nested relation, we need store all nested relation as array
278
+ * and reverse order to apply where query.
279
+ *
280
+ * With this method we can create nested sub query with properly relation.
281
+ */
282
+
283
+ /**
284
+ * Store all relation data that require in next step
285
+ */
286
+ $ relationChunk = [];
287
+
288
+ /**
289
+ * Store last eloquent query builder for get next relation.
290
+ */
291
+ $ lastQuery = $ query ;
292
+
293
+ $ relations = explode ('. ' , $ relation );
294
+ $ lastRelation = end ($ relations );
295
+ foreach ($ relations as $ relation ) {
296
+ $ relationType = $ myQuery ->getModel ()->{$ relation }();
297
+ $ myQuery ->orWhereHas ($ relation , function ($ builder ) use (
298
+ $ column ,
299
+ $ keyword ,
300
+ $ query ,
301
+ $ relationType ,
302
+ $ relation ,
303
+ $ lastRelation ,
304
+ &$ relationChunk ,
305
+ &$ lastQuery
306
+ ) {
307
+ $ builder ->select ($ this ->connection ->raw ('count(1) ' ));
308
+
309
+ // We will perform search on last relation only.
310
+ if ($ relation == $ lastRelation ) {
311
+ $ this ->compileQuerySearch ($ builder , $ column , $ keyword , '' );
312
+ }
313
+
314
+ // Put require object to next step!!
315
+ $ relationChunk [$ relation ] = [
316
+ 'builder ' => $ builder ,
317
+ 'relationType ' => $ relationType ,
318
+ 'query ' => $ lastQuery
319
+ ];
320
+
321
+ // This is trick make sub query.
322
+ $ lastQuery = $ builder ;
323
+ });
324
+
325
+ // This is trick to make nested relation by pass previous relation to be next query eloquent builder
326
+ $ myQuery = $ relationType ;
327
+ }
328
+
329
+ /**
330
+ * Reverse them all
331
+ */
332
+ $ relationChunk = array_reverse ($ relationChunk , true );
333
+
334
+ /**
335
+ * Create valuable for use in check last relation
336
+ */
337
+ end ($ relationChunk );
338
+ $ lastRelation = key ($ relationChunk );
339
+ reset ($ relationChunk );
340
+
341
+ /**
342
+ * Walking ...
343
+ */
344
+ foreach ($ relationChunk as $ relation => $ chunk ) {
345
+ // Prepare variables
346
+ $ builder = $ chunk ['builder ' ];
347
+ $ relationType = $ chunk ['relationType ' ];
348
+ $ query = $ chunk ['query ' ];
279
349
$ builder = "( {$ builder ->toSql ()}) >= 1 " ;
280
350
351
+ // Check if it last relation we will use orWhereRaw
352
+ if ($ lastRelation == $ relation ) {
353
+ $ relationMethod = "orWhereRaw " ;
354
+ } else {
355
+ // For case parent relation of nested relation.
356
+ // We must use and for properly query and get correct result
357
+ $ relationMethod = "whereRaw " ;
358
+ }
359
+
281
360
if ($ relationType instanceof MorphToMany) {
282
- $ query ->orWhereRaw ($ builder , [$ relationType ->getMorphClass (), $ this ->prepareKeyword ($ keyword )]);
361
+ $ query ->{ $ relationMethod } ($ builder , [$ relationType ->getMorphClass (), $ this ->prepareKeyword ($ keyword )]);
283
362
} else {
284
- $ query ->orWhereRaw ($ builder , [$ this ->prepareKeyword ($ keyword )]);
363
+ $ query ->{ $ relationMethod } ($ builder , [$ this ->prepareKeyword ($ keyword )]);
285
364
}
286
- });
365
+ }
287
366
}
288
367
289
368
/**
0 commit comments