Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Stephen Reay



> On 24 Nov 2023, at 01:09, Rowan Tommins  wrote:
> 
> On Thu, 23 Nov 2023 at 14:20, Stephen Reay  wrote:
> 
>> 
>> Out of the box, with no package manager or module loader or anything, you
>> can do as little as call `spl_autoload_register` with no arguments, and
>> have working class autoloading.
>> 
> 
> 
> Sure, it's just about possible that you could paste that one line into each
> of your PHP files, and they'd all pick up the right classes. But it's more
> likely that you have some shared include called "startup.php",
> "boostrap.php", "header.php", etc, which has that line plus a bunch of
> other setup. So, the argument goes that adding a line "require
> 'namespace_foo_functions.php';" to that shared include isn't that big a
> problem.
> 
> (If it happens you are using Composer, the files and config are listed in a
> JSON file rather than a PHP one, and Composer generates the shared include,
> but the logic's basically the same.)
> 
> The strongest counter-argument, I think, is that it *scales* badly: once
> you have more than a handful of such include files, an autoloader solution
> becomes more attractive than listing all the files.
> 

I think attractive is the wrong word here, but yes in general the issue is that 
it becomes a developer overhead as the number and location of files increases, 
particularly if you want to keep the files organised in the filesystem in a 
similar fashion to classes (i.e. namespaces mapping to directory names).

> However, in itself that's not an argument for static classes; it's an
> argument for function autoloading; the argument for static classes needs to
> be either:
> 
> - "admit it, we're never going to get function autoloading";
> - or "I'd want this even if we had function autoloading" (in which case the
> discussion of require vs autoloading becomes irrelevant).
> 

I couldn't agree more - like I said at the start: I have no dog in this 
particular race about static classes, my only concern is the continued use of 
Composer as a flimsy argument about why features aren't required.



Cheers

Stephen 


> Regards,
> -- 
> Rowan Tommins
> [IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC][Discussion] Why can constructors violate LSP?

2023-11-23 Thread Mike Schinkel


> On Nov 23, 2023, at 4:50 PM, Robert Landers  wrote:
> 
> On Thu, Nov 23, 2023 at 10:30 PM Deleu  wrote:
>> 
>> Constructors are an implementation detail of a specialized class and as such 
>> they're not subject to LSP because the goal of LSP is to be able to make 
>> sure that any object of a given type hierarchy can be used to accomplish a 
>> certain behavior. If you take a step back from PHP's dynamic nature and 
>> think about LSP from a more pure type system, the fact you're expecting an 
>> object of type C, but then you completely disregard everything about the 
>> object itself and dive into it's metadata to build another object, that's 
>> the moment you're no longer playing by the rules of OOP. It's like those 
>> mathematical equations that prove that 1 = 2, they all have one thing in 
>> common: they end up dividing by 0 at some point.
>> 
>> OOP here dictates that you should reach for patterns like Builder, Abstract 
>> Factory or similar. That way you constraint yourself to the rules of OOP and 
>> you won't get weird outcomes.
>> 
>> From another point of view, when a type is expected by a function or method, 
>> all we can expect from it is whatever was defined as the blueprint 
>> (class/interface) of that object and the __construct() is a special method 
>> that is not assumed to be part of that blueprint because it's not reasonable 
>> to do `$object->__construct();` after receiving an object. As such, a 
>> constructor cannot break LSP because the constructor is not part of the 
>> object's API from a "receptor" point of view.
>> 
>> I don't have a vote so take my opinion with a bucket of salt, but if I could 
>> I would definitely vote against such RFC.
>> 
>> 
>> --
>> Marco Deleu
> 
> Thanks Marco,
> 
> That's an interesting perspective and one I would agree with for the
> most part, especially if you take my illustration at face value. Where
> it gets weird/breaks down is when you have a class-string, that you
> assert is the correct type, and then try to instantiate it:
> 
> // from somewhere
> $class = "C";
> 
> if(is_subclass_of($class, P::class)) {
>$example = new $class("world");
> }
> 
> If PHP didn't offer these built-in methods, then I would fully agree
> with you, but it does, which puts it into a weird position where
> sometimes a class is substitutable, and in this one special case, it
> is not.

What Marco said pretty much mirrors the answer in Software Engineering SE:

https://softwareengineering.stackexchange.com/a/270738/9114 


As if probably obvious now, when you are using a variable containing a class 
name to instantiate a class you are actually not using OOP, you are using the 
text expansion capabilities of PHP. The fact that it appears to be similar to a 
method call is just likely coincidence,

Now if classes were first class objects in PHP, then there might be an 
argument, but alas, they are not.

Anyway, I always addressed the problem you are running into by defining a 
`make_new()` static method.  Here's what your example might look after an 
initial refactor:

class P {
public $msg;
function __construct($msg){
$this->msg = $msg;
}
}
class C extends P {
static function make_new($props){
return new C($props["msg"]);
}
}

$class = "C";

if(is_subclass_of($class, P::class)) {
   $example = $class::make_new( ["msg"=>"world"] );
   print_r($example);
}

Of course, getting it to production code will take a lot more, like you can see 
here (although this code has now been update for probably five years since I am 
no longer coding in PHP professionally):

https://github.com/search?q=repo%3Awplib%2Fwplib%20make_new=code 


And if you are dealing with 3rd party classes, you'll need to write wrapper 
classes.

Hope this helps.

-Mike



[PHP-DEV] [RFC] [VOTE] Change the edge case of round()

2023-11-23 Thread Saki Takamachi
Hi internals,

I started voting on my RFC "Change the edge case of round()”.

Voting will end December 8th, 00:00 GMT.

https://wiki.php.net/rfc/change_the_edge_case_of_round

Regards.

Saki
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] Re: [RFC] [VOTE] Adding bcround, bcfloor and bcceil to BCMath

2023-11-23 Thread Saki Takamachi
Hi internals,


> Voting will end November 30th, 00:00 GMT.


I made a mistake in my calculation. It's until the 29th.

Regards.

Saki

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC][Discussion] Why can constructors violate LSP?

2023-11-23 Thread Robert Landers
On Thu, Nov 23, 2023 at 10:30 PM Deleu  wrote:
>
>
>
> On Thu, Nov 23, 2023 at 5:31 PM Robert Landers  
> wrote:
>>
>> Hello Internals,
>>
>> As you may know, an inherited method cannot reduce the visibility of
>> an overridden method. For example, this results in a fatal error
>> during compilation:
>>
>> class P {
>> public function hello($name = 'world') {
>> echo "hello $name\n";
>> }
>> }
>>
>> class C extends P {
>> private function hello($name = 'world') {
>> parent::hello($name);
>> echo "goodbye $name\n";
>> }
>> }
>>
>> However, we can make certain methods private anyway, namely,
>> constructors (I haven't gone hunting for other built-in methods yet).
>> This is perfectly allowed:
>>
>> class P {
>> public function __construct($name = 'waldo') {
>> echo "hello $name\n";
>> }
>> }
>>
>> class C extends P {
>> private function __construct($name = 'world') {
>> parent::__construct($name);
>> echo "goodbye $name\n";
>> }
>> }
>>
>> To my somewhat trained eye, this appears to violate the Liskov
>> Substitution Principle, for example, this now can have hidden errors:
>>
>> function create(P $class) {
>> return new (get_class($class))();
>> }
>>
>> proven by:
>>
>> $c = (new ReflectionClass(C::class))
>>   ->newInstanceWithoutConstructor();
>>
>> create($c);
>>
>> Even though we thought we knew that the constructor was declared public.
>>
>> I'd like to propose an RFC to enforce the covariance of constructors
>> (just like is done for other methods), to take effect in PHP 9, with a
>> deprecation notice in 8.3.x.
>>
>> I'm more than happy to implement it.
>>
>> Does anyone feel strongly about this one way or the other?
>
>
> Constructors are an implementation detail of a specialized class and as such 
> they're not subject to LSP because the goal of LSP is to be able to make sure 
> that any object of a given type hierarchy can be used to accomplish a certain 
> behavior. If you take a step back from PHP's dynamic nature and think about 
> LSP from a more pure type system, the fact you're expecting an object of type 
> C, but then you completely disregard everything about the object itself and 
> dive into it's metadata to build another object, that's the moment you're no 
> longer playing by the rules of OOP. It's like those mathematical equations 
> that prove that 1 = 2, they all have one thing in common: they end up 
> dividing by 0 at some point.
>
> OOP here dictates that you should reach for patterns like Builder, Abstract 
> Factory or similar. That way you constraint yourself to the rules of OOP and 
> you won't get weird outcomes.
>
> From another point of view, when a type is expected by a function or method, 
> all we can expect from it is whatever was defined as the blueprint 
> (class/interface) of that object and the __construct() is a special method 
> that is not assumed to be part of that blueprint because it's not reasonable 
> to do `$object->__construct();` after receiving an object. As such, a 
> constructor cannot break LSP because the constructor is not part of the 
> object's API from a "receptor" point of view.
>
> I don't have a vote so take my opinion with a bucket of salt, but if I could 
> I would definitely vote against such RFC.
>
>
> --
> Marco Deleu

Thanks Marco,

That's an interesting perspective and one I would agree with for the
most part, especially if you take my illustration at face value. Where
it gets weird/breaks down is when you have a class-string, that you
assert is the correct type, and then try to instantiate it:

// from somewhere
$class = "C";

if(is_subclass_of($class, P::class)) {
$example = new $class("world");
}

If PHP didn't offer these built-in methods, then I would fully agree
with you, but it does, which puts it into a weird position where
sometimes a class is substitutable, and in this one special case, it
is not.

Robert Landers
Software Engineer
Utrecht NL

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] [RFC][Discussion] Why can constructors violate LSP?

2023-11-23 Thread Deleu
On Thu, Nov 23, 2023 at 5:31 PM Robert Landers 
wrote:

> Hello Internals,
>
> As you may know, an inherited method cannot reduce the visibility of
> an overridden method. For example, this results in a fatal error
> during compilation:
>
> class P {
> public function hello($name = 'world') {
> echo "hello $name\n";
> }
> }
>
> class C extends P {
> private function hello($name = 'world') {
> parent::hello($name);
> echo "goodbye $name\n";
> }
> }
>
> However, we can make certain methods private anyway, namely,
> constructors (I haven't gone hunting for other built-in methods yet).
> This is perfectly allowed:
>
> class P {
> public function __construct($name = 'waldo') {
> echo "hello $name\n";
> }
> }
>
> class C extends P {
> private function __construct($name = 'world') {
> parent::__construct($name);
> echo "goodbye $name\n";
> }
> }
>
> To my somewhat trained eye, this appears to violate the Liskov
> Substitution Principle, for example, this now can have hidden errors:
>
> function create(P $class) {
> return new (get_class($class))();
> }
>
> proven by:
>
> $c = (new ReflectionClass(C::class))
>   ->newInstanceWithoutConstructor();
>
> create($c);
>
> Even though we thought we knew that the constructor was declared public.
>
> I'd like to propose an RFC to enforce the covariance of constructors
> (just like is done for other methods), to take effect in PHP 9, with a
> deprecation notice in 8.3.x.
>
> I'm more than happy to implement it.
>
> Does anyone feel strongly about this one way or the other?
>

Constructors are an implementation detail of a specialized class and as
such they're not subject to LSP because the goal of LSP is to be able to
make sure that any object of a given type hierarchy can be used to
accomplish a certain behavior. If you take a step back from PHP's
dynamic nature and think about LSP from a more pure type system, the fact
you're expecting an object of type C, but then you completely disregard
everything about the object itself and dive into it's metadata to build
another object, that's the moment you're no longer playing by the rules of
OOP. It's like those mathematical equations that prove that 1 = 2, they all
have one thing in common: they end up dividing by 0 at some point.

OOP here dictates that you should reach for patterns like Builder, Abstract
Factory or similar. That way you constraint yourself to the rules of OOP
and you won't get weird outcomes.

>From another point of view, when a type is expected by a function or
method, all we can expect from it is whatever was defined as the blueprint
(class/interface) of that object and the __construct() is a special method
that is not assumed to be part of that blueprint because it's not
reasonable to do `$object->__construct();` after receiving an object. As
such, a constructor cannot break LSP because the constructor is not part of
the object's API from a "receptor" point of view.

I don't have a vote so take my opinion with a bucket of salt, but if I
could I would definitely vote against such RFC.


-- 
Marco Deleu


Re: [PHP-DEV] [RFC][Discussion] Why can constructors violate LSP?

2023-11-23 Thread Rowan Tommins
On 23 November 2023 20:31:09 GMT, Robert Landers  
wrote:

>I'd like to propose an RFC to enforce the covariance of constructors
>(just like is done for other methods), to take effect in PHP 9, with a
>deprecation notice in 8.3.x.

There's a lot more than visibility that is enforced on normal methods, but 
isn't on constructors. For instance this is also valid:

class A {
public function __construct(int $foo) {}
}
class B extends A {
public function __construct(string $bar) {}
}

From a theoretical perspective, I think the argument is roughly that classes 
aren't first-class citizens that you can pass around, so substitutability 
doesn't apply. You can't for instance write a function that explicitly depends 
on "a class definition inheriting from A", like this:

function foo(class $class) {
 $instance = new $class(42);
}

You can certainly simulate such code with some strings and maybe a bit of 
reflection, but the language isn't going to make any guarantees about it.

I did just think of a counter-example, though, which is that "new 
static($param)" is allowed, even though there's no way to know if $param will 
be accepted by subclasses. Maybe it shouldn't be allowed?


From a practical point of view, it's often very useful to sub-class something 
and provide a constructor with a different signature. Maybe your subclass has 
additional dependencies; maybe it can hard-code or calculate some of the inputs 
to the parent constructor for a special case, etc.

A private constructor can be used in conjunction with static methods to 
simulate multiple named constructors (createFromString, createFromRequest, 
etc). Given the lack of other guarantees, there's no particular gain in 
preventing that just because the parent class has a public constructor.

Regards,

-- 
Rowan Tommins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] [RFC][Discussion] Why can constructors violate LSP?

2023-11-23 Thread Robert Landers
Hello Internals,

As you may know, an inherited method cannot reduce the visibility of
an overridden method. For example, this results in a fatal error
during compilation:

class P {
public function hello($name = 'world') {
echo "hello $name\n";
}
}

class C extends P {
private function hello($name = 'world') {
parent::hello($name);
echo "goodbye $name\n";
}
}

However, we can make certain methods private anyway, namely,
constructors (I haven't gone hunting for other built-in methods yet).
This is perfectly allowed:

class P {
public function __construct($name = 'waldo') {
echo "hello $name\n";
}
}

class C extends P {
private function __construct($name = 'world') {
parent::__construct($name);
echo "goodbye $name\n";
}
}

To my somewhat trained eye, this appears to violate the Liskov
Substitution Principle, for example, this now can have hidden errors:

function create(P $class) {
return new (get_class($class))();
}

proven by:

$c = (new ReflectionClass(C::class))
  ->newInstanceWithoutConstructor();

create($c);

Even though we thought we knew that the constructor was declared public.

I'd like to propose an RFC to enforce the covariance of constructors
(just like is done for other methods), to take effect in PHP 9, with a
deprecation notice in 8.3.x.

I'm more than happy to implement it.

Does anyone feel strongly about this one way or the other?

Robert Landers
Software Engineer
Utrecht NL

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] PHP 8.3.0 Released!

2023-11-23 Thread Paul Dragoonis
On Thu, Nov 23, 2023 at 4:57 PM Jakub Zelenka  wrote:

