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

Experience Laravel Package

ibexa/experience

Ibexa Experience is the Composer metapackage for the Experience edition of Ibexa DXP. It installs the Symfony-based platform and bundled components for content management, page building, personalization, and customer-facing digital experiences. Requires access to Ibexa's commercial package repositor...

Deep Wiki
Context7

Getting Started

ibexa/experience is a Composer metapackage, not an application. It is the Enterprise feature set of Ibexa DXP: requiring it pulls in ibexa/content, ibexa/admin-ui, ibexa/page-builder, ibexa/scheduler, ibexa/forms, ibexa/personalization, ibexa/customer-center and the related connectors. There is no src/ in this package worth reading — your code lives in your project, and your extension points live in the Ibexa\Contracts\* packages that ship alongside it.

Minimal steps

  1. Do not composer require this into an existing Symfony app. Start from the project skeleton so you get the directory layout, config/packages/ibexa.yaml, and the Symfony Flex recipes:
    composer create-project ibexa/experience-skeleton my-dxp
    
    (Or clone the Ibexa DXP project template and adjust composer.json to ibexa/experience for the Enterprise tier.)
  2. Configure repository credentials — the ibexa/* packages resolve from updates.ibexa.co, which requires the credentials from your Ibexa support portal in auth.json / COMPOSER_AUTH. Without them, composer install 401s and you will waste an hour blaming the network.
  3. Bring up the required services. Experience tier expects MySQL/PostgreSQL plus Elasticsearch (not optional here, unlike on OSS) and usually Redis/Varnish for HTTP cache. docker-compose from the skeleton is the fastest path.
  4. Install and check the license. Enterprise features (Page Builder, Forms, Personalization, Scheduler UI) need a valid license configured; dev installs typically run in a limited/trial mode. Verify with a plain page render plus a Page Builder edit before writing any code.
  5. Where to look first, in this order:
    • composer.json → the exact ibexa/* set and version. This tells you which features exist at all.
    • config/packages/ibexa.yaml → ibexa.system.<siteaccess> (languages, repositories, design/theme, var dirs) and ibexa.repositories.
    • config/bundles.php → then read each bundle's DependencyInjection/Configuration.php in vendor/ibexa/<pkg>/src/bundle.
    • vendor/ibexa/contracts/ → the interfaces you are supposed to implement. Code against these, never against Ibexa\Core\* internals.
  6. First real use case: build a landing page in Page Builder. Create a Content Type with a Page field, drop two custom blocks into it. That single exercise touches almost everything you will do day-to-day: content type definitions, field types, block definitions, template resolution, view caching, and permissions.

Implementation Patterns

Feature-by-feature extension, not framework hacking. Almost every requirement maps to one of five extension points:

Need Pattern
New content modelling primitive Custom Field Type (Contracts + storage converter + ibexa.field_type tag)
New editable page component Page Builder Block (block definition class + template + YAML/attribute config)
New scheduled job Scheduler EventType implementation registered with the scheduler tag
New form input Form field mapper / ibexa_form extension
New API surface GraphQL schema extension (.graphql/YAML mapping + resolver) or REST controller

Custom block, the canonical example

// src/Block/MapBlock.php
use Ibexa\FieldTypePage\FieldType\Page\Block\Definition\BlockDefinition;
use Ibexa\Contracts\FieldTypePage\FieldType\Page\Block\Definition\BlockAttributeDefinition;

final class MapBlock extends BlockDefinition
{
    public function getName(): string { return 'map_block'; }

    public function getAttributes(): array
    {
        return [
            'latitude'  => new BlockAttributeDefinition('latitude', 'number'),
            'longitude' => new BlockAttributeDefinition('longitude', 'number'),
            'zoom'      => new BlockAttributeDefinition('zoom', 'number'),
        ];
    }

    public function getViewTemplate(): string
    {
        return '@ibexadesign/blocks/map.html.twig';
    }
}

Register it where your bundle loads the Page Builder block definitions, then place the Twig template under your theme/design directory — not a global templates/blocks/ path, which is the most common reason "the block renders but my template is ignored."

Template overrides via the design engine. Override vendor templates by matching the design/theme path in ibexa.system.<siteaccess>.design, or by adding your bundle's template dir with a higher-priority design. Never edit vendor/; you will lose it on the next composer update and the metapackage upgrades everything in lockstep.

Configuration over code. Semantic config is the cheapest customisation: content views, pagination, search, personalization scenarios, scheduler defaults, and admin UI menus all have YAML config. Prefer config/packages/*.yaml plus a bundle Extension class over decorating services.

Service decoration for behaviour. For anything not covered by config, decorate the Contract service:

services:
  App\Decoration\MyContentService:
    decorates: Ibexa\Contracts\Core\Repository\ContentService
    arguments: ['@.inner']

This survives minor upgrades far better than subclassing core services.

Migrations, not manual content type clicking. Use the Ibexa Migrations bundle to version content types, roles, policies, and languages in YAML/PHP, then run them in CI:

php bin/console ibexa:migrations:generate --type=content_type
php bin/console ibexa:migrations:migrate

Permissions and limitations. Anything you build that reads content at scale should respect the Repository API's permission layer rather than raw SQL. Custom Limitation types (e.g. "own department") register a LimitationType and a policy provider — do this early; retrofitting permissions into an existing feature is painful.

Workflow and editorial. Editorial review goes through Symfony Workflow configured against the content draft states, not through custom "publish" buttons.

Gotchas and Tips

  • There is nothing to patch here. Bugs belong to a specific sub-package. When something breaks, find the owning bundle first (composer why ibexa/<pkg>) and open the issue there. Filing against ibexa/experience gets you nothing.
  • Upgrade lockstep is mandatory. Every ibexa/* package must share the same minor version. Pin the metapackage ("ibexa/experience": "4.6.*") rather than letting composer update walk the whole DXP forward. A partial upgrade produces cryptic container-compile errors from mismatched Contracts.
  • Elasticsearch is a hard dependency on this tier. If indexing is stale after adding a Field Type or changing a Content Type, you get empty views and no error: run a full reindex and clear the HTTP cache. Field type changes also require the Content Type to be re-saved so the schema is regenerated.
  • Licensing fails quietly-ish. Enterprise features degrade or refuse to run without a valid license, and the message is often in a log rather than the UI. Put the license into env/secret management and make sure CI and staging have it, or "works locally, broken in staging" becomes a recurring ticket.
  • Caches are layered and every layer lies. Symfony container cache, view cache, HTTP cache (Varnish/Fastly), search index, and Page Builder's own block cache. When a template or block change does not appear, clear them in that order — cache:clear, then the HTTP cache pool, then reindex only if content shape changed. Blocks are cached inside the rendered page; if a block shows stale data, suspect the block cache TTL before your controller.
  • Always resolve against Ibexa\Contracts\*. Autowiring against a Core service works until a minor release moves it. php bin/console debug:container --tag=ibexa.field_type (and the equivalent tags for blocks, form fields, scheduler events) is the fastest way to discover what is actually registered.
  • debug:config ibexa is your friend. Siteaccess-aware semantic config resolves differently per siteaccess and per repository; what you see in YAML is not necessarily what the container ended up with.
  • Multi-site and multi-repository multiply every assumption. Anything keyed by content ID, location ID, or language must be siteaccess-aware. Test with at least two siteaccesses and two languages from day one; retrofitting i18n into a single-language build is a rewrite.
  • Page Builder attribute edits need explicit invalidation. When your block pulls external data (a map API, a product feed), cache it deliberately with a short TTL and a key that includes the block ID and siteaccess. Otherwise an editor changes an attribute and sees nothing change.
  • GraphQL schema changes require validation. Extending the schema means updating the domain content type mapping too; a mismatched mapping fails at query time, not at build time, so add a schema smoke test to CI.
  • Small community footprint. With stars in the low tens, Stack Overflow and GitHub issues will not rescue you — budget for the official docs and the commercial support channel. That also means: read the changelog for every DXP minor release before upgrading, since deprecations land there and rarely in blog posts.
  • Do not build business logic into templates or block definitions. Blocks are presentation. Put logic in a service and expose a Twig function; Page Builder rendering happens inside cached fragments where side effects (writes, API POSTs) will be executed unpredictably.
  • Extension point worth knowing about: content view matchers and the view builder let you route many content types to one template without touching PHP — learn this before writing a custom controller per content type.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons