Download the PHP package maurice2k/querycheck without Composer

On this page you can find all versions of the php package maurice2k/querycheck. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package querycheck

QueryCheck for PHP

QueryCheck is a logical JSON query evaluator which uses the MongoDB™ query style.

This is a PHP 8.3+ port of the original JavaScript/Node.js querycheck package. Both packages support the same query and $expr aggregation operators. The PHP version has its own comparison rules, so it does not inherit PHP's type juggling (see Differences from the JavaScript Version).

Supported Operators

Comparison Operators

Logical Operators

Aggregation Expressions ($expr)

The following operators can be used within $expr:

Arithmetic Operators:

Query Operators (for aggregation context):

Logical Operators:

Array Operators:

String Operators:

Conditional Operators:

Literal Operators:

Field References: Field references within $expr use MongoDB syntax with $ prefix (e.g., $fieldName, $customer.address.city).

Installation

Install with Composer:

Simple Example

Using $expr for Aggregation Expressions

The $expr operator allows you to use aggregation expressions for field-to-field comparisons and calculations:

Notes:

Comparison Rules

These rules apply to the query operators and to the same operators inside $expr, with and without strict mode unless noted.

Types

PHP uses arrays for both lists and objects. QueryCheck treats a sequential array ([1, 2]) as an array and an associative array (['x' => 1]) as an object. Integers and floats are one numeric type everywhere: 12.1 > 10 is true, {v: 12} matches 12.0, and {v: {$ne: 1}} does not match 1.0. This matters because JSON encoders often write 137.0 as 137.

Equality ($eq, $ne, $in)

Ordering ($gt, $gte, $lt, $lte)

PHP's own > and < order values of any type: "admin" > 18, [] > 18 and null < 5 are all true. QueryCheck only compares values that can be ordered against each other:

Value vs operand Result
number vs number compared numerically (1 and 1.0 are equal), exactly also beyond 2^53
string vs string compared as text, byte by byte, like MongoDB: "10" < "9", "12.0" > "12", "9:00" > "10:00"
boolean vs boolean false < true
null vs null equal, so $gte and $lte match
number vs numeric string without strict mode compared numerically (137 > "136", is_numeric() decides, so "1e2" is 100); in strict mode an error
NaN vs a number never greater or less (NaN >= NaN is true, as NaN equals NaN)
anything else (null or a boolean vs another type, arrays, objects, "admin" vs 18) does not match (in strict mode an error, except for null)

To order numeric strings as numbers, compare them with a number: {v: {$gt: 9}} matches "10", {v: {$gt: "9"}} does not. String bounds compare as text, so zero-pad times and dates ("09:00", "2020-09-15").

$not inverts the result, so {age: {$not: {$gte: 18}}} matches "admin". Use QueryCheck as an allow check (if ($qc->test($doc)) allow();), not as a deny list.

Array Fields

As in MongoDB, $eq, $ne and $in on an array field match if the whole array matches or one of its elements does:

Query ["user", "admin"] ["user"] []
{role: "admin"} match no no
{role: {$ne: "admin"}} no match match
{role: {$in: ["admin", "owner"]}} match no no
{role: {$not: {$in: ["admin"]}}} no match match

So {role: {$ne: "banned"}} does not match ["banned", "admin"]. A whole array can be matched too: {tags: ["a", "b"]} and {tags: {$in: [["a", "b"]]}} match ["a", "b"], while {tags: ["a"]} does not match ["a", "b"]. {v: null} matches [null].

$gt, $gte, $lt and $lte do not look into arrays: an array field never matches them (MongoDB compares each element, see Differences from MongoDB).

Strict Mode

Strict mode is off by default. It turns type mismatches into errors:

Without strict mode, strings and numbers mix ("137" equals 137, 137 > "136") and every other mismatch simply does not match. Use strict mode when your documents have reliable types and a wrong type points to bad data or a wrong query; leave it off for loosely typed input such as form fields or CSV.

Not strict Strict
$eq string vs number ({v: 137} on "137") compared as text, matches throws StrictTypeError
$ne string vs number ({v: {$ne: 137}} on "137") compared as text, does not match throws StrictTypeError ($ne throws exactly when $eq would)
$eq / $ne with other mismatched types ({v: true} on 1) does not match / matches throws StrictTypeError
$eq / $ne with null on one side does not match / matches does not match / matches
$in element, array element, $eq/$ne/$in inside $expr: string vs number compared as text, matches does not match
$gt, $gte, $lt, $lte with values that cannot be ordered (string vs number, boolean vs another type, arrays, objects) does not match throws StrictTypeError, also inside $expr
$gt, $gte, $lt, $lte with null against another type ({amount: {$gte: 1000}} on a missing amount with setThrowOnUnknownVariable(false)) does not match does not match
$regex on a non-string numbers are matched as text, null, booleans, arrays and objects do not match throws StrictTypeError (null does not match)
$in operand from the operand evaluator that is not a list (a literal one is a SyntaxError) does not match throws StrictTypeError
test() with data that is not an object returns false throws StrictTypeError

Missing Fields

By default, a field that does not exist in the document throws an UnknownVariableException. An existing field with the value null is not missing.

setThrowOnUnknownVariable(false) makes a missing field compare as null instead of throwing. Use it for MongoDB-like queries where {field: null} means "null or missing":

A null in the middle of a path makes the whole path null: {'profile.age': null} matches ['profile' => null].

