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

Page Bundle Laravel Package

rz/page-bundle

rz/page-bundle offers a lightweight way to define, organize, and render reusable pages in Laravel/PHP applications. It provides bundle-style integration for page management, helping developers keep page content and templates structured with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you install anything. This is rz/page-bundle, a Symfony 2-era bundle (RzPageBundle), archived, with zero stars and zero dependents. You are a Laravel developer, so the first step is not composer require — it is deciding whether this belongs in your composer.json at all. It almost certainly does not. If you are evaluating it because a ticket says "add editable pages," stop here and move to the Laravel-native pattern in Implementation Patterns below.

If you are forced onto it (e.g. auditing a legacy Symfony app that already vendors it), minimal steps are:

  1. Open composer.json first. Check the symfony/*, doctrine/*, and php constraints against your runtime. A Symfony 4+/PHP 8 project will not resolve cleanly. This is a 10-minute composer why-not check, not a design exercise.
  2. If it resolves, register the bundle in the Symfony kernel (not a Laravel service provider — there is no PageServiceProvider here):
// app/AppKernel.php
new Rz\PageBundle\RzPageBundle(),
  1. Import its routing:
# app/config/routing.yml
rz_page:
    resource: "@RzPageBundle/Resources/config/routing.xml"
    prefix: /
  1. Point the config at your page entity if you intend to extend it:
# app/config/config.yml
rz_page:
    page_class: AppBundle\Entity\Page

Where to look first, in this order:

  1. Resources/config/ — routing, DI service definitions, default config. This is where the actual behaviour lives; there is no README worth trusting.
  2. Entity/ — the Page model and its Doctrine mapping. This tells you the real schema: title, slug, body, SEO fields, parent/tree relationships, publication flags.
  3. Controller/ — how a slug is resolved and handed to a Twig template.
  4. DependencyInjection/ — the config tree, which is the only extension point you get.

First use case: create one Page with a slug, a title, and a body, render it at /{slug} through the bundle's controller, and confirm the SEO metadata fields land in the template. That single loop is the whole package. If you cannot get it running in an afternoon, abandon it — it will not get easier, because nobody is upstream to fix it.

Implementation Patterns

The pattern the bundle is trying to sell. Page-as-entity, resolved by slug, rendered through a per-page template, with SEO metadata attached to the record. That is a genuinely useful shape. Here is how it maps to what you should actually build.

If you are (unfortunately) using the bundle in Symfony: you extend the Page entity, set rz_page.page_class to your subclass, and add fields in your app's Doctrine mapping. Templates are selected per page via a template field or a resolver service. Slug resolution goes through the bundle's controller, which effectively does a findOneBySlug and 404s on miss.

The Laravel-native equivalent (do this instead). The bundle's domain is ~150 lines of Laravel you fully own:

// database/migrations/xxxx_create_pages_table.php
Schema::create('pages', function (Blueprint $table) {
    $table->id();
    $table->string('slug')->unique();
    $table->string('title');
    $table->longText('body')->nullable();
    $table->string('meta_title')->nullable();
    $table->string('meta_description')->nullable();
    $table->string('canonical_url')->nullable();
    $table->string('template')->default('pages.show');
    $table->boolean('published')->default(false);
    $table->timestamps();
});
// app/Models/Page.php
class Page extends Model
{
    protected $guarded = [];
    protected $casts = ['published' => 'boolean'];

    public function getRouteKeyName(): string { return 'slug'; }
    public function scopePublished($q) { return $q->where('published', true); }
}
// routes/web.php
Route::get('/{page:slug}', [PageController::class, 'show'])
    ->where('page', '.*')          // allow nested slugs
    ->name('pages.show');

// app/Http/Controllers/PageController.php
public function show(Page $page)
{
    abort_unless($page->published, 404);
    return view($page->template, compact('page'));
}

This gives you the bundle's entire feature set — slug routing, SEO metadata, per-page templates — with route-model binding, Blade, and zero archival risk. An admin form (Filament, Nova, or a plain resource controller) is the remaining hour of work.

Workflows worth copying from the bundle conceptually:

  • Per-page template selection — store the Blade view name on the row (pages.show, pages.landing, pages.legal) and let the controller pick it. This is the bundle's "flexible templating" idea, done cleanly.
  • Tree/parent relationships — if pages nest (/about/team), model parent_id and build slugs from the path. The bundle does this; Eloquent belongsTo/hasMany does it better.
  • Routing helpers — rather than the bundle's static-route mapping, expose a route('pages.show', $page) helper and cache slugs with a route-cache-friendly table.

Integration tips for a Laravel shop:

  • Never composer require this into a Laravel app "to see." A Symfony bundle cannot be bootstrapped by Laravel's container without a bridge, and there is no maintained bridge.
  • If a PM asks for "the page bundle feature," point them at the migration + model + route trio above. It is one sprint-day, not a dependency decision.
  • If you inherit a Symfony project that already uses it: treat page_class config and the entity mapping as the contract, and port the data into the Laravel version above when you migrate frameworks.

Gotchas and Tips

It is not a Laravel package, and no amount of config will make it one. The Bundle suffix and Rz\PageBundle\RzPageBundle registration are Symfony kernel conventions. There is no service provider, no facade, no config publish. Trying to graft it means fighting two DI systems for a marginal page table. This is an architectural mismatch, not a setup problem — the correct fix is not to install it.

Archived means no patches, ever. composer audit findings against it or its dependency tree have no upstream remediation. Every PHP minor bump is your ticket. If it is already in a tree you own, that is a remediation item, not a "keep an eye on it."

Pinned constraints will fight you. Symfony 2 bundles typically pin symfony/symfony or component constraints to 2.x/3.x ranges and old Doctrine. On PHP 8.2+ and Symfony 5/6/7 you will hit resolution deadlocks. Run composer require --dry-run in a throwaway project first; expect it to fail, and do not spend time relaxing constraints by hand — you are then maintaining a fork of an abandoned package.

page_class is the only real extension point — use it or don't adopt. If you must customise the Page model, set rz_page.page_class to your subclass. If you find yourself needing more than that, you have outgrown an archived bundle and should port.

No tests = unknown behaviour at the edges. There is no test suite to read as spec, so edge cases (nested slugs, unpublished pages, slug collisions, canonical URL fallbacks) are undefined until you debug them yourself. Profile page-render queries early: if the bundle hydrates relationships per request without eager loading, you get N+1s on any page tree.

Debugging tips for the legacy case: enable Symfony's profiler, check router:debug to confirm the bundle's routes are actually loaded (prefix conflicts with app routes are common), and inspect the compiled container (app/cache/dev) if the rz_page config node is silently ignored — mis-indented YAML under a bundle key is the usual culprit.

Do not fork it "just in case." Forking makes you the permanent sole maintainer of a package nobody else uses, with no community to absorb bugs. If the domain logic were irreplaceable a fork might be justified; here it is a page table, so build the Laravel version and close the ticket.

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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
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