Anyone can write a listicle, but it's far more interesting to have a look at what I've never seen before and play with it a bit rather than just telling everyone what's out there and listing out features.
The majority of content I write centres around Laravel and Symfony, a logical pairing considering those are two of the largest communities out there in PHP land, bar WordPress and Drupal. Many, many developers have trod down the path with these names on, so why not look at something different?
One thing I noticed during this is that several new platforms that are getting traction are based entirely around performance.
Slow speed is a criticism often aimed at PHP that I don't see as particular relevant anymore, and perhaps these frameworks are a testament to that, especially with PHP 8.6 shipping with the new Polling API.
So, armed with some projects that I have heard of, and some that I have not, I dug out the Vonage PHP SDK and threw it at some frameworks to see what would happen.
TempestPHP
Caption: A new framework has got a storm brewingI've decided to kick off with TempestPHP, given that I recently wrote about JetBrains' PHPVerse event, which had Brent Roose as one half of the hosting duties.
It was some time ago now that I saw him launch TempestPHP on his blog, stitcher.io.
The "why to use a framework" is always important. There is a reason for everything. Laravel, for instance, came about because of dissatisfaction using CodeIgniter, and inspiration from Ruby on Rails. Symfony was born out of frustrations with Zend, and sometimes it's essentially a developer who has worked many, many hours on a particular framework and has the experience to say, "maybe I'll just do it my way?"
Tempest is that.
Using Composer's create-project to scaffold a new project:
What's Out of the Box
Everything in Tempest has been written from the ground up. That even includes a new templating engine. You've got a service container, views, database, and routing.
Looking at the internal API level, you've got everything new and shiny – property hooks, attributes for routing (Symfony and API Platform both use similar patterns), and proxy objects (something new that I'm not that familiar with).
Using Tempest to Send a Vonage RCS Message
I'm going for the basics here, to cover a smaller amount of ground. We're going to have a route to present a form, the user adds a phone number in and message, hits send, the code sends the message (this is also under the requirement that you have set up your sandbox for RCS messaging).
Install the Vonage PHP SDK
First up, let's bring in the Vonage PHP SDK:
You'll then need your credentials by creating a new application in the Vonage Dashboard or with the Vonage CLI, resulting in an Application ID and private.key if successful.
Open up your .env file and add your credentials:
Wire up the Vonage Client
Tempest has quite an interesting design, in that it doesn't give you a set pattern with which to follow; it's the antithesis of the "opinionated framework".
I find this approach fairly similar to SlimPHP, although really Tempest is designed to make the attributes/property hooks/proxies speak as the identifiers for your structure. It's certainly a departure from what I'm used to.
For the Vonage client, we're going to create a Service which will use Tempest's discovery to be injected to a controller.
Creating the Form
There are two parts to this: a Tempest request object which can handle things like validation, and the form itself, which is a view.
Something I quite like is the use of traits to identify your code for high-level discovery. Here is the request object:
I've just gone for string type and length, but you can also add custom rules. The Vonage PHP SDK has, for instance, a isValidE164() method built into it which you could bake into your validation rules.
Now for the form:
You can see that the form's action is a POST to /messages, so the final wire-up is a controller. Tempest lets you choose your own structure, so traditionally in frameworks I've used, it has the route → controller → view pattern. With attributes and discovery, though, you don't have to have a separate route file if you don't want one.
So I create a controller which handles the RCS sending logic, and we're done:
Similar to how other PHP frameworks work, it makes use of the session()->flash() functionality, so now all that's left to do is add the flash rendering below the form view:
You'll notice the PHP tags, but don't be alarmed! We've seen Laravel Livewire components used in this way, which is essentially a close template pattern to how VueJS works: the logic section comes first, the HTML template comes second.
Tempest has given me a pretty straight-up way to wire in Vonage, no big gotchas to mull over. The experience feels pretty smooth to me, especially with having Laravel and Symfony experience, but also absolutely worth having a play with as the autowiring discovery is slightly more novel (you can form your own opinion on whether more or less "magic" is a good thing).
Phalcon
Phalcon is a name I have heard bandied about for quite some time, and even back when I did hear about it in around 2016, it was the performance that was getting people's attention. This framework is like nothing I've seen before: it's actually a C extension that exposes the framework elements for PHP developers.
Getting Started (Throwing the Rulebook Out the Window)
I am immediately flummoxed. Such is the prevalence of creating a new framework installation for an app through either composer create-project or a CLI-wrapped implementation that uses it under the hood; I am immediately thrown outside of my comfort zone.
It doesn't use Composer; it's a PHP extension. The installation instructions are long; they depend on your operating system, and there are warnings and gotchas everywhere. The framework itself is all compiled and held in memory. This is going to be a bit left-field for me.
After following a mass of work, which honestly felt like a bit of harkening back to the old days of manually wiring Apache, MySQL, and php-fpm together, I can actually throw some code at it. It's not a Packagist project, so this is about as manual as it comes:
This sets up your project in the current directory, and then next we need Vonage:
I've used the client library here because it will also bundle in Guzzle, something that Phalcon won't have shipped out of the box. It's a very different approach.
As we did in the previous section with TempestPHP, you'll need an Application ID and a private.key file. Put the key file in the root of your project, but rather than the Application ID going into an .env file, think of how this would work more at a runtime level. Instead of an .env file, the Application ID goes in via a terminal:
A bit different, right?
Boot the Phalcon Application
That's right, nothing comes out of the box as there's no Composer. Instead, Phalcon is now (as a PHP C extension) available as "part of the core". So, we build our own bootstrap file in its own space, public/index.php:
We've set the folders for controllers and views, so we can create the view. Phalcon uses a basic view system with .phtml, but I'd recommend later on actually using a templating engine like Blade or Twig.
We've registered our views directory as app/views, so this view goes under app/views/index/index.phtml:
Ah, yes. Hence why I suggested using a templating engine. Out of the box, Phalcon has good old-fashioned PHP logic mixed into an HTML form. I guess you could say that was similar to Tempest, but Tempest definitely has a separation of concerns to make the logic and the template different parts that make a component up.
The last part is the controller, which comes under app/controllers/IndexController.php:
Remarkably, the code still looks like a mixture of plain PHP and a little bit of framework code. The routing got to me a little bit, though, as I didn't define a route or indeed used any of the routing or dispatching system within Phalcon. So, because index is the controller namespace, I've ended up with what I want (i.e. GET / and POST /) but the reason the home will land is that 'index' is the default route name.
To serve the app, it's easiest to use the PHP built-in web server:
The Verdict
Phew, done. I don't think I've ever really seen a pattern and structure like it in a framework, but given there are some nice features in here – a 'Micro' application structure you can use, for instance – I can absolutely see the value in using this as a microservices or serverless backend.
Better still, pairing the speed of the native C extension with an event loop like ReactPHP would really put benchmarks against other performance-focused languages, let alone frameworks.
LeafPHP: The Pivot to AI
Back into more conventional territory (to an extent), we leave behind the mad world of standalone C extensions and enter back into Web Application Development, but with an "AI-first" mantra.
It's another example, like Slim and Phalcon, where you really aren't given much out of the box. Just routing and the request/response objects. You can then build out as much as you want (and the list of packages is pretty extensive).
Because it's been designed to make sure the internal API is all chainable among the packages, it means a better experience for AI agents building out. Rather than just performance speed, they want (similar in a Laravel vein of thinking) to be fast at developing. From brain to shipped, something I am admittedly terrible at (but that's what the AI era is for).
Installing Leaf
Like Symfony and Laravel, Leaf comes with its own CLI to help things along. First, use Composer to install it globally on your machine:
Next, create a new LeafPHP application and install the Vonage PHP SDK:
We're going back to the more traditional usage of an .env file, although the internal syntax to call an env variable is somewhat different from what I've been used to. Add the Application ID to the .env file, and the private.key to the project root. Calling the env variable looks like this:
Unlike Phalcon, Leaf has a configuration system for env out of the box, which makes it quite a nice comparable developer experience to other frameworks (though there is a good reason that Phalcon doesn't – its use case is somewhat different).
Setting Up the Vonage Service
Like Tempest, Leaf ships with a Service container, which is a binding application pattern for Dependency Injection. Like other PHP frameworks like Symfony and Laravel, you can type-hint the Service into a Controller's constructor, and it becomes available (and you can create mock objects during testing to replace it).
You can see that the Service is actually just a PHP class, rather than extending anything. This is because Leaf acts in the more traditional framework style of registering a service provider that needs to be registered.
I could have also exposed the Client in a public method which would then use the Messages API Client (inside the Vonage Client) to use the send() method, but to mix it up a bit, the VonageService instead has a wrapper method named sendRcs() that handles this for you.
Next up, we need a controller that a route will eventually be wired to:
The VonageService is injected automatically, and we can use the sendRcs method after some basic validation. You'll note that the GET request is tied to a view named message, which we've not created yet (or routed to the create() method), so we now need to make the form.
Create it under app/views/message.blade.php – those Laravel developers among us might notice that Leaf ships with the Blade templating engine out of the box, which will be familiar.
There's the form with the action POSTing to the /message endpoint, so now we need to register the route. This is done in a similar bootstrap approach to something like Slim. Create your entry point under /public/index.php:
And there we have it: an RCS service, controller, and view.
Conclusion
So, a quick summary of our three frameworks:
Framework
Pros
Cons
Use Case Examples
TempestPHP
Brand new, modern PHP source code; Automatic framework discovery feature; An integrated Reflection API, brilliant for testing
Not production-ready yet; Documentation still an evolving work-in-progress; Small community due to lack of maturity
The rapid speed of development, plus less boilerplate in Tempest makes it an ideal candidate for building a custom SaaS Dashboard
Phalcon
Remarkable speed; Low memory usage and requirements; Adaptable to either a full MVC stack or a micro instance
DevOps pipelines and infrastructure are significantly more complex to handle, due to it being a C extension; Community is relatively niche
A REST (or gRPC) platform that requires high performance benchmarks for high throughput
LeafPHP
The bonus of features from something big, like Laravel, but far smaller and modular; Guardrails for rapid AI Development
Less production-ready than options like Slim, Symfony, or Laravel; Small community due to maturity
Due to the smaller footprint, Leaf makes an excellent choice for prototyping or developing an MVP at something like a Hackathon
The joy of using PHP is the vast amount of options you have. Symfony, Laravel, WordPress, and Drupal all have large, mature communities supporting them. However, so does TYPO3, and both CakePHP and CraftCMS boast an impressive array of clients that use their technology.
AI might be able to drive forward features and code at a lightning pace in the new world of software development, but the choice of stack that powers what you build is still something only you, an architect, can investigate and pick accordingly.












