Download the PHP package kafoso/questful without Composer

On this page you can find all versions of the php package kafoso/questful. 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 questful

Questful

Questful is an interfacing and metadata tool, providing a sensible link between HTTP queries and RESTful APIs. The name "Questful" is a word play and concatenation of the words "Query" (from HTTP query) and "RESTful".


Introduction

RESTful APIs are widely used throughout the web. While a consensus has emerged about how to structure HTTP requests and responses, disparity and disagreement still exists when it comes to filtering and sorting data for multiple results (lists).

Questful aims to close part of this gap by providing strict, manageable, and secure means of applying filters and sorting, all the way from HTTP requests through the extraction of data from a storage unit1 (e.g. database), and providing data and metadata in the final HTTP response.

Purpose

The primary goal of Questful is to allow developers to quickly manage and implement filtering and sorting options in web applications, so that they may focus their energy and skill on making great applications, instead of repeatedly implementing trivial procedures.

Disclaimer

This has started as a hobby project and is still in its infancy. Use Questful your own risk and please see the LICENSE file.

A quick example

In Questful, finding all users called "Homer" and then sorting (alphanumerically) by their names is as easy as:

PHP code for capturing and processing the above request:

Requirements

Recommended

Filtering

Filters (or conditions) allow the extraction of subsets of data from a storage unit.

?filter[]

In Questful, filters must be arrays and thus, an HTTP query must be specified as such: ?filter[]=foo="bar". This filter has the index of 0 (zero) and is equivalent to: ?filter[0]=foo="bar". Indexes may be chosen freely, but must be integers and unique. Non-unique indexes will result in only the lastly defined filter (with a non-unique index) being applied.

Indexes are used in conjunction with filter expressions, which is explained futher down.

If a non-integer (e.g. filter[a]=foo="bar") or negative integer (e.g. filter[-1]=foo="bar") is provided as an index a Kafoso\Questful\Exception\BadRequestException is thrown.

Notice: The name "filter" is singular.

Why is there an equal sign, =, after foo?

That's because foo is the key and "bar" is the value; i.e. a "key-value" pair. Everything past the first equal sign should be URL encoded before being sent to the API, making it look like ?filter[]=foo%3D%22bar%22. That's not very pretty - or readable - so for simplicity's sake we stick to unencoded strings in most examples.

The equal sign after foo is just one of several operators; details futher down.

Why is "bar" wrapped in double quotes?

That's because we specifically want to target the data type "string".

Syntax

, where:

Filter types

Questful handles the following:

Notice: Use LIKE with extreme care. This search type is tied to a certain risk of Denial of Service attacks2. Only allow this search type if you are absolutely sure you know what your are doing. It may come in handy if providing a rich search feature to a restricted number of users (e.g. super users or administrators).

As a security measure, all filters and sorting must be mapped.

Filter values must evaluate to PHP syntax (excluding modifiers).

Null

Must be left empty or spelled out as null.

Accepted operators
Samples

Booleans

Must be spelled out as "true" or "false", and not 1 or 0; these characters are by Questful considered to be integers.

Accepted operators
Samples

Floats

The decimal point period, ., and a precision of at least 1 decimal number is mandatory. An optional minus symbol may be provided. Simply specifying 1 will cause Questful to interpret the value as an integer.

Accepted operators
Samples:

Integers

Digits. An optional minus symbol may be prepended.

Accepted operators
Samples:

Strings

Strings must be wrapped in double quotes "". The double quotes make strings clearly distinguishable from other data types, e.g. when an integer is in fact a string like "42".

The value part, i.e. the double quotes and the contents inside it, must evaluate to PHP syntax. Naturally, encapsed variables (e.g "$a") are not supported and will be considered to be part of the string. Double quotes inside the string must be escaped by backslash, e.g. "\"".

Single quotes are not supported and will cause a \Kafoso\Questful\Exception\BadRequestException to be thrown.

Accepted operators
Modifiers
Samples

Substrings (LIKE)

The terminology LIKE is borrowed from SQL and it works the same: finds substrings within other strings, commonly in columns in an SQL database table.

Same rule applies as for strings, i.e. that the value part must evaluate to PHP syntax and that only double quotes are supported.

The syntax is a little different from SQL, though. While the percentage symbol % is used in both Questful and SQL, and may be used as a wildcard on the lefthand side, righthand side, or both at once, the symbol goes outside the quotes in Questful. I.e. %"bar"%, and not "%bar%", as the syntax would be in SQL.