Differences from MongoDB

QueryCheck follows MongoDB's query semantics where that is safe. It deliberately differs in these places:

Topic MongoDB QueryCheck
String vs number never equal or ordered ({v: 137} does not match "137") equal and ordered as numbers without strict mode ("137" equals 137, 137 > "136"); an error in strict mode
Ordering across types inside $expr uses the BSON type order: every string is greater than every number, arrays are greater than both, NaN is less than every number values of different types never match ("admin" >= 18 is false); an error in strict mode. NaN is never greater or less than a number
$gt, $gte, $lt, $lte on array fields match if one element matches; different conditions may be satisfied by different elements ({v: {$gt: 10, $lt: 13}} matches [5, 20]) an array field never matches; an error in strict mode
Type errors never raised; a mismatch simply does not match strict mode throws StrictTypeError for mismatched non-null types
Missing fields behave like null ({v: null} matches a document without v) throw UnknownVariableException by default; setThrowOnUnknownVariable(false) gives MongoDB's behaviour
Evaluation order clauses may be reordered by the query planner; short-circuiting is not guaranteed $and and $or are evaluated left to right and short-circuit, so an earlier clause can guard a later one
Syntax errors reported by the server reported by the first test(), for the whole query
Number types int32, int64, double and decimal128 PHP integers and floats (no decimal128); integers are compared exactly with floats
Operators the full query language the operators listed above; not supported are, for example, $nin, $exists, $type, $all, $elemMatch, the query operators $size and $mod, and most aggregation operators
$regex PCRE with the options i, m, x, s and u; matches strings, and the elements of array fields PCRE through preg_match() with the same options; matches strings, and numbers as text without strict mode; array fields never match

Values of the same type, integer vs float, NaN, null vs null, booleans, $eq/$ne/$in on array fields and text comparison of strings behave as in MongoDB.

Differences from the JavaScript Version

The JavaScript version 2.0.0 follows this version: the same operators, Comparison Rules, strict mode, missing-field handling, compiled queries and syntax errors. What differs comes from the languages:

Advanced Features

Compiled Queries

The query is compiled into a tree of closures on the first call to test() and reused for every later call, so create one QueryCheck per query and call test() as often as needed. Changing a setting (setStrictMode(), setOperandEvaluator(), ...) discards the compiled query; it is rebuilt on the next test().

Because the whole query is compiled up front, a syntax error such as an unknown $operator throws a SyntaxError on the first test(), even if it sits in a branch that would not have been evaluated for that document. The message starts with the location of the error:

To find syntax errors before the first document, call validate() after the setters, for example where rules are loaded or saved. It compiles the query and throws the SyntaxError; the compiled query is kept, so the next test() does not compile again:

Besides unknown operators and the wrong number of arguments, compiling rejects mistakes that would otherwise silently change the result:

Query Error
{age: {$gtt: 18}} age: Unsupported query operator: $gtt (it would be compared as the literal object {$gtt: 18} and never match)
{age: {foo: 1, $gt: 18}} age: Cannot mix fields and operators in one object: $gt
{name: {$options: "i"}} name: $options requires $regex (it would match every document)
{name: {$regex: "("}}, {$options: "e"}, a pattern that is not a string or ends with a backslash name.$regex: Invalid $regex pattern "(": ... and similar
{age: {$in: 30}} age.$in: $in requires an array, got integer
{age: {$not: 30}} age.$not: $not requires an operator expression like {$not: {$gt: 5}}
{age: {$gt: [18]}} age.$gt: $gt cannot compare with an array or object (it could never match)
{$and: []}, {$or: []} $and: $and requires a non-empty array
{"a..b": 1}, {".": 1}, "$" inside $expr a..b: Invalid field path "a..b": empty segment (. would be the whole document)
{$expr: {gte: [...]}} $expr: $expr requires an operator expression ... (a plain object counts as true)
{$expr: {$gte: [...], $lt: [...]}} $expr: An operator expression must have exactly one key, found: $gte, $lt (as in MongoDB; $lt would be ignored)
{$divide: ["$a", 0]} $expr.$divide: $divide: division by zero

validate() cannot find errors that depend on the document, such as a value $add cannot add. With an operand evaluator, objects like {$var: ...} are custom functions, not unknown operators; parts of $expr, $not and literal operands are then only checked when a document reaches them and the evaluator returns them unchanged. Errors there come from test(), also with the location.

A $regex that fails while matching a value, because PCRE's backtrack limit is exhausted or the value is not valid UTF-8 with the u option, throws a RegexError instead of counting as "no match". Otherwise $not would turn the failure into a match.

Short-circuit Evaluation

$and stops at the first branch that does not match and $or stops at the first branch that matches, in the order given. Later branches are not evaluated, so they cannot throw, and an operand evaluator is not called for them. This lets an earlier branch guard a later one:

MongoDB's evaluators short-circuit the same way, but MongoDB does not guarantee it and may reorder branches, so errors in skipped branches can differ.

Custom Operand Evaluator

You can extend QueryCheck with custom operand evaluation functions. The operand evaluator works with both regular query operators and $expr aggregation expressions:

Testing

Run the test suite locally:

Run static analysis:

Or with Docker (tests PHP 8.3, 8.4, and 8.5):

License

QueryCheck is available under the MIT license.


All versions of querycheck with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package maurice2k/querycheck contains the following files

Loading the files please wait ...