esbenp / esbenp/bruno

Reuse of custom filter within the same query will result in a join error

Open
#43 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.