xwero/idable-queries-core

base package for Idable queries libraries

Installs: 14

Dependents: 1

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/xwero/idable-queries-core

0.3.0 2025-11-30 04:28 UTC

This package is auto-updated.

Last update: 2025-11-30 04:30:41 UTC


README

This package provides the base functions and types for the database specific packages.

The main part of this package functions are helpers to work with the Identifier instances.

Overview

Idable queries are a set of packages that are at the core a multi-database wrapper. While you can use it as a wrapper with the same functions and types per database, the libraries provide an abstraction for the database names and parameters. At the base of the abstraction is the Identifier interface. It is nothing more than a library specific name for enums.

enum Users implements Indentifier
{
   case Users; // It is recommended to use enun name for the table/collection/set/... to make the identifier more universal
   case Name;
}

A backed enum is recommended to separate database name from the enum name.

A SQL query, SELECT name FROM users WHERE name = 'me';, can now be written as SELECT ~Users:Name FROM ~Users:Users WHERE ~Users:Name = :Users:Name;. A Redis query like HMSET users name "Hello" email "World" can be written as HMSET ~Users:Users ~Users:Name :Users:Name ~Users:Email :Users:Email. And so on with other database types.

note: The placeholders are case-insensitive, but for the best compilation path in PHP it is recommended to use capitals.

To make it easier to add multiple parameters an CustomParameterIdentifier attribute can be added to an Identifier instance. This signals to the parameter functions that the parameter value will use a transformer to replace a single placeholder.

#[CustomParameterIdentfier('Xwero\IdableQueriesRedis\setParameterTransformer')]
enum Set implements Identfier
{
   case Users;
}

Now the Redis query can be written as HMSET ~Users:Users :Set:Users. And depending on the values in the IdableParameterCollection instance the query will be changed. Each database package will have predefined transformer functions. Creating the Identifier instance is up to the implementers.

The libraries will have map functions that transform the result of the query in an array-like structure where the key is an Identifier instance. As an example the SELECT ~Users:Name FROM ~Users:Users WHERE ~Users:Name = :Users:Name; query result called with the createMapFromFirstLevelResults function will have the $map[Users:Name] value me. This prevents typos when using the results.

The libraries are build with utility in mind. That is why the main functionality is in the functions, rather than in objects. Use as much or as little as you like.

Functions

addIdableParameters

This is the more dangerous version of the collectIdableParameters function, as it adds the values to the query without preparation.

addIdableParameters('SELECT * FROM ~Users:Users WHERE ~Users:Name = :Users:Name;', IdableParameterCollection::createWithItem(User::Name, 'me')) results in SELECT * FROM ~Users:Users WHERE ~Users:Name = me

Used by the database system packages.

buildAliasMap

This function allows full control over the creation of a Map instance. The data needs to be an associate array.

used by buildAliasMapCollection

buildAliasMapCollection

Helper function to transform a two-dimensional data array into an array of Map instances.

buildLevelMap

Helper function to create a Map instance from an associate array.

Used by createMapFromFirstLevelResults and createMapFromSecondLevelResults.

collectIdableParameters

This function allows the application code to prepare the parameters before adding it to the query.

Used by replaceParametersInQuery.

createMapFromFirstLevelResults

Function with extra checks on top of buildLevelMap.

note: This is more robust function, and should be the one used in a function chain.

Used by the database system packages.

createMapFromSecondLevelResults

When the query returns multiple items use this function to create a MapCollection.

Used by the database system packages.

fillMapWithAliases

A helper method for buildAliasMap and buildLevelMap to add data to the Map based on the added aliases.

getIdentifierFromStrings

This function accepts the class and case as a string and insures the return is either null or an identifier.

It is possible to add a number to the case in the occasion the same identifier needs to be used more than once. As an example WHERE ~Users:Name = :Users:Name1 AND ~Users:Name != :Users:Name2

Used by queryToPlaceholderCollection.

getIdentifierRegex

This function gets the default regex or a custom one from the IDENTIFIER_REGEX environment variable.

getParameterRegex

This function get the default regex or a custom one from the PARAMETER_REGEX environment variable.

note: Both regexes should have a colon as divider between the class and the case.

isIdableQuery

Check to verify if a query has placeholders that can be picked up by the idable regexes.

queryStringFromIdentifier

Gets a backed enum value or a lower string basic enum name.

Used by buildlevelmap and PlaceholderReplacementCollection.

queryToPlaceholderCollection

This function extracts the strings that match the identifier regex and makes identifiers from the strings.

An error is returned when placeholders are found but the collections is empty. the most likely cause is a wrong namespace. It is not possible to return an error when only one or a few namespaces are wrong. To prevent unexpected results it is best to use the namespaces argument when the functions provide it.

note: The collection is sorted from largest string size to smallest string size of the placeholders. This is to prevent bad replacements.

Used by addQueryParameters, collectQueryParameters, createMapFromFirstLevelResults, createMapFromSecondLevelResults and replaceIdentifiersInQuery.

replaceIdentifiersInQuery

Replaces the identifier placeholders from the query with the database names.

Used by the database packages.

replaceParametersInQuery

Replaces the parameter placeholders where the data isn't matched by the query placeholders. :Arr:Test will become (:Arr:Test_0,:Arr:Test_1) when used in the PDO package. The number of placeholders is based on the data in the IdableParameterCollection.

A $placeholderTransformer closure can be added to make sure the placeholders don't contain characters the database doesn't recognize.

