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

Core Bundle Laravel Package

unite-cms/core-bundle

Unite CMS CoreBundle is the foundational Symfony bundle for the Unite CMS headless content management system. It provides core services, configuration, and integration points for managing structured content, building custom APIs, and supporting extensible admin workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you type composer require: this is a Symfony bundle, not a Laravel package. It assumes Symfony's DI container, event dispatcher, security voters, Doctrine ORM/DBAL, and its own GraphQL schema builder. It will not "just install" into a Laravel app. The day-to-day leverage you get is one of two shapes:

  1. Sidecar service — run Unite CMS as a standalone Symfony app (Docker container), expose its GraphQL endpoint, and consume it from Laravel over HTTP. This is the realistic path for a Laravel team.
  2. Reference/legacy — clone the repo to read its content-type and field-type abstractions when designing your own content model. Do not ship it as a dependency.

Minimal path to a first query (sidecar route):

  1. Pin versions first. Last tagged release is January 2020 — Symfony 4.x/5.0-era, PHP 7.2–7.4. Check the tag's composer.json constraints and build the sidecar on a matching skeleton (e.g. Symfony 4.4). Do not attempt a modern Symfony 6/7 install.
  2. Stand up the CMS app separately. Clone/extend an existing Unite CMS skeleton, composer require unite-cms/core-bundle, register UniteCMS\CoreBundle\UniteCMSCoreBundle, configure Doctrine + the unite_cms_core config block, and create schema tables.
  3. Create a domain, then a content type. Domain = tenant boundary. Content type = schema (a set of fields). Use the manager services (see below) or the Unite admin UI.
  4. Query over GraphQL. From Laravel, hit the endpoint with a trivial query on a one-text-field type to validate the wiring end-to-end (domain resolution → content type → field type → schema → resolver) before modeling anything real.

Where to look first in the source:

  • ContentType/ and FieldType/ — the type system and manager services.
  • Domain/ — multi-tenant resolution and domain-scoped config.
  • GraphQL/ — how field types contribute to the generated schema.
  • Security/ — role-based, field-aware permissions.

First real use case: model an Article (title/slug/body), create a domain, insert a record, read it back over GraphQL from a Laravel HTTP client. Once that loop closes, everything else (permissions, custom field types, event listeners) is incremental.

Implementation Patterns

Model content types as data, not code. Content types live in the database as runtime configuration (name, fields, settings), managed by the content type manager. In practice you seed them from a fixture or console command — build a ContentType, attach FieldType instances, persist via the manager. Keep a repeatable seeder per environment because there is no migration story for content-type changes in this bundle.

Go through the manager services, not the Doctrine entities. The bundle exposes a content type manager, field type manager, and domain manager as DI services. Resolve them from the container in commands, fixtures, and tests. Treating the entities as your API invites breakage when schema changes or lifecycle events fire.

Custom field types are the main extension point. Implement the field type interface, register it as a service and add it to the field type manager (tagged service or explicit addFieldType call — check which your version supports). You inherit GraphQL type generation and validation for free.

Use lifecycle events for cross-cutting behavior. Subscribe with a standard Symfony listener to do slug generation, audit logging, cache invalidation, or webhook dispatch instead of overriding core services.

Never let Unite types leak into Laravel domain code. Wrap the GraphQL client behind an adapter interface (e.g. ContentRepository) on the Laravel side. DTOs in, arrays out. This keeps the sidecar swappable and makes the day-to-day cost of the framework mismatch manageable.

Domain resolution belongs at the edge. Resolve the domain early (host/subdomain via the domain manager) and scope every query to it. A small request-scoped "current domain" service beats threading domain IDs through every layer.

GraphQL is your integration surface. Register your own *.graphql queries/mutations; the schema builder merges core and app schemas. Keep resolvers thin and delegate to managers. On the Laravel side, cache query results with tagged cache keys per domain/content type.

Testing pattern. Boot a Symfony kernel with the bundle and SQLite in CI, seed one domain + one content type per test, and assert against the GraphQL endpoint. On the Laravel side, contract-test your adapter against a recorded GraphQL fixture.

Gotchas and Tips

  • Age is the dominant gotcha. A January 2020 release fights Symfony 5.2+/6/7 with deprecations, removed DI features, and ReturnTypeWillChange issues. Check composer.json constraints and composer why-not before committing; assume fork ownership.
  • No content-type migrations. Changing fields does not migrate existing records — expect missing values and schema mismatches. Write data backfill scripts alongside every type change.
  • Clear the schema cache after every content-type/field-type edit. The GraphQL schema is built and cached; stale schema is the #1 "my field doesn't appear" cause. bin/console cache:clear.
  • Field-type registration fails silently. An unregistered field type throws "unknown field type" at runtime rather than boot. Add a smoke test that lists registered field types.
  • Config tree is strict. Unknown keys in unite_cms_core throw at container compile time. Use bin/console debug:config unite_cms_core instead of guessing key names.
  • Domain resolution fails open. If no domain matches the request host, content lookups return empty rather than erroring. When "no data" appears mysteriously, check the current-domain service first.
  • Doctrine coupling cuts both ways. The bundle owns entities and mappings. Use explicit migrations, diff against the bundle's mappings, and avoid doctrine:schema:update blind. Don't share table prefixes with app entities.
  • Debugging shortcuts. bin/console debug:container | grep unite finds manager services and listeners; GraphiQL against the endpoint is the fastest way to confirm a type/field made it into the schema.
  • Extension points, in order of daily usefulness: custom field types → event listeners → custom GraphQL queries/mutations → custom permission objects. Favor these over subclassing core services, which aren't designed as public extension surfaces.
  • Bus factor / support risk. Single-digit stars, zero dependents, no release since 2020. Read the repo's tests — they're the most reliable documentation. Pin a validated commit, and if you go the sidecar route, isolate it behind an adapter so a replacement (maintained headless CMS, or a Laravel-native content layer) is a swap, not a rewrite.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource