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

Blog Bundle Laravel Package

stfalcon/blog-bundle

StfalconBlogBundle adds a ready-to-use blog to Symfony apps, with posts, categories, tags, comments, and an admin interface for content management. It plugs in via standard Symfony bundle configuration, giving you a simple, customizable blogging layer without building one yourself.

View on GitHub
Deep Wiki
Context7

Getting Started

First, accept that this is not installable in a Laravel app. stfalcon/blog-bundle is a Symfony2 bundle: no service provider, no publishable config, no Blade views, no Eloquent models. composer require stfalcon/blog-bundle will fail on php and symfony/* constraints; forcing it with --ignore-platform-reqs gives you a bundle Laravel never boots. So "day-to-day" use means one thing: mine it as a feature spec and reference implementation while building your own Laravel module.

Where to look first, in order:

  1. composer.json — pins the era. This tells you the whole package is EOL-coupled (Symfony 2.x, Twig 1.x, Doctrine 2.x, PHP 5.x). Do not try to resolve it.
  2. Entity/ — Post, Category/Tag, the Post↔Tag join, Comment. This is the only genuinely reusable artifact: the schema.
  3. Controller/ — admin CRUD and the frontend index/show actions. Read these to enumerate the actual endpoints and routing behavior.
  4. Resources/views/ — Twig templates for index, show, tags, breadcrumbs, pagination, and the Disqus widget.
  5. Resources/config/ — DI service definitions and routing. Not portable, but tells you which bundles were hard dependencies (StofDoctrineExtensionsBundle for sluggable/timestampable, KnpPaginatorBundle for pagination are the usual suspects — verify).
  6. The test suite — a cheap, executable acceptance checklist for "did I reach parity."

First use case: a 2–3 day spike. Read the above and produce (a) a one-page feature inventory and (b) a data-model diagram. Then decide: build native vs. adopt a maintained Laravel blogging package vs. headless CMS. Default recommendation is build native — the scope is small and only the schema is worth copying.

Your Laravel starting schema, derived from the spike:

// posts: id, slug (unique), title, body, excerpt, published_at, author_id, timestamps
// tags: id, slug (unique), name
// post_tag: post_id, tag_id (composite PK)
// index: unique(slug), (published_at, id) for keyset/cursor pagination

Implementation Patterns

1. Port the domain, not the framework. Translate Doctrine annotations → Eloquent models and relationships. The bundle's value here is that it answers "what does a simple blog actually cost?" — posts, categories/tags, many-to-many tagging, cut/read-more, syntax highlighting, breadcrumbs, pagination, comments. That list is a credible spec you can write tickets against.

2. Read-more parsing — decide the contract explicitly. The bundle supports a "cut and read more" marker in the body. In Laravel, resolve this in the model:

public function getExcerptAttribute(): string
{
    return $this->attributes['excerpt']
        ?? Str::of($this->body)->before('<!--more-->')->stripTags();
}

Do not rely on a delimiter you haven't documented. If you need an explicit excerpt column, add it — the bundle's ambiguity here is exactly the kind of thing to nail down rather than inherit.

3. Admin CRUD → Laravel resource controllers. The bundle's admin screens map cleanly to Route::resource('posts', ...), Form Requests for validation, and Gate/Policy checks for authorization. You gain things the bundle never offered (middleware-based auth, validation error bags) by not porting its form types.

4. Public index/show → paginated queries with eager loading. The bundle's archive pages are the classic N+1 trap for per-post tags. In Laravel:

Post::query()
    ->whereNotNull('published_at')->where('published_at', '<=', now())
    ->with('tags')          // prevents N+1
    ->latest('published_at')
    ->paginate(15);

5. Slugs — replicate sluggable behavior deliberately. The bundle delegates to Stof's sluggable extension. If you have bulk-imported content, generate slugs with Str::slug() and handle collisions (append -2, -3, or fall back to a short id). Make published slugs immutable to avoid breaking URLs.

6. Comments — make this an explicit product decision, not an inherited default. The bundle ships Disqus. That's the 2013 default. For a Laravel module: prefer a first-party comments table (moderation, data ownership, SEO) unless legal/ops explicitly sign off on Disqus with consent gating. This is the single highest-judgment area of the port.

7. Render pipeline for bodies and code blocks. Adopt the bundle's intent — rich HTML bodies plus highlighted code — but not its assets. Use a maintained server-side highlighter (e.g. a modern PHP highlighter) or a self-hosted client library, and pass rendered HTML through HTML Purifier. This is non-negotiable given author-supplied HTML.

8. Breadcrumbs and tag archives. Simple Post belongsToMany Tag plus a /tags/{tag:slug} route. Keep the bundle's SEO-friendly tag page structure but generate structured data yourself — it won't be in the templates.

9. Acceptance checklist from the tests. Run the bundle's test scenarios as behavior descriptions ("post index paginates at N", "draft posts are excluded from the public index", "tag page lists only published posts tagged with X"). They encode intended behavior for free.


Gotchas and Tips

  • The composer failure is blocking, not cosmetic. Don't burn time on --ignore-platform-reqs; the bundle boot lifecycle (Bundle::boot(), registerContainerConfiguration()) has no Laravel analogue, and the bundle will silently no-op if forced in.
  • Stored XSS is the real risk. "Cut and read more" means you're rendering author-supplied HTML. Any port must route bodies through a sanitizer. Treat the bundled syntax highlighter as a supply-chain liability, not a feature — do not vendor its assets.
  • N+1 on archive pages. Tag loading per post is the bundle's natural weak point. Always ->with('tags') and paginate at 10–20 items.
  • Pagination indexing. Add (published_at, id) so pagination doesn't table-scan as content grows.
  • Slug churn on import. If your importer doesn't exactly replicate the sluggable behavior (transliteration rules, uniqueness suffixing), you'll get collisions and 404s on old links. Test with your real content.
  • Disqus is a GDPR/availability dependency. Consent gating or legal sign-off required; a third-party outage means an empty comment section on every article.
  • No field validation, auth, or authorization in the original. You're not "adding" these — you're writing them because nothing exists. Don't assume the reference implementation is a security baseline.
  • Twig template overrides don't map. The bundle's "configurable templates" feature is Symfony bundle-path resolution. In Blade, that's view()->exists() fallbacks or a published-views convention — reimplement the intent, not the mechanism.
  • Extension points are Symfony-shaped. The bundle extends via kernel events, form types, and DI compiler passes. The Laravel analogues are middleware, Form Requests, service container bindings, and model events. Read the concept, write the Laravel idiom.
  • Zero dependents means zero bug reports to learn from. When you hit something odd, there's no upstream community to search — read the source. Budget an owner and recurring maintenance time for whatever you build; the bundle itself is unmaintained.
  • License check before any copying. Verify the bundle's license and any vendored JS/CSS before lifting code into your project.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource