How to create a framework-agnostic application in PHP
June 20, 2022
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.
Inherits DomainException rather than directly extending PHP’s Exception.
RunResult
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:
The last thing to notice in the sample below is that read/write repositories are shown.
RunnerRepository
RunnerParticipationRepository
If you’re going to design sophisticated framework-agnostic components, you’ll almost certainly end up exploring.