php / php/php-src

Fatal errors for property hooks in combination with pipes

Open
#22,587 3 comments 0 reactions 1 assignee View on GitHub

@iluuu1994 is already working on this.

Since Jul 4, 2026.

Bug Category: Engine Status: Needs Triage
Dominant language
C
Stars
40.4k
Forks
8.1k
Avg merge
2d 13h
Merged PRs (30d)
96

Description

Description

Hey there!

I came across the following...

public string $path = '%s/foo/%s' {
    get => sprintf($this->path, $this->name, str_replace('output', '%s', basename($this->stub)));
}

which works. PHPStorm offers a refactor to:

public string $path = '%s/foo/%s' {
    get => $this->stub
            |> basename(...)
            |> (fn($x) => str_replace('output', '%s', $x))
            |> (fn($x) => sprintf($this->path, $this->name, $x));
}

Which results in:

Fatal error: Cannot specify default value for virtual hooked property

The RFC explicitly shows such example, although without default value. There is, however, no word about that using pipes in hooks would turn a backed hooked property into a virtual property. Hence, I would have expected it to work. Then I tried:

public function __construct(
    public string $path = '%s/foo/%s' {
        get => sprintf($this->path, $this->name, str_replace('output', '%s', basename($this->stub)));
    }
) {}

Which works, with and without passing $path to the constructor. Then I again apply the proposed refactor...

    public function __construct(
        public string $path = '%s/foo/%s' {
            get => $this->stub
                    |> basename(...)
                    |> (fn($x) => str_replace('output', '%s', $x))
                    |> (fn($x) => sprintf($this->path, $this->name, $x));
        }
    ) {}

which with and without passing $path to the constructor results in:

Fatal error: Uncaught Error: Property x::$path is read-only in

even though there is no readonly involved at all.

Nothing of this seems expected to me. Feels similar to what was added as errata regarding arrow functions, but wrapping the whole thing into parentheses does not help (and is not mentioned in the RFC), and get {} has the same issues.

PHP Version
PHP 8.5.7 (cli) (built: Jun  2 2026 20:59:56) (NTS)
Copyright (c) The PHP Group
Built by Homebrew
Zend Engine v4.5.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.7, Copyright (c), by Zend Technologies
Operating System

macOS latest

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.