Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CakePHP Structarmed preset

StructArmed preset for CakePHP 5 application conventions.

Reuses the ideas of StructArmed's built-in MVC preset (layer isolation, thin entry points, naming, safety rules) but maps them to CakePHP's real layout.

Layers

Layer CakePHP namespace Naming
Controller <App>\Controller\FooController suffix Controller
Component <App>\Controller\Component\FooComponent suffix Component
Table <App>\Model\Table\FooTable suffix Table
Entity <App>\Model\Entity\Foo
Behavior <App>\Model\Behavior\FooBehavior suffix Behavior
View <App>\View\AppView
Cell <App>\View\Cell\FooCell suffix Cell
Helper <App>\View\Helper\FooHelper suffix Helper
Command <App>\Command\FooCommand suffix Command
Mailer <App>\Mailer\FooMailer suffix Mailer
Middleware <App>\Middleware\FooMiddleware suffix Middleware
Form <App>\Form\FooForm suffix Form
Type <App>\Database\Type\FooType suffix Type
Route <App>\Routing\Route\FooRoute suffix Route
Widget <App>\View\Widget\FooWidget suffix Widget
CacheEngine <App>\Cache\Engine\FooEngine suffix Engine
LogEngine <App>\Log\Engine\FooLog suffix Log
MailerTransport <App>\Mailer\Transport\FooTransport suffix Transport
Event <App>\Event\FooListener
Policy <App>\Policy\FooPolicy suffix Policy
Authenticator <App>\Authenticator\FooAuthenticator suffix Authenticator
Identifier <App>\Identifier\FooIdentifier suffix Identifier
PasswordHasher <App>\PasswordHasher\FooPasswordHasher suffix PasswordHasher
UrlChecker <App>\UrlChecker\FooUrlChecker suffix UrlChecker

<App> is the root namespace of your application (or plugin), passed to the constructor (default App).

Templates are not classes — the preset calls skipPathsForRuleset(['templates/']) so templates/* is still scanned for PSR checks but excluded from layer rules.

Nested layers are never forced into their parent's suffix: a class that resolves to Component is exempt from the Controller suffix rule even when a broader host-defined App\Controller\* pattern also matches it (same for Behavior/ Entity vs Table).

Plugins

Plugins are separate namespaces (Billing\, Inventory\, …). Pass them to the preset and the same canonical layers, naming, quality and safety rules apply inside the plugin code:

return Architecture::define()
    ->withPreset(new CakeAppPreset(
        pluginNamespaces: ['Billing', 'Inventory'],
        // pluginAppAccess: ['Billing' => ['App\Util']],  // grant app kernel access
    ));

Each plugin gets an owner layer (PluginBilling/^Billing\\.*$/) registered before the canonical layers, so per-plugin rules can be keyed on it in ruleset(). By default a plugin may not import the app namespace at all; grant specific app namespaces per plugin via pluginAppAccess.

Install

composer require --dev crustum/structarmed-cakephp

Usage

// structarmed.php
use Boundwize\StructArmed\Architecture;
use Crustum\StructArmed\Cake\CakeAppPreset;

return Architecture::define()
    ->layer('Source', [])                 // PSR-4 scan paths (needed for the PHPUnit extension)
    ->withPreset(new CakeAppPreset())
    ->ruleset([                           // your own domain layers, if any
        // ...
    ]);

Tune it like the built-in presets:

new CakeAppPreset(
    namespace: 'App',           // root namespace (no trailing backslash)
    controllerMaxComplexity: 3, // default: 5
    controllerMaxMethodLength: 15, // default: 20
    controllerMaxDependencies: 4, // default: 5
    viewMaxComplexity: 2,       // default: 3 — View classes should just load helpers
)

Skip a rule or a path:

use Crustum\StructArmed\Cake\CakeAppPreset;

return Architecture::define()
    ->withPreset(new CakeAppPreset())
    ->skip(CakeAppPreset::CONTROLLER_MAX_DEPENDENCIES);          // whole rule
    // or: ->skip([CakeAppPreset::ENTITY_MUST... => ['src/Legacy/']]);

Rule keys

Rule keys live on the Crustum\StructArmed\Cake\CakeRule enum and are prefixed with cakephp.. Pass CakeRule::X->value to skip() / replaceRule():

use Crustum\StructArmed\Cake\CakeRule;

return Architecture::define()
    ->withPreset(new CakeAppPreset())
    ->skip(CakeRule::CONTROLLER_MAX_DEPENDENCIES->value);
  • Layer isolation: cakephp.layer.<from>_not_depend_<to> (TABLE_NOT_DEPEND_CONTROLLER, VIEW_NOT_DEPEND_TABLE, MAILER_NOT_DEPEND_CONTROLLER, TYPE_NOT_DEPEND_TABLE, …)
  • Naming: cakephp.<layer>.name_must_end_with_<suffix>
  • Quality: <layer>.max_complexity / max_method_length / max_dependencies, <layer>.no_superglobals, <layer>.must_have_return_types
  • Safety: cakephp.safety.<layer>_no_<fn|construct> (dd, dump, var_dump, print_r, var_export, die, exit) — derived per layer, not enumerated on the enum

What is intentionally not enforced

  • MustBeFinalRule — CakePHP controllers/tables are meant to be extended, not final.
  • MustBeInterfaceRule — no repository interfaces in Cake; Table is the interface.
  • Doctrine/PDO bans — Cake uses its own ORM; DateTime is fine in Model layer.

Requirements

  • PHP 8.2+

License

Licensed under the MIT License. Redistributions of the source code included in this repository must retain the copyright notice found in each file.

About

StructArmed preset for CakePHP 5 conventions (Controller/Component, Table/Entity/Behavior, View/Cell/Helper, Command)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages