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

Tuna Bundle Laravel Package

tuna-cms/tuna-bundle

Tuna CMS Bundle packages the Tuna CMS core into a reusable PHP bundle, making it easier to add structured content management to applications. It centralizes CMS services and configuration for quicker, cleaner integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you run composer require, confirm two things: this is a Symfony bundle, not a Laravel package (it will not work with artisan or service providers), and the repo has essentially no ecosystem around it (0 dependents). Treat it as a research spike, not a drop-in dependency.

Minimal path:

  1. Check compatibility first. Open composer.json in the repo and compare symfony/* and php constraints against your project. If it pins an older Symfony (e.g. 3.x/4.x), stop here — adapting it is usually more work than writing your own content model.
  2. Install into a Symfony app: composer require tuna-cms/tuna-bundle.
  3. Register the bundle in config/bundles.php (or AppKernel::registerBundles() on older versions) alongside its dependencies — expect transitive deps like Doctrine ORM, a form component, and likely an admin generator (Sonata-style) or its own admin controllers.
  4. Import routing: add the bundle’s routing file (@TunaBundle/Resources/config/routing.xml or similar) under a prefix such as /admin and /.
  5. Configure: copy any sample config from Resources/config into config/packages/tuna.yaml; set at minimum the entity classes, upload directories, and security role required for the admin.
  6. Schema: run bin/console doctrine:schema:validate then doctrine:schema:update --dump-sql (or the bundle’s migrations if shipped) and inspect the SQL before applying.
  7. Security: add a firewall/access_control entry protecting the admin path, otherwise you have an unauthenticated CMS backend.

First use case: stand up a single static "page" with a text block, render it through a Twig template you control, and only then explore menus/media. That validates install → schema → admin → frontend routing end to end with the smallest surface area.

Where to look first, in order: README.md → composer.json (version/dep reality check) → DependencyInjection/Configuration.php (the real config contract, better than any docs) → Entity/ (your content model) → Controller/ (routing and template names).

Implementation Patterns

Content model as Doctrine entities. Expect Page, Block/ContentBlock, Menu, and media entities. The practical pattern is to extend them in your app (class Page extends BasePage) and point the bundle config at your subclass, so you can add fields without forking. Do this before writing any templates — retrofitting an entity swap later means a migration.

Admin as a CRUD surface, frontend as thin controllers. Keep the bundle handling persistence and admin UI; keep all rendering in your own templates/ directory. Override templates by placing files at the same relative path in templates/bundles/TunaBundle/... (Symfony’s bundle override convention) rather than editing vendor files.

Blocks as composable partials. A CMS of this shape usually maps block types to Twig partials. Build a small dispatcher in your app — a Twig function or a {% include 'blocks/' ~ block.type ~ '.html.twig' %} with a default fallback — so unknown block types degrade gracefully instead of throwing.

Route-everything-through-a-slug controller. Typical integration: a catch-all route (/{slug}) that queries Page by slug and 404s cleanly. Register it last in your routing so it doesn’t swallow admin and asset routes.

Config-as-code for structure, admin for content. Seed menus and page skeletons in a Doctrine fixture or a console command so environments are reproducible; let editors own the text. This keeps dev/staging/prod in sync and avoids "works on my database" bugs.

Service decoration for behaviour. If you need to change how pages resolve or how media URLs are generated, decorate the bundle’s service (decorates: tuna.some_service) instead of subclassing controllers. Verify the actual service IDs with bin/console debug:container | grep -i tuna.

Multi-locale, if supported. Check for a locale/translations field on entities. If present, wire your frontend controller to read the request locale and fall back explicitly — CMS locale fallbacks are a common source of blank pages.

Gotchas and Tips

  • The Laravel mental model will mislead you. No service providers, no facades, no config/*.php returning arrays in the Laravel sense. Config is YAML under a bundle-specific root key; "publishing" assets/config is bin/console assets:install / manual copy, not vendor:publish.
  • Zero dependents is a signal. There is no community to fall back on: no Stack Overflow answers, no third-party tutorials, and the README may be stale relative to the code. Budget time for reading source. Pin the exact commit in composer.json so a surprise push doesn’t break your build.
  • Bundle registration errors are opaque. If you get There is no extension able to load the configuration for "tuna", your bundle isn’t registered or the config key doesn’t match the extension alias — read DependencyInjection/*Extension.php for the true alias.
  • Doctrine mapping conflicts. Bundles frequently ship XML/YAML mappings that collide with your auto_mapping. Use doctrine.orm.mappings with type: annotation|xml and prefix: set explicitly, and run debug:doctrine equivalents (doctrine:mapping:info) when entities "exist" but aren’t found.
  • Schema drift. schema:update can silently drop columns added by other bundles. Always --dump-sql first, and prefer generating a real migration you can review.
  • Admin path is unauthenticated by default. Immediately add access_control: { path: ^/admin, roles: ROLE_ADMIN } and confirm with an incognito window. Don’t rely on "it wasn’t documented, so it must be locked".
  • Template overrides silently do nothing when the path or bundle name is wrong. bin/console debug:twig lists the resolved paths; if your override isn’t in the list, the name is off.
  • Asset pipeline assumptions. Older bundles assume Assetic or web/-relative assets. If you’re on Webpack Encore or Vite, the admin CSS may 404 — check the browser network tab before debugging PHP.
  • Cache clearing is not optional. After config or entity changes: bin/console cache:clear. A stale container will report services and routes that no longer exist, sending you down false trails.
  • Extension points to prefer, in order: config → template override → service decoration → event subscriber → entity subclass. Forking the bundle is a last resort; if you reach it, that’s a signal to evaluate replacing it.
  • Have an exit plan. Given the project’s size, isolate it behind your own repository/service layer for page retrieval (PageRepository::findBySlug) so a future swap to a maintained CMS bundle or a hand-rolled content model touches one class, not your templates.
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.
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
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle