Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Document existing
Fragment
implementations
- Loading branch information
1 parent
51d0e0a
commit 9d60eb5
Showing
3 changed files
with
145 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# `Fragment` implementations | ||
|
||
Everything that is passed to a query method of `GeenricTableGateway` will eventually be represented by | ||
an implementation of `Fragment` and kept in a `FragmentList`. | ||
|
||
## `FragmentList` | ||
|
||
An instance of this class aggregates fragments used to build a query and parameter values used to execute it. | ||
It implements `SelectFragment` and `Parametrized` package interfaces as well | ||
as native `IteratorAggregate` and `Countable`. | ||
|
||
Constructor of this class accepts a variable number of `Fragment` or `FragmentBuilder` instances | ||
* `__construct(Fragment|FragmentBuilder ...$fragments)` | ||
|
||
which are passed to `add()` method. | ||
|
||
There is also a static `normalize()` method that accepts `$fragments` parameter that is passed to a query method | ||
of `TableGateway` and returns an instance of `FragmentList`: | ||
* `normalize($fragments): self` - `$fragments` can be either a `\Closure`, an implementation of `Fragment` | ||
or `FragmentBuilder`, or, most commonly, iterable over `Fragment` or `FragmentBuilder` implementations. | ||
Anything else will result in `InvalidArgumentException`. | ||
|
||
The class defines several additional methods: | ||
* `add(Fragment|FragmentBuilder $fragment): self` - adds a fragment to the list. If an instance of `FragmentList` | ||
is given, it will be "flattened" with its items added rather than the list itself. If `FragmentBuilder` | ||
is given, the return value of its `getFragment()` method is added to the list, not the builder. | ||
* `mergeParameters(array<string, mixed> $parameters, ?KeyEquatable $owner = null): self` - adds values | ||
for several named parameters. `$owner` is used only for a possible exception message in `RecursiveParameterHolder`. | ||
* `getParameters(): array<string, mixed>` - shorthand for `$list->getParameterHolder()->getParameters()`. | ||
Note that all parameter values are returned: those that were merged into the list itself and those that belong | ||
to `Parametrized` fragments in the list. | ||
* `getSortedFragments(): Fragment[]` - returns fragments sorted by priority (higher first) and key (alphabetically). | ||
This is used by `applyTo()` to apply contained fragments in a defined order. | ||
* `filter(\Closure $callback): self` - filters the `FragmentList` using the given callback (uses `array_filter()` | ||
internally). `TableSelect::executeCount()` uses this to leave only relevant fragments in the list. | ||
|
||
You only really need an explicit instance of `FragmentList` when you want to use `create*()` methods | ||
of `GenericTableGateway`. Anywhere else the `$fragments` parameter will be normalized to `FragmentList` automatically. | ||
|
||
## `ClosureFragment` | ||
|
||
Wrapper for a closure passed to a `TableGateway` query method as `$fragments` parameter. Queries using this fragment | ||
won't be cached. | ||
|
||
## `InsertSelectFragment` | ||
|
||
Wrapper for `SelectProxy` object passed as `$values` to `GenericTableGateway::insert()`. | ||
|
||
## `SetClauseFragment` | ||
|
||
Fragment populating either the `SET` clause of an `UPDATE` statement or columns and `VALUES` clause of an `INSERT`. | ||
|
||
This is created from `$values` given as an array to `GenericTableGateway::insert()` and from `$set` parameter | ||
to `GenericTableGateway::update()`. | ||
|
||
You may need to use that explicitly if you want to create a preparable `INSERT` / `UPDATE` statement, e.g. | ||
```PHP | ||
$update = $gateway->createUpdateStatement(new FragmentList( | ||
new SetClauseFragment( | ||
$gateway->getColumns(), | ||
$tableLocator, | ||
['name' => null] | ||
), | ||
// For the sake of example only, using $gateway->primaryKey() is easier | ||
new PrimaryKeyCondition($gateway->getPrimaryKey(), $tableLocator->getTypeConverterFactory()) | ||
)); | ||
|
||
$update->prepare($gateway->getConnection()); | ||
$update->executePrepared([ | ||
'id' => 1, | ||
'name' => 'New name' | ||
]); | ||
$update->executePrepared([ | ||
'id' => 2, | ||
'name' => 'Even newer name' | ||
]); | ||
|
||
``` | ||
|
||
|
||
## `WhereClauseFragment` and `HavingClauseFragment` | ||
|
||
These fragments add an expression generated by a `Condition` instance to the `WHERE` or `HAVING` clause of | ||
a `Statement` being built, respectively. | ||
|
||
`Condition` instances can be used directly in the query methods of `TableGateway` as they implement | ||
the `FragmentBuilder` interface. This will add their expressions to the `WHERE` clause due to their `getFragment()` | ||
methods returning `WhereClauseFragment`: | ||
```PHP | ||
$gateway->select([ | ||
// ... | ||
$gateway->isNotNull('field') // Returns a Condition | ||
// | ||
]) | ||
``` | ||
|
||
If a `Condition` should be applied to the `HAVING` clause, you should explicitly use `HavingClauseFragment`: | ||
```PHP | ||
$gateway->select([ | ||
// ... | ||
new HavingClauseFragment( | ||
$gateway->sqlCondition('count(self.field) > 1') | ||
) | ||
// ... | ||
]) | ||
``` | ||
|
||
## `SelectListFragment` and `ReturningClauseFragment` | ||
|
||
These fragments modify the output list of `SELECT` statement or the `RETURNING` clause of | ||
`DELETE` / `INSERT` / `UPDATE`, respectively. Actual modification is performed by an instance of | ||
`TargetListManipulator` used to configure the fragment. | ||
|
||
It is rarely needed to use these directly as there are builders and builder methods available: | ||
```PHP | ||
$gateway->update([ | ||
// ... | ||
$gateway->returningColumns() | ||
->primaryKey() | ||
]); | ||
|
||
$gateway->select([ | ||
// ... | ||
$gateway->outputExpression("coalesce(self.a, self.b) as ab") | ||
]); | ||
``` | ||
|
||
## `JoinFragment` | ||
|
||
Joins an implementation of `SelectProxy` to the current statement using the given `JoinStrategy` implementation. | ||
Can be additionally configured by a join `Condition`. | ||
|
||
It is recommended to use `JoinBuilder` and related `GenericTableGateway::join()` method rather than instantiating | ||
this class directly: | ||
```PHP | ||
$documentsGateway->select([ | ||
// ... | ||
$documentsGateway->join('documents_tags') // Creates a SelectProxy for a given table | ||
->onForeignKey() // configures join condition | ||
->lateralLeft() // configures join strategy (LateralSubselectStrategy) | ||
->useForCount(false) // join will not be used by executeCount() | ||
]); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters