PHPackages                             burzum/cakephp-service-layer - 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. burzum/cakephp-service-layer

ActiveCakephp-plugin

burzum/cakephp-service-layer
============================

Service layer and domain / business model implementation for CakePHP

3.1.0(4mo ago)68152.5k↓20%141MITPHPPHP &gt;=8.1CI failing

Since Apr 3Pushed 4mo ago7 watchersCompare

[ Source](https://github.com/burzum/cakephp-service-layer)[ Packagist](https://packagist.org/packages/burzum/cakephp-service-layer)[ RSS](/packages/burzum-cakephp-service-layer/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (5)Versions (17)Used By (1)

A Service Layer for CakePHP
===========================

[](#a-service-layer-for-cakephp)

[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.txt)[![Build Status](https://camo.githubusercontent.com/9dbbb7c57fe6ca660ad93e0f8005de8f416646cab9ade224e280ec46f07414f2/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f6275696c642f672f6275727a756d2f63616b657068702d736572766963652d6c617965722f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/burzum/cakephp-service-layer/)[![Coverage Status](https://camo.githubusercontent.com/ca5f0a4182042a634024d4bd5af9b1bf580bba8f8c3f671c8982e3c8a2020b95/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f6275727a756d2f63616b657068702d736572766963652d6c617965722f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/burzum/cakephp-service-layer/?branch=master)[![Code Quality](https://camo.githubusercontent.com/9e5d226e92e87e71c84520dbeb739f7bfe98d7ca294dacf0c2545fee594d53d4/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f6275727a756d2f63616b657068702d736572766963652d6c617965722f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/burzum/cakephp-service-layer/?branch=master)[![Latest Stable Version](https://camo.githubusercontent.com/855ea0d9cd78b3aad9f39a63f85b2d649bdd5fc4b8b38b21ac971285ac4ad895/68747470733a2f2f706f7365722e707567782e6f72672f6275727a756d2f63616b657068702d736572766963652d6c617965722f762f737461626c652e737667)](https://packagist.org/packages/burzum/cakephp-service-layer)[![Minimum PHP Version](https://camo.githubusercontent.com/183804d09fec16ca7b6209b007250b7d8db1b915042feb093a9f20e6e1f25359/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230382e312d3838393242462e737667)](https://php.net/)

This is more a **design pattern** and **conceptual idea** than a lot of code and will *improve the maintainability* of your code base. This plugin just provides some classes to help you applying this concept in the CakePHP framework following the way of the framework of convention over configuration.

Supported CakePHP Versions
--------------------------

[](#supported-cakephp-versions)

This branch is for use with **CakePHP 5.0+**. For details see [version map](https://github.com/burzum/cakephp-service-layer/wiki#cakephp-version-map).

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

[](#introduction)

The rule of thumb in any MVC framework is basically "fat models, skinny controllers".

While this works pretty well the abstraction can be done even better by separating for example the DB operations from the actual [business logic](https://en.wikipedia.org/wiki/Business_logic). Most Cake developers probably use the table objects as a bucket for everything. This is, strictly speaking, not correct. Business logic **doesn't** belong into the context of a DB table and should be separated from *any* persistence layer. CakePHP likes to mix persistence with business logic. Very well written business logic would be agnostic to any framework. You just use the framework to persists the results of your business logic.

A table object should just encapsulate whatever is in the direct concern of that table. Queries related to that table, custom finders and so on. Some of the principles we want to follow are [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns) and [single responsibility](https://en.wikipedia.org/wiki/Single_responsibility_principle). The `Model` folder in CakePHP represents the [Data Model](https://en.wikipedia.org/wiki/Data_model) and should not be used to add things outside of this conern to it. A service layer helps with that.

The service class, a custom made class, not part of the CakePHP framework, would implement the real business logic and do any kind of calculations or whatever else logic operations need to be done and pass the result back to the controller which would then pass that result to the view.

This ensures that each part of the code is easy to test and exchange. For example the service is as well usable in a shell app because it doesn't depend on the controller. If well separated you could, in theory, have a plugin with all your table objects and share it between two apps because the application logic, specific to each app, would be implemented in the service layer *not* in the table objects.

[Martin Fowler's](https://en.wikipedia.org/wiki/Martin_Fowler) book "[Patterns of Enterprise Architecture](https://martinfowler.com/books/eaa.html)" states:

> The easier question to answer is probably when not to use it. You probably don't need a Service Layer if your application's business logic will only have one kind of client - say, a user interface - and it's use case responses don't involve multiple transactional resources. \[...\]
>
> But as soon as you envision a second kind of client, or a second transactional resource in use case responses, it pays to design in a Service Layer from the beginning.

It's opinionated
----------------

[](#its-opinionated)

There is a simple paragraph [on this page](https://blog.fedecarg.com/2009/03/11/domain-driven-design-and-mvc-architectures/) that explains pretty well why DDD in MVC is a pretty abstract and very opinionated topic:

> According to Eric Evans, Domain-driven design (DDD) is not a technology or a methodology. It’s a different way of thinking about how to organize your applications and structure your code. This way of thinking complements very well the popular MVC architecture. The domain model provides a structural view of the system. Most of the time, applications don’t change, what changes is the domain. **MVC, however, doesn’t really tell you how your model should be structured. That’s why some frameworks don’t force you to use a specific model structure, instead, they let your model evolve as your knowledge and expertise grows.**

CakePHP doesn't feature a template structure of any DDD or service layer architecture for that reason. It's basically up to you.

This plugin provides you *one possible* implementation. It's not carved in stone, nor do you have to agree with it. Consider this plugin as a suggestion or template for the implementation and as a guidance for developers who care about maintainable code but don't know how to further improve their code base yet.

How to use it
-------------

[](#how-to-use-it)

CakePHP by default uses locators instead of a dependency injection container. This plugin gives you a CakePHP fashioned service locator and a trait so you can simply load services anywhere in your application by using the trait.

The following example uses a `SomeServiceNameService` class:

```
use Burzum\CakeServiceLayer\Service\ServiceAwareTrait;

class AppController extends Controller
{
    use ServiceAwareTrait;
}

class FooController extends AppController
{
    public function initialize()
    {
        parent::initialize();
        $this->loadService('Articles');
    }

    /**
     * Get a list of articles for the current logged in user
     */
    public function index()
    {
        $this->set('results', $this->Articles->getListingForUser(
            $this->Auth->user('id')
            $this->getRequest()->getQueryParams()
        ));
    }
}
```

If there is already a property with the name of the service used in the controller a warning will be thrown. In an ideal case your controller won't have to use any table instances anyway when using services. The tables are not a concern of the controller.

The advantage of the above code is that the args passed to the service could come from shell input or any other source. The logic isn't tied to the controller nor the model. Using proper abstraction, the underlying data source, a repository that is used by the service, should be transparently replaceable with any interface that matches the required implementation.

You can also load namespaced services:

```
// Loads BarService from MyPlugin and src/Service/Foo/
$this->loadService('MyPlugin.Foo/Bar');
```

Make sure to get IDE support using the documented IdeHelper enhancements.

For details see **[docs](/docs)**.

Why no DI container?
--------------------

[](#why-no-di-container)

You could achieve the very same by using a DI container of your choice but there was never really a need to do so before, the locators work just fine as well and they're less bloat than adding a full DI container lib. There was no need to add a DI container to any CakePHP app in the past ~10 years for me, not even in big projects with 500+ tables. One of the core concepts of CakePHP is to go by conventions over wiring things together in a huge DI config or using a container all over the place that is in most cases anyway just used like a super global bucket by many developers.

This is of course a very opinionated topic, so if you disagree and want to go for a DI container, feel free to do so! It's awesome to have a choice!

DI plugins for CakePHP:

- [Piping Bag](https://github.com/lorenzo/piping-bag)
- [Pimple DI](https://github.com/rochamarcelo/cake-pimple-di)
- [CakePHP DI Generic PSR 11 Adapter](https://github.com/robotusers/cakephp-di)

You might find more DI plugins in the [Awesome CakePHP list of plugins](https://github.com/FriendsOfCake/awesome-cakephp#dependency-injection).

Demo
----

[](#demo)

The [sandbox](https://sandbox.dereuromark.de/sandbox/service-examples) showcases a live demo. Check the publically available code for details.

License
-------

[](#license)

Copyright Florian Krämer

Licensed under The MIT License Redistributions of files must retain the above copyright notice.

###  Health Score

59

—

FairBetter than 99% of packages

Maintenance75

Regular maintenance activity

Popularity46

Moderate usage in the ecosystem

Community23

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 55% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~205 days

Recently: every ~396 days

Total

13

Last Release

135d ago

Major Versions

1.0.2 → 2.0.02020-03-11

1.x-dev → 2.1.22021-01-19

2.2.0 → 3.0.0-RC2023-09-28

PHP version history (4 changes)1.0.0PHP &gt;=7.0

2.1.0PHP &gt;=7.2

2.2.0PHP &gt;=7.4

3.0.0-RCPHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/0643e6255da841fe65260ec6e263d8908a40a84b884c32e9fc6be6a15e252fa8?d=identicon)[burzum](/maintainers/burzum)

---

Top Contributors

[![burzum](https://avatars.githubusercontent.com/u/162789?v=4)](https://github.com/burzum "burzum (71 commits)")[![dereuromark](https://avatars.githubusercontent.com/u/39854?v=4)](https://github.com/dereuromark "dereuromark (52 commits)")[![predragleka](https://avatars.githubusercontent.com/u/5904211?v=4)](https://github.com/predragleka "predragleka (2 commits)")[![davidyell](https://avatars.githubusercontent.com/u/49889?v=4)](https://github.com/davidyell "davidyell (1 commits)")[![bouillerot](https://avatars.githubusercontent.com/u/101400827?v=4)](https://github.com/bouillerot "bouillerot (1 commits)")[![NickBusey](https://avatars.githubusercontent.com/u/280825?v=4)](https://github.com/NickBusey "NickBusey (1 commits)")[![TABTyrell](https://avatars.githubusercontent.com/u/46192336?v=4)](https://github.com/TABTyrell "TABTyrell (1 commits)")

---

Tags

architecturecakephpcakephp-frameworkddddesign-patternserviceservices

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/burzum-cakephp-service-layer/health.svg)

```
[![Health](https://phpackages.com/badges/burzum-cakephp-service-layer/health.svg)](https://phpackages.com/packages/burzum-cakephp-service-layer)
```

###  Alternatives

[friendsofcake/cakepdf

CakePHP plugin for creating and/or rendering Pdfs, several Pdf engines supported.

3752.1M3](/packages/friendsofcake-cakepdf)[cakephp/bake

Bake plugin for CakePHP

11211.2M158](/packages/cakephp-bake)[dereuromark/cakephp-tools

A CakePHP plugin containing lots of useful and reusable tools

338920.1k32](/packages/dereuromark-cakephp-tools)[dereuromark/cakephp-queue

The Queue plugin for CakePHP provides deferred task execution.

308850.3k14](/packages/dereuromark-cakephp-queue)[dereuromark/cakephp-ide-helper

CakePHP IdeHelper Plugin to improve auto-completion

1862.1M27](/packages/dereuromark-cakephp-ide-helper)[dereuromark/cakephp-tinyauth

A CakePHP plugin to handle user authentication and authorization the easy way.

129228.6k10](/packages/dereuromark-cakephp-tinyauth)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
