PHP code example of tiny-blocks / http-query

1. Go to this page and download the library: Download tiny-blocks/http-query library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

tiny-blocks / http-query example snippets




declare(strict_types=1);

use Psr\Http\Message\ServerRequestInterface;
use TinyBlocks\HttpQuery\Offset\Criteria;
use TinyBlocks\HttpQuery\Operator;
use TinyBlocks\HttpQuery\Schema;
use TinyBlocks\HttpQuery\Sort;
use TinyBlocks\HttpQuery\ValueKind;

$schema = Schema::create()
    ->maxPerPage(maxPerPage: 100)
    ->sortable(fields: ['created_at', 'id'])
    ->defaultSort(sort: Sort::fromExpression(expression: '-created_at'))
    ->filterable(field: 'total', operators: [Operator::GREATER_THAN_OR_EQUAL], valueKind: ValueKind::INTEGER)
    ->filterable(field: 'status', operators: [Operator::EQUAL, Operator::IN], allowedValues: ['paid', 'pending']);

# GET /v1/orders?filter=status==paid;total=ge=100&sort=-created_at,id&page[number]=3&page[size]=20
/** @var ServerRequestInterface $request */
$criteria = Criteria::fromQuery(schema: $schema, request: $request);



declare(strict_types=1);

use TinyBlocks\HttpQuery\Offset\Criteria;
use TinyBlocks\HttpQuery\Operator;

# filter=status==paid;total=ge=100  ->  a validated list<Comparison>.
/** @var Criteria $criteria */
foreach ($criteria->comparisons() as $comparison) {
    $comparison->field();                                 # 'status', then 'total'.
    $comparison->values();                                # ['paid'], then ['100'].
    $comparison->firstValue();                            # The first compared value, 'paid'.
    $comparison->hasField(field: 'status');               # True for the status leaf.
    $comparison->hasOperator(operator: Operator::EQUAL);  # True for an equality leaf.
}



declare(strict_types=1);

use TinyBlocks\HttpQuery\Direction;
use TinyBlocks\HttpQuery\Offset\Criteria;

# sort=-created_at,id  ->  the effective Sort, ordered as requested.
/** @var Criteria $criteria */
foreach ($criteria->sort()->orders() as $order) {
    $order->field();                               # 'created_at' then 'id'.
    $order->direction() === Direction::DESCENDING; # true then false.
}



declare(strict_types=1);

use Psr\Http\Message\ServerRequestInterface;
use TinyBlocks\HttpQuery\Offset\Criteria;
use TinyBlocks\HttpQuery\Schema;

# GET /v1/orders?page[number]=3&page[size]=20
/** @var ServerRequestInterface $request */
$criteria = Criteria::fromQuery(schema: Schema::create(), request: $request);

/** @var iterable<mixed> $items */
$page = $criteria->page(total: 480, items: $items);

$page->hasNext();     # true
$page->metadata();    # The JSON:API meta contents.
$page->totalPages();  # 24



declare(strict_types=1);

use Psr\Http\Message\ServerRequestInterface;
use TinyBlocks\HttpQuery\Offset\Criteria;
use TinyBlocks\HttpQuery\Schema;

# GET /v1/orders?page[number]=2&page[size]=20
/** @var ServerRequestInterface $request */
$criteria = Criteria::fromQuery(schema: Schema::create(), request: $request);

/** @var iterable<mixed> $items */
$slice = $criteria->slice(items: $items);

$slice->hasNext(); # Inferred from the extra fetched element.



declare(strict_types=1);

use Psr\Http\Message\ServerRequestInterface;
use TinyBlocks\HttpQuery\Cursor\Criteria;
use TinyBlocks\HttpQuery\Schema;

$schema = Schema::create()->sortable(fields: ['created_at', 'id']);

# GET /v1/orders?sort=-created_at,id&page[cursor]=BS3RvKY4LqEjYD19mQ0mCpJ&page[size]=20
/** @var ServerRequestInterface $request */
$keyset = Criteria::fromQuery(schema: $schema, request: $request)->keyset();

$keyset->limit()->toInteger();  # The page size, 20.
$keyset->orders();              # The list<Order> the seek is ordered by.
$keyset->cursor();              # ['created_at' => ..., 'id' => ...], null per field on the first page.



declare(strict_types=1);

use TinyBlocks\HttpQuery\Cursor\Keyset;

/** @var Keyset $keyset */
/** @var iterable<array{id: int, created_at: string}> $items */
$cursorPage = $keyset->page(items: $items);

$cursorPage->next();    # The Cursor\Pagination for the next page, or null.
$cursorPage->hasNext(); # Inferred from the extra fetched element.

$cursorPage->map(transformation: static fn(array $row): array => ['id' => $row['id']]);



declare(strict_types=1);

use TinyBlocks\HttpQuery\Clause\Every;
use TinyBlocks\HttpQuery\Clause\FilterColumns;
use TinyBlocks\HttpQuery\Clause\Filters;
use TinyBlocks\HttpQuery\Clause\SeekClause;
use TinyBlocks\HttpQuery\Clause\SortClause;
use TinyBlocks\HttpQuery\Comparison;
use TinyBlocks\HttpQuery\Cursor\Keyset;

/** @var Keyset $keyset */
/** @var list<Comparison> $comparisons The validated comparisons read from Criteria::comparisons(). */
$columns = FilterColumns::create()
    ->plain(field: 'status', column: 'pay.status')
    ->plain(field: 'created_at', column: 'pay.created_at')
    ->wrapped(field: 'id', column: 'pay.id', binding: 'UUID_TO_BIN(%s)');

# Filters renders the comparisons, SeekClause renders the keyset predicate, both SqlClause.
$predicate = Every::of(
    Filters::from(columns: $columns, comparisons: $comparisons),
    SeekClause::from(keyset: $keyset, columns: $columns)
);

$sort = SortClause::from(orders: $keyset->orders(), columns: $columns);
$limit = $keyset->limit()->plusOne();

$where = $predicate->isEmpty() ? '' : sprintf(' WHERE %s', $predicate->sql());
$sql = sprintf('%s%s ORDER BY %s LIMIT %d', $base, $where, $sort->sql(), $limit->toInteger());
# Bind $predicate->parameters() and run $sql against your store.



declare(strict_types=1);

use TinyBlocks\HttpQuery\Clause\FilterColumn;
use TinyBlocks\HttpQuery\Clause\Fragment;
use TinyBlocks\HttpQuery\Clause\OperatorRenderer;
use TinyBlocks\HttpQuery\Comparison;
use TinyBlocks\HttpQuery\Operator;

final readonly class CaseInsensitiveContains implements OperatorRenderer
{
    public function render(FilterColumn $column, int $offset, Comparison $comparison): Fragment
    {
        $name = sprintf('filter_%d', $offset);
        $bind = sprintf($column->binding(), sprintf(':%s', $name));

        return Fragment::of(
            sql: sprintf('LOWER(%s) LIKE LOWER(%s)', $column->column(), $bind),
            parameters: [$name => sprintf('%%%s%%', $comparison->firstValue())]
        );
    }

    public function supports(Operator $operator): bool
    {
        return $operator === Operator::EQUAL;
    }
}

# Filters::from($columns, $comparisons, new CaseInsensitiveContains());



declare(strict_types=1);

use Psr\Http\Message\ServerRequestInterface;
use TinyBlocks\HttpQuery\Offset\Criteria;
use TinyBlocks\HttpQuery\Schema;

$schema = Schema::create()->sortable(fields: ['created_at', 'id']);

# GET /v1/orders?filter=status==paid&sort=-created_at,id&page[number]=3&page[size]=20
/** @var ServerRequestInterface $request */
$criteria = Criteria::fromQuery(schema: $schema, request: $request);

/** @var iterable<mixed> $items */
$response = $criteria->page(total: 480, items: $items)->toResponse(baseUri: '/v1/orders');