How to create a framework-agnostic application in PHP

June 20, 2022

How to create a Framework Agnostic Application in PHP

Using the term agnosticism in the context of software engineering is a stretch, but it makes sense to me. When it comes to an application that uses a database but doesn’t know and has no way of knowing (or doesn’t care) what database engine it is, the term database-agnostic application is used. A Java and JavaScript online store, for example, is an example of such a system. It would require a database to store products, orders, and transactions, but any database engine may be used. By any, we mean SQL Server, Oracle, MySQL, PostgreSQL, and NoSQL database engines, to name a few.


Framework-agnostic application: Overview

No matter the tools you use, you may create a framework-agnostic application. Domain-Driven Design (DDD) — hexagonal design and similar patterns – has recently been a hot topic among PHP developers. Their main purpose is to decouple business logic from a framework, storage, and code. I’d like to expand on this issue and demonstrate how to segregate domain-related information from all boilerplate required to get everything up and to run. This would most likely assist others (including myself) in the beginning to write reusable extensions for Phalcon, something this amazing framework now lacks. There’s no need for bundles or service providers for Composer/Packagist; they’re all just shortcuts for DI containers anyhow, and they bind your package to a framework. Make something universally useful and teach others how to use it effectively with a DI container.

That is the hypothesis. When you need to accomplish something tangible, you choose an ORM as a minimum right away, so it’s immediately tied to something other than PHP. If you try to do it without using a framework, you’ll wind up with many heavy abstractions and a lot of design headaches.

Building a framework-agnostic application in PHP for domain.


Runner Model

  • This model suggests crucial properties like password or emails.
  • The RunResult and RunParticipation classes which relate our runner to runs and their outcomes.

Runner-Model--software-engineeringInherits DomainException rather than directly extending PHP’s Exception.



RunParticipation Model



We just emphasis on the most critical aspects!

The crucial domain layer is already covered. We’ll utilise a command bus in this layer, therefore there will be a class for each application operation. We have a very simple Command class in this pattern that contains data introduced by a system operator.

Let’s discover the runner’s enrolment.



Eloquent representation

Eloquent maps these properties via magic getters/setters, so having these properties explicitly defined would prevent Eloquent from working.


There’s only one challenge now: how can you connect these two classes that are so dissimilar? Extending may not be a good idea because they are so dissimilar, especially if the storage model extends ORM’s Model class. We do, however, have a second choice. Let’s make a class that can translate between these two models in both directions.


RunParticipation: Eloquent model


RunnerRepository Implementation


Framework-agnostic app integration

Let’s link everything together with Laravel now. The application layer is where we connect.


Connect Eloquent and Doctrine to create a framework-independent app with storage.


Corresponding Transformer


The entities of doctrine aren’t at all self-contained. To maintain relationships between classes, you must utilise the ORM’s ArrayCollection class.

Here’s the example of RunParticipation entity:

RunParticipation entity--software-engineeringThe last thing to notice in the sample below is that read/write repositories are shown.




RunnerParticipationRepository--software-engineeringIf you’re going to design sophisticated framework-agnostic components, you’ll almost certainly end up exploring.



Let's get in touch


+91 9408707113


+1 864 492 1364




+91 9408707113