> The PHP development team announces the immediate availability of PHP 8.3.0.
> This release marks the latest major release of the PHP language.
>
> PHP 8.3 comes with numerous improvements and new features such as:
> - Typed Class Constants
> - Fetch class constant dynamically syntax
> - Readonly Amendments
> - Override Attribute
> - New Randomizer method Random\Randomizer::getBytesFromString
> - New function json_validate
> - And much much more...
>
> For source downloads of PHP 8.3.0 please visit our downloads page
> (https://www.php.net/downloads.php), Windows source and binaries can be
> found on https://windows.php.net/download/.
> The list of changes is recorded in the ChangeLog
> (https://www.php.net/ChangeLog-8.php#8.3.0).
> The migration guide (http://php.net/manual/en/migration83.php) is
> available
> in the PHP Manual.
> Please consult it for the detailed list of new features and backward
> incompatible changes.
>
> Many thanks to all the contributors and supporters!
>
> Release Manifest here and below:
> https://gist.github.com/bukka/9b83d9718de090953eec989be16ba91a
>
> Jakub Zelenka, Eric Mann, & Pierrick Charron
>

What an achievement!

Just giving my personal thanks to Jakub, Eric, & Pierrick, and obviously to
all contributors, you all rock! :-)

Looking forward to trying it out

Many thanks,
Paul



>
> php-8.3.0.tar.bz2
> SHA256 hash:
> de67d0833d42b196e5a66fa1a332f45e296cbe8e9472e9256b2a071c34dc5ed6
> PGP signature:
> -BEGIN PGP SIGNATURE-
>
> iHUEABYIAB0WIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCZVzCAgAKCRAcB3ncXAqd
> 5JBFAQCaYK3jZ8YtgaOUpIRTYsAEVf4wgHshahMsxyOOL9GP9AEAlz/sd2HK/Wod
> J9AsSbX68jX98PK0RG/WE+gA2L/DXQs=
> =Y0F0
> -END PGP SIGNATURE-
>
>
> php-8.3.0.tar.gz
> SHA256 hash:
> 557ae14650f1d1984d3213e3fcd8d93a5f11418b3f8026d3a2d5022251163951
> PGP signature:
> -BEGIN PGP SIGNATURE-
>
> iHUEABYIAB0WIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCZVzCAwAKCRAcB3ncXAqd
> 5NDPAQDieVJDb9nL/HnB/mTLfzbcwIBiIVlQpGAp9V3WrYS6ZAD/cvQ5U4Uljaq2
> 2fv4hdBTjcaxlTjjsq+GK8GGz2C67gs=
> =n0At
> -END PGP SIGNATURE-
>
>
> php-8.3.0.tar.xz
> SHA256 hash:
> 1db84fec57125aa93638b51bb2b15103e12ac196e2f960f0d124275b2687ea54
> PGP signature:
> -BEGIN PGP SIGNATURE-
>
> iHUEABYIAB0WIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCZVzCAwAKCRAcB3ncXAqd
> 5KKuAQCtutsDX4GEimUkxyeBOlHtAa3sZohmSimjchPlz0G3dwD/bDvvI836HsGt
> rZ3OAWTPI6e0W+M0MbJwq6o54sxDqQg=
> =eSjV
> -END PGP SIGNATURE-
>


[PHP-DEV] PHP 8.1.26 Released!

2023-11-23 Thread Ben Ramsey

The PHP development team announces the immediate availability of PHP
8.1.26. This is a bug fix release.

All PHP 8.1 users are encouraged to upgrade to this version.

For source downloads of PHP 8.1.26 please visit our downloads page.
Windows binaries can be found on the PHP for Windows site.
The list of changes is recorded in the ChangeLog.

Release Announcement: 
Downloads:
Windows downloads:
Changelog:
Release Manifest:


Many thanks to all the contributors and supporters!

Ben Ramsey, Patrick Allaert, & Joe Watkins



php-8.1.26.tar.bz2
SHA256 hash: 
83bde249c84aa1a043a8c8d0eea09345c2cae69b9784cdf02229fc916fbb9ea0

PGP signature:
-BEGIN PGP SIGNATURE-

iQIzBAABCAAdFiEEObZBND2MEEsrFG3D+cOdwLlphUQFAmVdKYYACgkQ+cOdwLlp
hUSjgg//e29SOGk+4NcHFq7cT6881EST1w1G/G8Ig9MbZzdXM3eJMLy7Zo+q60fq
3R+26ysXuKk1rPkGIiXwjUXWO6LD72FCzEd9krofRwyoA/GjpqzcTxtd509Vt1HN
9u4DkQupk6ljyrIfaybSVjROp06y741hvpX9xxGaZZHmVm3CscoZa0PyNOv+7kFW
LVg8YSPNIfWfkoa8ug05V2lr34WxX+PGip76TiXlzN2rBepN02R6kzrDwf/1U5bm
UPFqFzbG0AumY85wYFwr3oXlPwTC9oPdASN+OOmI0W1YxA0nBk0E6d8ZRig1taZP
TBTlGolxb8WUukDjitulp16uJy8ShSCQd1jWP+nNwhj4yB2uRbxZzmQUCIlktkRW
+auHAXv5GhBMvP2hwq905YN3pb7wGUnWmwcqDaHmdnkg98/q5+daUmhAujUkMt+8
OU4YFlvCqaJvUSD0tV4BSkWuXkFhxmgyRxS/L/O8DQnbY7CS9D0vwlxrP/ToAN8u
hOB9iEF0uZ5D8XtOmu+gWoF8qjFM43HIgntgWUGZrN0MJk2ARWlsRNuvY3bj4+1U
onQBkj5k6cwk8rCm1ZldTQpbYb3q4J6KPNvsNoW4FhgDGsAb0UQXwH6Khk09XR98
oN1dRGFWzQz0WuaFZQETS0uv0ZN1bOl5babQoctoLIH5/yfo57U=
=5guD
-END PGP SIGNATURE-


php-8.1.26.tar.gz
SHA256 hash: 
d954cecfc3d294c2fccbe2b1a6bef784ce0d6c5d44a9e28f8a527e092825f2cb

PGP signature:
-BEGIN PGP SIGNATURE-

iQIzBAABCAAdFiEEObZBND2MEEsrFG3D+cOdwLlphUQFAmVdKYcACgkQ+cOdwLlp
hUR0Vw//XQZJE2T4F03wJ+1zf3+vetshuTz9xmLj/gLNwjcDjK9XbLb6ojSI5UIu
+npTD3M+Grw9FSun9+LlNPuBgq4hJuZwqtuUbCtStffELMvscYchKb0JqW2F0MG4
naTS0rgXefuNTl/T1Gg2+sj3Zw92w++CvXaZ0J9F/ocSA9dVR1aOyqkrsitCl72j
Km4v6iwSeTY380npA6B1BYPajv+BCtVeqgWeuFmHyU0ZVtqmvs6bh3O2x+yXcDsB
9yrwOVYU7GL5nmmkZ0Ur6a/DPpa4IHSVDJOAlXWzy/yJWLzcdo7cygVU2j7pS0u7
iByVdPHE8aVK9yuxLBWBOz7lODwCK+q16NgDrw+QhNU/liCBeckF8CjQCSKuLKB9
MjwzppxnMck7+5ofl51hi+ER/1VEL7dm1YylnqmESo7+ZPp5GAxR7oq92DAtAh7s
6X9qcfkQ19MdTEp0Axea4go4D8qzdlp7ezo9mEr4Utu8LbI3MezQPdc1YmypE4MM
nBV5nXgPd70qp3BLJ0dGSfnUXLsW+hTC1q9seNT3V8HjSHwfCeOUV1XgyWvSm0JK
Lpw2BJsPRT35fWx/uReUuo5is5RlFLQJAJ8axtxUMehSgHtaiXVf+y1FxuaNnNbg
8BVcSMHB5K1U4hwX716uCC8WTzjvKcrqpKmnwvb9LBvkyLi64Ss=
=aect
-END PGP SIGNATURE-


php-8.1.26.tar.xz
SHA256 hash: 
17f87133596449327451ad4b8d9911bfaea59ff5109f3a6f2bb679f967a8ea0f

PGP signature:
-BEGIN PGP SIGNATURE-

iQIzBAABCAAdFiEEObZBND2MEEsrFG3D+cOdwLlphUQFAmVdKYgACgkQ+cOdwLlp
hUTarg//Wa9GIjl24fK01hAi4961TXWz+RS9Dl/ySxRuiC9FMSYaCZ3EfR/ri+Jv
DfGwHpVJblc2WTtfk6e8caKq2bk3RTZD/YONG+yfHf7RVJTo17mWICS65t7O2YB3
3++14DR3s+OpDiszf7i7Muv5Yq/twMeooCqcGBCe9OSS6v3i4Odz+NwUpMZ734wj
+5OlvWNCp+Z//UhwiRp5p8gkXgaIQWn5qf3xBJ9S+cQCa3GgVN7BvdwAdlUIVRW7
s8eAsX+piYuDuG1djpK3FaxUZQbJmTzS9cBQfbpIPFOiTCTD1/GDHMp3CcFo2wmk
ZejSOp1/HLsvWICSwxcNdNjladCW7s7TAi+JWywjqhKQj4Y2p1u0wESGYx8Kjc2I
dchL/aK5Fh9qKw7r0YB11zvz59MHDRSd45SZo1Oy18idVovjFYUk86qfK0DT+sxa
y3Yq5aDHdzlSqrHnwCUj2PXgXboSxKBtfRCnF6QdLM12Tpxz7Ivgh5yEj2Kjzyah
tkPJbzQuPxFIPomS+5/E0z9ASTLNhSXL3OofuCudHo0fDYahyaUnEeErp+bgets8
oZBGI0GbhuOfYRMSgmqpDL0Lfmm6D8gzuLRsVAtVqwsyceEo2rRyv1i0INS8G0GR
9NoUrV1c4aLwURG9O+Et1ERJ+O2zRi22F4xYrPcHn9o8cSNsdQY=
=dmLS
-END PGP SIGNATURE-



OpenPGP_signature.asc
Description: OpenPGP digital signature


Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Lanre Waju
Seriously? Are you really this stupid or just feigning ignorance? How is 
this a global:

class X {
private static $count = 0;

}

I am no longer pushing this RFC because idiots like you are in charge of 
the votes but seriously your argument is dumb as fuck. If you aren't 
sure then why say anything before looking more into it? A class level 
static is not equivalent to a global in any sense and if I have to 
explain the differences to you, you are not in a position to be speaking 
this confidently.


This isn't me taking anything personally, i have just come to the 
realization that this community is not for me, so you guys can have fun 
jerking each other off, and I will keep my ideas to myself.


Cheers,

Lanre

On 2023-11-23 10:55 a.m., Larry Garfield wrote:

On Thu, Nov 23, 2023, at 1:43 AM, Robert Landers wrote:


I'd venture to say that static classes have some unique benefits over
plain functions. One, you can encapsulate state using private static
variables. That simply isn't possible with regular functions (unless
you use static variables in the functions themselves, which isn't
quite the same thing).

It's close enough to the same thing that it has the same problems.

As far as I am aware, a static variable in a function is stored in global 
memory as a singleton.  It's logically the same as a global variable, but with 
access restricted to one function.

A static property of a class is also stored in global memory.  It's logically 
the same as a global variable, but with a funny name that has colons in it.  It 
may be access restricted depending on the code.

(Engine experts, if I am subtly wrong there please do correct me.)

So static variables and static properties are both simply "globals with funny 
extras."  And global-maintained state is well known and understood as a bad idea 
that hinders testing, refactoring, tractability, maintenance, and everything else 
developers care about.

Using global state, with or without funny syntax around it, is the anti-pattern 
we should not be encouraging.

Generally speaking, even my prototypes eschew globals and statics in 95% of 
cases.

--Larry Garfield



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Rowan Tommins
On Thu, 23 Nov 2023 at 14:20, Stephen Reay  wrote:

>
> Out of the box, with no package manager or module loader or anything, you
> can do as little as call `spl_autoload_register` with no arguments, and
> have working class autoloading.
>


Sure, it's just about possible that you could paste that one line into each
of your PHP files, and they'd all pick up the right classes. But it's more
likely that you have some shared include called "startup.php",
"boostrap.php", "header.php", etc, which has that line plus a bunch of
other setup. So, the argument goes that adding a line "require
'namespace_foo_functions.php';" to that shared include isn't that big a
problem.

(If it happens you are using Composer, the files and config are listed in a
JSON file rather than a PHP one, and Composer generates the shared include,
but the logic's basically the same.)

The strongest counter-argument, I think, is that it *scales* badly: once
you have more than a handful of such include files, an autoloader solution
becomes more attractive than listing all the files.

However, in itself that's not an argument for static classes; it's an
argument for function autoloading; the argument for static classes needs to
be either:

- "admit it, we're never going to get function autoloading";
- or "I'd want this even if we had function autoloading" (in which case the
discussion of require vs autoloading becomes irrelevant).

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Lanre Waju
Again, with so many absolutes. Static APIs aren't inherently bad; 
rather, bad programmers write poor code. It seems like you're assuming 
that PHP developers can't make decisions about what tools to use 
independently and need explicit encouragement or endorsement from you. 
Just because you are using what I would call "garbage" (my preferred 
term for legacy) Stripe API doesn't mean we all do. When did I ever say 
the cost to add this would be zero? If everything has a non-zero 
development cost, doesn't that make it implied? What exactly is your point?


For example, the get/set hooks you proposed: why go the C# route instead 
of using JS-like modifiers, which PHP already supports? What was the 
cost analysis on that? Then, you talk about Laravel. How are Facades 
anything like what I have suggested exactly? The idea that Laravel is 
somehow more difficult to test than any other framework is simply a 
myth; they have a robust test suite. I write embedded code for a living; 
I have crafted far more critical tests for code being shipped to 
millions of devices that may never update, compared to your "legacy" 
Stripe code that you still use for some reason. So, you don't have to 
explain how mocks and unit tests work, but thanks for your summary.


I made a suggestion for something i thought would be a nice addition to 
the language, and instead of questions, I'm met with absolutes on why my 
Idea is bad, and some nonsense about how everything has maintenance cost.



On 2023-11-20 4:28 p.m., Larry Garfield wrote:

On Mon, Nov 20, 2023, at 9:00 PM, Lanre Waju wrote:

I will have to disagree with everything you said:

I outlined what a static class would be: A class that cannot be
instantiated in which all members are implicitly static. We already have
static members, so please elaborate on the maintenance burden that
adding static to a class as that could help explain better, i mean what
feature doesn't have technical debt associated with it? The new JIT engine?

That's part of the point.  Literally every feature added to a system (PHP or 
otherwise) has some maintenance overhead associated with it.  It may be small, 
it may be huge, it may be worth it, it may not be worth it, but it's always 
non-zero.

As for what a static class is, from your description I am understanding it to 
mean this:

static class Foo {
   public function beep(): string { ... }
   public function boop(): string { ... }
}

Is effectively a shorthand for:

class Foo {
   public function __construct() { throw new \Exception("You can't do that"); }

   public static function beep(): string { ... }
   public static function boop(): string { ... }
}

Much the same way a readonly class is.  Is that understanding of the intent 
more or less accurate?


3. It is entirely opt-in. If you hold reservations about using static
classes, you can simply choose not to use them.

This is a spurious and disingenuous argument, even if it gets trotted out 
frequently on many RFCs.  I'm not picking on you in particular here, but it's a 
bad argument to use, period, 99% of the time, no matter who is saying it.

If you insist, Mr. Larry.

Cultural side note: At least in the US, where I am, "Mr. Firstname" is pretty much never 
used except with some families that teach their children to use that with adults.  It's not 
necessary and kind of weird.  "Mr. Garfield" if you want to be formal is fine, or just 
Larry, or Crell, as that's the handle I use virtually everywhere and there are people who know me 
as that more than as Larry.  (I am not offended, just noting a cultural mismatch point.)


Similarly, if we add a static marker to classes, that means all future improvements to classes need 
to consider "but what if the class is static?"  Eg, there was discussion a while back 
about `data` classes.  What happens if you have a `static data class`?  Is that a syntax error?  
Does it work?  If it works, what does "work" mean?  What about sealed classes?  Can you 
have a sealed static class?  What would that mean?  Those are questions that would need to be 
answered, because this feature exists.

Either i'm in an alternate reality where the data classes and sealed
classes rfcs passed, or I've just been straw-manned. Either way, is it
really that difficult to decide on as a community what a static data
class implies? We have already established that a static class means all
the members are static, but i can try to dumb it down for you if need be.

There is no need to dumb it down, just to read what I actually wrote.  *Every* feature 
added has implications for future features added.  Data and Sealed classes are ideas that 
have been floated but never to a full RFC, but may end up as an RFC in the future.  They 
were convenient examples of future work that would be impacted by adding a static keyword 
to classes, as those RFCs would have to determine how to interact with static classes.  
Maybe the solution would be simple, maybe it wouldn't, I have no idea.  It 

Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Larry Garfield
On Thu, Nov 23, 2023, at 1:43 AM, Robert Landers wrote:

> I'd venture to say that static classes have some unique benefits over
> plain functions. One, you can encapsulate state using private static
> variables. That simply isn't possible with regular functions (unless
> you use static variables in the functions themselves, which isn't
> quite the same thing). 

It's close enough to the same thing that it has the same problems.

As far as I am aware, a static variable in a function is stored in global 
memory as a singleton.  It's logically the same as a global variable, but with 
access restricted to one function.

A static property of a class is also stored in global memory.  It's logically 
the same as a global variable, but with a funny name that has colons in it.  It 
may be access restricted depending on the code.

(Engine experts, if I am subtly wrong there please do correct me.)

So static variables and static properties are both simply "globals with funny 
extras."  And global-maintained state is well known and understood as a bad 
idea that hinders testing, refactoring, tractability, maintenance, and 
everything else developers care about.

Using global state, with or without funny syntax around it, is the anti-pattern 
we should not be encouraging.

Generally speaking, even my prototypes eschew globals and statics in 95% of 
cases.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



[PHP-DEV] PHP 8.3.0 Released!

2023-11-23 Thread Jakub Zelenka
The PHP development team announces the immediate availability of PHP 8.3.0.
This release marks the latest major release of the PHP language.

PHP 8.3 comes with numerous improvements and new features such as:
- Typed Class Constants
- Fetch class constant dynamically syntax
- Readonly Amendments
- Override Attribute
- New Randomizer method Random\Randomizer::getBytesFromString
- New function json_validate
- And much much more...

For source downloads of PHP 8.3.0 please visit our downloads page
(https://www.php.net/downloads.php), Windows source and binaries can be
found on https://windows.php.net/download/.
The list of changes is recorded in the ChangeLog
(https://www.php.net/ChangeLog-8.php#8.3.0).
The migration guide (http://php.net/manual/en/migration83.php) is available
in the PHP Manual.
Please consult it for the detailed list of new features and backward
incompatible changes.

Many thanks to all the contributors and supporters!

Release Manifest here and below:
https://gist.github.com/bukka/9b83d9718de090953eec989be16ba91a

Jakub Zelenka, Eric Mann, & Pierrick Charron

php-8.3.0.tar.bz2
SHA256 hash:
de67d0833d42b196e5a66fa1a332f45e296cbe8e9472e9256b2a071c34dc5ed6
PGP signature:
-BEGIN PGP SIGNATURE-

iHUEABYIAB0WIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCZVzCAgAKCRAcB3ncXAqd
5JBFAQCaYK3jZ8YtgaOUpIRTYsAEVf4wgHshahMsxyOOL9GP9AEAlz/sd2HK/Wod
J9AsSbX68jX98PK0RG/WE+gA2L/DXQs=
=Y0F0
-END PGP SIGNATURE-


php-8.3.0.tar.gz
SHA256 hash:
557ae14650f1d1984d3213e3fcd8d93a5f11418b3f8026d3a2d5022251163951
PGP signature:
-BEGIN PGP SIGNATURE-

iHUEABYIAB0WIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCZVzCAwAKCRAcB3ncXAqd
5NDPAQDieVJDb9nL/HnB/mTLfzbcwIBiIVlQpGAp9V3WrYS6ZAD/cvQ5U4Uljaq2
2fv4hdBTjcaxlTjjsq+GK8GGz2C67gs=
=n0At
-END PGP SIGNATURE-


php-8.3.0.tar.xz
SHA256 hash:
1db84fec57125aa93638b51bb2b15103e12ac196e2f960f0d124275b2687ea54
PGP signature:
-BEGIN PGP SIGNATURE-

iHUEABYIAB0WIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCZVzCAwAKCRAcB3ncXAqd
5KKuAQCtutsDX4GEimUkxyeBOlHtAa3sZohmSimjchPlz0G3dwD/bDvvI836HsGt
rZ3OAWTPI6e0W+M0MbJwq6o54sxDqQg=
=eSjV
-END PGP SIGNATURE-


Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Stephen Reay



> On 23 Nov 2023, at 19:42, Rowan Tommins  wrote:
> 
> On Thu, 23 Nov 2023 at 11:48, Stephen Reay  wrote:
> 
>> 
>> Respectively, I disagree that it's "not a big problem" if your goal is to
>> encourage people to use regular functions over classes with static methods.
>> 
> 
> 
> Just to be clear, my answer was specifically addressing your point about
> using Composer as an argument for not including things.
> 
> I was not saying "... and therefore the argument is true", only "... and
> therefore we can discuss the argument without mentioning Composer if we
> want to".
> 
> 

Fair enough, apologies for misunderstanding what you were saying there.

> 
>> PHP ships with a built in class autoloader function, and pretending that
> using 'require_once' everywhere a function is used, is just as easy for the
> developer seem disingenuous to be honest.
> 
> PHP ships with *the ability to configure* an autoloading function; it will
> not load any files without you first telling it where to look.

I'm talking about php's builtin *implementation* of an autoloader not just 
support for the *concept* of class autoloading using a userland function.

Out of the box, with no package manager or module loader or anything, you can 
do as little as call `spl_autoload_register` with no arguments, and have 
working class autoloading. Yes you *may* also end up setting the include path 
and/or autoload extensions at runtime, or even writing a custom autoload 
implementation - but none of that is required for it to work.

> The
> workaround being proposed is not to use require_once every time you want a
> function, it's to use require_once in the same place you configure your
> autoloader.
> 
> I totally agree that we can debate whether that workaround is sufficient.
> I'm just trying to frame that debate as "autoloading vs require", rather
> than a distraction of "Composer vs something else".
> 

Ok, again, apologies for the misunderstanding of the point you're making - and 
thank you, I agree that is a better way to frame the debate, when it comes to 
language / stdlib features.







> 
> Regards,
> -- 
> Rowan Tommins
> [IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Rowan Tommins
On Thu, 23 Nov 2023 at 11:48, Stephen Reay  wrote:

>
> Respectively, I disagree that it's "not a big problem" if your goal is to
> encourage people to use regular functions over classes with static methods.
>


Just to be clear, my answer was specifically addressing your point about
using Composer as an argument for not including things.

I was not saying "... and therefore the argument is true", only "... and
therefore we can discuss the argument without mentioning Composer if we
want to".



> PHP ships with a built in class autoloader function, and pretending that
using 'require_once' everywhere a function is used, is just as easy for the
developer seem disingenuous to be honest.

PHP ships with *the ability to configure* an autoloading function; it will
not load any files without you first telling it where to look. The
workaround being proposed is not to use require_once every time you want a
function, it's to use require_once in the same place you configure your
autoloader.

I totally agree that we can debate whether that workaround is sufficient.
I'm just trying to frame that debate as "autoloading vs require", rather
than a distraction of "Composer vs something else".


Regards,
-- 
Rowan Tommins
[IMSoP]


[PHP-DEV] PHP 8.2.13 Released!

2023-11-23 Thread Sergey Panteleev


The PHP development team announces the immediate availability of PHP
8.2.13. This is a security release.

All PHP 8.2 users are encouraged to upgrade to this version.

For source downloads of PHP 8.2.13 please visit our downloads page.
Windows binaries can be found on the PHP for Windows site.
The list of changes is recorded in the ChangeLog.

Release Announcement: https://php.net/releases/8_2_13.php
Downloads: https://php.net/downloads
Windows downloads: https://windows.php.net/download#php-8.2
Changelog: https://php.net/ChangeLog-8.php#8.2.13
Release Manifest:
https://gist.github.com/saundefined/d9854205df8fa3e9bff9f902cea044ab

Many thanks to all the contributors and supporters!

Pierrick Charron, Sergey Panteleev & Ben Ramsey


php-8.2.13.tar.bz2
SHA256 hash: 66529f43b213131e6b253c5602bef05f049458d21292730fccd63b48a06d67ba
PGP signature:
-BEGIN PGP SIGNATURE-

iQIzBAABCAAdFiEE5gkT5N8gmQfY4w2WZZqXyc8qeVoFAmVcfz8ACgkQZZqXyc8q
eVqeiA/9HOcOiX98v3Ibk+cm9r29aEe5Pv610bwCodw9cYDZetgR/sminLmIOg2d
GAtwJCIrxrRJ1b4OXIqn8N13wU+T1OskTMDjHNjTWnLrGmvUMr3OTJwGseHSPC6W
ieBpLe6hPhKqXTgHV2vR7hEHC3BoAAJbjqbMJO6TTXk/zmSJIuljTG+Buuc/0bqw
onJyG26blWYWf7rsySvmWoJF4q+z5FXr3xxw1jIXFtX70sgZTfI/O8cHzK8d08MV
SyW4Bw6qwfgcmxIizeSjiNkrVcpZIl+2VRP4NrkpJEH3ZS0SYqA7dNfTMtkj0ANC
OngPUMBQ7D7rJVpihsgPAzWI9A2mDt9l+rgXx3LOAkZWg4o0SU/2c45egLKcuF2y
V+rXs5ndjhdgOtYCS6PxbjMAlabT8MzDyU1X+umKGl27F5SOtCKGTozpFlC22Ow+
x1ud6C2ZNr68SiK8BMRuD0+zPfSnQcmrntP/1SAw01+fHxJQKhN7K7XY92QTKtwC
V7yccr1rhKn6ztnva2Qt/2fdxBUwa/cF/9APIuMk8IjZXrv09If+zUDH+l/KiWSN
RtMMzQ15NBabLy/tKhJceIBVmL+38myZ7OPAlsX6kTlwrt7Yio5j7cJcB1KfC75D
8cCBBpiWjDAY6exLmYE7laRICI8GyFwQoAZZbDx/gqUcY/Ybk3Q=
=JrJb
-END PGP SIGNATURE-


php-8.2.13.tar.gz
SHA256 hash: 6a194038f5a9e46d8f70a9d59c072c3b08d6edbdd8e304096e24ccf2225bcf1b
PGP signature:
-BEGIN PGP SIGNATURE-

iQIzBAABCAAdFiEE5gkT5N8gmQfY4w2WZZqXyc8qeVoFAmVcf0QACgkQZZqXyc8q
eVoseRAArZh3Fkkb2zyKxkV86Q2BkzJOwpKf3+MC2ecKP7NgUcBe7v9IiAv1Omzu
cbvOyW7xsjlpLnDQ+7AKlq6M1xFd4tmIdmX0p+U9+WdZeDn/EDxbxw8futx3hgk4
I6pZ8ZIRApGuOQw88RxVXUtfvOME5LDcdUOL+OjQylMaxLAEj7VAupgMnRJby6PT
IDX1bD9nDHfpWROGoIzWuf2JrginJxXPjAv1YF8L/mAgbvzCDckgtcKckECFgT5D
r76MkmtFe2dskHHphroyg8FKdQL+Bue49KmpOMKOB9cKxyHugKH9TDNFcyuqoej6
/n8pzAaPbqAcnRVBPi+anTGNZ0fCUSpFGLzaJO93eyFn6zZ7rsEmkfC36iT++1Sj
JhkaGRRFPiQZDpXd92XI9O1JR4EcttvJkHi4X6pX9Q6qUV9VnmTgYLbUuACuloYT
9VYUuNSaw2aJ8E1hYkumLmgNq2FDFl1KeTJfMtze05o86U5uqnpfPdmvZQEWhoKp
sAa/IZb3BYkHqvi4iYdJZFJspZi5G7ZPwa6ANonjSOdZF7/DAjj6YjM4VSO0iNh1
PWwE5OffLlHjLTcmS14hEyzwDPxeySebZz4VOZsfxDjBsQzhCwvmQ+qtNsvGpXpS
KUeqm89t7HK/43uNtnIfnVoBenJ7S2Ov06ZoWtlXhfBooFBJ2ak=
=xCE1
-END PGP SIGNATURE-


php-8.2.13.tar.xz
SHA256 hash: 2629bba10117bf78912068a230c68a8fd09b7740267bd8ebd3cfce91515d454b
PGP signature:
-BEGIN PGP SIGNATURE-

iQIzBAABCAAdFiEE5gkT5N8gmQfY4w2WZZqXyc8qeVoFAmVcf0UACgkQZZqXyc8q
eVraYQ/8DoEepPVWkOMydjySwwhocfkT3RXXagAmNwqF5LKqgUr8iaXyAMZIBrsM
aIcPLsW6VbfjjZeqSPatZ7mLmHWEzRvW1JM1guqvKIxhtnFrmsRq9jWCvGZJGiWa
SkzpVcjTZQ/NMtWb+gN0K67W+IPFdB/8B/CgcpG+2Z5MmQFoZ4+KjNuxCf+hVAN0
+TYTEUXozuz5gQH3IwJ2lze4TbdYzBqYQjdz/ruSJwv3Cp1iW2TuCYIfwl1WNE5T
TMFg7uoGrw9VQuYySwqFic1FgcKHWTwHsUIxFXI/kxwpF9AKladLEW0PvuMLXJYz
r3iFLhd7TXij24mIbJm9znj464xvVZmM8Lq8owEC2jozFeDEoXQ+9YVW80GrowO0
ZpvBUL4nT3xuem4s2LzB+ynnMLvA/agg7f+13W+cmWrRYFHcVuLwoSiJyZjy1SD5
bo0ery8Ck4nFUldAQRHYMm6LLiEePpXZQnZwSrLTcVamJxJhMmWVH+JUoPhGXB5G
35kC6NZ2WiS/09Kdgo4R2DY5isyziCctnMFYailgePZtx1GhQYBmyRfUhnBDgO6q
HTe9ZFjl61BVtmvuoiCxyUvwYabNiGeVYL0ySY6oTDkiL9QyxJiDAngkXbn8jT5z
c3fQGPigrIihR3iQJiyI94BeX4Q+YPntgU2W6VVL7Sh8DU5HFb0=
=Z0yq
-END PGP SIGNATURE-

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC][Discussion] Harmonise "untyped" and "typed" properties

2023-11-23 Thread Rowan Tommins
On Thu, 23 Nov 2023 at 08:48, Nicolas Grekas 
wrote:

> Sorry this comes as a surprise to you but you're rewriting history here.
> The current behavior, the one that was fixed in that commit, matches how
> PHP behaved before typed properties, so this commit brought consistency.
>


The question of "what does __get do with a property that has been declared
but not assigned a value?" has no answer before PHP 7.4, because that
situation simply never happened. So there isn't really one answer to what
is "consistent".

If I understand rightly, your position, and Nikita's, is that the behaviour
should be consistent with the statement "if you have declared a property,
access doesn't trigger __get unless you explicitly call unset()". This is
what the change that slipped into 7.4.1 "fixed".

The reason it surprised me is that I expected it to be consistent with a
different statement: "if you have an __get method, this takes precedence
over 'undefined variable' notices/warnings/errors". That statement was true
in 7.3, and still true in the original implementation in 7.4.0 (including
"unitialized" alongside "undefined"), but was *broken* by the change in
7.4.1: now, the "uninitialized property" error takes precedence over __get
in the specific case of never having assigned a value.




> About the behavior, it's been in use for many years to build lazy proxies.
> I know two major use cases that leverage this powerful capability: Doctrine
> entities and Symfony lazy services. There are more as any code that
> leverages ocramius/proxy-manager relies on this.
>


Just to be clear, it is not the behaviour *after* calling unset which I am
concerned about, it is the behaviour *before* calling unset or assigning
any value. I was aware of the interaction with __get, but wrongly assumed
that the rule was simply "uninitialized properties trigger __get".




> About the vocabulary, the source tells us that "uninitialized" properties
> that are unset() become "undefined". I know that's not super accurate since
> a typed property is always defined semantically
>


Just "undefined" is not sufficiently unambiguous; you have to distinguish
four different states:

1) Never declared, or added dynamically and then unset
2) Declared without a type, then unset
3) Declared with a type, not yet assigned any value
4) Declared with a type, then unset

The messages presented to the user refer to both (1) and (2) as
"undefined", and both (3) and (4) as "uninitialized".  As it stands, the
RFC would replace all instances of (2) with (4), but that still leaves us
with two names for three states.



Claude Pache wrote:

> However, it is not a problem in practice, because users of classes
implementing (1) but not (2) do not unset declared properties, ever.

Nikita Popov wrote:

> ... and then forbid calling unset() on declared properties


Right now, unset() is also the only way to break a reference, other than
another assign-by-reference, so it's quite reasonable to write
"unset($this->foo)" instead of "$this->foo" to ensure a property is truly
reset to a known state. Maybe we need a new function or operator to
atomically break the reference and assign a new value, e.g.
unreference($this->foo, 42); or $this->foo := 42; to replace
unset($this->foo); $this->foo=42;


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Stephen Reay

> On 23 Nov 2023, at 17:21, Rowan Tommins  wrote:
> 
> On Thu, 23 Nov 2023 at 06:00, Stephen Reay  wrote:
> 
>> I'm disappointed to see yet again that there's this implied notion that
>> working with PHP in 2023 means "well surely you must be using composer",
>> which leads to "but composer..."  somehow being an accepted argument when
>> it comes to missing/incomplete builtin functionality.
>> 
> 
> 
> While I appreciate your point in the general case, in this particular
> thread, the mentions of Composer are really just examples, or can be
> reworded that way:
> 
> Functions lack autoloading, but in practice this isn't a big problem
> because you can just require_once a file defining them, and as long as
> OpCache is running there's very little performance penalty. If you're using
> a package manager or module loading system to integrate multiple
> autoloaders, it's generally easy to add one or more required files as part
> of the package / module config - *for example* Composer has a "files" array
> in each package's "autoload" config.
> 
> So the actual assumption is "surely you must be using OpCache", which
> unlike Composer is bundled with PHP.
> 
> Regards,
> -- 
> Rowan Tommins
> [IMSoP]


(Resending from list-address)

Hi Rowan,

Respectively, I disagree that it's "not a big problem" if your goal is to 
encourage people to use regular functions over classes with static methods.

"No autoloading" is clearly a well known barrier to the use of userland 
functions, and "rewriting 'use composer' to 'use require_once'" isn't a 
comparable workaround, as evidenced by:

- https://wiki.php.net/rfc/core-autoloading (from April 2023) paragraph 2 says:

> The need for such a feature seems very clear as users will create “helper” 
> classes with static methods to take advantage of autoloading via the class 
> autoloading mechanism.

An email earlier in this thread makes the same point (shiny gold sticker if you 
remember who wrote this):

> The only issue being that we don't have good autoloading support for such 
> functions, and that's a whole different problem...



> you can just require_once a file defining them,

To paraphrase a certain secret agent: Do you want people writing faux-namespace 
classes? Because this is how you get people writing faux-namespace classes.


> So the actual assumption is


No, the assumption was very clearly written:

> Autoloading is frankly mostly solved by using the `files` block in your 
> composer.json's autoload config, and then you don't need to care.

Saying "a package loader" instead of "composer" isn't any better really. 
Autoloading of classes in PHP doesn't require a "package loader" to work. PHP 
ships with a built in class autoloader function, and pretending that using 
'require_once' everywhere a function is used, is just as easy for the developer 
seem disingenuous to be honest.



