Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fiquela.io/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Namespace: FQL\Results ResultsProvider is the abstract base class for result sets returned by Query::execute(). It implements IteratorAggregate and provides methods to iterate, fetch individual rows, perform aggregate calculations, and export results to a file. You never instantiate ResultsProvider directly — you receive it from execute().
use FQL\Query\Provider;

$results = Provider::fromFile('orders.json')
    ->select('id', 'total', 'status')
    ->where('status', \FQL\Enum\Operator::EQUAL, 'paid')
    ->execute();

echo $results->count();      // 42
echo $results->sum('total'); // 18340.00

Subtypes

Query::execute() returns one of two concrete implementations depending on query complexity:
ClassWhen used
Results\StreamSimple queries without joins or sorting. Processes data lazily as a generator — low memory usage.
Results\InMemoryQueries with joins, sorting, or DISTINCT. Loads all rows into an ArrayIterator before returning.
Results\DescribeResultReturned by describe() queries. Contains one row per column with schema statistics (types, completeness, uniqueness). See DESCRIBE.
You can force a specific mode by passing the class name to execute():
use FQL\Results\InMemory;

$results = $query->execute(InMemory::class);
Both classes expose the same ResultsProvider interface described below.

Iteration

getIterator()

Returns a Traversable over all result rows. Each row is an associative array.
public function getIterator(): \Traversable
ResultsProvider implements IteratorAggregate, so you can use it in a foreach loop directly.
foreach ($results as $row) {
    echo $row['name'];
}

Fetching rows

fetchAll()

Yield all rows as a Generator. Optionally hydrate each row into a DTO class.
public function fetchAll(?string $dto = null): \Generator
dto
string | null
Fully qualified class name of a DTO. When provided, each row is mapped to an instance of that class using constructor parameters or public properties.
returns
Generator
Yields associative arrays (or DTO objects when $dto is set).
foreach ($results->fetchAll() as $row) {
    echo $row['id'] . ': ' . $row['name'];
}

// Hydrate into a DTO
class ProductDto {
    public function __construct(
        public readonly int $id,
        public readonly string $name,
        public readonly float $price,
    ) {}
}

foreach ($results->fetchAll(ProductDto::class) as $product) {
    echo $product->name;
}

fetch()

Return the first row only, or null if the result set is empty.
public function fetch(?string $dto = null): mixed
dto
string | null
Optional DTO class name for hydration.
returns
array | object | null
The first row as an associative array, a DTO object, or null.
$product = $results->fetch();
if ($product !== null) {
    echo $product['name'];
}

fetchSingle()

Return a single field value from the first row.
public function fetchSingle(string $field): mixed
field
string
required
Field name, including dot-notation for nested fields (e.g. address.city).
returns
mixed
The value of the field, or null if the row or field does not exist.
$name = $results->fetchSingle('name');
$city = $results->fetchSingle('address.city');

fetchNth()

Yield every nth row, or every even/odd row.
public function fetchNth(int|string $n, ?string $dto = null): \Generator
n
int | 'even' | 'odd'
required
  • Integer: yield every nth row (1-indexed count).
  • 'even': yield rows at even positions (0-indexed: 0, 2, 4…).
  • 'odd': yield rows at odd positions (0-indexed: 1, 3, 5…).
dto
string | null
Optional DTO class name.
Throws: InvalidArgumentException for invalid $n values.
// Every 3rd row
foreach ($results->fetchNth(3) as $row) { ... }

// Even-positioned rows
foreach ($results->fetchNth('even') as $row) { ... }

exists()

Return true if the result set contains at least one row.
public function exists(): bool
if ($results->exists()) {
    echo 'Found records';
}

Counting

count()

Return the total number of rows in the result set.
public function count(): int
Results\Stream caches the count internally after the first call, so repeated count() calls do not re-read the file.
echo $results->count(); // e.g. 1024

Aggregation

Interface: FQL\Interface\Aggregable The Aggregable interface defines four aggregate methods: sum(), avg(), min(), and max(). It is implemented by Results\Stream and Results\InMemory. These methods iterate the result set and compute aggregate values. For Results\Stream, computed values are cached so that repeated calls do not re-read the stream.
DescribeResult does not implement Aggregable and does not provide these methods. If you need aggregation on a describe result, run a separate query.

sum()

public function sum(string $field): float
field
string
required
Field name to sum. Non-numeric values are treated as 0.

avg()

public function avg(string $field, int $decimalPlaces = 2): float
field
string
required
Field name to average.
decimalPlaces
int
Number of decimal places in the result (default 2).

min()

public function min(string $field): float
field
string
required
Field name to find the minimum of.

max()

public function max(string $field): float
field
string
required
Field name to find the maximum of.
$total   = $results->sum('price');        // 4850.00
$average = $results->avg('price', 2);     // 121.25
$lowest  = $results->min('price');        // 9.99
$highest = $results->max('price');        // 499.00

Exporting

into()

Write all result rows to a file. The output format is determined by the file extension in the FileQuery string. Returns a FileQuery with the effective query defaults applied, which you can use to read the written file back.
public function into(string|FileQuery $target): ?FileQuery
target
string | FileQuery
required
A file path string (e.g. output/report.csv) or a FileQuery object. The directory is created automatically if it does not exist.
returns
FileQuery | null
A FileQuery object with defaults applied (ready for reading the written file back), or null when running under EXPLAIN ANALYZE mode. The returned FileQuery contains the effective query path — for example, * for CSV/JSON/NDJSON, or rows.row for XML.
Throws: FileQueryException, InvalidFormatException, InvalidArgumentException
// Export to JSON — returns FileQuery with effective query
$fileQuery = $results->into('json(output/filtered.json).root.items');

// Export to CSV
$fileQuery = $results->into('csv(output/report.csv)');

// Export to XML
$fileQuery = $results->into('xml(output/report.xml).ROOT.ROW');

// Using a FileQuery object
use FQL\Query\FileQuery;
$fileQuery = $results->into(new FileQuery('csv(exports/products.csv)'));

// Read back the written file using the returned FileQuery
if ($fileQuery !== null) {
    $readBack = \FQL\Query\Provider::fromFileQuery((string) $fileQuery)
        ->selectAll()
        ->execute();
}
Calling aggregation methods (sum, avg, etc.) before into() on a Results\Stream will exhaust the generator. Call into() first, or use Results\InMemory.