Showing posts with label evolvephp. Show all posts
Showing posts with label evolvephp. Show all posts

Wednesday, 12 August 2026

Why I’m Rebuilding EvolvePHP: Lessons From a Framework I Built Years Ago

 

Back in early 2016, while working on several PHP projects, I didn’t realize I was building a framework.

At the time, I had already learned CodeIgniter and was proficient with WordPress and Joomla. Most of the applications I was working on were not simple websites; they were larger business and enterprise systems with recurring requirements such as user management, authentication, roles, access control, sessions, administrative interfaces, and other shared functionality.

As I moved from one project to another, I started noticing a pattern.

I was repeatedly rebuilding many of the same features.

User management.

Login and authentication.

ACL.

Roles and permissions.

Database access.

Routing.

Sessions.

Controllers.

Common utilities.

I wanted a better way to reuse those capabilities without copying an old application and removing everything I didn't need.

evolvephp1-evolvephp2

 

The idea started with modularity

CodeIgniter influenced how I thought about MVC and application structure, but Joomla had also exposed me to a different idea that I found very interesting: components and modular functionality.

I liked the idea of being able to build a feature independently and then plug it into another application when needed.

Instead of every new project starting like this:

New project
    ↓
Build authentication again
    ↓
Build roles again
    ↓
Build ACL again
    ↓
Build common infrastructure again

I wanted something closer to:

Application
    ├── Users
    ├── Authentication
    ├── ACL
    ├── Reporting
    └── Other reusable components

If another application needed one of those capabilities, I could reuse or adapt the component rather than starting from scratch.

So I began creating my own structure around the applications I was developing.

At that point, I wasn't really thinking:

"I am going to create a PHP framework."

I was simply trying to solve a problem I kept encountering in my daily development work.

Then I realized I had built a framework

After deploying one of the applications, I looked at the underlying code more carefully.

By then, I had already created many of the things we normally associate with a framework:

  • Routing

  • MVC structure

  • Session management

  • Database abstractions

  • Controllers and models

  • Reusable components

  • Configuration management

  • Authentication-related utilities

  • ACL and permission handling

  • Common application helpers

The application-specific code was sitting on top of a reusable foundation.

At that point it became obvious that what I had created was no longer just a collection of helper files.

It was the beginning of a framework.

That framework eventually became EvolvePHP.

EvolvePHP grew with the applications I built

I continued using the framework for other projects.

Whenever I encountered something missing, I added it.

Whenever I found myself repeating code between projects, I looked for a way to make that functionality reusable.

Whenever an application exposed a weakness in the framework, I improved the framework.

So EvolvePHP grew organically.

It wasn't designed in one sitting from a perfect architectural specification.

It evolved alongside real applications and real business requirements.

That experience was incredibly valuable.

Several applications I built with EvolvePHP are still running today, years after they were originally deployed.

For me, that matters more than whether the framework ever became widely adopted publicly.

It proved that the ideas behind it were useful enough to support real systems.

What EvolvePHP 1 taught me

Building EvolvePHP taught me far more than I expected when I started.

It forced me to understand PHP beyond simply using existing frameworks.

I had to think about questions such as:

  • How should requests enter an application?

  • How should routes be resolved?

  • How should controllers be instantiated?

  • How should reusable components communicate?

  • How should authentication state be handled?

  • How should permissions be represented?

  • How should application configuration work?

  • How should database access be structured?

  • How much responsibility should a framework take from the application?

  • Where should framework code end and business code begin?

It gave me practical experience with:

  • PHP internals and application structure

  • MVC architecture

  • Reusable software design

  • ACL and authorization systems

  • Framework development

  • System design

  • Design patterns

  • Component architecture

  • Application lifecycle concerns

Some of the architectural decisions I made back then are decisions I would not make today.

But that is part of the value of the project.

You learn a lot when you have to live with your own architectural decisions for several years.

Why I am preserving EvolvePHP 1

When I decided to begin EvolvePHP 2, one question was whether I should simply transform the existing codebase into the new framework.

I decided against that.

EvolvePHP 1 represents a particular period in my development career and a particular era of PHP development.

There is value in preserving that history.

It shows where the project started.

It also gives me a reference point when designing EvolvePHP 2.

There may be ideas worth revisiting.

There may also be decisions that serve as useful reminders of what not to repeat.

And practically, preserving the existing version costs me very little.

So EvolvePHP 1 remains preserved rather than being overwritten by EvolvePHP 2.

Why EvolvePHP 2 is a redesign instead of an upgrade

