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

Sulu Event Bundle Laravel Package

manuxi/sulu-event-bundle

Sulu Event Bundle adds event management to Sulu CMS, letting editors create and organize events with dates, locations, and details, then display them through flexible templates. Integrates cleanly with Sulu’s admin and frontend.

View on GitHub
Deep Wiki
Context7

Getting Started

This is still a Symfony/Sulu bundle, not a Laravel package — no artisan, no Eloquent, no Blade, no config/*.php service providers. It's Composer + Symfony bundles + Doctrine + Twig + YAML/XML config. The service container, facades-free DI, and bin/console will feel familiar; everything else is Sulu-flavoured.

Minimal path to a running feature:

  1. composer require manuxi/sulu-event-bundle — check composer.json for the Sulu major it supports (^2.x) and the PHP floor; a Sulu 3 project will not accept it. Recent releases have moved quickly (v3.1.6 → v3.5.0 in a short window) — pin the minor you tested.
  2. Register the bundle in the Sulu kernel (config/bundles.php in Flex-style projects, or registerBundles() in src/Kernel.php). Sulu projects have two kernels — AdminKernel and WebsiteKernel — and this bundle needs to be in both (admin UI and website rendering).
  3. If you're upgrading from an earlier version, run the new upgrade command first: bin/console sulu:events:clean-image-data --dry-run, review the output, then re-run without --dry-run. It strips bloated image data that older releases wrote into the event's templateData — skipping this leaves dirty data in your DB and, per the release notes, can interact badly with the new "full media object" resolution.
  4. Import the bundle's routing for the website kernel if you want the bundled calendar/detail controllers. New in this release: the bundle now provides direct routes for event templates, which simplifies linking to an event detail page from listings and smart content — check Resources/config/routing*.xml for the exact route names.
  5. Run bin/console doctrine:migrations:migrate (or doctrine:schema:update --force in dev). The bundle ships Event and Location entities, and Sulu entities carry extra columns for dimensions, locale, and audit fields.
  6. Grant permissions. In Sulu Admin → Settings → Roles, add the sulu.event.* contexts to your role (names live in Admin/*Admin.php::getSecurityContexts()). Without this the list views load empty and no error appears. This trips up every Laravel dev once.
  7. bin/console cache:clear and clear the Sulu admin cache if admin JS/metadata changed.

Where to look first:

  • src/Admin/ — *Admin.php classes expose exact security contexts, list-view keys, form XML paths, and navigation entries.
  • src/Entity/ — the real schema: fields, translatable properties, Event↔Location associations.
  • src/Content/ (or SmartContent/) — the smart content data provider; the primary integration surface.
  • src/Command/ — the sulu:events:* commands, including clean-image-data and the recurring-events command.
  • src/Mcp/ (or wherever the MCP tool definitions live — grep for mcp) — new in this release, the "agent/automation" surface.
  • Resources/config/forms/*.xml and lists/*.xml — the admin UI is defined in XML, not PHP. This is the Sulu equivalent of Laravel Nova resources.

End-to-end smoke test: create a Location, create an Event tied to it with start/end dates, publish it (the list now shows a publish-state indicator — verify it flips), drop the event smart content into a page template, confirm it renders. Add an editorial tag or category to the event and confirm the smart content filter honours it — that's a new capability in this release.

Implementation Patterns

Admin CRUD comes for free; extend the XML, not the PHP. Sulu generates list and form UIs from XML metadata. To add a field (say registration_url), add the column to the Doctrine entity + migration, then add a <property> to the bundle's form XML — but override the file in your project (config/forms/ with a matching name, or a sulu_admin resource override) rather than editing vendor/. Editing vendor works until the next composer update.

Smart content is the primary integration point — now with category/tag evaluation. In a page template XML:

<property name="events" type="smart_content">
    <meta>
        <title lang="en">Events</title>
    </meta>
    <params>
        <param name="provider" value="events"/>
        <param name="max_per_page" value="10"/>
    </params>
</property>

As of this release the provider evaluates website categories and tags, so editors can build "next 10 talks in the Conference category" without a custom provider. This is the Sulu analogue of a Nova relationship field or a Laravel "block" and it's the reason to install the bundle. Confirm in the admin sidebar that category/tag filters appear — if they don't, you're on a cached admin or a stale template definition.

Decorate the provider for anything bespoke. For "only upcoming", "only at this location", or business rules the smart content params don't model, wrap the bundle's provider with decorates: in services.yaml. You inherit the bundled filtering/search/pagination plus the new category/tag handling. This is the pattern to reach for before forking.

Programmatic creation for imports and seeders. No Eloquent factory — use the Doctrine EntityManager from a console command or Symfony fixture. Two Sulu-specific rules: set locale/dimension explicitly, and set creator/changer to a UserInterface (Sulu audit traits) or the list shows blanks. flush() per N records, not per record. Two recent fixes make this safer: start/end dates are now normalized before persisting (so passing DateTimeImmutable, DateTime, or a partial "date only" string should land in UTC consistently), and referenced locations serialize as plain arrays rather than raw entity references — check any custom serializers you wrote against the old shape.

MCP tools — new, and useful even if you aren't building an agent. The bundle now exposes MCP tools for events and locations. The event-update tool is field-scoped: it only changes the fields you pass, so partial updates are safe. Two practical uses:

  • Wire it into an AI writing assistant (Claude, Cursor, etc.) so editors or devs can query/patch events through a model instead of clicking around.
  • Use it as a stable internal API surface for small automation scripts — you call the tool by name and get schema-shaped payloads back, which beats hand-rolling a controller that duplicates the admin list logic.

For the event-selection payload, ids are now UUID strings (previously sometimes treated as objects) — normalize on the consumer side if you have your own integration reading the same shape.

Automation bundle integration (optional). If sulu/automation-bundle is installed, the bundle now participates in scheduled publish/unpublish, so editors can set "publish Tuesday 9am, unpublish after the last session." The integration is guarded with interface_exists(), so it silently no-ops when the automation bundle isn't present — no dependency to add unless you want the feature.

Website rendering. Sulu does not do implicit routing. The bundle's controllers render Twig from templates/bundles/SuluEventBundle/... — override those files to restyle, don't copy the controller. The new direct routes for event templates mean you can link /events/{slug} from a listing without a controller wrapper; verify the slugs match your content-type convention. For a calendar view, server-render the shell with Twig, then hydrate FullCalendar from a JSON endpoint — either the new direct route or a small JsonResponse controller wrapping the bundle's repository.

Single-event content is now locale-aware. Recent fixes skip events with no content in the requested locale and populate webspaces on website search documents. If you build a "related event" or "next event" widget, expect an empty result instead of a fallback-locale rendering — handle that explicitly in Twig rather than letting a blank block ship.

Reuse over rebuild for the list API. Admin list endpoints are wired to Sulu's ListBuilder/DoctrineListBuilder. If you need events in a headless context, hit the admin endpoint (or the MCP tool) rather than writing a parallel API — you inherit filtering, sorting, and pagination the editors already understand.

Gotchas and Tips

  • Run the new image-data cleanup as an upgrade task, and dry-run first. bin/console sulu:events:clean-image-data --dry-run lists what will change; without it the command mutates rows. This is the only explicit upgrade note in the release and skips quietly if you treat the minor bump as routine.
  • Template data ownership changed — verify your custom templates. The release no longer clears image, pdf, speaker, author in templateData, and the event image is no longer written into templateData (it lives on the proper media field and is resolved as a full media object). If your Twig reads content.templateData.image, migrate to the resolved media field. If you relied on "saving a form wipes the fields I didn't submit", that behaviour is gone.
  • Removed global sulu_admin.smart_content_label override. If your project or another bundle depends on that key being globally set, re-add it explicitly. This is the closest thing to a breaking change in the release; audit custom admin translations.
  • Single event selection ids are UUID strings now. Any consumer that did instanceof or ->getId() against the old selection payload needs a look. Same for locations now serialized as plain arrays rather than entity references.
  • Live-stage events always render. The workflowPlace check was removed for live-stage event content, so an event that's published may appear even if the editor thinks it isn't. Confirm the publish-state indicator in the list before debugging anything else — it's the fastest signal.
  • Empty list ≠ broken code. Nine times out of ten it's missing role permissions on sulu.event.*, or the admin cache holding stale metadata. Role first, then cache:clear (and the Sulu admin cache clear).
  • XML metadata is cached hard. After form/list XML or template <property> changes, run bin/console cache:clear and the admin cache-clear command. A stale cache silently ignores your new field — this also masks the new category/tag smart-content params, making you think the feature isn't shipping.
  • Doctrine, not Eloquent. No $model->save(), no mass assignment, no soft deletes by default. persist() + flush(). flush() in a loop is the classic write-N+1. Run doctrine:schema:validate before every release.
  • No more workflowPlace guard on live content — but the recurring-events command now needs a content workflow. If you've customized or scheduled the recurring command, pass through the workflow argument the bundle expects; a missing workflow silently produces events in the wrong stage. Recurrence does exist in this bundle now (see the recurring-events command) — the old "check before you promise it" caveat is obsolete; instead, test at least one recurring series against the new date-normalization logic.
  • Do not edit vendor/. Override forms, lists, Twig templates in your project. The bundle is small enough that you'll be tempted; the release cadence (four minors in a short window) makes vendor edits especially short-lived.
  • Maturity signal: still low-traffic, but actively maintained. No Stack Overflow corpus, no blog posts, few third-party extensions — but the velocity of v3.1.7–v3.5.0 shows someone is shipping fixes. That means: pin the version, read the changelog each bump (this one has behaviour changes with no deprecation warning), and keep a fork ready for small patches. The upgrade notes here are your primary source, not the docs.
  • Timezone policy up front. Store UTC, render in the site's configured timezone. The new normalization on persist helps at the write boundary but does not fix rendering — verify with a non-UTC site-locale.
  • HTTP cache invalidation. Sulu caches whole pages hard. A smart content block listing events serves a stale "next event" indefinitely. Wire event create/update/delete (and the new automation-bundle scheduled publish/unpublish!) into your cache-invalidation strategy. Automation makes this worse if you ignore it: content flips live on a schedule and the page cache won't notice unless you hook the automation trigger.
  • Search index. Website search documents now get their webspaces populated — a real improvement — but new event entities still need indexing config and a reindex after bulk imports. Silent failure mode: events exist, are indexed, but scoped to no webspace.
  • Debugging toolkit: bin/console debug:container | grep event, doctrine:schema:validate, router:debug (and check the new direct event-template routes here), sulu:events:clean-image-data --dry-run to inspect image-data health, bin/console debug:messenger if you're using the automation bundle, and the Symfony Profiler's Doctrine panel on calendar pages.
  • Best extension points, ranked: (1) decorate the smart content provider, (2) override Twig templates, (3) override form/list XML, (4) MCP tool calls for programmatic workflows, (5) Symfony event subscribers on Doctrine lifecycle events, (6) automation-bundle listeners for scheduled publishing, (7) fork. Work down that list in order.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager