@@ -319,7 +319,7 @@ public function orderBy($column, $direction)
319
319
*/
320
320
public function getSearchableKeys ()
321
321
{
322
- return array_values (array_map (function ($ value , $ key ) {
322
+ return array_values (array_map (function ($ value , $ key ) {
323
323
return (is_array ($ value ) || is_numeric ($ key ) === false ) ? $ key : $ value ;
324
324
}, $ this ->searchable , array_keys ($ this ->searchable )));
325
325
}
@@ -341,7 +341,8 @@ public function search($queries)
341
341
}
342
342
343
343
return $ this ->addScopeQuery (function ($ query ) use ($ queries ) {
344
- $ alias_suffix = 1 ;
344
+ // Keep track of what tables have been joined and their aliases
345
+ $ joined = [];
345
346
346
347
foreach ($ this ->searchable as $ param => $ columns ) {
347
348
// It doesn't always have to map to something
@@ -357,62 +358,31 @@ public function search($queries)
357
358
$ columns = (array )$ columns ;
358
359
359
360
// Loop though the columns and look for relationships
360
- foreach ($ columns as $ key=> $ column ) {
361
+ foreach ($ columns as $ key => $ column ) {
361
362
@list ($ joining_table , $ options ) = explode (': ' , $ column );
362
363
363
364
if ($ options !== null ) {
364
- @list ($ column , $ foreign_key , $ related_key ) = explode (', ' , $ options );
365
-
366
- // Allow for overrides
367
- $ related_key = $ related_key ?: $ param ;
368
-
369
- // We need to join to the intermediate table
370
- $ local_table = $ this ->getModel ()->getTable ();
371
-
372
- // Create an alias for the join
373
- $ alias = "join_ {$ joining_table }_ {$ alias_suffix }" ;
374
-
375
- // Create the join
376
- $ query ->join (
377
- "{$ joining_table } as {$ alias }" ,
378
- "{$ alias }. {$ foreign_key }" ,
379
- "{$ local_table }. {$ related_key }"
380
- );
365
+ @list ($ column , $ foreign_key , $ related_key , $ alias ) = explode (', ' , $ options );
366
+
367
+ // Join the table if it hasn't already been joined
368
+ if (isset ($ joined [$ joining_table ]) == false ) {
369
+ $ joined [$ joining_table ] = $ this ->addSearchJoin (
370
+ $ query ,
371
+ $ joining_table ,
372
+ $ foreign_key ,
373
+ $ related_key ?: $ param , // Allow for related key overriding
374
+ $ alias
375
+ );
376
+ }
381
377
382
378
// Set a new column search
383
- $ columns [$ key ] = "{$ alias }. {$ column }" ;
384
-
385
- $ alias_suffix ++;
379
+ $ columns [$ key ] = "{$ joined [$ joining_table ]}. {$ column }" ;
386
380
}
387
381
}
388
382
389
- // Get the range type
390
- $ range_type = strtolower (substr ($ value , 0 , 2 ));
391
-
392
383
// Perform a range based query if the range is valid
393
384
// and the separator matches.
394
- if (substr ($ value , 2 , 1 ) === ': ' && in_array ($ range_type , $ this ->range_keys )) {
395
- // Get the true value
396
- $ value = substr ($ value , 3 );
397
-
398
- switch ($ range_type ) {
399
- case 'gt ' :
400
- $ query ->where ($ this ->appendTableName ($ columns [0 ]), '> ' , $ value , 'and ' );
401
- break ;
402
- case 'lt ' :
403
- $ query ->where ($ this ->appendTableName ($ columns [0 ]), '< ' , $ value , 'and ' );
404
- break ;
405
- case 'ne ' :
406
- $ query ->where ($ this ->appendTableName ($ columns [0 ]), '<> ' , $ value , 'and ' );
407
- break ;
408
- case 'bt ' :
409
- // Because this can only have two values
410
- if (count ($ values = explode (', ' , $ value )) === 2 ) {
411
- $ query ->whereBetween ($ this ->appendTableName ($ columns [0 ]), $ values );
412
- }
413
- break ;
414
- }
415
-
385
+ if ($ this ->createSearchRangeClause ($ query , $ value , $ columns )) {
416
386
continue ;
417
387
}
418
388
@@ -747,6 +717,78 @@ protected function createSearchClause(Builder $query, $param, $column, $value, $
747
717
}
748
718
}
749
719
720
+ /**
721
+ * Add a search join to the query.
722
+ *
723
+ * @param Builder $query
724
+ * @param string $joining_table
725
+ * @param string $foreign_key
726
+ * @param string $related_key
727
+ * @param string $alias
728
+ *
729
+ * @return string
730
+ */
731
+ protected function addSearchJoin (Builder $ query , $ joining_table , $ foreign_key , $ related_key , $ alias )
732
+ {
733
+ // We need to join to the intermediate table
734
+ $ local_table = $ this ->getModel ()->getTable ();
735
+
736
+ // Set the way the table will be join, with an alias or without
737
+ $ table = $ alias ? "{$ joining_table } as {$ alias }" : $ joining_table ;
738
+
739
+ // Create an alias for the join
740
+ $ alias = $ alias ?: $ joining_table ;
741
+
742
+ // Create the join
743
+ $ query ->join ($ table , "{$ alias }. {$ foreign_key }" , "{$ local_table }. {$ related_key }" );
744
+
745
+ return $ alias ;
746
+ }
747
+
748
+ /**
749
+ * Add a range clause to the query.
750
+ *
751
+ * @param Builder $query
752
+ * @param string $value
753
+ * @param array $columns
754
+ *
755
+ * @return bool
756
+ */
757
+ protected function createSearchRangeClause (Builder $ query , $ value , array $ columns )
758
+ {
759
+ // Get the range type
760
+ $ range_type = strtolower (substr ($ value , 0 , 2 ));
761
+
762
+ // Perform a range based query if the range is valid
763
+ // and the separator matches.
764
+ if (substr ($ value , 2 , 1 ) === ': ' && in_array ($ range_type , $ this ->range_keys )) {
765
+ // Get the true value
766
+ $ value = substr ($ value , 3 );
767
+
768
+ switch ($ range_type ) {
769
+ case 'gt ' :
770
+ $ query ->where ($ this ->appendTableName ($ columns [0 ]), '> ' , $ value , 'and ' );
771
+ break ;
772
+ case 'lt ' :
773
+ $ query ->where ($ this ->appendTableName ($ columns [0 ]), '< ' , $ value , 'and ' );
774
+ break ;
775
+ case 'ne ' :
776
+ $ query ->where ($ this ->appendTableName ($ columns [0 ]), '<> ' , $ value , 'and ' );
777
+ break ;
778
+ case 'bt ' :
779
+ // Because this can only have two values
780
+ if (count ($ values = explode (', ' , $ value )) === 2 ) {
781
+ $ query ->whereBetween ($ this ->appendTableName ($ columns [0 ]), $ values );
782
+ }
783
+ break ;
784
+ }
785
+
786
+ return true ;
787
+ }
788
+
789
+ return false ;
790
+ }
791
+
750
792
/**
751
793
* Handle dynamic static method calls into the method.
752
794
*
0 commit comments