PHPackages                             webrider/cake-dm - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. webrider/cake-dm

ActiveLibrary[Framework](/categories/framework)

webrider/cake-dm
================

Domain Manager for CakePHP 3

1.3.1(6y ago)323[1 PRs](https://github.com/pabloelcolombiano/cake-dm/pulls)MITPHPPHP &gt;=5.6.0

Since Dec 11Pushed 6y ago1 watchersCompare

[ Source](https://github.com/pabloelcolombiano/cake-dm)[ Packagist](https://packagist.org/packages/webrider/cake-dm)[ RSS](/packages/webrider-cake-dm/feed)WikiDiscussions master Synced 5d ago

READMEChangelog (4)Dependencies (3)Versions (5)Used By (0)

cake-dm
=======

[](#cake-dm)

A layer manager for CakePHP applications.

Introduction
------------

[](#introduction)

As your CakePHP grows, the respective sizes of your Controller, Model and Template folders increase.

Your *src/Template/Element* folder has probably become a mess too, if you haven't split it in several sub-folders.

New-joiners wonder where to start and, just as you, do not grasp which models relate to another.

An alternative would be to split everything into plugins. But this might not be what you expect from plugins. You would end up with a quantity of plugins added to the *real* plugins, and a deserted *src* folder.

Sub-folders! this is the approach proposed by cake-dm. With domain separation in mind, the package proposes to split your MVC structure into layers. And sub-layers.

Requirements
------------

[](#requirements)

*CakePHP &gt;= 3.5*

Installation
------------

[](#installation)

With composer, run:

```
composer require webrider/cake-dm
```

Example
-------

[](#example)

### Without cake-dm

[](#without-cake-dm)

Assuming the following minimalistic structure for a flight company.

```
- src
    - Console
    - Controller
        - Component
            GeneralComponent.php
            UserRelatedComponent.php
        AdminController.php
        AppController.php
        DiscountsController.php
        FlightsController.php
        InvoicesController.php
        MachinesController.php
        PagesController.php
        PilotsController.php
        SeatsController.php
        StewardsController.php
        TicketsController.php
        UsersController.php
        UserProfilesController.php
    - Model
        - Table
            AppTable.php
            DiscountsTable.php
            FlightsTable.php
            ...
        - Entity
        ...
    - Template
        - Admin
        - Discounts
        - Flights
        - Element
            company_logo.ctp
            flight_description.ctp
            user_avatar.ctp
        - Invoices
        - Layout
            default.ctp
        - Machines
        ...
    - View
        - Cell
        - Helper
        AjaxView.php
        AppView.php
    Application.php
```

### With cake-dm

[](#with-cake-dm)

Cake-dm makes it possible to organize your code as follows:

```
- src
    - Admin
        - Controller
            AdminController.php
        - Template
            - Layout
                default.ctp
    - App
        - Console
        - Controller
            - Component
                GeneralComponent.php
            - AppController.php
            - PagesController.php
        - Model
        - Template
            - Element
                company_logo.ctp
            - Layout
                default.ctp
        - View
            - Cell
            - Helper
            AjaxView.php
            AppView.php
        Application.php
    - Invoicing
        - Controller
            DiscountsController.php
            TicketsController.php
        - Model
        - Template
    - Logistic
        - Controller
            FlightsController.php
            MachinesController.php
            SeatsController.php
        - Model
        - Template
            - Element
                - Flight
                    flight_description.ctp
            - Flights
            - Machines
            - Seats
    - Staff
    - User
        - Controller
            - Component
                UserRelatedComponent.php
            UsersController.php
            UserProfilesController.php
        - Model
            - Table
                UsersTable.php
                UserProfilesTable.php
            - Entity
        - Template
            - Element
                user_avatar.ctp
            - Users
            - UserProfiles

```

The advantages are that:

- The structure of your app becomes clearer.
- The different domains of your application can be clearly assigned to different developers or teams.
- Template paths pile up. For example here, the layout of all the templates within the layer Admin is different than the others. This can easily be read from the structure.
- If a template, layout or element is not found in a layer, it will be searched in *App/Template* per default.
- Elements and Components can be spread throughout the layers according to their relevance.

Note that:

- It is possible to split your layers in sub-layers, for example by creating a folder *src/Staff/Internal* and a folder *src/Staff/External*. In that case, no MVC folders should be located in the folder *src/Staff*.
- The domain layer name *App* should actually be your app's namespace, which is *App* by default in CakePHP. For plugins, it should be *Plugin*, regardless of the plugin's name.
- Plugin structures can be split in the same manner. You should then replace the *App* domain layer by a *Plugin* domain layer.
- Namespaces do not change. It is therefore forbidden to have two classes with the same name in different layers. More about that below.
- Cells, Views, Behaviors and Helpers can be distributed along domain layers too, just as the Components.

Settings
--------

[](#settings)

The structure is managed by three components.

### Composer

[](#composer)

In order to have Cake following the paths without changing the namespaces and intruding in the middleware, you must modify the following in your composer.json file:

```
"autoload": {
    "psr-4": {
        "App\\": [
            "src/Admin",
            "src/App",
            "src/Invoicing",
            "src/Logistic",
            "src/Staff",
            "src/User"
        ],
        ...
    }
},
```

Run `composer dump-autoload`after any structural change.

The same applies when introducing domain layers in your plugins.

### Controller

[](#controller)

In your *AppController.php*, the relevant paths to the templates should be added as early as in the *AppController::initialize()*.

Cake-dm will know in which layer the request was performed. It will include the template paths of that layer, as well as the *App* layer. To do so, add:

```
...

use CakeDomainManager\DomainController;

...

class AppController extends Controller
{

    ...

    public function initialize()
    {
        ...

        DomainController::init($this)->setTemplatePaths();
    }

    ...

}

```

### View

[](#view)

In the view, we have to change the way the elements are getting loaded. In your *AppView.php* you should overwrite the *\_getElementFileName()* of the *Cake\\View\\View* class.

To do that, in *AppView.php*:

```
...

use CakeDomainManager\DomainView;

...

class AppView extends View
{
    ...

    /**
     * @param string $name
     * @param bool $pluginCheck
     * @return false|string
     */
    protected function _getElementFileName($name, $pluginCheck = true)
    {
        return DomainView::init($this)->_getElementFileName($name, $pluginCheck);
    }

    ...
}

```

### Optional 1

[](#optional-1)

Having multiple directories under one same namespace (see [Composer](#composer)), there is a risk that a developer creates a class in a directory, and a different class with the same name in another directory. This is the price of adding a layer to the MVC.

Neither PHP nor Composer will throw any error or warning if this happens.

In order to avoid this, the following test can be added to your *ApplicationTest.php* file, to ensure that all your classes are correctly reached by Composer.

```
...

use Cake\Error\FatalErrorException;
use Cake\Log\Log;
use CakeDomainManager\DomainApplication;

...

    /**
     * Makes sure that the domain structure is coherent
     * @throws \ReflectionException
     */
    public function testTrackDuplicatedClassesInNamespaceNoError()
    {
        $error = false;
        try {
            $app = new Application(dirname(dirname(__DIR__)) . '/config');
            DomainApplication::init($app)->trackDuplicatedClassesInNamespace(
                Configure::read('App.namespace', 'App'),
                APP
            );
        } catch (FatalErrorException $exception) {
            Log::error($error = $exception->getMessage());
        }

        $this->assertEquals(false, $error, $error);
    }
...

```

Should you absolutely need to have two classes named identically in the *src* folder, there is nothing the present version of the package can do.

### Optional 2

[](#optional-2)

I recommend editing the following line in your *config/app.php* file under the *'App.paths'* entry to:

```
'templates' => [APP . DS . 'App' . DS . 'Template' . DS],

```

or your app's namespace, if it is not *App*.

Should you run into any error messages during the installation, Cake will know the path to the Error template.

This can be eventually removed once the migration is completed. The DomainController sets up that path for you, as described in the section *Controller* above.

Usage
-----

[](#usage)

With the settings done you can call elements of the same layer just as before:

```
Request: /users/view/1

```

To call elements from another layer, just use the magical *@* at the end of the traditional CakePHP notation.

Elements of another layer:

```
Request: /pilots/view/1

```

Elements of another sub-layer, e.g. *User/Settings*:

```
Request: /pilots/view/1

```

Elements of another layered plugin:

```
E.g.: plugins/Advertisements/src/CarRenting/Template/Element/weekly_offers.ctp

Request: /pilots/view/1

```

The notation:

```
