Skip to content
This repository has been archived by the owner on Aug 22, 2023. It is now read-only.

PHPORM-46 Throw an exception when Query\Builder::orderBy() is used with invalid direction #7

Merged
merged 3 commits into from
Jul 12, 2023

Conversation

GromNaN
Copy link
Owner

@GromNaN GromNaN commented Jul 11, 2023

Fix PHPORM-46

Consistent with Laravel Query Builder.

@GromNaN GromNaN requested review from jmikola and alcaeus July 11, 2023 22:03
$direction = match (strtolower($direction)) {
'asc' => 1,
'desc' => -1,
default => throw new \InvalidArgumentException(sprintf('Order direction must be either "asc" or "desc", "%s" given.', $direction)),
Copy link
Owner Author

@GromNaN GromNaN Jul 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mongosh throws this error:

db.getCollection('books').find().sort({'_id': 'descd'});
MongoInvalidArgumentError: Invalid sort direction: "descd"

db.getCollection('books').find().sort({'_id': 2});
MongoInvalidArgumentError: Invalid sort direction: 2

PHPC throw this error:

MongoDB\Driver\Exception\CommandException : $sort key ordering must be 1 (for ascending) or -1 (for descending)

We can decide that it's not necessary to add an exception in the query builder since there is already an exception. But here, the exception is thrown as early as possible to help debug.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an exception is fine for this string conversion logic, since one could argue this is the Laravel library itself converting a value. Beyond that, though, we should rely on the server to validate (as will be the case with $meta for text score).

*/
public function orderBy($column, $direction = 'asc')
{
if (is_string($direction)) {
$direction = (strtolower($direction) == 'asc' ? 1 : -1);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most impactful change: any invalid value was converted to a "desc" direction. This seems wrong.

Copy link
Collaborator

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a minor comment on sorting by text score.

@@ -505,11 +505,16 @@ public function distinct($column = false)

/**
* @inheritdoc
* @param int|string $direction
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When sorting, MongoDB supports sorting by text score metadata, which would have an invocation like so:

$query->orderBy('textScore', ['$meta' => 'textScore']);

While it looks like the code may handle that just fine, the parameter type hint suggests this is invalid. Feel free to leave that change to a follow-up ticket, but I wanted to point it out.

Copy link
Owner Author

@GromNaN GromNaN Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need a test to cover this use-case. I'll add one after rebasing on #6.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the doc, I added a test case for this specific example, and updated the method signature.

@GromNaN GromNaN merged commit 8562a4b into master Jul 12, 2023
@GromNaN GromNaN deleted the PHPORM-46 branch July 12, 2023 12:54
'asc', 'ASC' => 1,
'desc', 'DESC' => -1,
default => throw new \InvalidArgumentException('Order direction must be "asc" or "desc".'),
};
}

if ($column == 'natural') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this problematic if a model/collection actually contains a natural field? Even $natural is a valid field name since the server relaxed restrictions on using dots and dollars in fields names (although I'm less concerned about that edge case).

$direction = match (strtolower($direction)) {
'asc' => 1,
'desc' => -1,
default => throw new \InvalidArgumentException(sprintf('Order direction must be either "asc" or "desc", "%s" given.', $direction)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an exception is fine for this string conversion logic, since one could argue this is the Laravel library itself converting a value. Beyond that, though, we should rely on the server to validate (as will be the case with $meta for text score).

GromNaN added a commit that referenced this pull request Aug 22, 2023
…th invalid direction (#7)

* Convert only strings, let the driver fail for int values
* Add more tests on Builder::orderBy
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants