Backend
Hire PHP Developers
PHP engineers who write modern PHP 8 and can also stabilise the legacy code you inherited.
PHP earns its place through the sheer volume of working software already written in it, and PHP 8 is a genuinely different language from the one its reputation was formed on — typed, fast, with an opcache and JIT that closed most of the performance argument. Laravel and Symfony are serious frameworks by any standard.
The distinguishing skill in PHP is not writing it. It is safely changing code somebody else wrote, on a server somebody else configured, that has been reachable from the public internet for years.
What actually finds a compromise
We rebuilt an estate of PHP sites after a long-running intrusion, and the single most useful lesson was about detection method. Signature and pattern scanning of the file tree returned zero hits on a site that turned out to hold 211 malicious files. Comparing every file against the official distribution — checksums, not regular expressions — found them.
The reason is straightforward once stated: attackers write code to defeat patterns, not
checksums. Anything that can be obfuscated will be, and a scanner looking for eval and
base64_decode is looking for the version of the payload that a competent attacker has already
stopped writing.
Four hiding places were each responsible for something real, and any PHP engineer auditing an inherited application should check them by name:
- Drop-ins such as
object-cache.php, which load on every request and never appear in a plugin list. One of ours was a restorer that quietly reinstalled payloads after cleanup. - Plugins listed as active in the database but absent from the plugin listing, because they filter themselves out of it.
- Backdated file timestamps — the backdoors carried dates two years older than the intrusion, which defeats every “recently modified” check.
- Stray PHP in the document root, random hexadecimal directories, and anything executable under an uploads directory.
The hosting assumptions that are wrong on a modern server
Plenty of PHP security advice assumes Apache. Nginx ignores .htaccess entirely, which means every
Apache-era protection a plugin claims to add is decorative — that is how hundreds of megabytes of
publicly downloadable site backups sat unnoticed in a document root.
The other assumption worth breaking is the shared worker pool. Sites running as one common user can read each other’s configuration files, which is precisely how one compromised site reaches all the others on a box. Each site gets its own process pool, its own user and a path confinement, and PHP execution is blocked in uploads at the web server rather than in the application.
An engineer who has only ever worked on managed hosting will not have met any of this, and it is worth finding out in an interview rather than during an incident.
How a legacy upgrade is sequenced
Inherited PHP arrives without tests, so the first work is not refactoring. It is writing characterisation tests: capture real inputs and the outputs the current code actually produces — including the wrong ones, because something downstream now depends on them — so that any later change has something to be judged against.
After that the order is: get onto a supported PHP version with the code as it is, adopt a static
analyser at whatever level currently passes and raise it one step at a time, then convert the
oldest patterns — database calls from the mysql_ era, global state, untyped functions — into typed
services. Rewriting first and testing afterwards is how a six-week job becomes a six-month one.
Where PHP is the wrong choice
Long-running processes and real-time work. The request-per-process model is a strength for web applications and a poor fit for websockets, streaming and background workers that must hold state, even with the runtimes that now make it possible.
Heavy numerical or machine learning work, where the ecosystem is thin and there is no reason to fight that. And any project where the team’s PHP experience is entirely WordPress theming, because application PHP and template PHP are different disciplines that share a syntax.
What we interview for
The useful question is about inherited code, because that is what most PHP engineers will be handed. Ask how they approach an application with no tests and no documentation, how they decide what to rewrite and what to leave alone, and what they check first on a codebase that has been publicly exposed for years. Anyone who reaches immediately for a rewrite has not maintained one of these.
Then two specifics. How do they take a WordPress site from customised theme files to something upgradable — the answer should involve a child theme and plugin-level or API-level work, not patching core. And what does their static analysis configuration look like: a level that is actually enforced in continuous integration is worth more than a higher one that everybody ignores with baseline files.
What these engineers do
- PHP 8.3 and 8.4 with typed properties, enums, readonly classes and fibers
- Laravel 11 and Symfony 7 applications with queues, events and feature tests
- Upgrades from PHP 5 and 7 codebases, starting with characterisation tests
- WordPress and WooCommerce work at plugin and API level rather than theme patching
- PHPStan or Psalm at a level that is actually enforced, with PHPUnit coverage that means something
Delivered AI-first
Most PHP work arriving at an agency is inherited rather than new, so AI assistance is aimed at legacy first - reading undocumented code and drafting the characterisation tests that make a change safe, then converting mysql_ era database calls, global state and untyped functions into typed, injectable services. Static analysis and the test suite decide whether each step was correct. Security-sensitive code is read by a human every time. Review discipline is unchanged. The measurable effect is throughput per engineer, not fewer reviews.
PHP engineers in client teams
Other Backend roles
Node.js
Node engineers who run services in production and have been on call for the ones they wrote.
Python
Python engineers who build typed, tested services rather than scripts that grew into one.
.NET
.NET engineers who are equally at home in modern .NET and in the Framework estates still running the business.
Java
Java engineers who maintain and modernise the services larger organisations genuinely depend on.
Go
Go engineers who use the language where it wins — throughput, concurrency and small deployable binaries.
What an unfilled engineering role costs while you hire — worked out on your own numbers.