Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[10.x] Database Expressions that are conditions #47210

Merged
merged 3 commits into from
May 30, 2023

Conversation

tpetry
Copy link
Contributor

@tpetry tpetry commented May 25, 2023

With #46558 merged, the database expressions could now support more extended use cases: A common thing for database drivers or users is to extend the query builder to support new whereXyz() methods. But these are not database-agnostic.

I've created a new interface (ConditionExpression) to indicate expressions that will be transformed into an entire database condition. These can be passed to where and having:

/** @see https://github.com/tpetry/laravel-query-expressions/blob/main/src/Operator/Comparison/DistinctFrom.php */
$query->where(new DistinctFrom('type', new Value('pending')))

Expressions built on the new interface will be handled differently by WHERE and HAVING. At the moment, an expression passed as a single parameter to where will result in a SQL string that is no longer the intended use-case. By changing the query builder very minimal to handle ConditionExpression different, those conditions can be embedded into the SQL query correctly:

-- expression using the Expression interface
WHERE (type IS DISTINCT FROM 'pending') IS NULL

-- expression using the ConditionExpression interface
WHERE (type IS DISTINCT FROM 'pending')

But this approach is much more compelling if you consider more complex use cases. For example, geographical operations or statistical queries require many transformations on columns and values. These are hard to generalize, and you must fall back to raw parts. Some spaghetti code often insecurely interpolates those raw strings when complex customization is used.

With condition expressions, you can safely composite multiple objects to form the condition you want to have. Complex dynamic query-building logic can be transformed into parsers that return a single object that can be used with Laravel:

$condition = createDBCondition($request);
// returns:
// new LessThan(
//   new GeoDistance('location', new GeoPoint(-39.08677, 58.64465, srid: 4326), srid: 4326),
//   new Value(50),
// );

$query->where(condition);

@taylorotwell taylorotwell merged commit e0788c9 into laravel:10.x May 30, 2023
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants