new in Initializers (PHP 8.4)
Also Known As
new in defaults
new in initializers
PHP 8.4 new expression
TL;DR
PHP 8.4 allows 'new ClassName()' expressions in default parameter values, attribute arguments, and static property initialisers — removing the need for null defaults combined with late assignment in constructors.
Explanation
PHP previously required that default parameter values, attribute arguments, and property initialisers be compile-time constants — scalar values, arrays, class constants, and null. Creating a default object value required a null default and manual assignment in the constructor body. PHP 8.4 allows 'new' expressions in these positions. 'function foo(Logger $log = new NullLogger())' is now valid. The object is created fresh for each call where the default is needed. This also works in property promotion: 'public function __construct(private Logger $log = new NullLogger()) {}' — clean null-object pattern without boilerplate.
Common Misconception
✗ The default object is shared across all calls like a static variable. It is not — 'new NullLogger()' in a default creates a fresh instance for each invocation that uses the default. This is the opposite of a singleton.
Why It Matters
This feature eliminates a common boilerplate pattern: nullable parameters with manual instantiation. The null object pattern — where you provide a 'do nothing' default implementation — becomes a one-liner. Code that previously required three or four lines (nullable param + docblock + null check in body + assignment) now expresses intent cleanly in the signature.
Common Mistakes
- Using new in initializers in PHP < 8.4 — parse error; check version before adopting.
- Expecting the same instance to be reused across calls — each call that triggers the default creates a new object.
- Using new with classes that have constructor side effects (DB connections, file handles) as defaults — the side effect runs on every call that omits the argument.
- Forgetting this works in attribute arguments too — attribute classes that accept object dependencies can now have clean defaults.
Code Examples
✗ Vulnerable
<?php
// ❌ Pre-8.4 null default + manual instantiation boilerplate
class OrderService
{
private Logger $logger;
private Cache $cache;
public function __construct(
?Logger $logger = null,
?Cache $cache = null
) {
$this->logger = $logger ?? new NullLogger();
$this->cache = $cache ?? new ArrayCache();
}
}
✓ Fixed
<?php
// ✅ PHP 8.4 — new in initializers, clean constructor promotion
class OrderService
{
public function __construct(
private Logger $logger = new NullLogger(),
private Cache $cache = new ArrayCache(),
) {}
}
// Also valid in standalone functions
function sendNotification(
string $message,
Mailer $mailer = new SmtpMailer(),
): void {
$mailer->send($message);
}
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
23 Mar 2026
Views
20
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
Amazonbot 1
No pings yesterday
Amazonbot 7
Perplexity 2
Google 2
ChatGPT 1
Ahrefs 1
Also referenced
How they use it
crawler 12
crawler_json 1
Related categories
⚡
DEV INTEL
Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Replace 'function log(?Logger $l = null) { $l ??= new NullLogger(); }' with 'function log(Logger $l = new NullLogger()) {}' in PHP 8.4+.
📦 Applies To
PHP 8.4+
web
cli