Returns a DirtyQuery instance or false when there are no query changes.

Used by the database packages.

runChain

When using a PHP version under 8.5, this function can be used to have a similar experience than with the pipe operator.

$query = 'SELECT ~Users:Name, ~Users:Email FROM ~Users:Users WHERE ~Users:Id = :UsersId';
$namespaces = new BaseNamespaceCollection('Test\Identifiers');
$result = replaceIdentifiersInQuery($query, $namespaces)
  |> (fn($query) => replaceParametersInQuery($query, new IdableParameterCollection(Users::Id, 1), $namespaces))
  |> (fn($queryAndParameters) => someDatabaseFunction($queryAndParameters))
  |> (fn($data) => createMapFromSecondLevelResults($data, $query, namespaces: $namespaces))
  ;
  
// with runChain

$query = 'SELECT ~Users:Name, ~Users:Email FROM ~Users:Users WHERE ~Users:Id = :UsersId';
$namespaces = new BaseNamespaceCollection('Test\Identifiers');
$result = runChain(new Chain(
                fn() => replaceIdentifiersInQuery($query, $namespaces)
                fn($query) => replaceParametersInQuery($query, new IdableParameterCollection(Users::Id, 1), $namespaces),
                fn($queryAndParameters) => someDatabaseFunction($queryAndParameters),
                fn($data) => createMapFromSecondLevelResults($data, $query, namespaces: $namespaces)
              ));

Types

Most of the collection types are added to make sure the content is of a certain type.

Alias

A data transfer object that holds the information to be used by the functions that use the AliasCollection.

AliasCollection

It is used to match aliases in the buildAliasMap, buildAliasesMapCollection, buildLevelMap, createMapFromFirstLevelResults and createMapFromSecondLevelResults functions.

The constructor only accepts Alias instances.

It has the methods:

  • createWithItem: a static convenience method for new AliasCollection()->add().
  • add: this method uses the Alias constructor arguments to create an instance. This method can return an Error or the instance.
  • getAlias: finds the matching Alias instance by a string value.

It extends BaseCollection.

BaseCollection

Has a single array to contain the collection items. Can be used for collections with a single type.

It has the methods:

  • getAll: returns array
  • isEmpty: checks the array size

Chain

Used to add closures to the runChain function.

The constructor only accepts Closure values.

Extends BaseCollection.

CustomParameterIdentifier

The class attribute to add to an identifier to allow custom parameter transformations. Database specific packages have data transformer functions to add to the attribute.

DirtyQuery

A DTO that is instantiated in replaceParametersInQuery when a query needs parameter replacements.

Error

The catch-all exception type to make it easier to let them pass through a function chain.

ExecutablePair

Exposes the changed query and the placeholders that match the changed query.

IdableParameter

The name is chosen to differentiate between parameter placeholders that use Identifier cases, and the native language parameters. The latter are most of the time added as an array to the functions.

To allow query placeholders with a trailing number this class is created get the value by Identifier and number.7 An example is new IdableParameter(Users::Name, 'me', 1).

IdableParameterCollection

Used to add values to the parameter identifier placeholders in the query. :Users:name is replaced by me when executing the query with the collection instance, IdableParameterCollection::createWithItem(Users::Name, 'me').

The constructor accepts IdableParameter instances.

It has the methods:

  • createWithItem: a static convenience for new IdableParameterCollection()->add()
  • add: this uses the same arguments as the IdableParameter constructor to create an instance, and add it to the collection
  • findValueByIdentifierAndPlaceholder: used by the addIdableParameters and collectIdableParameters functions

Extends BaseCollection.

Identifier

The interface all the enums must implement to be used as placeholders in the queries and keys in maps.

A backed enum is recommended because it provides the best configuration. When it is a basic enum the case name will be lowercased to replace the placeholders.

JSONError

A convenience class were the message needs to added to create an Error instance with and instance of the JSONException as the exception.

JSONException

The message you add to the exception is appended with the JSON error message from PHP.

Map

Added to make the language more consistent.

MapCollection

The constructor only allows Map instances.

It has the method:

  • addMap: appends a Map instance to the collection.

Extends BaseCollection.

NamespaceCollection

It is used to make the identifier placeholders in the queries shorter.

The constructor only accepts string values.

Extends BaseCollection.

PlaceHolder

This class binds the placeholder with the identifier, and optionally the value.

The class required properties are placeholder and identifier. The value property is used for collecting the data that a function passes on. The prefix and suffix properties are used to manipulate the placeholder return.

It has the methods:

  • getFullPlaceholder: which concatenates the prefix, placeholder and suffix property values.
  • getCustomValue: when the ´identifier´ value has a CustomParameterIdentifier attribute, this method will execute the data transformer function

PlaceHolderCollection

The constructor only accepts PlaceHolder instances.

It has the methods:

  • createWithPlaceholderItem: a static convenience with for new Placeholder()->add()
  • add: uses the same arguments as the PlaceHolder constructor to create an instance and add it to the collection.
  • getPlaceholderReplacements: returns a flattened array in case the placeholders in the query need to be replaced.
  • getPlaceholdersAsText: calls the getFullPlaceholder on every item of the collection to create a string.
  • getPlaceholderValuePairs: returns a flattened array with the placeholders and matching values

Extends BaseCollection.

QueryReturnConfig

The interface for database specific output configuration.

Statement

The interface to make the Statement classes consistent in the database specific packages.

Tips

  • Use the namespaces argument of the functions to prevent unexpected results because of typos or changed namespaces.