I am developing a web framework in PHP, and I want to make it fully extendable. My goal is to make it possible for a developer to change the behavior of any component without having to modify the "core" codebase at all. Developers should be able to encapsulate all of their work in a separate directory. And, I want to do this without using "hooks" (i.e., event listeners), which can quickly turn into a huge mess.

For most components, I have this figured out:

  • The Pimple DI container allows you to extend existing services.
  • I'm using Twig as my template engine, which allows templates to be overridden.
  • Front controller routes can be overridden by redefining them.
  • I'm using an extendable uniform resource locator to allow developers to override or add search paths for resources (assets, configuration, schema, etc).

The problem I face is extending the functionality of a class when there are places in the core codebase that already instantiate that class (because my framework is a full-fledged application rather than a library, even with IoC, I still need to instantiate the class at some point).

Inheritance alone won't solve this problem, because I'm still instantiating the base class in my core controllers/routes/whatever. It would seem that I need to introduce an additional layer of abstraction.

One idea I have is to just use PHP's dynamic class instantiation feature. For example, if I have a base User class, and I want to allow developers to replace all instances with a CustomUser class:

// In a config file (which *can* be overridden) 
$userClassName = "User";


// Anywhere I need a User, or User subclass: 
$user = new $userClassName(...);

Now, a dev simply needs to override the value of $userClassName and set it to the name of their child class.

Alternatively, I could wrap this all in a Factory pattern:

class UserFactory
    public function createUser($type = "User", $args)
        return new $type($args);

The advantage of the Factory class would be that I could do some type-checking, but then I'd need a separate Factory for each base class.

Are either of these approaches the right way to implement this kind of extensibility?

  • And, I want to do this without using "hooks" (i.e., event listeners), which can quickly turn into a huge mess. Why do you think that?
    – Andy
    Aug 12, 2016 at 20:46
  • 1
    @david-packer Because, you have to predict every single point in the code where a developer might want to inject functionality. In the extreme, you could end up with code where every other line in the code is an event emitter!
    – alexw
    Aug 12, 2016 at 21:21
  • Framework is a tool to solve common problems so they do not need to be solved over and over again and which are required by pretty much any project (routing, autoloading,...). If you feel like every other lc could be an event emitter you're getting at it from the wrong side. Your framework is usually not supposed to do everything. It's just supposed to make things easier. Most projects contain a completely framework-agnostic core anyway where the business logic lives, that's usually the main part of an application. Framework is just a handy wrapper.
    – Andy
    Aug 12, 2016 at 21:36
  • @DavidPacker it is more like a "framework+". This write-up might explain better what I am trying to create.
    – alexw
    Aug 12, 2016 at 22:08

1 Answer 1


My goal is to make it possible for a developer to change the behaviour of any component without having to modify the "core"

I would prefer to use interface here with a base class implementation. Developers can use this class or introduce a new class that implements the interface.

Dynamic class names are not discoverable and may add to technical debt.

Your controllers/routes/whatever would have Pimple Dependency Container. Developer would inject the custom class object and the core would make the object of this injected custom class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.