php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #70549 Allow `new Foo()->bar()` without parens around `(new Foo)`
Submitted: 2015-09-22 07:04 UTC Modified: 2015-09-29 03:01 UTC
Votes:4
Avg. Score:4.5 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:2 (66.7%)
From: vovan-ve at yandex dot ru Assigned: yohgaki (profile)
Status: Assigned Package: Scripting Engine problem
PHP Version: 7.1.0 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: vovan-ve at yandex dot ru
New email:
PHP Version: OS:

 

 [2015-09-22 07:04 UTC] vovan-ve at yandex dot ru
Description:
------------
PHP 5.4 allowed us to chain member assess to `new Foo`, but there must be parens:

    (new Foo)->bar();
    (new Foo(42, 37))->bar();
    something((new Foo(42, 37))->lorem()->ipsum()->dolor());

Why do we need that redundant parenses? Compare what ECMAScript allows - you know:

    new Foo().method();
    new Foo().field;
    new some.where.Foo().method();
    new Foos[i]().method();
    new (anything)().method();

PHP 7 should to remove redundant parens.

Test script:
---------------
class Foo {
    protected $id;
    public function __construct($id) {
        echo "new ", get_called_class(), "($id)\n";
        $this->id = $id;
    }
    public function __toString() {
        return get_class($this) . "{" . $this->id . "}";
    }
    public function bar($x) {
        echo $this, "->", __FUNCTION__, "($x)\n";
        return $this;
    }
    public function val($x) {
        echo $this, "->", __FUNCTION__, "($x) => $x\n";
        return $x;
    }
    public function lorem(self $foo, $x) {
        echo $this, "->", __FUNCTION__, "($foo, $x)\n";
        $foo->bar($x);
        return $this;
    }
}

new Foo(10)->bar(20)->bar(30)->bar(new Foo(40)->val(50));
new Foo(60)->lorem(new Foo(70)->bar(80), new Foo(90)->val(100));
// same as
// (new Foo(10))->bar(20)->bar(30)->bar((new Foo(40))->val(50));
// (new Foo(60))->lorem((new Foo(70))->bar(80), (new Foo(90))->val(100));


Expected result:
----------------
new Foo(10)
Foo{10}->bar(20)
Foo{10}->bar(30)
new Foo(40)
Foo{40}->val(50) => 50
Foo{10}->bar(50)
new Foo(60)
new Foo(70)
Foo{70}->bar(80)
new Foo(90)
Foo{90}->val(100) => 100
Foo{60}->lorem(Foo{70}, 100)
Foo{70}->bar(100)


Actual result:
--------------
Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-09-22 15:38 UTC] enoquejoseneas at gmail dot com
Good idea. PHP need this feature, already available on Java and Javascript
 [2015-09-25 07:07 UTC] kalle@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: nikic
 [2015-09-25 07:07 UTC] kalle@php.net
(assigning to Nikita for his PoV on this)
 [2015-09-25 07:17 UTC] nikic@php.net
-Assigned To: nikic +Assigned To:
 [2015-09-25 07:17 UTC] nikic@php.net
We currently allow code like this:

    $obj = new $foo->bar();
    // Meaning:
    $class = $foo->bar;
    $obj = new $class();

You are proposing to interpret this as $obj = (new $foo)->bar() instead, which would break backwards compatibility.

This could have been changed as part of the UVS RFC, but I felt like this change would be too intrusive and the consequences rather weird. I expect something like `new $foo['bar']` to behave as `new {$foo['bar']}` not `(new $foo)['bar']`.
 [2015-09-25 07:24 UTC] vovan-ve at yandex dot ru
> You are proposing to interpret this as `$obj = (new $foo)->bar()` instead

No, it's not. `new $foo->bar()->method()`
is exactly `new ($foo->bar)()->method()`
like `new foo.bar().method()` is ECMAScript.
 [2015-09-25 08:13 UTC] nikic@php.net
Ah, I think I get what you mean now. You only want to allow omission of parentheses if new is used with an argument list, correct?

I.e. `new Foo->bar()` will be forbidden, but `new Foo()->bar()` will be allowed and interpreted as `(new Foo())->bar()`?
 [2015-09-25 08:20 UTC] vovan-ve at yandex dot ru
nikic, Yes, right. `new Foo->bar()` start with `Foo->...` and it is "unexpected ->".
 [2015-09-25 13:57 UTC] nikic@php.net
In that case it should be very easy to support this. Something along these lines: https://gist.github.com/nikic/47ee4f5e67bc90866099 This allows `new Foo()->bar()`, `new Foo()->bar`, `new Foo()['bar']`. Adding it to callable vars as well would allow `new Foo()()`.

So from the technical side this is no problem. I don't know if we should actually allow it, as the syntax looks somewhat ambiguous. I'm neutral regarding that.

If we want this change, somebody should RFC it.
 [2015-09-29 03:01 UTC] yohgaki@php.net
-PHP Version: 7.0.0RC3 +PHP Version: 7.1.0 -Assigned To: +Assigned To: yohgaki
 [2015-09-29 03:01 UTC] yohgaki@php.net
@Nikic
Good news. I'll prepare RFC for 7.1.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 08 12:01:28 2024 UTC