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

Ezplatform Site Api Laravel Package

netgen/ezplatform-site-api

Netgen Site API offers a developer-friendly abstraction over the eZ Platform/Ibexa content repository, simplifying content and location queries, field access, and template rendering. It reduces boilerplate and speeds development of websites and APIs.

Deep Wiki
Context7

Getting Started

  1. Install the package matching your platform: composer require netgen/ezplatform-site-api for eZ Platform 2.x. If you are on Ibexa 3.3+ (this repo is the older, renamed lineage), use netgen/ibexa-site-api instead — the namespaces become Netgen\IbexaSiteApi\*.
  2. Register the bundle: Netgen\EzPlatformSiteApi\EzPlatformSiteApiBundle in app/AppKernel.php (or config/bundles.php on Flex). The bundle wires the Site and Finder services plus the Twig extension.
  3. Minimum config: add config/packages/ng_site_api.yaml (or app/config/config.yml) with at least content_view / location_view entries once you start rendering. Everything else works out of the box; the site and finder services are auto-registered.
  4. Look here first: Netgen\EzPlatformSiteApi\API\Site (entry point for loading content/locations), Netgen\EzPlatformSiteApi\API\Finder (the SQL query builder), Netgen\EzPlatformSiteApi\API\Query (the fluent query DSL), and the Twig extension (ng_view, ng_image, ng_field_*).
  5. First use case — replace a legacy $contentService->loadContent($id) with the Site API:
    use Netgen\EzPlatformSiteApi\API\Site;
    
    public function show(Site $site, int $id)
    {
        $content = $site->findContent($id);       // Content API object
        $location = $site->findLocation($id);
        $root     = $site->getRootLocation();     // siteaccess-aware
    }
    
    The returned Content/Location objects expose typed ->fields and ->innerContent (raw eZ object) — most controller code simply stops calling the repository.

Implementation Patterns

Finder-first list pages. The Finder is the reason most teams adopt this bundle: it compiles a Query into a single SQL statement instead of the legacy search stack.

use Netgen\EzPlatformSiteApi\API\Query;

$query = Query::create()
    ->withContentType('article')
    ->withParentLocation($location->id)       // or withParentLocationId($id)
    ->withIsVisible(true)
    ->withIsMainLocation(true)
    ->sortBy('published', Query::SORT_DESC)
    ->slice($offset, $limit);

$items = $finder->findContent($query);         // array of Content
$one   = $finder->findOneContent($query);      // Content|null
$total = $finder->countContent($query);        // int

findLocations(), findOneLocation(), countLocations() are the equivalents for location results.

Build reusable queries. Extract a Query factory (a small service or static method on a domain class) and inject the Finder. This keeps controllers thin and lets you unit-test query criteria. Filter helpers include withContentType, withContentTypeGroup, withSection, withField, withFieldRelation, withRemoteIdIn, withContentIdIn, withLocationIdIn, withIsVisible, withIsMainLocation, withLanguages, and sortBy overloads for content fields, dates and location priority.

Controllers render through the view layer. Instead of hand-wiring templates, name a view:

{{ ng_view(content, 'full') }}          {# preferred #}
{{ ng_render(ng_view(content, 'line')) }} {# older alias, still valid #}

Configure the mapping once in ng_site_api.content_view / location_view using match value types (Id\ContentType, Id\Section, Id\Content, Id\Location, Id\ParentContentType, etc.). Views are matched in insertion order, so put the most specific match blocks first.

Fields and images. Field access is lazy and typed:

{{ content.fields.title.value }}
{{ content.fields.body.xml|raw }}
<figure>{{ ng_image(content.fields.image, 'large', {class: 'hero'}) }}</figure>
<img src="{{ ng_image_alias(content.fields.image, 'thumb').uri }}" width="…" height="…">

ng_image_alias returns an object with uri, width, height, name — use it when you need attributes the tag helper doesn’t expose.

Pagination. Wrap a Finder query directly with Pagerfanta using the shipped adapters (Netgen\EzPlatformSiteApi\Core\Site\Pagination\Pagerfanta\ContentSearchAdapter / LocationSearchAdapter), then render with pagerfanta(pager) in Twig. This avoids hand-rolling countContent + slice.

Integration tips.

  • Inject Site/Finder via autowiring (aliases are registered) or with netgen.ezplatform_site.site / netgen.ezplatform_site.finder service IDs.
  • Use $content->innerContent when you must call a legacy service that expects an eZ\Publish\API\Repository\Values\Content\Content.
  • For ESI/edge-side includes, point the fragment controller at your normal view controller action — the view layer is HTTP-safe and stateless.
  • Custom view matching: implement the value-object matcher interface and tag it; the bundle picks it up for match entries like MyApp\Match\Foo: 123.

Gotchas and Tips

  • This repo is the legacy lineage. ezplatform-site-api is frozen around eZ Platform 2.x (last release Feb 2023). On Ibexa you want netgen/ibexa-site-api (Netgen\IbexaSiteApi\*). Mixing the two is the most common source of "service not found" errors.
  • GPL-2.0. This is a copyleft license — check with legal before shipping in a closed-source distribution. Netgen has historically offered commercial terms; don’t assume MIT.
  • The Finder is SQL, not a search engine. withField('body', 'LIKE', '%foo%') scans content attribute rows and will crawl on large installs. For editorial full-text search use Solr with the native search API; keep the Finder for structured, location- or type-scoped listings.
  • Default filtering is not automatic. Always be explicit with withIsVisible(true) (and withIsMainLocation(true) for content that has multiple locations) or you will leak drafts/invisible content into listings.
  • Site scoping is real. $site->findContent() / the Finder are scoped to the current siteaccess root location. Content outside it returns null even though $repository->getContentService()->loadContent() would find it — a frequent surprise when debugging “missing” items from a CLI or admin context.
  • Fields and relations are lazy. Accessing content.fieldRelations or content.fields.related_items triggers additional repository calls. On a 100-item listing that’s 200 queries; either preload with withFieldRelation(), select only needed fields, or accept a bounded page size.
  • View config is cached. After touching ng_site_api.content_view, run bin/console cache:clear (and in prod, warm the cache). A miss falls back to the default ezplatform templates silently — no error, just the wrong output.
  • ng_* Twig functions live in the bundle’s extension. “Unknown function ng_view” means the bundle isn’t registered for that kernel environment, or you are rendering from a bundle template that runs before the extension loads.
  • Image variations must exist. ng_image/ng_image_alias will throw if the requested variation isn’t defined under system.<site>.image_variations in ezplatform.yml / ibexa.yaml. Define new variations there, not in ng_site_api.
  • Type juggling in match. Id\Content: 42 (int) will not match '42' (string) from YAML in all cases — keep the value type consistent with what the matcher expects.
  • Extension points. Decorate netgen.ezplatform_site.site or ...finder, and register custom Query subclasses as services if you want a domain-specific DSL. The query builder is intentionally extensible; extending Query and adding whereX() helpers is the cleanest way to avoid duplicating criteria across controllers.
  • Debugging tip. The Finder compiles to SQL; enable the Doctrine SQL logger in dev and grep for your content-type identifiers. That reveals missing is_visible / is_main_location conditions faster than stepping through the API.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib