Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fieldtype Query Laravel Package

ibexa/fieldtype-query

Ibexa Query Field Type lets content managers map an executable Repository Query directly to a content field, making dynamic, query-driven content easy to configure within Ibexa DXP. Part of the Ibexa DXP package suite.

View on GitHub
Deep Wiki
Context7

Getting Started

Install & confirm it is active. The Field Type ships as part of Ibexa DXP and is normally pulled in by the ibexa/experience / ibexa/dxp meta-packages. If you are on a slim install:

composer require ibexa/fieldtype-query:^5.0   # match your DXP major (^4.6 for v4.6 LTS)

Pin the package to the same major as your DXP install — the package is versioned in lockstep with Ibexa (4.6.x, 5.0.x), and 5.x requires PHP 8.3 + Symfony 7. Confirm the Field Type appears when you add a field to a content type in Admin → Content Types → [type] → Add field (search for Query). If it does not, the bundle is not registered — check config/bundles.php and clear the cache.

Read the source first — it is small. Everything you need is in vendor/ibexa/fieldtype-query/src/:

  • FieldType/ — the Field Type class, its Value object and the field-definition settings/form mappers (this is where the query configuration schema lives).
  • Resources/config/ — service definitions, Field Type registration, the admin form (query builder) wiring.
  • Resources/views/ — the editing template and any GraphQL/REST wiring.

Twenty minutes here answers every question this package raises faster than the docs do.

First use case — a "latest/related" block. Create a Folder (or Landing Page) content type and add a Query field, e.g. related_query. In the field definition configure it to search ContentTypeIdentifier = article, sort by DatePublished desc, limit 5. Then in a controller:

$value = $content->getFieldValue('related_query');
$query = $value->getQuery();               // Ibexa\Contracts\Core\Repository\Values\Content\Query

$results = $this->contentService->findContent($query);
// or ->findContentInfo($query) if you only need metadata for a listing

Pass $results to the template and render names/URLs with ibexa_content_name / ibexa_path. The Field Type stores and resolves the query definition — your code executes it, which is exactly what makes it composable.

Implementation Patterns

Wrap execution in one service. Do not scatter findContent() calls through controllers/templates. A small resolver gives you one place for caching, permission filtering and fallbacks:

final class QueryFieldResolver
{
    public function __construct(private ContentService $contentService) {}

    public function resolve(Content $content, string $fieldIdentifier, int $limit = 10, int $offset = 0): ContentList
    {
        $query = clone $content->getFieldValue($fieldIdentifier)->getQuery();
        $query->limit = $limit;
        $query->offset = $offset;

        return $this->contentService->findContent($query);
    }
}

Always clone before paginating. The Query object exposes mutable $limit, $offset, $sortClauses, $filter. Mutating the one returned by the value object leaks state if the same content/field is rendered twice on a page (header + footer + a block). Clone first, then override limit/offset from the request (?page=N).

Hand-picked beats automatic — combine field types. The classic editorial pattern is a relationlist field ("manual picks") that, when empty, falls back to the Query field ("automatic"). Editors get an override without needing a developer:

{% set items = manual_picks is not empty ? manual_picks : query_results %}

Use it as a per-content-type "config object". Because the query belongs to the field definition / content structure, it is ideal for reusable listings driven by content: "products in category X", "news tagged Y". Duplicating the same query across many content types is the smell that you want a shared query content item or a custom Field Type instead.

GraphQL / headless. The field is exposed through Ibexa's GraphQL schema (the package ships the resolver wiring — the deprecated @=resolver syntax was replaced in v5.0.7 / v4.6.29, so check your custom config/graphql/types overrides if you extend the schema). Note that a headless consumer receives the query definition, not the results; the actual content still has to be fetched by the client or by your own endpoint.

Content migrations. The query configuration ends up as a nested array in the Field Definition settings (filter/criteria, sort clauses, limit, offset). Define it in ibexa/migrations alongside the field definition so staging and production stay identical — never configure queries only through the admin UI on production.

Gotchas and Tips

  • No runtime context inside the query. The stored query cannot reference the current content, current location, current user or request parameters — there are no placeholders. "Other articles in the same category as this one" is not expressible; build that filter in PHP by merging criteria into the cloned query, or generate it in a controller.
  • Configuration is content-type level, not per object. Editing the query in the field definition changes the results for every content object of that type at once. Treat it as schema, version it in migrations, and review it in code review.
  • Searches are not permission-filtered. ContentService::findContent() will return content the current user may not be allowed to read in some configurations — filter with canRead/canUser or hide at render time. Do not assume the Field Type did it for you.
  • No cache-dependency tracking for arbitrary queries. A page cached while showing "latest 5 news" is not automatically purged when article #6 is published. Either tag responses with the content types/IDs involved via the HTTP cache API, or give query-driven blocks a short TTL. This is the #1 production surprise with this feature.
  • Search engine parity. Criteria behave differently on the Legacy engine versus Solr/Elasticsearch (scoring, FullText, facets, custom fields). Test the same content type against the engine you actually run in production, and remember to reindex after changing index-time fields.
  • Empty/degenerate queries. A query with no filter returns everything up to the default limit — never rely on that default; always set limit explicitly in the field configuration and clamp it in code when paginating.
  • Admin UI offers a subset of criteria. Complex criteria (nested logical operators, custom criteria) often have to be authored directly in the settings array / migration rather than through the query builder form. Inspect the stored array with var_dump($fieldDefinition->getFieldSettings()) to learn the shape.
  • Identifier rebranding. v5.0 rebranded Field Type identifiers (IBX-9947) — content types created on older versions referencing the previous identifier need updating/migrating when you upgrade. If a field suddenly has no value after an upgrade, check the identifier first.
  • Debugging. $query->filter is a deeply nested Criterion tree — dump it with json_encode rather than print_r. To see what actually ran, decorate the repository search service or enable the Ibexa\FieldTypeQuery log channel; the compiled query (filter + sort + limit) is the fastest way to explain "why is this empty?".
  • Licensing. The package is dual-licensed Ibexa BUL / GPLv2 — it is not MIT. Confirm your subscription covers the environments you deploy to before shipping it into a client project.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json