Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130096 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id EEBE51A00BC for ; Thu, 19 Feb 2026 12:52:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1771505538; bh=Wn66UmeFO6tDNSkOkSShkW6M08sLYxI88cs25lT9gPU=; h=Date:Subject:To:References:From:In-Reply-To:From; b=PebX6BIkN2l9ZJeJNci5sY7o5y66yUdnRVQSmHwz4GrBfT0QxuXtOpOsXXANcYooR u9iWgJ1sM9r7Bsnbx+NIjVb4RUbAgVLBpR6G+kCt9q8cKU+3SmWUvH6VaVyUjjwiE2 d5PqePdwxhTaK4SsqB2PK+lWGvp6Olqx/YpOUFhjxxyWDYFwwFxEhweOwNMFJEoeAL /GmhnCpeJ0JTg/MQJZW4PjM+4zgfN3ukygosXRr+BrKuKELTf1aLzFt3QQnJ7+ADJI Qy4JYlcfrf+Wk3ZnyZTwbAQLDVvTg3fnuofOJAT5ZtQpG1w6FsMD0xYn/nIpl3fsJe eKDbNbuPaEWSw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6ED75180048 for ; Thu, 19 Feb 2026 12:52:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from fout-b2-smtp.messagingengine.com (fout-b2-smtp.messagingengine.com [202.12.124.145]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 19 Feb 2026 12:52:17 +0000 (UTC) Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailfout.stl.internal (Postfix) with ESMTP id 9B2BE1D000D7 for ; Thu, 19 Feb 2026 07:52:10 -0500 (EST) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Thu, 19 Feb 2026 07:52:10 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm3; t=1771505530; x=1771591930; bh=fL0an+5WzY ONphGfVc+7OciaWViAfu6wvgHKYHLQZAU=; b=n04GJd7+b2Ft1tOyvtgBuOFkpf 5NGzFpX0KNVQXJq6ED9ucdIfUK6+VYLUKdrDvQCLbJB/TJ2Tx8eI4VdugCHxWv+W m6Okvrc4aX9DJJpf3lD+HL2rSS9VanVi/C/K/jBbTVq3qC9YqVEiBzI/bYrodX/c MjyxTWZNFkq7yFBln0jVZPYWpfJQ7KNigPW64ut6loLIhyWMnVswpQBQdGbgBVD9 2JiTYV4B+rn6Nt/ZyOTbfXOwrr4JuqrKhc06S2sMX1wACwTvweobYETshXPqzDTl zaDvcVU3HGK7kacMbGIFkbpFmcGb50USIiPVb5xD33kT6KbfWtQDhtrIZ38Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1771505530; x=1771591930; bh=fL0an+5WzYONphGfVc+7OciaWViAfu6wvgH KYHLQZAU=; b=uhosQmRxNxfC0x5ZG1Mo3C+UFEyG5idc8Wvq0bpFHsGnv42p72Z 7WB87n+9WLYrK4hZ+OvUK3urysdHOvCMqFsoXp8Nlnv9MPCmyBrOs3oi/vyhq4rU Vr3HMIin/QCzFZ7H5m7rjCmhL0QrdUdH1etWK40kp0l31qF8WpgbFI+tzGnI35iV iD9uz5Geu0zgMkhuQGNBOaQPSBdYzA2VO4B+AdSybIW9lAym6B5PCR7/FQS3q0sP iOFNZiP7lJwKQXCQk9n8wHjv3h55QkvQQeVYPxHu3pB5Rn0qwWkAyCCSOJJNtMp3 cJ9APiml9wv/Zq1wZBJyIsFdQ62H1/Qh8pg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddvvdehheekucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucenucfjughrpegtkfffgggfuffvfhfhjgesrgdtreertd dvjeenucfhrhhomhepfdftohifrghnucfvohhmmhhinhhsucglkffoufhorfgnfdcuoehi mhhsohhprdhphhhpsehrfigvtgdrtghordhukheqnecuggftrfgrthhtvghrnhepheetle eiiefgueduieeuieffvdevheduueefkeejuefgffeftdeitdegtedtleetnecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepihhmshhophdrphhhph esrhifvggtrdgtohdruhhkpdhnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhu thdprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Thu, 19 Feb 2026 07:52:09 -0500 (EST) Content-Type: multipart/alternative; boundary="------------lAqyczpasWWd3olefxcYUNew" Message-ID: Date: Thu, 19 Feb 2026 12:52:08 +0000 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] [IDEA for RFC] let the "new" operator fail when the __construct() function returns a value. To: internals@lists.php.net References: <1f25d77e-224b-40d6-bf19-18dfdfc9de54@rwec.co.uk> <453bc043-b4ee-423e-9561-55510f5c20a7@rwec.co.uk> Content-Language: en-GB In-Reply-To: From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") This is a multi-part message in MIME format. --------------lAqyczpasWWd3olefxcYUNew Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 18/02/2026 15:23, Mirco Babin wrote: >> In fact, the only way to guarantee a class is unaffected would be to >> write a method called "__construct", but then use static analysis to >> prove that nothing actually uses that method as a constructor. > At the moment, without changing anything to Php, PHP Code Sniffer static > analysis is the only option. Would this RFC be accepted, there are at > least additional deprecation notices. But to be sure upfront, you still > would have to use PHP Code Sniffer. The deprecation notices will tell you about code that *is* affected, but they can't prove that code is *not* affected, if they only happen at run-time. >> In which >> case, why use the reserved name "__construct"? > I'd go one step further. Why can "__construct" be called as a regular > function? Why not prohibit that and make it a truly magical function? That's a different kind of "why". I meant, "why would a programmer deliberately call a function __construct, and have no intention of *ever* using it as a constructor". If they are using it as *both* a constructor and a normal method, *their code will break with your proposal* because at some point they will call it as a constructor and hit the new error. >> My suggestion is that classes which are affected should show an error >> *as soon as possible*, so that users are prompted to fix the definition. > That's a personal preference. Yes and no. Detecting problems early is widely recognised as reducing the cost and risks of a project. See for instance discussion around the term "shift left". >> Once I'm told about the problem, I can choose between two things: >> >> 1) Stop the constructor returning a value, e.g. by replacing "return >> foo();" with "foo(); return;" >> 2) Rename the method to a non-reserved name, and if needed add a new >> constructor which calls the method and discards the result > There is a 3rd option: > > if ($calledAsRegularFunction_and_not_as_constructor) { > return foo(); > } Can you point to any real-life example of this? It feels like a lot of this discussion of BC breaks is assuming that there's some common code pattern relying on the current behaviour, but the only examples I've seen so far are of why it would be *wrong* to return a value. > There are two conflicting goals in the prologue: "Maximum warning" > and "Minimal BC impact". You prioritize Maximum warning. I prioritize > Minimal BC impact. I disagree that your proposal has a lower BC impact. The majority of code that currently relies on a constructor returning a value *will break under both versions of the proposal*. The only difference that delaying the error to run-time makes, is that it will take longer for people to notice that it is broken. > Your points are correct, from the perspective of a new PHP project. > However, reasoning from the perspective of a very old PHP project, > every BC break is one too many. It is exactly those old PHP projects that I'm worried about. The ones that have poor testing coverage, large amounts of spaghetti code, and will cause some poor engineer to have a 2am alarm because someone the other side of the world just crashed the application with a run-time error. -- Rowan Tommins [IMSoP] --------------lAqyczpasWWd3olefxcYUNew Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 7bit
On 18/02/2026 15:23, Mirco Babin wrote:
In fact, the only way to guarantee a class is unaffected would be to
write a method called "__construct", but then use static analysis to
prove that nothing actually uses that method as a constructor.
At the moment, without changing anything to Php, PHP Code Sniffer static
analysis is the only option. Would this RFC be accepted, there are at
least additional deprecation notices. But to be sure upfront, you still
would have to use PHP Code Sniffer.


The deprecation notices will tell you about code that *is* affected, but they can't prove that code is *not* affected, if they only happen at run-time.


In which
case, why use the reserved name "__construct"?
I'd go one step further. Why can "__construct" be called as a regular
function? Why not prohibit that and make it a truly magical function?


That's a different kind of "why". I meant, "why would a programmer deliberately call a function __construct, and have no intention of *ever* using it as a constructor".

If they are using it as *both* a constructor and a normal method, *their code will break with your proposal* because at some point they will call it as a constructor and hit the new error.


My suggestion is that classes which are affected should show an error
*as soon as possible*, so that users are prompted to fix the definition.
That's a personal preference. 


Yes and no. Detecting problems early is widely recognised as reducing the cost and risks of a project. See for instance discussion around the term "shift left".

Once I'm told about the problem, I can choose between two things:

1) Stop the constructor returning a value, e.g. by replacing "return
foo();" with "foo(); return;"
2) Rename the method to a non-reserved name, and if needed add a new
constructor which calls the method and discards the result
There is a 3rd option:

if ($calledAsRegularFunction_and_not_as_constructor) {
    return foo();
}


Can you point to any real-life example of this?

It feels like a lot of this discussion of BC breaks is assuming that there's some common code pattern relying on the current behaviour, but the only examples I've seen so far are of why it would be *wrong* to return a value.


There are two conflicting goals in the prologue: "Maximum warning"
and "Minimal BC impact". You prioritize Maximum warning. I prioritize
Minimal BC impact.


I disagree that your proposal has a lower BC impact.

The majority of code that currently relies on a constructor returning a value *will break under both versions of the proposal*. The only difference that delaying the error to run-time makes, is that it will take longer for people to notice that it is broken.


Your points are correct, from the perspective of a new PHP project.
However, reasoning from the perspective of a very old PHP project,
every BC break is one too many.


It is exactly those old PHP projects that I'm worried about. The ones that have poor testing coverage, large amounts of spaghetti code, and will cause some poor engineer to have a 2am alarm because someone the other side of the world just crashed the application with a run-time error.


-- 
Rowan Tommins
[IMSoP]
--------------lAqyczpasWWd3olefxcYUNew--