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

Simplecms Bundle Laravel Package

ibrows/simplecms-bundle

iBrows SimpleCMS Bundle is a Symfony bundle for adding lightweight content management to your application, with simple page and content handling so editors can manage site text without a full CMS.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you write a single line, internalize the headline finding: ibrows/simplecms-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no illuminate/* dependency, no publishable config, no migrations. It targets the Symfony 2-era bundle model (IbrowsSimpleCMSBundle class, DependencyInjection/IbrowsSimpleCMSExtension.php, Resources/config/services.yml, Twig templates, Doctrine entities, and Sonata Admin wiring). You cannot composer require it into a Laravel app and get anything usable — expect dependency resolution to fail on modern PHP, and even if it resolved, there is no integration seam.

So the realistic "first use case" for a Laravel developer is reference, not adoption. Read the source to extract the domain model, then build it natively.

Where to look first, in this order:

  1. composer.json — confirm it's Symfony 2.x era, note PSR-0 autoloading and pinned dependencies. This alone tells you whether a spike is worth 30 minutes.
  2. The Doctrine entities under Entity/ (or Model/) — typically a Page (slug, title, route, template) and a ContentElement/Block concept (region/position, type, body, page or global scope). This is the reusable asset.
  3. Resources/config/routing.xml and the controller(s) — how pages are resolved by slug and rendered.
  4. The admin templates / Sonata admin classes — the editorial UX pattern (list pages, edit blocks inline, choose a template).

The native Laravel translation of the domain model is small. A page + blocks schema lands in roughly this shape:

// database/migrations/xxxx_create_pages_table.php
Schema::create('pages', function (Blueprint $table) {
    $table->id();
    $table->string('slug')->unique();
    $table->string('title');
    $table->string('template')->default('default');
    $table->json('meta')->nullable();      // SEO fields
    $table->timestamp('published_at')->nullable();
    $table->timestamps();
});

Schema::create('blocks', function (Blueprint $table) {
    $table->id();
    $table->morphs('blockable');            // page-scoped or global
    $table->string('region')->default('main');
    $table->string('type');                // text, html, image, faq
    $table->longText('body')->nullable();
    $table->unsignedInteger('position')->default(0);
    $table->timestamps();
});

That is the entire "getting started" worth doing with this repository. If your intent is adopt, stop — the license (NOASSERTION) and the zero-maintenance reality are blocking before any code matters.

Implementation Patterns

Pattern 1 — Reference extraction (recommended). Clone the repo, read the entities and admin classes, write down the feature list (page CRUD, slug routing, region-scoped blocks, block types, template selection), then discard the code. You avoid the license/derivative-work ambiguity and get the schema in an afternoon. Do not copy code verbatim; re-express the model in Eloquent/Blade.

Pattern 2 — Polymorphic block rendering. The bundle's core idea is that content is data attached to a page or a region, not hardcoded in templates. In Laravel:

// App\Models\Page.php
public function blocks(): MorphMany
{
    return $this->morphMany(Block::class, 'blockable')->orderBy('position');
}

public function renderBlocks(string $region = 'main'): HtmlString
{
    return new HtmlString(
        $this->blocks->where('region', $region)
            ->map(fn (Block $b) => view("blocks.{$b->type}", ['block' => $b])->render())
            ->implode('')
    );
}
{{-- resources/views/pages/show.blade.php --}}
@extends("templates.{$page->template}")
@section('content')
    {!! $page->renderBlocks('main') !!}
@endsection

Pattern 3 — Block type registry. A small type→view map, mirroring how the bundle associates a content element type with a template, keeps editors constrained and rendering deterministic:

// config/cms.php
return [
    'blocks' => [
        'text' => 'blocks.text',
        'html' => 'blocks.html',
        'image' => 'blocks.image',
        'faq'   => 'blocks.faq',
    ],
    'templates' => ['default', 'landing', 'legal'],
];

Pattern 4 — Slug routing with caching. The bundle resolves pages by slug through a controller. Native equivalent: a catch-all route that looks up a published page and caches the resolution.

Route::get('/{slug}', PageController::class)
    ->where('slug', '[a-z0-9\-\/]+')
    ->name('cms.page');
public function __invoke(string $slug)
{
    $page = Cache::remember("page:{$slug}", 3600, fn () =>
        Page::with('blocks')->where('slug', $slug)
            ->whereNotNull('published_at')->firstOrFail()
    );
    return view('pages.show', compact('page'));
}

Pattern 5 — Admin surface. The bundle uses Sonata Admin; in Laravel use Filament or Nova to get the same "list pages, edit blocks" experience in a fraction of the code. A Filament PageResource with a Repeater or relation manager for blocks covers the whole editorial flow.

Pattern 6 — Sidecar (last resort). If for some reason the Symfony app must ship, run the bundle in its own Symfony 2 container and expose content over HTTP/DB to Laravel. This works but inherits every operational and CVE liability. Only defensible if content is read-mostly and you need to ship this quarter.

Pattern 7 — Genuinely on Symfony? Then the normal flow applies: register the bundle in app/AppKernel.php (or config/bundles.php), import @IbrowsSimpleCMSBundle/Resources/config/routing.xml, ensure Doctrine picks up its mapping, and render pages via its controller. That path is out of scope for a Laravel codebase, but it's why the package exists.

Gotchas and Tips

  • License is the hard stop. NOASSERTION means GitHub could not identify a recognized license, which by default means all rights reserved. A NOASSERTION badge is not permission. Commercial use is a legal question, not an engineering one — get clearance before you even copy snippets, since reading a repo to extract a model carries its own (lower) derivative-work questions.
  • Do not attempt a Composer bridge into Laravel. Symfony bundles and Laravel service providers are structurally incompatible. There is no maintained bridge, and you'd be porting, not integrating.
  • Assume the code does not run on PHP 8.x. Symfony 2-era bundles typically use PSR-0 autoloading, @ORM/@Route annotation readers, Symfony Form type APIs that don't exist in Symfony 5/6/7, and Twig 1.x syntax. Test a throwaway Composer resolve in a disposable container before spending any spike time, but treat failure as the expected outcome.
  • Transitive CVEs with no patch path. Even in a sidecar, you inherit unmaintained Symfony 2 dependencies. Your security scanner will flag them and there is no upstream to fix them. Budget a fork if you go that route — and a fork means owning a small framework forever.
  • Watch for missing model features. A "simple CMS" typically lacks draft/publish workflows, versioning, localization, roles/permissions, and media management. If editors are a primary user group, discover these gaps before committing, not mid-build.
  • N+1 on render. Symfony 2-era CMS code frequently queries per block. In a native port, eager-load blocks (Page::with('blocks')) and cache the resolved page + block payload rather than re-rendering each request. A fragment/full-page cache keyed on page:slug is cheap insurance.
  • Slug route must not shadow app routes. A catch-all /{slug} will swallow other routes if registered too early. Register it last, constrain it with a regex, and return 404 for unknown slugs rather than falling through to a controller that assumes a page exists.
  • Block type whitelist. If editors can pick a type freely, a bad value becomes a view("blocks.{$type}") failure. Validate against config('cms.blocks') on save and on render so the failure is a missing type, not an exception from view().
  • Extension points to mirror, not depend on. The bundle's value is its shape: a page entity, regioned blocks, a type registry, template selection, slug resolution. Copy the concepts, not the code — and if you do copy, keep an eye on the license question above.
  • Decision hygiene. With zero stars, zero dependents, and no maintainer, you are the maintainer the moment you depend on it. If content is on the roadmap, evaluate maintained Laravel-native options (Statamic, Twill, Filament-based admin) or a 1–2 week first-party build; either is cheaper than a Symfony 2 fork plus perpetual maintenance.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo