Reuse of custom filter within the same query will result in a join error
- Dominant language
- PHP
- Stars
- 163
- Forks
- 70
- PR merge metrics
- No merged PRs in 30d
Description
When using the same custom filter multiple times, the join statement will be appended twice to the query builder.
Example of the custom filter:
```php
/**
* @param Builder $query
* @param $method
* @param $clauseOperator
* @param $value
*
* @return Builder
*/
public function filterStartLocation(Builder $query, $method, $clauseOperator, $value): Builder
{
// if clauseOperator is identical to false,
// we are using a specific SQL method in its place (e.g. `in`, `between`)
if ($clauseOperator === false) {
$query->$method('locations.location_type_id', $value);
} else {
$query->$method('locations.location_type_id', $clauseOperator, $value);
}
return $query;
}
```
As you can see, the custom filter will check the `location_type` within the `location`. the `startLocation` is an eloquent relation defined in the Model.
An error will occur when using this filter more then once within the same query:
The output of the Builder is:
```
Builder {#431 ▼
#query: Builder {#417 ▼
+connection: MySqlConnection {#128 ▶}
+grammar: MySqlGrammar {#129 ▶}
+processor: MySqlProcessor {#130}
+bindings: array:7 [▶]
+aggregate: null
+columns: array:1 [▶]
+distinct: false
+from: "schedules"
+joins: array:2 [▼
0 => JoinClause {#877 ▼
+type: "inner"
+table: "locations"
-parentQuery: Builder {#417}
+connection: MySqlConnection {#128 ▶}
+grammar: MySqlGrammar {#129 ▶}
+processor: MySqlProcessor {#130}
+bindings: array:7 [▶]
+aggregate: null
+columns: null
+distinct: false
+from: null
+joins: null
+wheres: array:1 [▼
0 => array:5 [▼
"type" => "Column"
"first" => "schedules.end_location_id"
"operator" => "="
"second" => "locations.id"
"boolean" => "and"
]
]
+groups: null
+havings: null
+orders: null
+limit: null
+offset: null
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
+operators: array:29 [▶]
+useWritePdo: false
}
1 => JoinClause {#878 ▼
+type: "inner"
+table: "locations"
-parentQuery: Builder {#417}
+connection: MySqlConnection {#128 ▶}
+grammar: MySqlGrammar {#129 ▶}
+processor: MySqlProcessor {#130}
+bindings: array:7 [▶]
+aggregate: null
+columns: null
+distinct: false
+from: null
+joins: null
+wheres: array:1 [▼
0 => array:5 [▼
"type" => "Column"
"first" => "schedules.end_location_id"
"operator" => "="
"second" => "locations.id"
"boolean" => "and"
]
]
+groups: null
+havings: null
+orders: null
+limit: null
+offset: null
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
+operators: array:29 [▶]
+useWritePdo: false
}
]
+wheres: array:2 [▼
0 => array:3 [▼
"type" => "Nested"
"query" => Builder {#886 ▼
+connection: MySqlConnection {#128 ▶}
+grammar: MySqlGrammar {#129 ▶}
+processor: MySqlProcessor {#130}
+bindings: array:7 [▶]
+aggregate: null
+columns: null
+distinct: false
+from: "schedules"
+joins: null
+wheres: array:1 [▼
0 => array:5 [▼
"type" => "Basic"
"column" => "locations.location_type_id"
"operator" => "="
"value" => array:1 [▶]
"boolean" => "and"
]
]
+groups: null
+havings: null
+orders: null
+limit: null
+offset: null
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
+operators: array:29 [▶]
+useWritePdo: false
}
"boolean" => "and"
]
1 => array:3 [▼
"type" => "Nested"
"query" => Builder {#871 ▼
+connection: MySqlConnection {#128 ▶}
+grammar: MySqlGrammar {#129 ▶}
+processor: MySqlProcessor {#130}
+bindings: array:7 [▶]
+aggregate: null
+columns: null
+distinct: false
+from: "schedules"
+joins: null
+wheres: array:1 [▼
0 => array:5 [▼
"type" => "Basic"
"column" => "locations.location_type_id"
"operator" => "="
"value" => "8"
"boolean" => "and"
]
]
+groups: null
+havings: null
+orders: null
+limit: null
+offset: null
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
+operators: array:29 [▶]
+useWritePdo: false
}
"boolean" => "and"
]
]
+groups: null
+havings: null
+orders: null
+limit: null
+offset: null
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
+operators: array:29 [▶]
+useWritePdo: false
}
#model: Schedule {#368 ▶}
#eagerLoad: []
#localMacros: []
#onDelete: null
#passthru: array:13 [▶]
#scopes: []
#removedScopes: []
}
```
Is there a workaround available for this issue?
--
Using Homestead with environment versions:
```
PHP: 7.2
Laravel: 5.6.39
```
Contributor guide
Research direction
Start by reproducing the repeated custom startLocation filter with the Laravel 5.6.39 query builder and inspect how the Eloquent relation adds its join. Confirm whether the same locations join is appended twice, then verify that repeated use completes without a join error and preserves both filter conditions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- laravel, php
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100