{"id":267406,"date":"2026-08-27T08:56:39","date_gmt":"2026-08-27T08:56:39","guid":{"rendered":"https:\/\/ded9.com\/?p=267406"},"modified":"2026-08-27T09:20:03","modified_gmt":"2026-08-27T09:20:03","slug":"php-8-4-a-full-review-and-what-it-means-for-wordpress","status":"publish","type":"post","link":"https:\/\/ded9.com\/tr\/php-8-4-a-full-review-and-what-it-means-for-wordpress\/","title":{"rendered":"PHP 8.4: A Full Review and What It Means for WordPress"},"content":{"rendered":"<p dir=\"ltr\">PHP 8.4 arrived on 21 November 2024. Nearly two years later, it has settled into the role most <a href=\"https:\/\/ded9.com\/what-is-php-programming-every-thing-about-it\/\">PHP<\/a> releases eventually take: not the newest branch, not the oldest supported one, but the version a large share of production traffic actually runs on. PHP 8.5 shipped a year behind it and is now the latest stable release, yet PHP\u00a08.4 remains the pragmatic default for most WordPress hosting because it has the longest track record among branches that are still fully patched.<\/p>\n<p dir=\"ltr\">This review covers what 8.4 changed at the language level, what it changed in practice, and what happens when you point a real <a href=\"https:\/\/wordpress.org\/\" target=\"_blank\" rel=\"noopener\">WordPress<\/a> site at it.<\/p>\n<p dir=\"ltr\"><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-267410\" src=\"https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/2-2.jpg\" alt=\"What PHP 8.4 actually added\" width=\"739\" height=\"415\" srcset=\"https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/2-2.jpg 739w, https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/2-2-300x168.jpg 300w\" sizes=\"(max-width: 739px) 100vw, 739px\" \/><\/p>\n<h2 dir=\"ltr\">What PHP 8.4 actually added<\/h2>\n<h3 dir=\"ltr\">Property hooks<\/h3>\n<p dir=\"ltr\">The headline feature. Property hooks let a class define get and set behavior directly on a property, without writing a separate getter-and-setter pair.<\/p>\n<p dir=\"ltr\"><code>class Product {<br \/>\npublic string $slug {<br \/>\nget =&gt; strtolower(str_replace(' ', '-', $this-&gt;name));<br \/>\nset (string $value) =&gt; $this-&gt;slug = trim($value);<br \/>\n}<br \/>\n}<\/code><\/p>\n<p dir=\"ltr\">This removes a great deal of boilerplate from model and value-object code. For WordPress specifically, it matters less than it does for Laravel or Symfony, because WordPress core is procedural at heart and most plugin code still leans on arrays and filters. Plugin authors building on modern object-oriented foundations will use it. Theme authors mostly will not notice.<\/p>\n<h3 dir=\"ltr\">Asymmetric visibility<\/h3>\n<p dir=\"ltr\">Related, and arguably more useful day to day. A property can now be readable publicly but writable only from inside the class:<\/p>\n<p dir=\"ltr\"><code>class Order {<\/code><br \/>\n<code>public private(set) string $status = 'pending';<\/code><br \/>\n<code>}<\/code><\/p>\n<p dir=\"ltr\">Before 8.4, this required a private property plus a public getter. Now it is one line, and the type system enforces it.<\/p>\n<h3 dir=\"ltr\">Four new array functions<\/h3>\n<p dir=\"ltr\"><code>array_find()<\/code>, <code>array_find_key()<\/code>, <code>array_any()<\/code> and <code>array_all()<\/code> fill gaps that have forced developers into awkward <code>array_filter()<\/code> plus <code>reset()<\/code> combinations for years. They read the way you would describe the operation out loud, and they short-circuit rather than walking the whole array.<\/p>\n<h3 dir=\"ltr\"><code>new<\/code> without parentheses<\/h3>\n<p dir=\"ltr\"><code>new Request()-&gt;getPath()<\/code> now works. Previously you needed <code>(new Request())-&gt;getPath()<\/code>. A small change that removes a persistent readability annoyance.<\/p>\n<h3 dir=\"ltr\">Lazy objects<\/h3>\n<p dir=\"ltr\">Objects whose initialization is deferred until first access, exposed through <code>ReflectionClass::newLazyGhost()<\/code> and <code>newLazyProxy()<\/code>. This is infrastructure for dependency injection containers and ORMs rather than something most application code touches directly, but it is why frameworks running on 8.4 boot faster.<\/p>\n<h3 dir=\"ltr\">A real HTML5 parser<\/h3>\n<p dir=\"ltr\">The new <code>\\Dom\\HTMLDocument<\/code> class parses HTML5 to spec. The old <code>DOMDocument<\/code> was built for HTML 4 and mangled modern markup in ways that produced quiet, hard-to-trace bugs. Anything that manipulates post content, rewrites image tags, or processes block markup benefits here.<\/p>\n<h3 dir=\"ltr\">Smaller additions<\/h3>\n<p dir=\"ltr\">The BCMath object API brings arbitrary-precision arithmetic into an <code>BcMath\\Number<\/code> object with operator overloading. PDO gained driver-specific subclasses such as <code>Pdo\\Mysql<\/code> and <code>Pdo\\Sqlite<\/code>. A <code>#[\\Deprecated]<\/code> attribute lets userland code mark its own functions as deprecated. New multibyte string helpers (<code>mb_trim()<\/code>, <code>mb_ucfirst()<\/code>) close longstanding gaps. The JIT was rebuilt on a new intermediate representation framework, which mostly means lower memory use and easier maintenance rather than dramatic speed gains.<\/p>\n<h2 dir=\"ltr\">The performance question<\/h2>\n<p dir=\"ltr\">Here is the part most upgrade guides overstate. PHP 8.4 is not meaningfully faster than 8.3 for standard WordPress workloads. The large jumps happened at 7.0 and again at 8.0. Everything since has been incremental, and the JIT still does very little for typical WordPress request handling, because WordPress is dominated by database queries and I\/O rather than tight computational loops.<\/p>\n<p dir=\"ltr\">If you are moving from PHP 7.4 to 8.4, expect a substantial improvement. If you are moving from 8.2 or 8.3, expect flat results with slightly better memory behavior. Upgrade for the security runway and the tooling, not for the benchmark.<\/p>\n<h2 dir=\"ltr\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-267413\" src=\"https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/4-1.webp\" alt=\"The deprecations that actually bite\" width=\"800\" height=\"543\" srcset=\"https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/4-1.webp 800w, https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/4-1-300x204.webp 300w, https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/4-1-768x521.webp 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/h2>\n<p dir=\"ltr\">This is where WordPress sites get hurt, and one deprecation dominates everything else.<\/p>\n<p dir=\"ltr\"><strong>Implicitly nullable parameter types are deprecated.<\/strong> Code written as <code>function example(string $text = null)<\/code> now emits a deprecation notice on every call. The fix is trivial at the declaration site (<code>?string $text = null<\/code>), but the pattern appears in an enormous volume of legacy PHP, including vendor libraries bundled inside plugins.<\/p>\n<p dir=\"ltr\"><strong>Removed extensions.<\/strong> IMAP, OCI8, PDO_OCI, and pspell moved out of core to PECL. The IMAP removal is the one that catches WordPress sites, since a handful of mail-handling and ticketing plugins depend on it.<\/p>\n<p dir=\"ltr\"><strong>Other deprecations.<\/strong> The <code>E_STRICT<\/code> constant, several session INI directives, and <code>_<\/code> as a class name. Low impact for most sites, but they will show up in logs.<\/p>\n<h2 dir=\"ltr\">Where WordPress stands today<\/h2>\n<p dir=\"ltr\">WordPress core has been clean on PHP 8.4 for some time. Core contributors resolved the implicit nullable issue during the 6.x cycle, and the project has since formalized its position.<\/p>\n<p dir=\"ltr\">In May 2026, the core team retired the &#8220;beta support&#8221; label for PHP entirely and applied the change retroactively. WordPress 6.8 and later are now documented as fully supporting PHP 8.4, with no qualifiers attached. The team reasoned that the beta label had become counterproductive: it made hosts hesitant to offer newer PHP versions and gave plugin developers an excuse to delay testing.<\/p>\n<p dir=\"ltr\">Two numbers are worth keeping straight. WordPress supports PHP 7.4 as an absolute minimum, but the minimum <em>recommended<\/em> version is 8.3. Supported and recommended are different claims, and hosting sales pages routinely blur them.<\/p>\n<h2 dir=\"ltr\">What breaks on real sites<\/h2>\n<p dir=\"ltr\">Core being clean does not mean your site is clean. Failures on PHP 8.4 almost always originate in third-party code, and they cluster in predictable places.<\/p>\n<p dir=\"ltr\"><strong>Abandoned plugins.<\/strong> Anything not updated in two years or more is the primary risk. Deprecation notices are the mild case. Fatal errors from removed functions are the serious ones.<\/p>\n<p dir=\"ltr\"><strong>Bundled vendor libraries.<\/strong> A well-maintained plugin can still ship an outdated Composer dependency that has not been touched since 2019. These are invisible in the plugin&#8217;s changelog and only surface under load.<\/p>\n<p dir=\"ltr\"><strong>Custom theme code.<\/strong> <code>functions.php<\/code> Files accumulated over a decade are rarely audited. This is where implicitly nullable declarations hide in quantity.<\/p>\n<p dir=\"ltr\"><strong>Deprecation notices breaking output.<\/strong> The most underrated failure mode. If <code>WP_DEBUG_DISPLAY<\/code> is on in production, a deprecation notice printed before headers are sent will corrupt REST API JSON responses, break <code>admin-ajax.php<\/code> calls, and produce &#8220;headers already sent&#8221; errors. The site looks broken in ways that have nothing obvious to do with PHP versions. Log deprecations to file, never to screen.<\/p>\n<h2 dir=\"ltr\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-267416\" src=\"https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/php_8_4.png\" alt=\"Should you run PHP 8.4 in late 2026?\" width=\"1200\" height=\"698\" srcset=\"https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/php_8_4.png 1200w, https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/php_8_4-300x175.png 300w, https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/php_8_4-1024x596.png 1024w, https:\/\/ded9.com\/wp-content\/uploads\/2026\/08\/php_8_4-768x447.png 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/h2>\n<p dir=\"ltr\">The support timeline makes this straightforward. PHP 8.2 reaches end of life on 31 December 2026. PHP 8.3 is already security-only and ends in December 2027. PHP 8.4 leaves active support at the end of 2026 but receives security patches through December 2028. PHP 8.5 runs until December 2029.<\/p>\n<p dir=\"ltr\">If you are on 8.2, you have a hard deadline in a few months and should be planning now. If you are on 8.3, 8.4 is a lateral move that buys a year of extra runway for very little migration effort. If you are starting fresh on WordPress 6.9 or later, 8.5 is supported and gives the longest window, though 8.4 still has the broader plugin compatibility record.<\/p>\n<h2 dir=\"ltr\">A sane upgrade process<\/h2>\n<ol dir=\"ltr\">\n<li><strong>Clone to staging.<\/strong> Not a copy of the theme. The full stack, including the plugin set and a representative database.<\/li>\n<li><strong>Audit before switching.<\/strong> Run PHP_CodeSniffer with the PHPCompatibilityWP ruleset across <code>wp-content<\/code>. Rector can automate most of the nullable-type fixes in code you own.<\/li>\n<li><strong>Check plugin maintenance status.<\/strong> Last-updated date and recent support threads tell you more than the &#8220;Tested up to&#8221; field.<\/li>\n<li><strong>Switch PHP on staging and log everything.<\/strong> Set <code>WP_DEBUG<\/code> true, <code>WP_DEBUG_LOG<\/code> true, <code>WP_DEBUG_DISPLAY<\/code> false. Then exercise the site properly: checkout, forms, email, scheduled tasks, imports, the REST API, and the admin.<\/li>\n<li><strong>Confirm rollback works<\/strong> before touching production, then switch during low traffic and watch error logs for a full cron cycle.<\/li>\n<\/ol>\n<p dir=\"ltr\">Most WordPress sites running current core and maintained plugins move to PHP 8.4 without incident. The ones that break were carrying technical debt that a version bump simply made visible.<\/p>\n<h2 dir=\"ltr\">FAQ<\/h2>\n<div id=\"rank-math-rich-snippet-wrapper\"><div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-1\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Is PHP 8.4 safe for WordPress?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. WordPress 6.8 and later officially support PHP 8.4 with no exceptions attached. Core compatibility is not the variable; your plugins, theme and custom code are.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-2\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Will PHP 8.4 make my site faster?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Only if you are coming from PHP 7.x, where gains are significant. Moving from 8.2 or 8.3 produces roughly flat performance. Upgrade for the security support window instead.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-3\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">Should I skip 8.4 and go straight to PHP 8.5?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>If your site runs WordPress 6.9 or later and your plugins test clean, 8.5 gives you until December 2029. PHP 8.4 remains the safer choice if your stack includes older plugins or bundled dependencies.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>PHP 8.4 arrived on 21 November 2024. Nearly two years later, it has settled into the role most PHP releases eventually take: not the newest branch, not the oldest supported one, but the version a large share of production traffic actually runs on. PHP 8.5 shipped a year behind it and is now the latest [&hellip;]<\/p>\n","protected":false},"author":9,"featured_media":267407,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1088],"tags":[1074,841,929],"class_list":["post-267406","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-php","tag-html","tag-php","tag-wordpress"],"acf":[],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/posts\/267406","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/comments?post=267406"}],"version-history":[{"count":5,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/posts\/267406\/revisions"}],"predecessor-version":[{"id":267423,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/posts\/267406\/revisions\/267423"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/media\/267407"}],"wp:attachment":[{"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/media?parent=267406"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/categories?post=267406"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ded9.com\/tr\/wp-json\/wp\/v2\/tags?post=267406"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}