Cheers


Stephen

Re: [PHP-DEV] RFC Proposal - static modifier for classes

2023-11-23 Thread Rowan Tommins
On Thu, 23 Nov 2023 at 06:00, Stephen Reay  wrote:

> I'm disappointed to see yet again that there's this implied notion that
> working with PHP in 2023 means "well surely you must be using composer",
> which leads to "but composer..."  somehow being an accepted argument when
> it comes to missing/incomplete builtin functionality.
>


While I appreciate your point in the general case, in this particular
thread, the mentions of Composer are really just examples, or can be
reworded that way:

Functions lack autoloading, but in practice this isn't a big problem
because you can just require_once a file defining them, and as long as
OpCache is running there's very little performance penalty. If you're using
a package manager or module loading system to integrate multiple
autoloaders, it's generally easy to add one or more required files as part
of the package / module config - *for example* Composer has a "files" array
in each package's "autoload" config.

So the actual assumption is "surely you must be using OpCache", which
unlike Composer is bundled with PHP.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] [RFC][Discussion] Harmonise "untyped" and "typed" properties

2023-11-23 Thread Claude Pache



> Le 23 nov. 2023 à 08:56, Rowan Tommins  a écrit :
> 
> On 23 November 2023 01:37:06 GMT, Claude Pache  wrote:
>> What you describe in the last sentence is what was initially designed and 
>> implemented by the RFC: https://wiki.php.net/rfc/typed_properties_v2 
>> (section Overloaded Properties).
>> 
>> However, it was later changed to the current semantics (unset() needed in 
>> order to trigger __get()) in https://github.com/php/php-src/pull/4974
> 
> 
> Good find. So not only is it not specified this way in the RFC, it actually 
> made it into a live release, then someone complained and we rushed out a more 
> complicated version "to avoid WTF". That's really unfortunate.
> 
> I'm not at all convinced by the argument in the linked bug report - whether 
> you get an error or an unexpected call to __get, the solution is to assign a 
> valid value to the property. And making the behaviour different after unset() 
> just hides the user's problem, which is that they didn't expect to *ever* 
> have a call to __get for that property.
> 
> But I guess I'm 4 years too late to make that case.
> 

Hi, 

I think that the legitimacy of the current behaviour is not something to be 
convinced by abstract reasoning like we are doing now (otherwise, it wouldn’t 
probably have waited a live release to be implemented in a rush), but something 
that can be understood only by considering the conflicting uses of  __get(), 
which leads to conflicting expectations, and how they managed to live together 
despite a fundamental contradiction:

1. __get() is used to implement virtual properties (as mentioned in the linked 
bug report). For this use case, access to a declared property should not call 
__get() (whose implementation may be hidden away in a superclass).

2. __get() is used to implement lazy properties. For this use case, access to 
an uninitialised (or unset, or undeclared) property should call __get().

The two expectations did live together as long as declared properties were also 
initialised (implicitly, to null). It is true that they are formally 
incompatible; when you say:

> And making the behaviour different after unset() just hides the user's 
> problem, which is that they didn't expect to *ever* have a call to __get for 
> that property.

you are referring to the expectation given by use case 1, which contradicts the 
expectation given by use case 2. However, it is not a problem in practice, 
because users of classes implementing (1) but not (2) do not unset declared 
properties, ever.

The conflict became evident with the advent of typed properties, which cannot 
be implicitly initialised to null in general. As both use cases are firmly 
rooted in practice, both should be taken in account. The current, cumbersome 
and unfortunate behaviour allows to keep sane semantics for those classes using 
bad practices (use case 1), while not invalidating naughty hacks used by other 
classes (use case 2).


—Claude

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC][Discussion] Harmonise "untyped" and "typed" properties

2023-11-23 Thread Nikita Popov
On Thu, Nov 23, 2023, at 09:48, Nicolas Grekas wrote:
> Hi Rowan,
> 
> Le jeu. 23 nov. 2023 à 08:56, Rowan Tommins  a
> écrit :
> 
> > On 23 November 2023 01:37:06 GMT, Claude Pache 
> > wrote:
> > >What you describe in the last sentence is what was initially designed and
> > implemented by the RFC: https://wiki.php.net/rfc/typed_properties_v2
> > (section Overloaded Properties).
> > >
> > >However, it was later changed to the current semantics (unset() needed in
> > order to trigger __get()) in https://github.com/php/php-src/pull/4974
> >
> >
> > Good find. So not only is it not specified this way in the RFC, it
> > actually made it into a live release, then someone complained and we rushed
> > out a more complicated version "to avoid WTF". That's really unfortunate.
> >
> > I'm not at all convinced by the argument in the linked bug report -
> > whether you get an error or an unexpected call to __get, the solution is to
> > assign a valid value to the property. And making the behaviour different
> > after unset() just hides the user's problem, which is that they didn't
> > expect to *ever* have a call to __get for that property.
> >
> > But I guess I'm 4 years too late to make that case
> >
> 
> Sorry this comes as a surprise to you but you're rewriting history here.
> The current behavior, the one that was fixed in that commit, matches how
> PHP behaved before typed properties, so this commit brought consistency.
> 
> About the behavior, it's been in use for many years to build lazy proxies.
> I know two major use cases that leverage this powerful capability: Doctrine
> entities and Symfony lazy services. There are more as any code that
> leverages ocramius/proxy-manager relies on this.
> 
> About the vocabulary, the source tells us that "uninitialized" properties
> that are unset() become "undefined". I know that's not super accurate since
> a typed property is always defined semantically, but that's nonetheless the
> flag that is used in the source. Maybe this could help with the RFC.

This. The lazy initialization use case is the only reason why we still allow 
declared properties to be unset at all.

Our long term plan was to find an alternative way to support lazy 
initialization for properties, and then forbid calling unset() on declared 
properties. However, we still don't have that alternative today.

Regards,
Nikita


Re: [PHP-DEV] Re: [RFC][Discussion] Harmonise "untyped" and "typed" properties

2023-11-23 Thread Nicolas Grekas
Hi Rowan,

Le jeu. 23 nov. 2023 à 08:56, Rowan Tommins  a
écrit :

> On 23 November 2023 01:37:06 GMT, Claude Pache 
> wrote:
> >What you describe in the last sentence is what was initially designed and
> implemented by the RFC: https://wiki.php.net/rfc/typed_properties_v2
> (section Overloaded Properties).
> >
> >However, it was later changed to the current semantics (unset() needed in
> order to trigger __get()) in https://github.com/php/php-src/pull/4974
>
>
> Good find. So not only is it not specified this way in the RFC, it
> actually made it into a live release, then someone complained and we rushed
> out a more complicated version "to avoid WTF". That's really unfortunate.
>
> I'm not at all convinced by the argument in the linked bug report -
> whether you get an error or an unexpected call to __get, the solution is to
> assign a valid value to the property. And making the behaviour different
> after unset() just hides the user's problem, which is that they didn't
> expect to *ever* have a call to __get for that property.
>
> But I guess I'm 4 years too late to make that case
>

Sorry this comes as a surprise to you but you're rewriting history here.
The current behavior, the one that was fixed in that commit, matches how
PHP behaved before typed properties, so this commit brought consistency.

About the behavior, it's been in use for many years to build lazy proxies.
I know two major use cases that leverage this powerful capability: Doctrine
entities and Symfony lazy services. There are more as any code that
leverages ocramius/proxy-manager relies on this.

About the vocabulary, the source tells us that "uninitialized" properties
that are unset() become "undefined". I know that's not super accurate since
a typed property is always defined semantically, but that's nonetheless the
flag that is used in the source. Maybe this could help with the RFC.

Cheers,
Nicolas


Re: [PHP-DEV] [RFC] [Discussion] Resource to object conversion

2023-11-23 Thread Robert Landers
On Wed, Nov 22, 2023 at 10:53 PM Deleu  wrote:
>
> On Wed, Nov 22, 2023 at 2:08 PM G. P. B.  wrote:
>
> > On Wed, 22 Nov 2023 at 07:36, Mike Schinkel  wrote:
> >
> > > On Nov 21, 2023 at 11:33 PM, >
> > wrote:
> > >
> > > What is the point of a major release if we cannot even do such a BC
> > break?
> > > We don't even know when PHP 9.0 is going to happen yet.
> > >
> > >
> > > I have been using Go for about four years now and it seems they have
> > > gotten the backward compatibility issue nailed, and that pays great
> > > dividends in developer confidence in the language, i.e.:
> > >
> > >
> > >
> > https://www.reddit.com/r/golang/comments/17v4xja/anyone_face_issues_when_updating_version_of_go/
> > >
> > > They recently explained in depth how they do it:
> > >
> > > https://go.dev/blog/compat
> > >
> > > Also see:
> > >
> > > https://thenewstack.io/how-golang-evolves-without-breaking-programs/
> > >
> > > Although Go is compiled and PHP is not, I think there still may be
> > > significant insight that can be gained for PHP by studying how Go is
> > > handling it and applying any lessons learned.
> > >
> >
> > Go is a "new" programming language, with its 1.0.0 version being from 2012.
> > It was also designed from the ground up.
> >
> > PHP on the other hand wasn't designed, but the language grew organically,
> > and is 28 years old.
> > Comparing it to Go, in my opinion, makes no sense.
> >
> > We should be comparing ourselves to languages of that age or older, the
> > most famous example being Python, which did a major BC break between its
> > version 2 and 3.
> > But Fortran, C, Perl (with Raku), and for sure others have all made changes
> > to the language, recent or not, that break compatibility.
> >
> > Go even has a cave out that they *may* release a Go 2 specification, which
> > does not guarantee any backwards compatibility with Go 1. [1]
> > Even if the current lead engineer says this is "never" going to happen, the
> > cave out still exists.
> >
> > More importantly, it is possible to write cross compatible code, even
> > without changing anything about is_resource(), if we convert streams to
> > opaque objects.
> > It might be tedious and one might need to have redundant instanceof checks
> > with is_resource() if one does not want to check for a false return, or
> > duplicate checks for closed resources.
> > But it is possible, which was *not* the case for Python 2 and 3 as it
> > changed fundamentally how strings behaved.
> >
> > Finally, I think people would have more confidence in the language if it
> > stopped coming with various foot guns included that need to be explicitly
> > kept in check by using external tools such as static analysis tools, or
> > code style tools.
> > And removing those, or making the language overall more coherent and
> > consistent, requires us to break backwards compatibility.
> >
> > Sincerely,
> >
> > Gina P. Banyard
> >
>
> I sympathise with both sides on this topic. As a Software Engineer, not
> breaking 10-30 years of BC promise is unsustainable, but as a PHP user BC
> breaks have a heavy impact on legacy codebase written 10~20 years ago.
>
> A lot of discussion has happened around this subject, but unfortunately no
> consensus is ever reached. I've talked about increasing the stability and
> the pool of maintainers by providing PHP Packages under PHP namespace (
> https://externals.io/message/120335#120354). There were a lot of
> discussions on language evolution and editions that ultimately didn't go
> much further.
>
> Given how much time has passed and how this subject is always present, I
> now look at this with the optics that both PHP internals devs and PHP users
> suffer from the same condition of dealing with legacy. Between 1990 up to
> 2010, give or take, the way software used to be built vastly differs from
> how software is built today and these old software can be very hard to
> decommission given their lack of automation tests and inability to be
> statically analysed. With today's practices, I believe it's easier to
> introduce BC breaks that affect software written after 2018. And since I
> believe that, it's a natural consequence for me to believe that if PHP
> introduced a new `declare(backward_compatibility=0)`, it could be used for
> users to signal to the engine that 1) we're writing this file after 2023
> and 2) we will cover this file with automation tests and/or static analysis
> tools. PHP Internals wouldn't need to make a huge big-bang BC break
> all-at-once. Every year new BC breaks could be introduced affecting only
> the "new engine version". The idea isn't to build several combination of
> "PHP Editions" as it was discussed in the past, but rather to have a
> consensus between PHP Internals and PHP Developers that a new Engine is
> constantly being developed, this engine will break compatibility with the
> past 20 years of PHP whenever PHP Internals manage to rebuild something
> (throughout multiple versions), a migration 

Re: [PHP-DEV] Re: [RFC][Discussion] Harmonise "untyped" and "typed" properties

2023-11-23 Thread Robert Landers
On Thu, Nov 23, 2023 at 8:56 AM Rowan Tommins  wrote:
>
> On 23 November 2023 01:37:06 GMT, Claude Pache  wrote:
> >What you describe in the last sentence is what was initially designed and 
> >implemented by the RFC: https://wiki.php.net/rfc/typed_properties_v2 
> >(section Overloaded Properties).
> >
> >However, it was later changed to the current semantics (unset() needed in 
> >order to trigger __get()) in https://github.com/php/php-src/pull/4974
>
>
> Good find. So not only is it not specified this way in the RFC, it actually 
> made it into a live release, then someone complained and we rushed out a more 
> complicated version "to avoid WTF". That's really unfortunate.
>
> I'm not at all convinced by the argument in the linked bug report - whether 
> you get an error or an unexpected call to __get, the solution is to assign a 
> valid value to the property. And making the behaviour different after unset() 
> just hides the user's problem, which is that they didn't expect to *ever* 
> have a call to __get for that property.
>
> But I guess I'm 4 years too late to make that case.
>
> Regards,
>
> --
> Rowan Tommins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>

Heh

> But I guess I'm 4 years too late to make that case.

4 years ago, I was using this behavior to write proxies that actually
called things over the network instead of the properties. I didn't
file that bug, but I probably would have filed something similar.
Nowadays, those proxies are dead as we long since generated code based
on interfaces (so they'll pass PHP type checks). I venture once we
have property hooks (assuming that is still a thing coming along),
this behavior can be removed completely as you can just use property
hooks instead of unset to call __get. I'm actually quite excited about
property hooks and hope they pass.

Personally, I haven't used this behavior since 7.4-ish, and I'd be
surprised to see it relied on in modern PHP: code generation is too
easy these days.

Robert Landers
Software Engineer
Utrecht NL

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php