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

Cms Core Laravel Package

graham-campbell/cms-core

Core package for Graham Campbell's Laravel-based CMS, providing the foundational services, base classes, and shared utilities that power the CMS and its companion packages.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you type composer require, set the expectation: this package declares "Support only laravel 4.1", sits at v0.2.0-alpha, and lives under a GrahamDeprecated namespace. The only defensible day-to-day use is inside an existing Laravel 4.1 / Bootstrap CMS-derived application, or as read-only reference material while you reimplement the same primitives on a supported Laravel version. Everything below assumes the former.

Pin it exactly. No caret, no ~, no dev-master:

{
    "require": {
        "graham-campbell/cms-core": "0.2.0-alpha"
    }
}

Run composer update --dry-run graham-campbell/cms-core in a throwaway branch first and read the require/conflict block against your PHP and Laravel constraints. Then composer dump-autoload and confirm the namespace landed in vendor/composer/autoload_psr4.php — PSR-4 autoloading is the headline change in this release, so a stale classmap-era install is a real failure mode.

Where to look first, in order:

  1. composer.json — resolve the actual root namespace (autoload.psr-4). In the Bootstrap CMS lineage this has historically been Cms\Core; confirm rather than assume, because every class reference you write depends on it.
  2. src/ for the service provider — the single most informative file. It tells you what gets bound into the container, which config keys are merged, which facades are aliased, and which models/observers are registered.
  3. The model traits — slugs, publishing, metadata. These are the package's most reusable idea.
  4. The models/contracts for pages, posts, content types, menus, and redirects.
  5. config/ and any migrations — check whether schema is shipped, and whether it is safe to extend.

Wire it up (Laravel 4.1 style). Add the provider to app/config/app.php:

'providers' => array(
    // ...
    'Cms\Core\CoreServiceProvider',
),

Publish config if the package offers it, then read the published file before editing anything:

php artisan config:publish graham-campbell/cms-core

Run package migrations only against a disposable/local database first:

php artisan migrate --package="graham-campbell/cms-core"

First use case: define one concrete content type — say a Page — using the package's content trait, expose it through a route, render it, and then deliberately break the slug and change the publish state. That single loop exercises the three things the package actually gives you (shared model behaviour, publishing scope, slug resolution) and tells you within an hour whether the remaining surface is worth wiring.

Implementation Patterns

Content types via the trait. The package's core value is a shared model trait so every content type behaves identically. Build your domain models on top of it rather than extending package models directly:

class Article extends Eloquent
{
    use Cms\Core\Traits\Sluggable;   // confirm exact names in src/
    use Cms\Core\Traits\Publishable;
    use Cms\Core\Traits\Metadata;

    protected $table = 'articles';
    protected $fillable = array('title', 'slug', 'body', 'published_at');
}

Keep your own model as the boundary. If the trait method signatures shift in a later alpha — and they may — you change one file, not forty call sites.

Publishing as a query scope, not a column check. The pattern that pays off is treating publish state as an ambient scope on the read path: a published() scope that filters on status and published_at <= now(), applied by default in your repository, with an explicit withUnpublished() escape hatch for admin. Do not scatter where('published', 1) through controllers; you will miss one and leak a draft.

Slugs belong to a resolver, not a route. Laravel 4.1 has no route-model binding by default. Wrap slug lookup in a small resolver/repository so the "find by slug, 404 if missing or unpublished" decision lives in one place:

Route::get('{slug}', function ($slug) {
    $page = App::make('ContentRepository')->findPublishedBySlug($slug);
    if (!$page) App::abort(404);
    return View::make('page')->with('page', $page);
});

This is also your future migration seam — swap ContentRepository for an implementation on a supported Laravel version and the route does not change.

Menus as a resolved tree, cached by key. Build the menu tree once (parent/child ordering, visibility filtering), cache the rendered structure under a versioned key, and invalidate on any menu model save/delete via Eloquent model events. Never let a view walk the menu table directly — that is how you end up with N+1 queries and a menu that disagrees with itself between requests.

