Skip to content

RFC Discussion - Make PHP 9 Strict Internal Function Types and Dynamic Properties Optional #21145

@cdcrothers

Description

@cdcrothers

Description

Hello internals,

I'm writing to express concern about two major deprecations in PHP 8.4 that fundamentally change PHP's character as a loosely-typed language: null coercion in internal functions and dynamic property creation. Both are set to become hard errors in PHP 9.0.

Issue 1: Null Coercion in Internal Functions

PHP has always been a loosely-typed language where null, empty string, and false are interchangeable in most contexts. This wasn't a bug—it was a feature that made PHP accessible and reduced boilerplate. Functions like trim(null), trim(''), and trim(false) logically do the same thing: nothing meaningful to trim, return empty string.

The current trajectory forces millions of lines of existing code to add defensive ?? '' operators everywhere null might appear. This creates bloat without adding semantic value when the developer's intent was already "treat null as absence of value."

Issue 2: Dynamic Property Deprecations

The ability to create properties on the fly has been another core strength of PHP. For objects without typed properties—or properties that don't need to always be defined—dynamic property creation provided flexibility without ceremony. This is especially valuable for:

  • Working with variable data structures
  • Prototyping and rapid development
  • Objects that serve as flexible data containers
  • Legacy codebases where this pattern is pervasive

Deprecating this adds no value for untyped properties and forces developers to pre-declare every possible property or add boilerplate like #[AllowDynamicProperties] throughout codebases that were intentionally designed to be flexible.

The Proposal

Make both strictness changes opt-in features in PHP 9.0, similar to declare(strict_types=1).

  • Default behavior: maintain null coercion and dynamic properties (backward compatible)
  • Opt-in: declare(strict_internal_types=1) and/or declare(strict_properties=1) enable the new strict behaviors

This respects both philosophies: teams wanting strictness can adopt it, while codebases built on PHP's traditional loose typing aren't forced into large-scale rewrites for behavior changes that don't fix actual bugs.

Why This Matters

Decades of PHP code were written expecting these behaviors. Breaking backward compatibility at this scale—while claiming to maintain PHP's identity as a loosely-typed language—feels contradictory. The interchangeability of null and empty values, and the flexibility of dynamic properties, are PHP's strengths, not weaknesses to be eliminated.

I'd welcome discussion on whether these strict behaviors could remain optional rather than mandatory in 9.0.

Thank you for considering this feedback.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions