Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Mike Schinkel
> On Jul 8, 2024, at 12:03 PM, Alexandru Pătrănescu  wrote:
> Managed to simplify it like this and I find it reasonable enough:
> function strtok2(string $string, ?string $token = null): string|false {
> static $tokenGenerator = null;
> if ($token) {
> $tokenGenerator = (function(string $characters) use ($string): 
> \Generator {
> $pos = 0;
> while (true) {
> $pos += \strspn($string, $characters, $pos);
> $len = \strcspn($string, $characters, $pos);
> if ($len === 0)
> return;
> $token = \substr($string, $pos, $len);
> $characters = yield $token;
> $pos += $len;
> }
> })($token);
> return $tokenGenerator->current() ?? false;
> }
> return $tokenGenerator?->send($string) ?? false;
> }
Hi Alexandru,

Great attempt. 

Unfortunately, however, it seems around 4.5 slower than strtok():

https://3v4l.org/7lXlM#v8.3.9 


> On Jul 8, 2024, at 2:23 PM, Claude Pache  wrote:
>> Le 6 juil. 2024 à 03:22, Mike Schinkel  a écrit :
>>> On Jul 5, 2024, at 1:11 PM, Claude Pache >> > wrote:
>>> * About strtok(): An exact replacement of `strtok()` that is reasonably 
>>> performant may be constructed with a sequence of strspn(...) and 
>>> strcspn(...) calls; here is an implementation using a generator in order to 
>>> keep the state: https://3v4l.org/926tC 
>> Well your modern_strtok() function is not an _exact_ replacement as it 
>> requires using a generator and thus forces the restructure of the code that 
>> calls strtok(). 
> 
> Yes, of course, I meant: it has the exact same semantics. You cannot have the 
> same API without keeping global state somewhere. If you use strtok() for what 
> it was meant for, you must restructure your code if you want to eliminate 
> hidden global state.

Hi Claude,

Agreed that semantics would have to change. Somewhat. 

The reason I made the comment was when I saw you stated it was an "exact 
replacement" I was concern people not paying close attention to the thread may 
see it and and think: "Oh, okay, there is an exact, drop-in replacement so I 
will vote to deprecate" when that same person might not vote to deprecate if 
they did not think there was an exact drop-in replacement. But I did my best to 
try to soften my words so it did not come off as accusatory and instead just 
matter-of-fact. If I failed at that, I apologize.

Anyway, your comments about needing to change the semantics got me thinking 
that addressing the concern when remediating code with strtok() could be much 
closer to a drop in replacement than a generator, assuming there is a will to 
actually tackle this. And this it small enough scope that I might even be able 
to learn enough C-for-PHP to create a pull request, if the idea were blessed.

Consider this simple code for using `strtok()`:

$token = strtok($content, ',');
while ($token !== false) {
$token = strtok (',');
}

Now compare to this potential enhancement:

$handle=strtok($content, ',', STRTOK_INIT);
do  {
$token = strtok($handle);
} while ($token !== false);
strtok($handle, STRTOK_RELEASE)

This would be much closer to a drop-in replacement, would allow PHP to keep the 
fast strtok() function, AND would address the reason for deprecation.

See any reason this approach would not be viable?

-Mike



Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Mike Schinkel
> On Jul 8, 2024, at 5:41 AM, Rowan Tommins [IMSoP]  
> wrote:
> I agree. I wrote most of the below a couple of days ago, but I don't think it 
> posted correctly, so apologies if some people see it twice: 
> 
> Autoloading is just a way to load files later, by the engine telling you when 
> a class is first needed. PHP does not, and should not, make any assumptions 
> about how files are laid out on disk; an autoloader doesn't actually need to 
> load any files at all, and if it does, it uses the same include or require 
> statements which have been in PHP for decades.

I think maybe you are replying to an earlier iteration by Michael Morris and 
have not seen the more recent iteration?  

There he explored adding an additional function to named `spl_autoload_map()` 
where the difference from `spl_autoload_register()` is that while the latter 
uses procedural code to determine what should be loaded the former would use a 
declarative map to determine what should be loaded. Then Composer and/or other 
tools could/would generate that map for PHP.

With an `spl_autoload_map()` PHP would not need to make any assumptions about 
how files are laid out on disk. Instead, PHP would use a schema of a 
yet-to-be-determined data representation format to discover  declaratively 
where files needed to be laid out on disk.

> Likewise, installing packages and defining version schemes is a completely 
> separate problem space that can probably be served by a few small tweaks to 
> Composer once the language provides the underlying functionality.
> 
> The core of the problem you seem to want to solve is this: if you have two 
> files foo_1.php and foo_2.php, which both define a class \Acme\Foo, how do 
> you load both of them, so that you end up with two differently named classes? 

That is one (1) of the core problems, yes.

> In JS, that's easy, because functions and object constructors (and "classes") 
> exist as objects you can pass around as variables, they don't need to know 
> their own name. In PHP, everything is based on the idea that functions and 
> classes are identified by name. You can rewrite the name in the class 
> declaration, and in direct references to it, but what about code using 
> ::class, or constructing a name and using "new $name", and so on? How will 
> tools using static analysis or reflection handle the renaming - e.g. how does 
> DI autowiring work if names are in some sense dynamic?

This is one of the unfortunate  aspects of PHP never makes types a first-class 
data type. But I digress.

> You've also got to work out what to do with transitive dependencies - if I 
> "import 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php' as 
> MyGuzzle", what namespace do all Guzzle's classes get rewritten into? What 
> about dependencies that are specifically intended to bridge between packages, 
> like PSR-7 RequestInterface?

Which is a direct result of the other problem you mentioned, i.e. IOW without 
attempting to address the prior problem this would not be a problem. #fwiw

> My advice: start with the assumption that something has already installed all 
> the files you need into an arbitrary directory structure, and something is 
> going to generate a bunch of statements to load them.

And this sentence is why I chose to reply to your message.  That assumption 
itself blocks the needs of user-managed apps.

(Did you happen to read my compare-and-contrast of user-managed vs. 
developer-managed apps from a few days ago?)

I feel it is likely those who have never worked professionally in PHP on 
user-managed apps like WordPress  — which I assume describes you accurately? — 
are probably just simply unaware of the problems that your assumptions cause 
for user-managed apps. And yes, some developers have no empathy for others who 
have different circumstances, but I honestly don't think you (Rowan) are in the 
category. 

Developer-managed apps use a build tool to put all vendor code in a single 
hierarchical set of namespaces and then load needed code from there. But that 
really does not work for user-managed apps like WordPress or Drupal.  Or at 
least not as they exist today, and probably not even if they were rearchitected 
for the start.

What works for user-managed apps is that each `add-on` (`plugin` in WordPress, 
`module` in Drupal) is stored in its own self-contained directory containing 
its own vendor code — where some of the vendor code could easily be duplicated 
in another add-on — and then the user-managed apps itself manages loading of 
all add-ons itself without a PSR-4 autoloader. As it exists, there are no 
standard for how add-on filenames and directory structures much be named nor 
how they are to load their dependencies so it is impossible for WordPress or 
Drupal to take on that role using PSR-4 for them. 

Michael Morris' idea to add an `spl_autoload_map()` function would allow 
addressing the needs of user-managed apps that treat each add-on as a 

Re: [PHP-DEV] [Initial Feedback] Typed Arrays

2024-07-08 Thread Richard Miles
Howdy people,

> On Jul 1, 2024, at 10:01 AM, Richard Miles  wrote:
> 
> Hey Larry, 
> 
>>> interface iArrayA ['a' => string ]
>>> interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’ 
>>> =>  SomeClass, ‘e’=>  iArrayA, ‘f’ => mixed ]
>>> $array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ];
> 
> I will start by advocating for how much cleaner this is from its objective 
> counterpart. It also aids in reusability.
> 
>> As Stephen already said, we have this already.  It's spelled like this:
>> 
>> class A {
>>  public function __construct(public string $a) {}
>> }
>> 
>> class B extends A {
>>  public function __construct(
>>public string $a, 
>>public string $b, 
>>public ?string $c,
>>public SomeClass $d,
>>public A $e,
>>mixed $f,
>>  ) {}
>> }
>> 
>> If you know the keys at code time, use a class, not an array.  Full stop, 
>> period, end of story.  Using an array as a record object in PHP >= 7 *is 
>> wrong*.  It's slower, more memory-intensive, less ergonomic, harder to 
>> debug, harder to statically analyze, harder to learn, harder to use.  If 
>> you're still doing that, it's past time to stop.  If your legacy application 
>> from the PHP 3 days is still doing that, it's past time to upgrade it.
> 
> 
> I feel this is a common misconception, or can you clarify this for me? 
> Array access is faster than object access. 
> I didn’t want to claim this without first running the benchmarks:
> 
> https://github.com/EFTEC/php-benchmarks/blob/master/benchmark_array_vs_object.php
> Good news is these benchmarks already exist! I just cloned this repo, 
> required the table builder, and profit.
> 
> composer require eftec/mapache-commons
> php benchmark_array_vs_object.php
> ...
> To save you the trouble you can refer to this Medium post:
> https://medium.com/cook-php/php-benchmark-time-fc19d813aa98
> 
> I figured you’d say something about the ’newest’ syntax so I added 
> class DummyClass
> {
> public function __construct(public $hello, public $second, public $third)
> {
> }
> }
> Thus, my results are as follows:
> 
> Array numeric no factory: 0%   baseline at 0.414 (mind 
> you im on an older MacBook)
> Array no factory  0.95%
> Array numeric factory:566.1%
> Array factory:650.07%
> Object Constructor:   609.03%
> Object no constructor 82.77%
> Object no constructor setter/getter:  2058.43%
> Object no constructor magic methods:  2273.91%
> Object no constructor stdClass:   112.53%
> 
> These were pretty consistent with the medium post.
> 
>> So new language features to make "misuse arrays as objects" easier are 
>> actively counter-productive.
>> 
>> A Dict / Hashmap is appropriate when you do *not* know the keys in advance, 
>> and thus cannot use a pre-defined object for it.  There are plenty of use 
>> cases for that, but in that case, all you need type-wise is the key type and 
>> value type, because all entries should be of the same type (give or take 
>> inheritance).  Mixing in random other types... is wrong.  That's the whole 
>> reason why people keep talking about collections/typed arrays/generics.
> 
> 
> 
> I think the point we can take away from this is that we could 
> speed arrays up even more if we make typed arrays stricly bound and not a 
> ‘hash’. 
> If we knew the keys in advance then in theroy we could make access based on 
> the 
> numeric value of that property in the interface definition.
> But as I keep saying this is worth investigating. 
> 
>> So the "array interface" syntax you keep posting is actively 
>> counter-productive.
> 
> I’m absolutely just trying to help while I have an abundance of free time. I 
> do admit to been
> a n00b sometimes. If something isn’t fast lets talk about how we might make 
> it faster. 
> I don’t think anyone disagrees with you in that this is a big undertaking 
> that shouldn’t be 
> taken lightly, but the community is strong and we’ll manage, even if at a 
> turtles pace :)
> 
> If my understanding above is correct then Larry’s message actually highlights 
> why we 
> should implement this feature. The community thinks objects are the way to 
> go, 
> since its the only way to go.
> 
> Best,
> Richard Miles

So since im not getting any feedback about the above, we can concrete the 
fastness of array over objects access.

I’m ready to make this Syntax Proposal RFC but still need RFC karma. 

Could someone please give my wiki.php.net  account 
access: wookieetyler

Best,
Richard Miles




Re: [PHP-DEV] [RFC][Discussion] Enhance JSON error messages

2024-07-08 Thread juan carlos morales
El El dom, 30 de jun. de 2024 a la(s) 11:52, juan carlos morales <
dev.juan.mora...@gmail.com> escribió:

>
>
> El El dom, 30 de jun. de 2024 a la(s) 11:15, Tim Düsterhus <
> t...@bastelstu.be> escribió:
>
>> Hi
>>
>> On 6/30/24 15:43, juan carlos morales wrote:
>> > So, what I see here in my shortexperiencie is an RFC with 3 Options
>>
>> That is not an option. Each RFC needs a clear primary vote that is a
>> "Yes/No" vote.
>>
>> > 1) Enhance the error message we already have
>> >
>> > 2) keep json_last_error_msg as it is and add a new function
>> > json_last_error_info function
>> >
>> > 3) both
>> >
>>
>> Adjusting error messages to make them better is not something that
>> requires an RFC. We do this all the time without an RFC. Here's an
>> example PR: https://github.com/php/php-src/pull/14496
>>
>> A new json_last_error_info() for easier programmatic access of the
>> important bits can still be considered, but would not need an RFC either
>> from my point of view. It's a simple and obvious addition. Those can be
>> done without an RFC, unless someone complains.
>>
>> Best regards
>> Tim Düsterhus
>
>
>>
> Ok , then, i will prepare 2 PRs and lets see what happens then.
>
> Thanks.
>
> I will let everybody know When ready
>


Hello again. Well seems there are different opinions about how to approach
this.

Everyone agrees that having better error messages is always welcome but at
the moment are different postures about having

1) enhanced error message
2) have a new function with better data

3) having both


At the moment the mentioned pull request has both

But i need to understand WHAT are we going to keep. And in case an RFC is
needed then i will make it.

Please advice

Thanks

>


Re: [PHP-DEV] pcntl_exec update proposal

2024-07-08 Thread Jakub Zelenka
On Mon, Jul 8, 2024 at 11:14 PM Dusk  wrote:

> On Jul 8, 2024, at 14:12, David CARLIER  wrote:
> > Through this existing PR, I wanted to know how would appeal to you
> adding some access restriction upon this existing call, using the open
> basedir check. So if the sysadmin wants the php user having no business
> calling `/bin` commands for examples would do that, bringing a bit more of
> the former suhosin "spirit" here.
>
> open_basedir is usually used in conjunction with the disable_functions
> directive to disable all functions which execute external commands,
> including pcntl_exec(). It's largely ineffective if the user can execute
> external commands, as those commands are not themselves restricted by
> open_basedir. (For instance, if PHP is allowed to execute /bin/cat, that
> can be used to read any file; if it can execute /bin/sh, that can execute
> any other command.) Additionally, if there *are* PHP installations which
> set open_basedir but do allow pcntl_exec(), this change would introduce a
> major incompatibility by disallowing all commands.
>
> If your goal is to restrict what external commands can be executed by a
> PHP script, any solution would need to be applied to all functions which
> can execute shell commands - exec(), shell_exec(), system(), passthru(),
> proc_open(), shell_exec(), popen(), not just pcntl_exec(). Keep in mind
> that some of these functions take a string as input which is parsed by the
> shell; implementing path-based restrictions may be very difficult to do in
> a general fashion.


 Completely agree with this. Using open_basedir would be just a hard to
catch BC break without any extra protection. So -1 on this proposal.

Cheers

Jakub


Re: [PHP-DEV] pcntl_exec update proposal

2024-07-08 Thread Dusk
On Jul 8, 2024, at 14:12, David CARLIER  wrote:
> Through this existing PR, I wanted to know how would appeal to you adding 
> some access restriction upon this existing call, using the open basedir 
> check. So if the sysadmin wants the php user having no business calling 
> `/bin` commands for examples would do that, bringing a bit more of the former 
> suhosin "spirit" here.

open_basedir is usually used in conjunction with the disable_functions 
directive to disable all functions which execute external commands, including 
pcntl_exec(). It's largely ineffective if the user can execute external 
commands, as those commands are not themselves restricted by open_basedir. (For 
instance, if PHP is allowed to execute /bin/cat, that can be used to read any 
file; if it can execute /bin/sh, that can execute any other command.) 
Additionally, if there *are* PHP installations which set open_basedir but do 
allow pcntl_exec(), this change would introduce a major incompatibility by 
disallowing all commands.

If your goal is to restrict what external commands can be executed by a PHP 
script, any solution would need to be applied to all functions which can 
execute shell commands - exec(), shell_exec(), system(), passthru(), 
proc_open(), shell_exec(), popen(), not just pcntl_exec(). Keep in mind that 
some of these functions take a string as input which is parsed by the shell; 
implementing path-based restrictions may be very difficult to do in a general 
fashion.

[PHP-DEV] Re: [RFC] Static class

2024-07-08 Thread Bilge

On 07/07/2024 21:08, Bilge wrote:

On 24/06/2024 00:10, Bilge wrote:

Hi Internals!
I am excited to announce the final implementation for Static Class is 
ready for review at  and 
includes a brief summary of the key semantics of the feature.


Furthermore, the 1.3 (presumed) final version of the RFC is now 
published at .


Naturally, if there are any further weighty comments or criticisms to 
be levied against either one of these, they may still be subject to 
changes as appropriate.


For those of you (not) following along at home, a quick update:

After consulting with my Design Council (not a design by committee BTW), 
we agreed to release the restriction on `abstract static`. The RFC has 
been updated to 1.4 and the PR has been updated in kind to allow 
abstract static classes, since abstract static methods are already 
present in PHP and to forbid them in the context of static classes would 
be to forgo our fundamental design razor.



I expect to announce the vote to start very soon.
In light of this last-minute change, voting will be postponed until at 
least next week, to give everyone some time to catch up.


Kind regards,
Bilge


[PHP-DEV] pcntl_exec update proposal

2024-07-08 Thread David CARLIER
Hi,

Through this existing PR , I
wanted to know how would appeal to you adding some access restriction upon
this existing call, using the open basedir check. So if the sysadmin wants
the php user having no business calling `/bin` commands for examples would
do that, bringing a bit more of the former suhosin "spirit" here.

Regards.


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Jordan LeDoux
On Mon, Jul 8, 2024 at 2:42 AM Rowan Tommins [IMSoP] 
wrote:

>
>
> On 8 July 2024 04:25:45 CEST, Jordan LeDoux 
> wrote:
> >I think it's strange that this discussion has driven deep down the tangent
> >of versioning...
> [...]
> >Things like separating global scope between importer and importee, managed
> >visibility of symbols and exports from modules/packages, allowing for
> >separate autoloaders for things which are called or included via an
> import,
> >etc. Those are the things that the language itself can do.
> >
> >All this other stuff feels like a distraction.
>
> I agree. I wrote most of the below a couple of days ago, but I don't think
> it posted correctly, so apologies if some people see it twice:
>
> Autoloading is just a way to load files later, by the engine telling you
> when a class is first needed. PHP does not, and should not, make any
> assumptions about how files are laid out on disk; an autoloader doesn't
> actually need to load any files at all, and if it does, it uses the same
> include or require statements which have been in PHP for decades.
>
> Likewise, installing packages and defining version schemes is a completely
> separate problem space that can probably be served by a few small tweaks to
> Composer once the language provides the underlying functionality.
>
> The core of the problem you seem to want to solve is this: if you have two
> files foo_1.php and foo_2.php, which both define a class \Acme\Foo, how do
> you load both of them, so that you end up with two differently named
> classes?
>
> In JS, that's easy, because functions and object constructors (and
> "classes") exist as objects you can pass around as variables, they don't
> need to know their own name. In PHP, everything is based on the idea that
> functions and classes are identified by name. You can rewrite the name in
> the class declaration, and in direct references to it, but what about code
> using ::class, or constructing a name and using "new $name", and so on? How
> will tools using static analysis or reflection handle the renaming - e.g.
> how does DI autowiring work if names are in some sense dynamic?
>
> You've also got to work out what to do with transitive dependencies - if I
> "import 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php'
> as MyGuzzle", what namespace do all Guzzle's classes get rewritten into?
> What about dependencies that are specifically intended to bridge between
> packages, like PSR-7 RequestInterface?
>
> My advice: start with the assumption that something has already installed
> all the files you need into an arbitrary directory structure, and something
> is going to generate a bunch of statements to load them. What happens next,
> in the language itself, to make them live side by side without breaking? If
> we get a solid solution to that (which I'm skeptical of), we can discuss
> how Composer, or the WordPress plugin installer, would generate whatever
> include/import/alias/rewrite statements we end up creating.
>
> Regards,
> --
> Rowan Tommins
> [IMSoP]
> Rowan Tommins
> [IMSoP]
>

I think it could be done somewhat simply (relative to the other things that
have been discussed) if the engine reserved a specific namespace for
imported symbols internally. Something like:

`\__Imported\MyImportStatement`

Where the `\__Imported` namespace is reserved and throws a parser error if
it occurs in code anywhere, and `MyImportStatement` corresponds to an
application importing the code using something like `import MyPackage as
MyImportStatement;`

Then, all symbols which are loaded into the global space as a result of the
import are actually rewritten into the hidden namespace the engine actually
uses under the hood, and any uses from the import statement in the
application code which has the import would reference the symbols in the
prefixed namespace.

This would not be trivial however. The engine code which supports this
would need to keep track of a kind of "context" for each file, based on
what namespace the file was included from. For instance, if an autoload
occurs inside the package that was loaded into `MyImportStatement`, the
engine would need to be aware that the code being executed is defined in
that namespace, REGARDLESS of whether it was a class, function, or
statement, and load ALL symbols that are created as a result into the
rewritten namespace. It would also need to translate in the other direction
for `use` statements inside the package, since it would not know ahead of
time what rewritten namespace it would actually be loaded in.

However, this is the simplest solution I see that doesn't involve writing a
second PHP engine just for this sort of thing.

Jordan

PS: For those unaware, for each "symbol" (something that has a unique
referenceable name in the code, roughly), there is at least one name that
refers to ONLY that thing internally. (I'm fairly certain that there are NO
situations where one name can refer to two things at all, but I am not

Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Claude Pache
Le 6 juil. 2024 à 03:22, Mike Schinkel  a écrit :On Jul 5, 2024, at 1:11 PM, Claude Pache  wrote:Le 25 juin 2024 à 16:36, Gina P. Banyard  a écrit :https://wiki.php.net/rfc/deprecations_php_8_4* About strtok(): An exact replacement of `strtok()` that is reasonably performant may be constructed with a sequence of strspn(...) and strcspn(...) calls; here is an implementation using a generator in order to keep the state: https://3v4l.org/926tCWell your modern_strtok() function is not an _exact_ replacement as it requires using a generator and thus forces the restructure of the code that calls strtok(). Yes, of course, I meant: it has the exact same semantics. You cannot have the same API without keeping global state somewhere. If you use strtok() for what it was meant for, you must restructure your code if you want to eliminate hidden global state.—Claude 

Re: [PHP-DEV] [RFC] Static class

2024-07-08 Thread Bilge

On 08/07/2024 15:13, Alexandru Pătrănescu wrote:
But I understand that once a class is static, all the chain of 
inheritance should be made of static classes, going up or down (and I 
would also think we can add interfaces and traits.).

Correct.

If interfaces are not included, do we allow implementing an interface?

Yes.
If we allow implementing an interface, should that interface contain 
only static members?
Yes. You can technically implement an interface that has instance 
methods, but you will either: get a compile-time error that you didn't 
implement the instance method, or a compile-time error that you didn't 
mark the (instance) method as static in a static class. So although you 
won't get an error about implementing the interface itself, you will be 
forced to not implement an interface containing any instance methods in 
a static class, by one of those two (somewhat indirect) errors.

Same for traits.

Yes
For completeness, if we think that the static keyword on a class-level 
entity means that it will allow only static members on that entity, 
all class-level entities should be able to be marked as "static".:


I understand that sentiment, however I'm still not going to entertain it 
right now because this RFC seems to have a tenuous chance of passing at 
best. I should think we will be lucky to get 50% of the vote, let alone 
the 66% required to pass, and any further (unnecessary) language 
changes, such as introducing `static interface` or `static trait`s will 
probably lower those odds. I'm sorry it's like that, but that's how the 
landscape looks to me. But not to be too disheartened; both of those 
things can be trivially added in a follow-up PR if there is a strong 
desire. That is, accepting this RFC in no way precludes the possibility 
of going down that road later.


Cheers,
Bilge


Re: [PHP-DEV] [RFC] [Discussion] Add WHATWG compliant URL parsing API

2024-07-08 Thread Lanre
On Fri, Jun 28, 2024 at 3:38 PM Máté Kocsis  wrote:

> Hi Everyone,
>
> I've been working on a new RFC for a while now, and time has come to
> present it to a wider audience.
>
> Last year, I learnt that PHP doesn't have built-in support for parsing
> URLs according to any well established standards (RFC 1738 or the WHATWG
> URL living standard), since the parse_url() function is optimized for
> performance instead of correctness.
>
> In order to improve compatibility with external tools consuming URLs (like
> browsers), my new RFC would add a WHATWG compliant URL parser functionality
> to the standard library. The API itself is not final by any means, the RFC
> only represents how I imagined it first.
>
> You can find the RFC at the following link:
> https://wiki.php.net/rfc/url_parsing_api
>
> Regards,
> Máté
>
>
I was exploring wrapping ada_url for PHP (
https://github.com/lnear-dev/ada-url). It works, but it's a bit slower,
likely due to the implementation of the objects. I was planning to embed
the zvals directly in the object, similar to PhpToken, but I haven't had
the chance and don't really need it anymore. Shouldn't be too much work to
clean it up though


Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Alexandru Pătrănescu
On Mon, Jul 8, 2024 at 6:43 PM Alexandru Pătrănescu 
wrote:

>
> I'm hoping this can be simplified further, but to get to the point, I also
> think we should have a userland replacement suggestion in the RFC.
>
>
Managed to simplify it like this and I find it reasonable enough:

function strtok2(string $string, ?string $token = null): string|false {
static $tokenGenerator = null;
if ($token) {
$tokenGenerator = (function(string $characters) use ($string):
\Generator {
$pos = 0;
while (true) {
$pos += \strspn($string, $characters, $pos);
$len = \strcspn($string, $characters, $pos);
if ($len === 0)
return;
$token = \substr($string, $pos, $len);
$characters = yield $token;
$pos += $len;
}
})($token);
return $tokenGenerator->current() ?? false;
}
return $tokenGenerator?->send($string) ?? false;
}

Alex


Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Alexandru Pătrănescu
On Sat, Jul 6, 2024 at 4:25 AM Mike Schinkel  wrote:

>
> On Jul 5, 2024, at 1:11 PM, Claude Pache  wrote:
>
> Le 25 juin 2024 à 16:36, Gina P. Banyard  a écrit :
> https://wiki.php.net/rfc/deprecations_php_8_4
>
>
> * About strtok(): An exact replacement of `strtok()` that is reasonably
> performant may be constructed with a sequence of strspn(...) and
> strcspn(...) calls; here is an implementation using a generator in order to
> keep the state: https://3v4l.org/926tC
>
>
> Well your modern_strtok() function is not an _exact_ replacement as it
> requires using a generator and thus forces the restructure of the code that
> calls strtok().
>
> So not a drop-in — search-and-replace — replacement for strtok(). But it
> is a reasonable replacement for those who are motivated to do the
> restructure.
>
>
>
I looked a bit into this and, taking the idea further, let's also consider
defining a StringTokenizer class:

class StringTokenizer {
private \Generator $tokenGenerator;
public function __construct(public readonly string $string) {
}

public function nextToken(string $characters): string|null {
if (!isset($this->tokenGenerator)) {
$this->tokenGenerator = $this->generator($characters);
return $this->tokenGenerator->current();
}
return $this->tokenGenerator->send($characters);
}

private function generator(string $characters): \Generator {
$pos = 0;
while (true) {
$pos += \strspn($this->string, $characters, $pos);
$len = \strcspn($this->string, $characters, $pos);
if (!$len)
return;
$token = \substr($this->string, $pos, $len);
$characters = yield $token;
$pos += $len;
}
}
}


and if we define a wrapper function:

function strtok2(string $string, ?string $token = null): string|false {
static $tokenizer = null;
if ($token) {
$tokenizer = new StringTokenizer($string);
return $tokenizer->nextToken($token) ?? false;
}
if (!isset($tokenizer)) {
return false;
}
return $tokenizer->nextToken($string) ?? false;
}


I think that this might be a perfect replacement.

If we want, we could implement the StringTokenizer in the core, so that it
would be a nice replacement.

If we don't want to do this at this stage, we can completely avoid the
class for now, using an anonymous class:

function strtok2(string $string, ?string $token = null): string|false {
static $tokenizer = null;
if ($token) {
$tokenizer = new class($string)  {
private \Generator $tokenGenerator;
public function __construct(public readonly string $string) {
}
public function nextToken(string $characters): string|null {
if (!isset($this->tokenGenerator)) {
$this->tokenGenerator = $this->generator($characters);
return $this->tokenGenerator->current();
}
return $this->tokenGenerator->send($characters);
}
private function generator(string $characters): \Generator {
$pos = 0;
while (true) {
$pos += \strspn($this->string, $characters, $pos);
$len = \strcspn($this->string, $characters, $pos);
if (!$len)
return;
$token = \substr($this->string, $pos, $len);
$characters = yield $token;
$pos += $len;
}
}
};
return $tokenizer->nextToken($token) ?? false;
}
if (!isset($tokenizer)) {
return false;
}
return $tokenizer->nextToken($string) ?? false;
}

What do you think?
Mike, would you mind benchmarking this as well to make sure it's similarly
fast with the initial suggestion from Claude?

I'm hoping this can be simplified further, but to get to the point, I also
think we should have a userland replacement suggestion in the RFC.
And, ideally, we should have a class that can replace it in PHP 9.0,
similar to the above StringTokenizer.

Regards,
Alex


Re: [PHP-DEV] [RFC] Static class

2024-07-08 Thread Alexandru Pătrănescu
On Mon, Jul 8, 2024 at 3:22 PM Bilge  wrote:

> On 08/07/2024 12:48, Alexandru Pătrănescu wrote:
>
>
> If we support inheritance for static classes, we should allow static on
> both interface and abstract classes.
>
> What do you mean by *allow static on [...] interface*? Are you saying you
> also expect to see `static interface` support? (This is something I am
> absolutely not considering at this time, without a very good argument in
> favour of).
>
>
> For completeness, if we think that the static keyword on a class-level
entity means that it will allow only static members on that entity, all
class-level entities should be able to be marked as "static".:
Yes, it might not be really required, but I can see how it would help
define a static interface that can only be implemented by a static class.

Reading on :
> A static class only permits extending a parent class that is also marked
static. A non-static class cannot extend a static class.

The wording is a bit confusing for me.
But I understand that once a class is static, all the chain of inheritance
should be made of static classes, going up or down (and I would also think
we can add interfaces and traits.).
If interfaces are not included, do we allow implementing an interface? If
we allow implementing an interface, should that interface contain only
static members? Same for traits.

Alex


Re: [PHP-DEV] [RFC] Static class

2024-07-08 Thread Bilge

On 08/07/2024 12:48, Alexandru Pătrănescu wrote:


On Mon, Jul 8, 2024 at 1:12 PM Stephen Reay  
wrote:




So really the question should be: why do you feel the need to
*disallow* a combination that has no technical issues, and works
already? If you're going to disallow abstract why not disallow any
class inheritance at all? Because that's what abstract relates to:
class hierarchy. Why remove some support but keep the rest?

The reason to remove abstract was because it was thought `static` means 
the same as `abstract`. That is, neither can be instantiated. However, 
clearly that is short-sighted as Alex's example proves. That is, we 
cannot simply replace `abstract` with `static` because that precludes us 
from having an incomplete definition where some methods are still not 
yet implemented. As such, I am quite convinced by your arguments, and 
will make the change to add `abstract` support back in; mainly because 
removing abstract support defies our fundamental razor (it's something 
we can already do).


If we support inheritance for static classes, we should allow static 
on both interface and abstract classes.


What do you mean by /allow static on [...] interface/? Are you saying 
you also expect to see `static interface` support? (This is something I 
am absolutely not considering at this time, without a very good argument 
in favour of).


Cheers,
Bilge


Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Niels Dossche
On 08/07/2024 05:04, Juliette Reinders Folmer wrote:
> I'd suggest for an impact analysis/expected impact statement to be added to 
> the following deprecation proposals:
> (...)
> 
> And to a lesser degree for:
> (...)
> * Deprecate passing incorrect data types for options to ext/hash functions

Since this is my proposal, I went ahead and performed a simple test and found 
that at least the top 2K packages (likely) don't have any impact of this.
I added the full explanation for the impact of this in the RFC text.

Kind regards
Niels


Re: [PHP-DEV] [RFC] Static class

2024-07-08 Thread Alexandru Pătrănescu
On Mon, Jul 8, 2024 at 1:12 PM Stephen Reay 
wrote:

>
>
> So really the question should be: why do you feel the need to *disallow* a
> combination that has no technical issues, and works already? If you're
> going to disallow abstract why not disallow any class inheritance at all?
> Because that's what abstract relates to: class hierarchy. Why remove some
> support but keep the rest?
>
>
>
Exactly what I wanted to say for this topic. Have a look at this example
that could be very similar in production code in some systems:



Re: [PHP-DEV] [RFC] Deprecations for PHP 8.4

2024-07-08 Thread Niels Dossche
On 08/07/2024 01:12, Gina P. Banyard wrote:
> On Friday, 5 July 2024 at 18:11, Claude Pache  wrote:
>> * I don’t see the point of deprecating DOMImplementation::getFeature() 
>> instead of just removing it? “DOMImplementation::getFeature() is deprecated, 
>> throw manually an Error exception instead.”
> 
> Just removing it makes sense, I'll talk to Niels about it, to change what the 
> vote is actually about.

The reason I put it on deprecation instead of removal was because I thought we 
always had to go through deprecation first before we could remove things.
Gina and I talked and we concluded that we could just remove it indeed, as this 
method always threw an exception anyway due to it being unimplemented.
I'll update the RFC.

Kind regards
Niels


Re: [PHP-DEV] [RFC] Static class

2024-07-08 Thread Stephen Reay


> On 8 Jul 2024, at 14:42, Bilge  wrote:
> 
> On 08/07/2024 01:16, Mike Schinkel wrote:
>> Congrats on getting it to this point.
> Thanks. It's been an adventure :^)
> 
>> I support this in all but the RFC's restriction on `abstract`, as I have 
>> previously mentioned on the list.
> I must have missed a key point here. Let's suppose we're writing a follow-up 
> RFC to permit `static` and `abstract` together. In as few sentences as 
> possible, what is the benefit conferred to the developer?
> 
> Cheers,
> Bilge
> 


Hi,

I'm sure Mike has his own answer for this, but I'm going to reiterate mine 
again, because it apparently wasn't really understood the first several times I 
said it:

The reasons are two fold:

(a) so that a static class can declare abstract methods either explicitly or 
implicitly (by implementing an interface without providing concrete 
implementations of all methods in the interface)

(b) to keep consistency with regular classes. 


The suggested static keyword for classes doesn't introduce any additional 
behaviour that isn't already possible, it just prevents some uses without the 
need for boilerplate - the main purpose is to "signify developer intent".

The actual behaviour applied to "static" classes is already possible in PHP by 
simply omitting any instance members and declaring a private constructor. These 
classes work fine with the abstract keyword. There are no ambiguities, no 
gotchas or foot guns, there is nothing confusing. It's a standard part of class 
hierarchy.


So really the question should be: why do you feel the need to *disallow* a 
combination that has no technical issues, and works already? If you're going to 
disallow abstract why not disallow any class inheritance at all? Because that's 
what abstract relates to: class hierarchy. Why remove some support but keep the 
rest?




Cheers

Stephen 





Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Rowan Tommins [IMSoP]



On 8 July 2024 04:25:45 CEST, Jordan LeDoux  wrote:
>I think it's strange that this discussion has driven deep down the tangent
>of versioning...
[...]
>Things like separating global scope between importer and importee, managed
>visibility of symbols and exports from modules/packages, allowing for
>separate autoloaders for things which are called or included via an import,
>etc. Those are the things that the language itself can do.
>
>All this other stuff feels like a distraction.

I agree. I wrote most of the below a couple of days ago, but I don't think it 
posted correctly, so apologies if some people see it twice: 

Autoloading is just a way to load files later, by the engine telling you when a 
class is first needed. PHP does not, and should not, make any assumptions about 
how files are laid out on disk; an autoloader doesn't actually need to load any 
files at all, and if it does, it uses the same include or require statements 
which have been in PHP for decades.

Likewise, installing packages and defining version schemes is a completely 
separate problem space that can probably be served by a few small tweaks to 
Composer once the language provides the underlying functionality.

The core of the problem you seem to want to solve is this: if you have two 
files foo_1.php and foo_2.php, which both define a class \Acme\Foo, how do you 
load both of them, so that you end up with two differently named classes? 

In JS, that's easy, because functions and object constructors (and "classes") 
exist as objects you can pass around as variables, they don't need to know 
their own name. In PHP, everything is based on the idea that functions and 
classes are identified by name. You can rewrite the name in the class 
declaration, and in direct references to it, but what about code using ::class, 
or constructing a name and using "new $name", and so on? How will tools using 
static analysis or reflection handle the renaming - e.g. how does DI autowiring 
work if names are in some sense dynamic?

You've also got to work out what to do with transitive dependencies - if I 
"import 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php' as 
MyGuzzle", what namespace do all Guzzle's classes get rewritten into? What 
about dependencies that are specifically intended to bridge between packages, 
like PSR-7 RequestInterface?

My advice: start with the assumption that something has already installed all 
the files you need into an arbitrary directory structure, and something is 
going to generate a bunch of statements to load them. What happens next, in the 
language itself, to make them live side by side without breaking? If we get a 
solid solution to that (which I'm skeptical of), we can discuss how Composer, 
or the WordPress plugin installer, would generate whatever 
include/import/alias/rewrite statements we end up creating.

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


Re: [PHP-DEV] [RFC] [Discussion] Allow int type argument to BCMath function

2024-07-08 Thread Jordan LeDoux
On Sun, Jul 7, 2024 at 8:19 PM Saki Takamachi  wrote:

> Hi Juliette,
>
> > Hi Saki,
> >
> > Just wondering: why `int|string` instead of `float|string` ?
> > In my experience, floats are the more pertinent type for which to use
> the BCMath extension.
> >
> > Smile,
> > Juliette
>
> Since floating point numbers always contain a certain amount of error, I
> believe that they are not suitable as arguments for BCMath.
>
> For example, 0.285 becomes 0.284999... in floating point. From the
> perspective of arbitrary precision math, there is no universally agreeable
> way to properly handle values like this: there will always be people who
> want to treat it as 0.285, and people who want to treat it as 0.284999
>
> Therefore, I believe BCMath should not accept floats as arguments.
>
> Regards,
>
> Saki


I suspected the same thing when I was doing my arbitrary precision library,
but I actually have yet to find a test case in all my unit tests where this
happens when converting to a string. You can see this here:

https://3v4l.org/Ud8Cn

Jordan


Re: [PHP-DEV] [RFC][Vote] RFC1867 for non-POST HTTP verbs

2024-07-08 Thread Valentin Udaltsov
On Wed, 24 Jan 2024 г. at 14:01, Ilija Tovilo 
wrote:

> Hi Sara
>
> Thank you for your feedback.
>
> On Tue, Jan 23, 2024 at 8:41 PM Sara Golemon  wrote:
> >
> > On Mon, Jan 22, 2024 at 1:24 AM Ilija Tovilo 
> wrote:
> >
> > > I started the vote on the "RFC1867 for non-POST HTTP verbs" RFC.
> > > https://wiki.php.net/rfc/rfc1867-non-post
> > >
> >
> > 1/ This function reaches into the SAPI to pull out the "special" body
> > data.  That's great, but what about uses where providing an input string
> > makes sense.  For that, and for point 2, I'd suggest
> > `http_parse_query(string $query, ?array $options = null): array|object`.
>
> The RFC previously included support for the $input_stream variable
> (string is not very appropriate for multipart because the input may be
> arbitrarily large). The implementation wasn't complex, but it required
> duplication of all the reads to support both a direct read from the
> SAPI and a read from the stream, duplication of some limit checks and
> special passing of the streams to avoid SAPI API breakage.
>
> As for actual use cases, I found limited evidence that this function
> would be useful for worker-based services _right now_. Most services
> handle request parsing in some other layer. For example, RoadRunner
> has a Go server that stores the file to disk, and then just passes the
> appropriate path to PHP in the $_FILES array. It seems to me that a
> custom input would be useful exclusively for a web server written in
> PHP. The one that was pointed out to me (AdapterMan) handles requests
> as strings, which would not scale for multipart requests.
>
> I don't mind getting back to this if AdapterMan rewrites request
> handling to use streams. Adding back the $input_stream parameter can
> be done with no BC breaks. But for the time being, I don't think the
> motivation is big enough to justify the added complexity.
>
> Additionally, because multipart is used exclusively as a request
> content type, it isn't useful in a general sense either, because a PHP
> request will typically only receive one request (but potentially
> multiple responses, in case it communicates with other servers).
>
> > 2/ `request_` represents a new psuedo-namespace, functions are easier to
> > find and associate if we keep them grouped.  I recommend 'http_` because
> it
> > compliments the very related function `http_build_query()`, and for the
> > version of this function which refers directly to the request:
> > `http_parse_request(?array $options = null) : array|object`.
>
> That's fair. If the name bothers you I can create an amendment RFC. I
> think http_parse_body() would be a bit more appropriate, because
> request implies more than just the body.
>
> Ilija
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>
Hi, Ilija!

I think that removing $input_stream should be revisited.
The problem with Go/RoadRunner/PHP is that PHP parses `a[]=1[]=2[]=3`
differently from other languages.

PHP: [a => [1,2,3]]
GO: map[a[]:[1 2 3]]

See https://github.com/roadrunner-server/roadrunner/issues/1696 and
https://github.com/roadrunner-server/roadrunner/issues/1963#issuecomment-2209403600
for more details.

To mitigate this issue, RoadRunner allows raw body on the PHP side
by setting `http.raw_body = true`. Here's where request_parse_body would be
useful if it accepts other streams.
--
Best regards,
Valentin


Re: [PHP-DEV] [RFC] [Discussion] Add WHATWG compliant URL parsing API

2024-07-08 Thread Nicolas Grekas
Hi Maté,

Fantastic RFC :)

Le dim. 7 juil. 2024 à 11:17, Máté Kocsis  a écrit :

> Hi Ignace,
>
> As far as I understand it, if this RFC were to pass as is it will model
>> PHP URLs to the WHATWG specification. While this specification is
>> getting a lot of traction lately I believe it will restrict URL usage in
>> PHP instead of making developer life easier. While PHP started as a
>> "web" language it is first and foremost a server side general purpose
>> language. The WHATWG spec on the other hand is created by browsers
>> vendors and is geared toward browsers (client side) and because of
>> browsers history it restricts by design a lot of what PHP developers can
>> currently do using `parse_url`. In my view the `Url` class in
>> PHP should allow dealing with any IANA registered scheme, which is not
>> the case for the WHATWG specification.
>
>
> Supporting IANA registered schemes is a valid request, and is definitely
> useful.
> However, I think this feature is not strictly required to have in the
> current RFC.
> Anyone we needs to support features that are not offered by the WHATWG
> standard can still rely on parse_url().
>

If I may, parse_url is showing its age and issues like
https://github.com/php/php-src/issues/12703 make it unreliable. We need an
escape plan from it.

FYI, we're discussing whether a Uri component should make it in Symfony
precisely to work around parse_url's issues in
https://github.com/php/php-src/issues/12703
Your RFC would be the perfect answer to this discussion but IRI would need
to be part of it.

I agree with everything Ignace said. Supporting RFC3986 from day-1 would be
absolutely great!

Note that we use parse_url for http-URLs, but also to parse DSNs like
redis://localhost and the likes.


> And of course, we can (and should) add
> support for other standards later. If we wanted to do all these in the same
> RFC, then the scope of the RFC would become way too large IMO. That's why I
> opt for incremental improvements.
>
> Besides, I fail to see why a WHATWG compliant parser wouldn't be useful in
> PHP:
> yes, PHP is server side, but it still interacts with browsers very
> heavily. Among other
> use-cases I cannot yet image, the major one is most likely validating
> user-supplied URLs
> for opening in the browser. As far as I see the situation, currently there
> is no acceptably
> reliable possibility to decide whether a URL can be opened in browsers or
> not.
>
> - parse_url and parse_str predates RFC3986
>> - URLSearchParans was ratified before PSR-7 BUT the first implementation
>> landed a year AFTER PSR-7 was released and already implemented.
>>
>
> Thank you for the historical context!
>
> Based on your and others' feedback, it has now become clear for me that
> parse_url()
> is still useful and ext/url needs quite some additional capabilities until
> this function
> really becomes superfluous. That's why it now seems to me that the
> behavior of
> parse_url() could be leveraged in ext/url so that it would work with a
> Url/Url class (e.g.
> we had a PhpUrlParser class extending the Url/UrlParser, or a
> Url\Url::fromPhpParser()
> method, depending on which object model we choose. Of course the names are
> TBD).
>
> For all these arguments I would keep the proposed `Url` free of all
>> these concerns and lean toward a nullable string for the query string
>> representation. And defer this debate to its own RFC regarding query
>> string parsing handling in PHP.
>>
>
> My WIP implementation still uses nullable properties and return types. I
> only changed those
> when I wrote the RFC. Since I see that PSR-7 compatibility is very low
> prio for everyone
> involved in the discussion, then I think making these types nullable is
> fine. It was neither my
> top prio, but somewhere I had to start the object design, so I went with
> this.
>
> Again, thank you for your constructive criticism.
>
> Regards,
> Máté
>


Re: [PHP-DEV] [RFC] Static class

2024-07-08 Thread Bilge

On 08/07/2024 01:16, Mike Schinkel wrote:


Congrats on getting it to this point.


Thanks. It's been an adventure :^)


I support this in all but the RFC's restriction on `abstract`, as
I have previously mentioned on the list.

I must have missed a key point here. Let's suppose we're writing a 
follow-up RFC to permit `static` and `abstract` together. In as few 
sentences as possible, what is the benefit conferred to the developer?


Cheers,
Bilge