Redirects with real semantics. A flat path→path table is the naive version and it will bite you. If you implement or extend this, budget for: status-code selection (301 vs 302), loop detection (resolve chains with a depth cap), collision/ordering rules when two rules match, and 404 fallthrough so an unmatched request still reaches your normal router. In 4.1 the natural hook is App::missing() or a route filter — pick one and be consistent, because two 404 paths that behave differently is a support ticket generator.

Cache invalidation wired to model events. Register saved and deleted listeners that bump the relevant cache key. Cache keys should be namespaced and versioned (cms.content.{type}.{id}.v{n}) so you can invalidate an entire content class by incrementing the version rather than enumerating keys — Laravel 4.1's cache drivers do not universally support tagging.

Provider and facade wiring. Bind your own implementations against the package's contracts in your app's service provider, after the package provider is registered. That gives you a single place to swap behaviour and a single place to look when something is silently resolved to the wrong class.

Isolate every touchpoint. No controller, view, or job should reference a Cms\Core\* class directly. Everything goes through your own content repository, menu service, and redirect resolver interfaces. The package is alpha with no upgrade path; the exit must be a contained change, not a rewrite.

Gotchas and Tips

  • config:cache will make your config edits appear to do nothing. This is the classic one. Cached config freezes package config values; edit the file, see no change, lose an hour. Flush the cache after any config change, and check whether the package's config is merged at register-time or publish-time.
  • Event listeners silently not firing. The release that introduced PSR-4 also "improved events" and changed authentication and removed broken tests. If a listener seems dead, verify registration order (listeners must be attached after the provider registers), check for deferred providers, and test the listener in isolation rather than inferring from an end-to-end effect.
  • You have no test suite you can trust. "Removed broken tests" is coverage going down at exactly the highest-coupling surfaces: auth, events, models. Write your own regression tests around login/logout, listener firing, slug uniqueness, publish transitions, and menu cache invalidation before you change anything. Those tests are the only safety net you get.
  • Model changes are not guaranteed to be additive. 0.2.0-alpha plus an archived repo means breaking changes are plausible and possibly permanent. Pin the exact version in composer.json and commit composer.lock; do not let CI resolve fresh.
  • Auth is not the auth you know. Laravel 4.1 guards, password brokers, and remember-token behaviour diverge sharply from 5.x+. Anything you read in modern Laravel docs about Auth::attempt, guard drivers, or Authenticatable contracts does not apply. Read the 4.1 docs specifically.
  • Autoload drift. After any composer operation, if classes are "not found" that clearly exist, run composer dump-autoload. PSR-4 was new to this release and stale classmaps are the usual culprit.
  • Slug collisions and soft deletes. Two articles titled "Hello World" will collide; a slug check that ignores soft-deleted rows will let a resurrected record conflict with a live one. Decide on a suffixing strategy (hello-world-2) and enforce uniqueness at the database level as well as the application level.
  • Stale cache serving the wrong menu or redirect is the worst failure mode here because it produces silently wrong output rather than an error — a user sees the old navigation, or a redirect points at a URL you retired last week. Wire invalidation to model events, and add a blunt "flush CMS cache" affordance for editors.
  • Facade alias collisions. Check the package's facade aliases against existing entries in app/config/app.php before registering them; a collision fails quietly or, worse, shadows an alias your app already relies on.
  • Extension points to prefer, in order: (1) your own models using the traits, (2) your own implementations bound to the package's contracts, (3) overriding published config, (4) extending package classes. Each step further down couples you harder to an unmaintained alpha.
  • The most valuable thing here is the spec, not the code. The redirect-with-persistence model, the content trait, and the menu tree are a free requirements checklist. If your roadmap does not already name persisted redirects and menu management, those are silent gaps — close them on a supported Laravel version rather than adopting this one. If you are already running it, open a migration ticket with a named owner and a date now, while you still have the context.
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.
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
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle