runroom-packages/basic-page-bundle
A lightweight PHP bundle that adds a ready-made page entity, admin CRUD, and routing for simple CMS-driven content. Includes sensible defaults for slugs, templates, and publishing states, giving editors editable pages without building the structure from scratch—a quick starting point for content-man...
Before anything else: this is a Symfony bundle, not a Laravel package. If you are coming from Laravel, the mental model does not transfer — there is no service provider auto-discovery, no Eloquent, no Blade, no php artisan. You need a Symfony application with Doctrine ORM and Sonata Admin already working. If your project is Laravel, stop here; you would be porting the concept (a Page model + admin CRUD + slug routing) rather than installing the package.
Minimal steps in a Symfony app:
composer require runroom-packages/basic-page-bundle — read the composer.json constraints on the repo first; it targets a specific Symfony/Sonata generation and will not install against arbitrary versions.config/bundles.php.routing.yaml under src/Resources/config/) so the front-end page controller is reachable.services.yaml, but verify in the container with bin/console debug:container | grep -i page).bin/console doctrine:schema:update --dump-sql (or a migration) — the bundle ships Doctrine mappings, so the page table needs creating.Where to look first, in order: the repository README, then src/Resources/config/ (routing + service wiring tell you what is actually exposed), then the Entity/ and Admin/ directories (they define your extension points), then src/Resources/views/ (the templates you will override).
First real use case: an editor-managed "About us" / "Terms" / "Contact" static page with a title, slug, body, and SEO metadata, editable in Sonata without a deploy.
Treat the shipped entity as a base class, not as your domain model. These Runroom bundles are typically built around a MappedSuperclass page entity that you subclass in your own src/Entity/Page.php. That subclass is what Doctrine manages, what Sonata administers, and what you can add fields to (hero image, publish date, related links) without forking the vendor. Check whether the bundle expects a concrete class or a mapped superclass before you start — this dictates your whole integration.
Sonata admin is the primary interface. Day-to-day work is configuring the admin: form fields, list columns, filters, and which fields are translatable. Keep your admin class in your app (src/Admin/PageAdmin.php) extending the bundle's, so upgrades do not clobber your config.
Routing pattern. The usual shape is a catch-all front controller matching /{slug} (or a localized /{_locale}/{slug}). Register it last in your routing so it does not swallow your other routes. If you need nested paths (/legal/terms), you will likely need to extend the slug handling yourself.
Rendering pattern. Override the bundle templates via Symfony's bundle inheritance (templates/bundles/RunroomBasicPageBundle/...) rather than editing vendor files. Wire your layout through config/packages/twig.yaml or by extending the bundle's base template.
Multi-locale usage. If the bundle pulls in translatable behaviour (Gedmo/Knp), the pattern is one page row with translation rows per locale, selected by the request locale. Plan your slug uniqueness strategy across locales early — the default is often per-locale uniqueness, which surprises people who expect globally unique URLs.
Integration with media/menus. Runroom publishes companion bundles (media, menu, etc.). Basic pages are usually the content half; images and navigation come from siblings. Compose them at the template/service level rather than expecting this bundle to do it.
Workflow tip: keep a thin app-level service (e.g. PageResolver) that maps a slug to a published page and throws a 404 for drafts/missing. That gives you one place to add caching, preview tokens, or redirects later without touching vendor code.
[READ-ONLY] description mean this is a split-out of a private monorepo. Issues and PRs are likely ignored. Budget for forking and owning it.composer update on Sonata is a multi-day problem.@MappedSuperclass vs @Entity, or forgetting to add the subclass to your Doctrine mapping config, yields "table not found" or duplicate-mapping exceptions that read nothing like the real cause./{slug} catch-all registered too early silently 404s or shadows your login, admin, and API routes. Put it at the bottom of config/routes.yaml and verify with bin/console debug:router.cache:pool:clear and any result-cache on the repository before assuming a bug.bin/console debug:container Page, bin/console debug:router | grep page, and bin/console doctrine:mapping:info. If the bundle appears wired but does nothing, it is almost always a missing service tag or an un-imported routing file.Entity/, Admin/, Controller/, and Resources/config/ — it is a small bundle, and this will save you more time than searching for docs that do not exist.How can I help you explore Laravel packages today?