Overview
PHP's reputation is stuck about a decade behind its reality. PHP 8 has a JIT compiler, proper type declarations, enums, readonly properties, attributes, match expressions and fibers, and it is roughly three times faster than PHP 5.6 on typical workloads. Combined with a mature framework it is a genuinely strong choice for business applications — and it runs everywhere, cheaply, which matters more than developers like to admit.
We work in Laravel and CodeIgniter 4, and we maintain a fair amount of older PHP that quietly runs real businesses.
Laravel or CodeIgniter
Laravel
Our default for applications of any size. Eloquent, migrations, queues, events, scheduling, broadcasting, authentication scaffolding and a strong testing story come out of the box, so the team builds features rather than plumbing. The ecosystem — Horizon for queues, Telescope for debugging, Sanctum and Passport for API authentication, Livewire or Inertia for interactive UI without a separate front-end app — covers most of what a business application needs.
The cost is a heavier framework and more to learn. On a genuinely small project that overhead is real.
CodeIgniter 4
Light, fast, with a small footprint and a shallow learning curve. It suits smaller applications, projects on modest shared hosting, and teams that want to understand the whole framework. It is also frequently the pragmatic choice when extending an existing CodeIgniter system — a rewrite into Laravel is rarely justified by framework preference alone.
We will tell you which one fits, including when the answer is "stay where you are".
Architecture
- Thin controllers. Business logic lives in service or action classes, so it is testable without an HTTP request.
- Form request validation at the boundary, with rules in one place rather than scattered through controllers.
- Repositories or query objects where data access is complex enough to warrant them — not as ceremony on a simple CRUD screen.
- Database migrations for every schema change, so environments are reproducible and deployments are not manual SQL.
- Typed properties, return types and enums throughout, with static analysis (PHPStan or Psalm) in CI to catch what the type system alone cannot.
Performance
Slow PHP applications are usually slow for database reasons, not language reasons.
- N+1 queries are the single most common cause. Eager loading, and query logging in development so the problem is visible before release.
- Indexing. Every query that filters or sorts on a large table gets an index designed for it, verified with
EXPLAINrather than assumed. - Caching in layers: Redis for application and query caching, HTTP caching where responses allow it, and cache invalidation designed alongside the cache rather than after it.
- Queues for anything slow — email, PDF generation, image processing, third-party API calls — so requests return quickly and failures can be retried.
- OPcache and preloading configured properly in production; JIT enabled where the workload benefits.
- Pagination and chunking for large datasets, so a report never tries to load a million rows into memory.
Security
We build to the OWASP Top 10 as a baseline:
- Parameterised queries everywhere. Raw SQL with interpolated input does not pass review.
- Output escaped by default in templates; anything rendered as HTML explicitly sanitised.
- CSRF protection on every state-changing route.
- Authorisation checked server-side on every request — policies and gates, never a hidden menu item as the control.
- Password hashing with bcrypt or Argon2, rate limiting on authentication, and secure session configuration.
- File uploads validated by content rather than extension, stored outside the web root, and served through a controller.
- Secrets in environment variables, never in version control, with a documented rotation process.
- Dependencies audited continuously; framework and PHP versions kept inside their support windows.
Legacy PHP
A great many businesses run on PHP written years ago that works, makes money, and frightens everyone. We take that work on without moralising about it.
- Assess first: PHP version, dependency health, security exposure, test coverage and the parts that change most often.
- Stabilise before improving — get it on a supported PHP version, close the security holes, put it in version control if it is not already.
- Migrate incrementally. New functionality is built in the framework alongside the old system, with routes moved across gradually, so the business keeps running throughout.
- Recommend a rewrite only when the numbers support it, and say so plainly when they do not.
APIs and integration
REST APIs with consistent resource shapes, proper status codes, versioning, cursor pagination on large collections, and rate limiting. Authentication with Sanctum for first-party clients or OAuth where third parties are involved. Outbound integrations get timeouts, retries with backoff, idempotency keys and structured logging, because the failure mode that hurts is the one that fails silently.
Testing and delivery
PHPUnit or Pest, with feature tests covering the routes that matter and unit tests on business rules. Static analysis and coding standards enforced in CI. Deployments are zero-downtime with migrations run as part of the pipeline and a rollback path defined before release.
What you get
- A modern PHP 8 codebase with strict types and static analysis in CI.
- Query and cache optimisation with before-and-after measurements.
- An OWASP-aligned security posture, documented.
- Automated tests and a repeatable deployment pipeline.
- For legacy systems, a staged plan that keeps the business running.
PHP applications are rarely slow because of PHP. They are slow because of a query in a loop that nobody has looked at since launch.
