Early work has started for CakePHP 3.0, and I’ve started re-visiting how CakePHP handles configuration and bootstrapping. I want to focus on configuration for this post, as bootstrapping, while related is worthy of its own post. The goal of this post is to provide some context on the planned changes, and to get feedback on those changes. My hope is that by getting feedback early on we can avoid problems & surprises later on.
I decided to start with configuration. Every application needs at some configuration even in a conventions over configuration framework like CakePHP. I feel that configuration can be improved from where it stands today, as there are a few problems.
Problems with configuration
When I think of configuation in CakePHP, I think of the
Configure class. From talking with others, they feel the same.
Configure has been around as long as CakePHP, and is the primary way most developers do configuration for their application/plugins. However, there are two other ways that configuration is currently managed outside of
- Classes like
EmailConfig. These classes are my least favorite method. They are clunky and don’t really offer much benefit over
Configurein terms of flexibility.
- Configuration methods like
CakeLog::config(). While these methods appear to offer more traditional dependency injection, they don’t. All engine class references are passed as strings, and you can never inject an instance anywhere.
While having 3 ways to do configuration may not seem like a problem for the experienced developer. But having 3 ways to do basically the same thing creates a steeper learning curve for developers who are new to CakePHP. Ideally, there would be only one way configuration is handled. Having systems like
DATABASE_CONFIG greatly increases the difficulty in creating configuration files in formats other than PHP.
Originally, I was very much in favour of removing the configuration classes and adding more
config() methods to the remaining classes needing them. However, Jose and Juan argued that using
Configure was a better solution because we’d still need to maintain
Configure. We’d still have 2 ways of doing configuration by adopting
config() methods, while the goal was 1. While I don’t like that many clasess in CakePHP will be coupled to
Configure. I want to avoid adding additional layers just to provide what I think will be a marginal amount of decoupling. While an additional layer could be more ‘proper’ it would also increase difficulty for beginners. Despite the downside of coupling there are some great benefits to putting all configuration in
- All core, app, and plugin classes only need one way to create, read and manage configuration.
- We can leverage the existing Config adapters to enable support for any format/source.
- Familliarity and simplicity. Existing developers are familliar with Configure, and its a very basic API so its easy for new developers to pick up.
Configure would be the primary way to handle configuration in a 3.0 application, we’re planning on adding more generic setter injection where it makes sense. For example, you’ll be able to directly add cache engines to
- use Vendor\Caching\CustomEngine;
- $engine = new CustomEngine($dependency);
- Cache::engine('custom', $engine);
This feature allows you to easily accomodate any type of caching that can’t or doesn’t make sense to store as configuration. In these situations, you’ll be able to use
engine() on Cache, and Log to set a specific instance. Other adapter based classes will have similar features.
I’m interested to hear any feedback on these plans. I’m still in the early stages of implementing them and would love to hear people’s thoughts before finishing. If you’re interested in seeing the in progress changes you can find them on my github fork .