A lot has changed since I last worked seriously on EvolvePHP 1.

PHP has changed significantly.

The ecosystem has changed.

The way applications are deployed has changed.

My own understanding of software architecture has changed.

EvolvePHP 1 was designed in an era where a typical PHP application was largely expected to handle one request, produce a response, and terminate.

Modern applications increasingly operate around:

  • Containers

  • Cloud infrastructure

  • Persistent workers

  • Queues

  • Background jobs

  • APIs

  • Distributed systems

  • Observability

  • OpenTelemetry

  • CI/CD

  • Horizontal scaling

  • Docker

  • Kubernetes

  • Long-running PHP runtimes

Trying to force all of that into the original EvolvePHP architecture would create more problems than it solves.

Some of the dependencies are outdated.

Some design decisions belong to an older PHP ecosystem.

And EvolvePHP 1 is much more comfortable around the PHP 7 generation than the environment I want EvolvePHP 2 to target.

So EvolvePHP 2 is not:

EvolvePHP 1
    +
new features

It is closer to:

Lessons from EvolvePHP 1
        +
14+ years of engineering experience
        +
modern PHP
        +
modern infrastructure
        +
new architectural principles
        ↓
EvolvePHP 2

That distinction is important.

The problem I want EvolvePHP 2 to solve

Another thing that has become clearer to me over the years is how difficult software modernization can be.

There are many PHP applications still running important businesses today.

Some were built with older frameworks.

Some are custom applications.

Some are based on versions of PHP that companies would like to move away from.

But rewriting a large production system from scratch is often unrealistic.

A company may have years of business logic inside an application.

Thousands of database records.

Integrations with other systems.

Customers actively using it.

Employees depending on it every day.

Telling that business:

"Rewrite everything."

is rarely useful advice.

That is one of the problems I want EvolvePHP 2 to explore more seriously.

What if a modern framework could help developers gradually improve an existing application?

Instead of:

Legacy System
      ↓
Complete Rewrite
      ↓
Modern System

the process could look more like:

Existing System
      │
      ├── Existing modules
      ├── Existing business logic
      │
      └── Evolve Bridge
              │
              ├── New capability
              ├── Modernized module
              └── New services

Modernization could happen incrementally.

One capability at a time.

Building for change

That thinking has started shaping the philosophy behind EvolvePHP 2.

The goal is not simply to build another framework with routing, controllers and dependency injection.

Those problems have already been solved extremely well by frameworks such as Laravel and Symfony.

The more interesting question is:

How do we design applications that are easier to change several years from now?

That means thinking about things such as:

  • Modular application architecture

  • Clear package boundaries

  • Explicit dependency contracts

  • Safe execution lifecycles

  • Persistent-worker safety

  • Plugin architecture

  • Observability

  • Incremental modernization

  • Framework interoperability

  • Service extraction

  • Upgrade safety

A new application may start as one modular monolith.

Later, one module may need to scale independently.

An old application may gradually move functionality into modern modules.

A company may want to adopt modern PHP without immediately replacing everything that already works.

EvolvePHP 2 is being designed around those realities.

Doing it differently this time

There is another major difference between how I built the original framework and how I am approaching EvolvePHP 2.

EvolvePHP 1 grew mostly through implementation.

EvolvePHP 2 is starting with architecture.

Before implementing major framework features, I am defining the decisions that those features must follow.

That includes architecture RFCs covering areas such as:

  • Framework vision and scope

  • Package boundaries

  • Versioning and compatibility

  • Module and plugin lifecycle

  • Execution scope and runtime reset

  • Incremental modernization through Evolve Bridge

  • Observability and OpenTelemetry

I am also applying a test-driven approach to the framework itself.

Instead of simply adding a feature because it appears to work, I want important framework behavior to have explicit tests and architectural rules around it.

The goal is to make accidental architectural drift harder.

Looking back before moving forward

EvolvePHP 1 was never perfect.

I wouldn't build it the same way today.

But I don't regret building it.

It taught me things that I probably would never have learned by only using other people's frameworks.

It forced me to understand what happens underneath the abstractions I normally depended on.

And most importantly, it gave me something real to learn from.

EvolvePHP 2 is therefore not an attempt to erase the original project.

It is the next step in its evolution.

The first version was built from the experience I had at the time.

The second version is being built from everything I have learned since.

And this time, the ambition is broader:

Build a PHP framework designed not only for creating applications, but for helping those applications evolve over time.

That is the journey I will be documenting as EvolvePHP 2 develops.