PHPVerse 2026

My slides, speaker notes, and all resources from PHPVerse 2026.
Slides: https://docs.google.com/presentation/d/1gFA-_yi8UA7aKyEnev37vdEgg9SaOZWl-tZQkpXg4ws/edit?usp=sharing
Recording:
WordPress is dead, long live WordPress!
Before I dive in, I need to take you back to the year I learned PHP and started to take it more seriously as a career path.
It was 2004, the year Gmail launched, the most popular mobile phones were clam shell, and if you had a 19inch black CRT monitor, you were l33t.
At the time PHP 5 had been released, so PHP 4 was still heavily in use. PHP was growing in popularity as a way to build for the emerging web, but it wasn’t without its detractors. This was my first introduction to programming language wars. Apparently, being a PHP developer meant that you weren’t a “real programmer”.
Fast-forward about 10 or so years to 2015, and I’ve had the chance to build not only with vanilla PHP but all sorts of PHP platforms, frameworks, and CMSs. That’s me at WordCamp Cape Town in 2015, a little younger, a little wider, and about to replicate “Tom Cruise jumping on Oprah’s couch” with the conference MCs!
What I discovered in those 10 or so years was that the growing popularity of PHP led to what I call the platform wars in the PHP community. Folks would argue about why their preferred framework or CMS was better, and condemn the rest. More often than not this was due to an early evaluation of the platform in question, not taking into account any recent additions or updates.
This seemed to be more prevalent with WordPress. For example, in 2014 Andrew Nacin, a WordPress core contributor and at the time one of the lead developers, gave a talk at PHP World titled Challenging Your WordPress Assumptions from 2009.
Over the next ten years, as I explored and became more involved with WordPress I saw similar patterns. Today many developers recycle the same criticisms of WordPress from a decade ago, even while it is evolving faster than people may realize.
So today I am here to challenge some of the common WordPress “myths” I often hear from other developers.
My goal today is not to convince you that WordPress is better than your chosen platform, but rather to shine a light on how WordPress has and continues to evolve, improve, and stay relevant.
Ok, let’s dive in!
🔟 Top 10 Reasons Developers Don’t Like WordPress
🧪 Outdated Codebase & Poor OOP Practices
WordPress’s codebase carries over 20 years of legacy code and doesn’t follow modern PHP standards (like PSR) or proper Object-Oriented Programming (OOP) patterns. This makes it difficult for developers to write clean, testable, and maintainable code, and can stunt the growth of developers who work exclusively in WordPress.
What’s Changed:
- Minimum PHP bumped from 5.2 → 7.2 (2024) → 7.4 (WordPress 7.0, April 2026). WordPress dropped PHP 5.x support in WordPress 5.2 (2019), PHP 7.0/7.1 in WordPress 6.6 (2024), and PHP 7.2/7.3 in WordPress 7.0 (2026).
- Full PHP 8.0, 8.1, 8.2, and 8.3 support is now officially documented. PHP 8.4 and 8.5 have beta support in WordPress 6.9. The old confusing “compatible with exceptions” label was retired in April 2025. (Make WordPress Core clarification)
- WordPress now recommends PHP 8.3. The official requirements page states this clearly.
- The Gutenberg project and newer core code (Core AI) make extensive use of modern PHP practices including type declarations, namespaces, and stricter patterns.
Sources: PHP Compatibility and WordPress Versions, Dropping PHP 7.0/7.1, Dropping PHP 7.2/7.3 for WP 7.0
📄 No Native Templating Engine
WordPress lacks a proper templating engine (like Blade, Twig, or similar). Templates are written in raw PHP, making them more verbose, harder to read, and more prone to security issues like unescaped output (XSS vulnerabilities).
What’s Changed:
- Block themes replaced PHP templates with HTML block markup. Templates are now
.htmlfiles containing declarative block markup instead of raw PHP:
<!-- wp:site-title /-->
<!-- wp:query -->
<!-- wp:post-template -->
<!-- wp:post-title /-->
<!-- wp:post-content /-->
<!-- /wp:post-template -->
<!-- /wp:query -->
- This is effectively WordPress’s own templating language — declarative, safe by default (no raw PHP execution), and visually editable in the Site Editor.
- WordPress automatically handles output escaping,
<html>/<head>/<body>wrappers, critical CSS extraction, and script enqueuing for block themes — reducing the surface area for XSS and other template-related vulnerabilities. - As 10up notes: “Block based themes are a superset on top of traditional themes. Instead of
index.php, you now havetemplates/index.html.” (10up Block Editor Best Practices)
Sources: WordPress Theme Handbook: Introduction to Templates, Full Site Editing: Creating Block Themes
🐌 Performance Issues (Slow REST API & Bloat)
WordPress’s REST API can be notoriously slow, with basic queries sometimes taking over a second. Layers of plugins, themes, and hooks add overhead, leading to bloated and sluggish sites compared to leaner frameworks like Laravel or Express.js, where sub-200ms response times are common.
What’s Changed:
- WordPress 6.1 brought major REST API performance improvements: cache priming in single queries (instead of N+1), conditional
prepare_linksexecution, and optimized post/user/comment controllers. (Make WordPress Core dev note) - A dedicated Performance Team now ships improvements with every release. WordPress publishes detailed performance benchmarks comparing each version (6.2→6.3→6.4→6.5→6.6).
- WordPress 6.9 delivered 2.8–5.8% speed gains over 6.8, and up to 23% faster on PHP 8.5, with 38 performance-related Trac tickets and 31 Gutenberg PRs. (Source)
- Speculative Loading (merged into core in WordPress 6.8) uses the browser’s Speculation Rules API to prerender linked pages, achieving up to 98.2% reduction in LCP (Largest Contentful Paint). (Weston Ruter’s benchmarks)
- Performance Lab plugin features now in core or near-core include: Modern Image Formats (WebP/AVIF), Image Prioritizer, Embed Optimizer, Enhanced Responsive Images, and Performant Translations. (WordPress/performance on GitHub)
🌐 Heavy Reliance on Global State
WordPress depends heavily on global state managed through imperative programming. Functions like the_title() and the_content() rely on the hidden state of “The Loop,” making code harder to understand, test, and debug. There are no clear relationships between functions and data without deep knowledge of WordPress internals.
What’s Changed:
- The
@wordpress/datapackage provides a Redux-like centralized state management system for the block editor. Developers use stores, selectors, and actions — standard patterns familiar to any React developer. - The Interactivity API (shipped in WordPress 6.5) introduces a proper reactive state system with
global state,local context, andderived state. Blocks can have independent state scoped viadata-wp-context, eliminating reliance on global variables:
<div data-wp-interactive="myPlugin" data-wp-context='{"counter": 0}'>
<span data-wp-text="context.counter"></span>
<button data-wp-on--click="actions.increment">+</button>
</div>
- Block themes use declarative block markup (e.g.,
<!-- wp:site-title /-->) rather than imperative PHP function calls likethe_title(), making relationships between data and output explicit.
Sources: Interactivity API docs, Interactivity API proposal
🧩 No Native Custom Fields / Over-reliance on Plugins
Handling custom meta fields — a core function of any CMS — requires third-party plugins like Advanced Custom Fields (ACF). Developers are frustrated that something so fundamental is missing from WordPress core, forcing reliance on external solutions for basic content modeling.
What’s Changed:
- The Block Bindings API (shipped in WordPress 6.5, March 2024) allows developers to bind custom fields directly to core block attributes — no plugin required. A Paragraph block can display post meta with simple markup:
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"book-genre"}}}}} -->
<p></p>
<!-- /wp:paragraph -->
- By WordPress 6.7, this included an editor UI showing bound attributes in the sidebar. By WordPress 6.9, the
getFieldsList()function lets custom binding sources appear in the Attributes panel. - Developers can also register custom binding sources via
register_block_bindings_source()for arbitrary dynamic data — not just post meta. - The API has a detailed roadmap for future iterations including more block support and an in-editor custom field editing experience.
Sources: Make WordPress Core announcement, WordPress Developer Blog tutorial
🔀 Incongruent Paradigms (Gutenberg/Block Editor vs. Classic)
The introduction of Gutenberg brought ultra-modern React development into a PHP-centric ecosystem, creating a jarring disconnect. Developers face two completely different paradigms within one platform. Updating block markup across thousands of pages requires loading and saving each one individually — a massive scalability problem.
What’s Changed:
- The Interactivity API (WordPress 6.5) was specifically designed as a “PHP-first” bridge between server-rendered content and client-side interactivity. It uses declarative HTML directives (
data-wp-on--click,data-wp-bind,data-wp-text) — no React knowledge required. As the docs state: “The API must work well with PHP and the current block system… Server-rendered HTML and client-hydrated HTML must be exactly the same.” - PHP-only block registration (targeting WordPress 7.0) allows developers to create blocks using only PHP — no JavaScript build step, no React. This was specifically designed for “PHP-focused developers” and to “prevent easier block adoption, especially in classic themes or server-driven workflows.” (Gutenberg issue #71792, Make WordPress Core announcement)
render.phpenables dynamic blocks to define their server-side rendering in a separate PHP file, keeping the PHP rendering logic clean and familiar.- Developers can now choose their comfort level: full React blocks, PHP-only blocks, or the Interactivity API for lightweight interactivity.
Sources: Interactivity API “About” page, PHP-only block registration
🔒 Security Vulnerabilities
WordPress is a massive target for hackers due to its market share (~40%+ of the web). Poor-quality plugins, weak default security settings, and the reliance on third-party code create a large attack surface. Keeping themes, plugins, and core updated without breaking the site is a constant struggle.
What’s Changed:
- Automatic updates for minor/security releases have been enabled by default since WordPress 3.7 (2013). Since WordPress 5.6 (2020), users can also opt-in to automatic updates for plugins, themes, and major core releases from the admin UI.
- WordPress 6.6 added rollback protections for auto-updates, reverting to the previous working version if an update fails.
- The WordPress Security Team patches critical vulnerabilities within days of disclosure. The core itself has had zero unpatched critical vulnerabilities in recent history — nearly all exploits target outdated plugins or neglected sites.
- Application Passwords (WordPress 5.6) replaced the need for users to share actual login credentials for REST API access.
Sources: WordPress auto-updates, Patchstack State of WP Security 2026
🔗 Lack of Proper Dependency Management
WordPress has no native way to declaratively define plugin dependencies and versions (like composer.json or package.json). This means clients can accidentally update or delete a plugin and crash their entire site. While the rest of the PHP ecosystem has embraced Composer, WordPress’s plugin model remains largely disconnected from modern package management.
What’s Changed:
- Composer is now a first-class citizen in the WordPress ecosystem. The Roots Bedrock project has long enabled managing WordPress core, plugins, and themes as Composer dependencies with
composer.json, version locking, and CI/CD deployment. - WP Packages (wp-packages.org) — In March 2026, the Roots team launched WP Packages, an open-source Composer repository for every free plugin and theme on WordPress.org. It supports Composer v2’s
metadata-urlprotocol, making cold dependency resolution ~17x faster than the older WPackagist (0.7s vs 12.3s for 10 plugins). WordPress.org itself endorsed the project publicly. - Pressable, WordPress VIP, and other managed hosts now support Composer-based WordPress workflows out of the box.
Sources: WP Packages announcement (Roots), WordPress.org endorsement, Pressable Composer guide
📚 Outdated / Incomplete Documentation & Low Barrier to Entry
WordPress documentation is often outdated, incomplete, or inconsistent. Combined with the low barrier to entry, the ecosystem is flooded with poorly written plugins and themes from inexperienced developers. This creates a reputation problem — bad code gives WordPress a bad name, and professional developers are frustrated by the resulting poor code quality in the ecosystem.
What’s Changed:
- The WordPress Developer Blog (developer.wordpress.org/news) launched as a dedicated resource for plugin and theme developers, publishing regular in-depth tutorials on new features (Block Bindings, Interactivity API, etc.) and monthly “What’s new for developers” roundups.
- Learn WordPress (learn.wordpress.org) provides structured courses including “Beginner WordPress Developer,” “Intermediate Theme Developer,” “Using the WordPress Data Layer,” and “Developing your first WordPress block” — with online workshops happening weekly.
- Developer Resources (developer.wordpress.org) has been overhauled with a comprehensive Block Editor Handbook, Theme Handbook, Plugin Handbook, REST API Handbook, and full Code Reference.
- The WordPress Developer Blog’s tutorial series on Block Bindings alone included 6+ posts walking through basic to advanced use cases.
- The
@wordpress/create-blockscaffolding tool generates a complete, well-documented block plugin structure with modern tooling out of the box.
Sources: WordPress Developer Blog, Learn WordPress, WordPress Developer Resources
⚠️ WP_Error Instead of Exceptions
WordPress functions return WP_Error objects instead of throwing exceptions when something goes wrong. If you forget to check with is_wp_error(), your code silently continues with a broken value — no stack trace, no try/catch, no typed error handling. For developers coming from Laravel, Symfony, or any modern PHP project, this is one of the most jarring discoveries. The pattern dates back to WordPress 2.1 (2007), when WordPress still supported PHP 4, which had no exception support at all.
What’s Changed:
- The REST API handles errors properly. Returning a
WP_Errorfrom a REST API callback automatically produces a structured JSON error response with the correct HTTP status code — no manual checking needed on the consumer side. - Newer core subsystems use exceptions. The Interactivity API directive processing throws actual PHP exceptions, signaling a shift in newer WordPress code.
- The PHP 4 constraint is long gone. WordPress now requires PHP 7.4+ (as of WP 7.0) and recommends PHP 8.3. Developers can use full exception-based error handling in their own plugins and themes, only interfacing with
WP_Errorat the WordPress API boundary. - Community packages bridge the gap. Libraries like wp-error-to-exception convert
WP_Errorto throwable exceptions. A simple helper function (wp_or_throw()) is a common pattern recommended in the WordPress developer community. - Honest caveat:
WP_Errorremains deeply embedded in core and won’t be fully replaced soon due to backward compatibility. This myth is only partially busted — but the tools to work around it are readily available.
Sources: REST API Handbook, WordPress requirements, WP Stack Exchange discussion
Leave a Reply