But why isn't the syntax the same?

Because we want to reliably perform wildcard searching without the necessity of - and reliance on - proper escaping in the client.

Example:

Consider the following table:

key percentage
a 10%
b 100%

It is correct that "10%" in the column "percentage" will be matched by this SQL statement:

But so will "100%", because % is a wildcard character, matching 0% within the "100%". That's not what we want. Therefore, percentage symbols go outside the quotes in Questful. This makes the above query become:

Questful will ensure that both symbols % and _ are escaped in MySQL.

Accepted operators
Modifiers

Modifiers are appended after the last double quote or percentage symbol.

Samples

Arrays (IN)

The terminology IN is - as for LIKE - borrowed from SQL. It enables a condition to look for multiple values within the same key (or column).

An array search is a more manageable alternative to writing a series of or-statements (see Filter expression further down).

Array filters are wrapped in square brackets, [] - and not round parentheses (as is the case in MySQL) - and values must be comma separated.

The contents of the square brackets must evaluate to PHP syntax. Otherwise, a \Kafoso\Questful\Exception\BadRequestException is thrown.

Questful respects strict null comparisons, making ?filter[]=t.foo=[null,\"foo\",42] become (in (PDO) MySQL syntax) (t.foo IN (:filter_0_1, :filter_0_2) OR t.foo IS NULL). For certain bridges, boolean values are converted from true and false to 1 and 0, respectively.

Arrays are optimized before querying the storage unit, removing redundant values by strict comparison (===), making e.g. [42,"42",42] become [42,"42"].

Syntax

, where:

Accepted operators
Supported data types

Syntaxes are (as you may have noticed) similar - but not always identical - to the previously described syntaxes for each of the data types.

Modifiers

Modifiers are appended after the last square bracket, e.g. ["foo", "BAR"]/i, and applies to all elements in the array. E.g. all strings becoming case insensitive.

Samples

Operators

Supported operators include:

Some operators are not usable with certain filtering options, though:

Strings do accept >, >=, <, <=, retaining the need for making comparison against certain values. E.g. dates.

In the \Kafoso\Questful\Exception\UnexpectedValueException is thrown.

?filterExpression

By default, all filters are concatenated using the logical operator AND. I.e. only datasets, where all conditions are met, are returned. However, the filterExpression options allows control over the concatenation of the filters in a readable and manageable way.

Accepted tokens

The expression must evaluate to PHP syntax. I.e. placement of the tokens, e.g. matching and proper closing of parentheses, is mandatory. Otherwise a \Kafoso\Questful\Exception\BadRequestException is thrown.

Indexes in filter[] and filterExpression must match. If a mismatch occurs a \Kafoso\Questful\Exception\BadRequestException is thrown.

Example

URL:

Resulting filter expression:

Precedence

Precedence between and, or, and xor may vary depending on the storage unit. Even the PHP language itself has differences between operators && and ||, and operators and and or.

As a result, all expressions in Questful are normalized and strict precedence is enforced. This means - unless parentheses are purposely provided - expressions like 0or1and2 will be wrapped in precedence parentheses, becoming 0or(1and2). You may, however, specify the placement of the parentheses yourself, making an expression like (0or1)and2 remain intact.

By enforcing precedence, different storage units should return identical results.

Precedence examples

Input expression Resulting normalized expression
0and1or2xor3 (0and1)or(2xor3)
0or1and(2or3) 0or(1and(2or3))
0or(1and2)or3 (0or(1and2))or3

Sorting

The sorting syntax is much simpler than that of the filtering mechanism. Although, some of the same logic does carry over.

?sort[]=foo is an array, too, and indexes may be provided as the do for filters. I.e. ?sort[]=foo is equivalent to ?sort[0]=foo.

The order of indexes is significant. Lower indexes get prioritized first, starting from zero. I.e. in ?sort[0]=foo&sort[1]=bar, sorting on foo is performed before sorting on bar.

Negative indexes (e.g. ?sort[-1]=foo) will throw a Kafoso\Questful\Exception\BadRequestException.

Syntax

, where:

Direction

By default, sorting occurs in ascending order. However, this order may be changed by appending - (minus) to the target column name, e.g. ?sort[]=-foo. For manageability and aesthetic reasons, both + (ascending) and - (descending) may be provided.

Samples

Modifiers

Modifiers including:

Examples

Letter cases and non-English characters are handled solely by your storage unit. This may yield results, ordered in an undesirable fashion.

A real world example: The Danish special letter "Ø" is often being interpreted as "O". This is down right wrong, because in Danish, we have a total of three special letters - "Æ", "Ø", and "Å" - appended to the normal English alphabet. I.e. "...XYZÆØÅ". And so, the results matching "Ø" must come after "ZÆ" and not alongside "O".

Questful allows you to sort case insensitively and binary-safe (e.g. when using UTF-8), respecting special characters.

Mapping and validation

The class Kafoso\Questful\Model\Mapping creates a map between the keys provided via the HTTP request and the respective key/column in the storage, e.g. a column in a database. This map ensures shielding against injection attacks and reveals less information about the application and storage unit infrastructure.

Relating a filter or sort key to a column is performed with the relate method. You may wildly obfuscate the naming of keys in the client should you desire, as long as they're correctly mapped to tables and columns server-side.

Allowing specific filters, filter expressions, and/or sorts is performed with the allow method.

Usage example:

In the above example, $mapping->validate() will throw a bridging logic.

Restricting operators

Operators are provided as the 2nd argument in \Kafoso\Questful\Exception\UnexpectedValueException is thrown.

See 006-restrict-operators for a practical example.

Sample

Validators

Validators are used to confine the input data.

Symfony's Validation bundle is utilized for this purpose. Aside from being a solid library, you may define your own validation error messages, should you desire.

For a list of supported constraints, see: http://symfony.com/doc/current/reference/constraints.html

Some common use cases include:

Validators are provided as the 3rd argument in \Kafoso\Questful\Model\Mapping\Allowable\Filter\AbstractAllowedFilter, which accepts null or an array of \Symfony\Component\Validator\Constraint.

All validators are applied upon calling Kafoso\Questful\Exception\BadRequestException is thrown.

Sample

For a more detailed example, see Examples.

Bridging with storage units

Bridging in Questful means translating the query values of the HTTP request to a format which is readable by a storage unit. And doing so in a safe manner.

A bridge (e.g. Kafoso\Questful\Model\Bridge\PdoMysql) outputs a partial set of conditions, parameters, and sorting, which is consumable by the storage unit. For MySQL using PDO, a series of WHERE and ORDER BY conditions are produced as SQL strings, together with an array of parameters, which must be provided in a prepared statement.

The character encoding of bridges is "UTF-8" by default, but may be changed.

Usage sample:

Notice how the index 42 carries over and becomes part of the parameter identifier filter_42. These indexes are safe to use (i.e. no risk of injection) since they are force-converted to integers. A non-digit or negative index cause a Kafoso\Questful\Exception\BadRequestException to be thrown.

You are free to add additional conditions and sorting in the SQL sentence. Notice that the contents of where above is always wrapped in parentheses.

Bridge types

The readily available bridges are:

You may implement your own bridges by extending Kafoso\Questful\Model\Bridge\AbstractBridge.

Errors and exceptions

A few custom exceptions are utilized:

Exception codes

Besides the above exception classes, the following exception codes are consistently used for each of the following namespace domains:

Exception code Namespace Note
1 Kafoso\Questful\Model\QueryParser All exceptions within this class and all classes contained within this namespace.
4 Kafoso\Questful\Model\Mapping All exceptions within this namespace.
5 Kafoso\Questful\Model\Bridge All exceptions within this namespace.

This concise format allow foreign code (i.e. code, which is not part of this library) to more accurately interpret and relay messages.

Perhaps developers wish to override a message (e.g. translate it to a different language), before returning it to the client. Or perhaps they wish to change the status code (e.g. to 404 Not Found) depending on the exception code. The options are there.

Examples

Ideas and plans

Footnotes

1 Storage unit: Any means of persisting data, including databases, cache, file system storage, and more.

2 (Distributed) Denial of Service (DDoS) - or simply DoS - attacks come in many forms. In respect to this library, one such DoS attack may be induced by long-running queries in the database. Using regular expressions, for instance, to search for content in a database is very costly and may induce long load times.


All versions of questful with dependencies

PHP Build Version
Package Version
Requires beberlei/doctrineextensions Version ^1.0.11
doctrine/orm Version ^2.5
nikic/php-parser Version ^3.0
symfony/validator Version ^2.8
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 kafoso/questful contains the following files

Loading the files please wait ....