Re: [PHP-DEV] [RFC]

2020-02-13 Thread Manuel Canga
On Fri, 14 Feb 2020 at 01:39, Mike Schinkel  wrote:

> > On Feb 13, 2020, at 7:24 PM, Rowan Tommins 
> wrote:
> >
> > An idea I had earlier which might solve some of them is if what was
> returned was not a normal Closure instance, but a new class like
> FunctionReference. It could then "remember" the name of the function
> wrapped, and implement __toString, Serializable, etc. It could inherit from
> Closure, so instanceof checks would work, and bindTo would return a normal
> Closure. I'm sure there's downsides I haven't thought of yet, but I thought
> I'd throw the idea into the mix.
>
> I thought about that too, and mentioned it yesterday in a reply[1] to you
> on this list.
>
> Here is the link to the Gist with the hypothetical code using such a
> concept:
>
> - https://gist.github.com/mikeschinkel/78684d708358e1d101e319c7a2fdef9c
>
> -Mike
>
>
> [1] https://www.mail-archive.com/internals@lists.php.net/msg100719.html
>
>
Maybe, bettern fn:  * fn(callable $to_clsoure ): *closure ?

I know fn is used in arrow functions. However, for that same reason fn is
the most convenient.

Using dik examples( by the way, they are brilliant ):

$result = Stats::of($string)
->analyze(fn(normalizeNewlines))
 ->analyze(fn(readingLevel))
 ->analyze(fn(countStats))
 ->analyze(fn($synonymSuggester, 'analyze'))
 ->analyze(fn(WordCouter::class, 'analyze'))
 ->analyze(fn($s) => wordDistribution($s, 3))

Returning to ::function again and with a modified example of dik( again ):

Now is:

result = Stats::of($string)
->analyze('\Stats\Analyzer\normalizeNewlines')
->analyze('\Stats\Readings\readingLevel')
->analyze('\Stats\Parser\countStats')
->analyze(fn($s) => \Stats\Analyzer\wordDistribution($s, 3));

Could be:
use function Stats\Analyzer\normalizeNewlines;
use function \Stats\Readings\readingLevel;
use function \Stats\Parser\countStats;

result = Stats::of($string)
->analyze(normalizeNewlines::function)
->analyze(readingLevel::function)
->analyze(countStats::function )
->analyze(fn($s) => \Stats\Analyzer\wordDistribution($s, 3));

Maybe '::function' is something long, however it wiil be autocompleted by
editors and, moreover, nowadays function is a reserved keyword.  Could we
use "normalizeNewlines::name", but in this case: normalizeNewlines is
function or class ?, because in this case could be "normalizeNewlines" a
class and "name" a constant of class.

Rowan put me in an awkward situation with [MyClass::class, method::function
] however, in this case, could be simply MyClass::class, 'method' ].
Because method don't need be used with namespace. ::function could be
documented with advice of being used  with name of functions. Because
::function is also useful in array:

$filters = [ normalizeNewlines::function, readingLevel::function,
countStats::function
]
$content = Stats::of($string);
foreach($filters as $filter) $filter($content);

Regards


Re: [PHP-DEV] [RFC]

2020-02-13 Thread Mike Schinkel
> On Feb 13, 2020, at 7:24 PM, Rowan Tommins  wrote:
> 
> An idea I had earlier which might solve some of them is if what was returned 
> was not a normal Closure instance, but a new class like FunctionReference. It 
> could then "remember" the name of the function wrapped, and implement 
> __toString, Serializable, etc. It could inherit from Closure, so instanceof 
> checks would work, and bindTo would return a normal Closure. I'm sure there's 
> downsides I haven't thought of yet, but I thought I'd throw the idea into the 
> mix.

I thought about that too, and mentioned it yesterday in a reply[1] to you on 
this list.

Here is the link to the Gist with the hypothetical code using such a concept: 

- https://gist.github.com/mikeschinkel/78684d708358e1d101e319c7a2fdef9c

-Mike


[1] https://www.mail-archive.com/internals@lists.php.net/msg100719.html
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Mike Schinkel
> On Feb 13, 2020, at 5:26 PM, Dik Takken  wrote:
> 
> On 13-02-2020 19:19, Mike Schinkel wrote:
>> function foo{}
>> 
>> foo::function  — Returns name of function
>> foo::fn  — Returns closure for function 
>> 
>> Since using `fn` creates anonymous function closures it kinda makes sense 
>> that `::fn` would return a closure.
> 
> That is somewhat confusing in my opinion, the two class constants are
> too similar. I would rather prefer:
> 
>foo::function  — Returns name of function
>foo::closure   — Returns closure for function
> 
> Regards,
> Dik Takken

I actually prefer foo::closure over foo::fn though either would be fine with 
me, especially if it means getting the feature vs. not getting the feature.

The reason I proposed ::fn was because I trying to suggest something that I 
though Larry Garfield would appreciate given his recent comment[1] in response 
to you where he said: 

"Analysis: I stand by my earlier statement that ::function is just too damned 
long for this funtionality. Not when already reserved shorter options exist.  
::fn"

-Mike
[1] https://externals.io/message/108459#108542 
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] token_get_all() TOKEN_AS_OBJECT mode

2020-02-13 Thread Levi Morrison via internals
On Thu, Feb 13, 2020 at 2:48 AM Nikita Popov  wrote:
>
> Hi internals,
>
> This has been discussed a while ago already, now as a proper proposal:
> https://wiki.php.net/rfc/token_as_object
>
> tl;dr is that it allows you to get token_get_all() output as an array of
> PhpToken objects. This reduces memory usage, improves performance, makes
> code more uniform and readable... What's not to like?
>
> An open question is whether (at least to start with) PhpToken should be
> just a data container, or whether we want to add some helper methods to it.
> If this generates too much bikeshed, I'll drop methods from the proposal.
>
> Regards,
> Nikita

Overall it looks great. Thanks, Nikita.

I do think it should use a separate function from `token_get_all`, and
am not sure I care whether it is a function or static method.

The only helper I see as totally non-controversial is `getTokenName`,
which seems completely reasonable and users should not have to keep
re-implementing that. I am open to more discussion about the others.

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Rowan Tommins
On 13 February 2020 18:19:08 GMT+00:00, Mike Schinkel  
wrote:
>Eloquently maybe, but of limited vision.


I think that's a rather negative way of putting it; there was a request for use 
cases, and you have supplied some, so thank you. :)

An idea I had earlier which might solve some of them is if what was returned 
was not a normal Closure instance, but a new class like FunctionReference. It 
could then "remember" the name of the function wrapped, and implement 
__toString, Serializable, etc. It could inherit from Closure, so instanceof 
checks would work, and bindTo would return a normal Closure. I'm sure there's 
downsides I haven't thought of yet, but I thought I'd throw the idea into the 
mix.

A possible future direction would then be to have ::class return some kind of 
ClassRef object, with the obvious downside that it would no longer pass string 
type hints without casting. I'm also not sure what the object would do, other 
than feel nicer from a type system point of view.

Regards,

-- 
Rowan Tommins
[IMSoP]

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Dik Takken
On 13-02-2020 17:55, Larry Garfield wrote:
> I walked right into that one, didn't I...

You did. :)

> Well, Dik asked me to post a "fabulous functional programming example".  I 
> dont' have one, so I'll go with one from the book I'm working on instead. :-)

Thanks, much appreciated.

> $() or variations thereof
> 
> $result = Stats::of($string)
> ->analyze($(normalizeNewlines))
> ->analyze($(readingLevel))
> ->analyze($(countStats))
> ->analyze($($synonymSuggester, 'analyze'))
> ->analyze($(WordCouter::class, 'analyze'))
> ->analyze(fn($s) => wordDistribution($s, 3))
> ;
> 
> Analysis: I'm not sure I like this one, visually.  "($(..))" feels like a lot 
> of sigils soup.  It also doesn't offer a way to deal with the method names in 
> the object versions, unless we just assume that bare strings are allowed 
> there, like so:
> 
> $result = Stats::of($string)
> ->analyze($(normalizeNewlines))
> ->analyze($(readingLevel))
> ->analyze($(countStats))
> ->analyze($($synonymSuggester, analyze))
> ->analyze($(WordCouter::class, analyze))
> ->analyze(fn($s) => wordDistribution($s, 3))
> ;

If the $() construct would only accept methods then it provides an
environment without the usual ambiguity and we can write:

$result = Stats::of($string)
->analyze($(normalizeNewlines))
->analyze($(readingLevel))
->analyze($(countStats))
->analyze($($synonymSuggester->analyze))
->analyze($(WordCouter::analyze))
->analyze(fn($s) => wordDistribution($s, 3));

The RFC of Michał (https://wiki.php.net/rfc/short-closures) would yield:

$result = Stats::of($string)
->analyze({normalizeNewlines})
->analyze({readingLevel})
->analyze({countStats})
->analyze({$synonymSuggester->analyze})
->analyze({WordCouter::analyze})
->analyze(fn($s) => wordDistribution($s, 3));

To me this looks less soup-ish compared to using $().

> I will say that, given the behavior of ::class now, ::fn or ::name "feel 
> like" they should return a string, whereas $() "feels like" it should return 
> a callable, or something richer than a string.  That's naturally subjective 
> but is consistent with ::foo being a constant value and $() being, um, jQuery.

Although a closure would also be a constant I share your 'feel like'
issue. It might just need getting used to.

> Of course... I feel compelled to ask why we can't just use bare function 
> names.  Treating a bare string as a string has been deprecated for several 
> versions.  If we remove that in PHP 8 and instead let it mean constant, then 
> function, then class name, the following would become legal:
> 
> $result = Stats::of($string)
> ->analyze(normalizeNewlines)
> ->analyze(readingLevel)
> ->analyze(countStats)
> ->analyze([$synonymSuggester, analyze])
> ->analyze([WordCouter, analyze])
> ->analyze(fn($s) => wordDistribution($s, DISTRIBUTION_LIMIT))
> ;
> 
> Which would be much more in line with how many other languages handle symbol 
> names.  (There is likely some engine reason why it's way harder than I make 
> it sound; I'd love to hear what that is so I know not to suggest it again, 
> unless it really is that simple in which case...)

I guess using bare function names in that context could be supported. I
would prefer getting rid of these awkward array constructs altogether
though and just write $synonymSuggester->analyze in stead. This requires
a context that only accepts methods, which is what $() or {} could provide.

As a side note, I would love to have a name for these closure producing
constructs we are talking about. Maybe: 'enclosure'?

Regards,
Dik Takken

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Dik Takken
On 13-02-2020 19:19, Mike Schinkel wrote:
> But since I seem to be in the minority of caring about the name, let me 
> propose the following which was influenced by Larry Garfield's most recent 
> post.  Since it seems that people want the convenience of a short notation to 
> get a closure, how about this:
> 
> function foo{}
> 
> foo::function  — Returns name of function
> foo::fn  — Returns closure for function 
> 
> Since using `fn` creates anonymous function closures it kinda makes sense 
> that `::fn` would return a closure.

That is somewhat confusing in my opinion, the two class constants are
too similar. I would rather prefer:

foo::function  — Returns name of function
foo::closure   — Returns closure for function

Regards,
Dik Takken

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Larry Garfield
On Thu, Feb 13, 2020, at 2:12 PM, Mike Schinkel wrote:
> > On Feb 13, 2020, at 1:48 PM, Larry Garfield  wrote:
> >> But since I seem to be in the minority of caring about the name, let me 
> >> propose the following which was influenced by Larry Garfield's most 
> >> recent post.  Since it seems that people want the convenience of a 
> >> short notation to get a closure, how about this:
> >> 
> >> function foo{}
> >> 
> >> foo::function  — Returns name of function
> >> foo::fn  — Returns closure for function 
> >> 
> >> Since using `fn` creates anonymous function closures it kinda makes 
> >> sense that `::fn` would return a closure.
> >> 
> >> -Mike
> > 
> > thinking-face-emoji.gif.  I could be convinced of that.  It seems like 
> > "both" is a possible solution, but my concern would be someone using one of 
> > them in a case where either works, inadvertently, when the callee is 
> > expecting just one.  Eg, getting into the habit of using foo::fn, and then 
> > using it on a builder routine that chokes "later" when it tries to 
> > serialize something.
> 
> True. 
> 
> But it would be a really high bar to say we can only add new features 
> if we can completely protect the developer from themselves.  At some 
> point we have to assume programmers are adults, or at least can take 
> responsibility for learning how the language works. 

Strawman argument.  Nothing can "completely" protect developers from 
themselves; not even Rust. :-)  But features should still be designed in such a 
way as to be hard to screw up.  Not impossible, hard.

The question I pose is whether "both" would be "hard enough" to get wrong that 
it's not going to cause more confusion than it solves.  I don't know the answer 
to that question.

--Larry Garfield

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



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-13 Thread Mike Schinkel
> On Feb 13, 2020, at 1:34 PM, Paul M. Jones  wrote:
> 
> Hi Mike,
> 
> Thanks for your continued evaluation of the RFC.
> 
>> Take a look at WordPress.  It does a lot of "fixup" to $_SERVER` variables — 
>> to deal with badly implemented web servers — to ensure all known variables 
>> have a value and that the format of the value is consistent.  
>> 
>> ...
>> 
>> Another option actually would be to allow changes to $_SERVER prior to 
>> instantiating ServerRequest() the first time.
> 
> Believe it or not, this RFC does make allowance for what you're describing, 
> as a result of requiring a $globals array as the first parameter. An 
> application-specific builder or factory can modify those $globals values as 
> desired, before instantiating ServerRequest with the modified values.
> 
> For example:
> 
>namespace App;
> 
>use ServerRequest;
> 
>class ServerRequestFactory
>{
>public function new(array $globals, ?string $content = null) : 
> ServerRequest
>{
>// do fixup to $globals['_SERVER'] ...
> 
>// ... then:
>return new ServerRequest($globals, $content);
>}
>}
> 
>$request = (new \App\ServerRequestFactory())->new($GLOBALS);
> 
> I can easily imagine many ways to achieve the same end (i.e., modification of 
> the constructor arguments before instantiating ServerRequest).
> 
> Do you get where I'm coming from?

Ah, I see now.  That does allow for changing.

OTOH, what it does not do is ensure that everyone looking at the values are 
looking at the fixed-up values, nor does it offer any way to cache the original 
value except to do so at the top of every PHP file that is a URL endpoint.  

I was hoping that your proposal was having a way to capture the original values 
before any PHP code could change them AND also then allow for fixed-up values 
to be provided for _every_ instantiation of ServerRequest(). This in case a 
library were to use it, I would not want the library to be getting the 
non-fixed up values.  

So in that respect, this is worse than what we have now.

>> Why a method is important is to support filters (I guess I assumed that was 
>> obvious but realize now it was not.) For example:
>> 
>>  $request->get('redirect', FILTER_SANITIZE_URL);
>>  $request->get('product_id', FILTER_SANITIZE_NUMBER_INT);
>>  $request->get('email', FILTER_SANITIZE_EMAIL);
>> 
>> You could potentially even have scoped, easier to remember constants that 
>> can work with autocomplete:
>> 
>>  $request->get('redirect', ServerRequest::URL);
>>  $request->get('product_id', ServerRequest::INT);
>>  $request->get('email', ServerRequest::EMAIL);
> 
> [snip]
> 
> I do see what you mean. Even so, I think filtering is out-of-scope for this 
> RFC.

I would implore you to reconsider.  Without incorporating the functionality of 
filter_input() you have effectively neutered much of the value I envision your 
RFC having.  In the USA we might say "Besides that Mrs. Lincoln, how was the 
play?"

If I had a vote I would vote I would enthusiastically vote for the RFC if it 
includes filter_input() functionality. But I would vote against this RFC if it 
omits filter_input() functionality because it would mean another subsystem in 
core that does not actually address day-to-day concerns.

>  Certainly I want to avoid adding methods to the ServerRequest class, which 
> as envisioned is a bag of values much the same way $_GET, $_POST, $_SERVER, 
> etc. are bags of values.


Unless I misunderstand avoiding methods in ServerRequest is an arbitrary 
constraint which has no real-world requirement.  And if your motivation is to 
only mirror what exists then filter_input() is a function so an equivalent in 
ServerRequest should be a method and thus this in not inconsistent with your 
mirroring aspect.

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Mike Schinkel
> On Feb 13, 2020, at 1:48 PM, Larry Garfield  wrote:
>> But since I seem to be in the minority of caring about the name, let me 
>> propose the following which was influenced by Larry Garfield's most 
>> recent post.  Since it seems that people want the convenience of a 
>> short notation to get a closure, how about this:
>> 
>> function foo{}
>> 
>> foo::function  — Returns name of function
>> foo::fn  — Returns closure for function 
>> 
>> Since using `fn` creates anonymous function closures it kinda makes 
>> sense that `::fn` would return a closure.
>> 
>> -Mike
> 
> thinking-face-emoji.gif.  I could be convinced of that.  It seems like "both" 
> is a possible solution, but my concern would be someone using one of them in 
> a case where either works, inadvertently, when the callee is expecting just 
> one.  Eg, getting into the habit of using foo::fn, and then using it on a 
> builder routine that chokes "later" when it tries to serialize something.

True. 

But it would be a really high bar to say we can only add new features if we can 
completely protect the developer from themselves.  At some point we have to 
assume programmers are adults, or at least can take responsibility for learning 
how the language works. 

-Mike
P.S. OTOH, if the routine that requires ::function and not ::fn were to type 
hint the parameter, it would choke with an applicable error message.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Larry Garfield
On Thu, Feb 13, 2020, at 12:19 PM, Mike Schinkel wrote:
> > On Feb 13, 2020, at 12:26 PM, Rowan Tommins  wrote:
> > Right, I'm with you now. However, I think the answer people are suggesting
> > to "how do we get the name string?" is "why do we need to?"
> 
> 1. Say I want to provide users with the ability to build queries and 
> use functions where I want to provide the names of the functions to the 
> users:
> 
> $qt = QueryTool();
> $qt->addFunction(substr::function);
> $qt->addFunction(add_product::function);
> $qt->showUI();
> 
> 2. Say I want to serialize any configuration that uses functions.  You 
> can't serialize closures but you can serialize function names to a 
> database or JSON.
> 
> 3. You cannot use a closure as an array index so if you want to use the 
> function name as an array key to associate additional information to 
> the use with the function, such as:
> 
> $qt = QueryTool();
> $qt->addFunction(substr::function, array( 
>   new FuncParam( 'string', 'string' ),
>   new FuncParam( 'int', 'start', QueryTool::Optional ),
>   new FuncParam( 'int', 'length', QueryTool::Optional )
> ));
> $qt->addFunction(add_product::function, array( 
>   new FuncParam( 'string', 'product_id' ),
>   new FuncParam( 'float', 'price' )
> ));

Those are valid examples.  I suppose along similar lines would be tooling that 
uses a builder to generate compiled code.  (Eg, if $qt were used to then 
generate an optimized function in a class on disk.)

Flipside: In those cases we really should standardize static methods better 
than with arrays, yet none of these address (nor can they) instance methods.

> 4. Being able to compose quality error and warning message that include 
> function names.
> 
> > Or as Chase Peeler more eloquently put it:
> > 
> >> Can anyone think of a use-case where you would want a string name of a
> >> function and a callable would not be acceptable, besides possibly debugging
> >> code that said 'echo "I'm calling ".myfunction::function;'? Everything that
> >> I can think of that accepts a function name, also accepts a callable (e.g.
> >> array_map), but I could be forgetting something.
> 
> Eloquently maybe, but of limited vision.
> 
> 
> > There's a Venn diagram, essentially, of:
> > a) use cases where a Closure would be useful, but a string wouldn't
> > b) use cases where a string would be useful, but a Closure wouldn't
> > c) use cases where either a string or a Closure would be useful
> > 
> > If (and it's a genuine open question) all the use cases fall into
> > categories (a) and (c), we can make the syntax for closures simpler by
> > skipping the "get name" step and making foo::fn return a closure straight
> > away.
> > 
> > So the question is, are there use cases that fall into category (b)?
> 
> Yes. Definitely.

I agree, the above examples demonstrate valid use cases for (b).

> But since I seem to be in the minority of caring about the name, let me 
> propose the following which was influenced by Larry Garfield's most 
> recent post.  Since it seems that people want the convenience of a 
> short notation to get a closure, how about this:
> 
> function foo{}
> 
> foo::function  — Returns name of function
> foo::fn  — Returns closure for function 
> 
> Since using `fn` creates anonymous function closures it kinda makes 
> sense that `::fn` would return a closure.
> 
> -Mike

thinking-face-emoji.gif.  I could be convinced of that.  It seems like "both" 
is a possible solution, but my concern would be someone using one of them in a 
case where either works, inadvertently, when the callee is expecting just one.  
Eg, getting into the habit of using foo::fn, and then using it on a builder 
routine that chokes "later" when it tries to serialize something.

--Larry Garfield

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



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-13 Thread Paul M. Jones
Hi Mike,

Thanks for your continued evaluation of the RFC.

> Take a look at WordPress.  It does a lot of "fixup" to $_SERVER` variables — 
> to deal with badly implemented web servers — to ensure all known variables 
> have a value and that the format of the value is consistent.  
> 
> ...
> 
> Another option actually would be to allow changes to $_SERVER prior to 
> instantiating ServerRequest() the first time.

Believe it or not, this RFC does make allowance for what you're describing, as 
a result of requiring a $globals array as the first parameter. An 
application-specific builder or factory can modify those $globals values as 
desired, before instantiating ServerRequest with the modified values.

For example:

namespace App;

use ServerRequest;

class ServerRequestFactory
{
public function new(array $globals, ?string $content = null) : 
ServerRequest
{
// do fixup to $globals['_SERVER'] ...

// ... then:
return new ServerRequest($globals, $content);
}
}

$request = (new \App\ServerRequestFactory())->new($GLOBALS);

I can easily imagine many ways to achieve the same end (i.e., modification of 
the constructor arguments before instantiating ServerRequest).

Do you get where I'm coming from?


>> First, I'd have to decline adding request() (or $request) at all; my opinion 
>> is that one ought to be reading from $get, $post, $cookies, etc. 
>> specifically, not from a pool of those values.
> 
> That's definitely fair.  I almost did not include request() in my suggestion 
> but did because PHP has $_REQUEST.

Good enough. :-)


> Why a method is important is to support filters (I guess I assumed that was 
> obvious but realize now it was not.) For example:
> 
>   $request->get('redirect', FILTER_SANITIZE_URL);
>   $request->get('product_id', FILTER_SANITIZE_NUMBER_INT);
>   $request->get('email', FILTER_SANITIZE_EMAIL);
> 
> You could potentially even have scoped, easier to remember constants that can 
> work with autocomplete:
> 
>   $request->get('redirect', ServerRequest::URL);
>   $request->get('product_id', ServerRequest::INT);
>   $request->get('email', ServerRequest::EMAIL);

[snip]

I do see what you mean. Even so, I think filtering is out-of-scope for this 
RFC. Certainly I want to avoid adding methods to the ServerRequest class, which 
as envisioned is a bag of values much the same way $_GET, $_POST, $_SERVER, 
etc. are bags of values.


>>> Would you not also add an option to generate a warning when using them for 
>>> those who want to deprecate their use in their own code (deprecating across 
>>> the board would be too extreme give how much CMS and framework code uses 
>>> them intimately.)
>> 
>> That seems a bit much at this point. ;-)
> 
> Really?  Seems like this and some guard code is all it would take:
> 
> ini_set( "disallow_superglobals", true);

Even if that's true (and I think that example masks some complexity) I must 
maintain that it's out of scope for this RFC.


-- 
Paul M. Jones
pmjo...@pmjones.io
http://paul-m-jones.com

Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp

Solving the N+1 Problem in PHP
https://leanpub.com/sn1php

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Mike Schinkel
> On Feb 13, 2020, at 12:26 PM, Rowan Tommins  wrote:
> Right, I'm with you now. However, I think the answer people are suggesting
> to "how do we get the name string?" is "why do we need to?"

1. Say I want to provide users with the ability to build queries and use 
functions where I want to provide the names of the functions to the users:

$qt = QueryTool();
$qt->addFunction(substr::function);
$qt->addFunction(add_product::function);
$qt->showUI();

2. Say I want to serialize any configuration that uses functions.  You can't 
serialize closures but you can serialize function names to a database or JSON.

3. You cannot use a closure as an array index so if you want to use the 
function name as an array key to associate additional information to the use 
with the function, such as:

$qt = QueryTool();
$qt->addFunction(substr::function, array( 
new FuncParam( 'string', 'string' ),
new FuncParam( 'int', 'start', QueryTool::Optional ),
new FuncParam( 'int', 'length', QueryTool::Optional )
));
$qt->addFunction(add_product::function, array( 
new FuncParam( 'string', 'product_id' ),
new FuncParam( 'float', 'price' )
));

4. Being able to compose quality error and warning message that include 
function names.

> Or as Chase Peeler more eloquently put it:
> 
>> Can anyone think of a use-case where you would want a string name of a
>> function and a callable would not be acceptable, besides possibly debugging
>> code that said 'echo "I'm calling ".myfunction::function;'? Everything that
>> I can think of that accepts a function name, also accepts a callable (e.g.
>> array_map), but I could be forgetting something.

Eloquently maybe, but of limited vision.


> There's a Venn diagram, essentially, of:
> a) use cases where a Closure would be useful, but a string wouldn't
> b) use cases where a string would be useful, but a Closure wouldn't
> c) use cases where either a string or a Closure would be useful
> 
> If (and it's a genuine open question) all the use cases fall into
> categories (a) and (c), we can make the syntax for closures simpler by
> skipping the "get name" step and making foo::fn return a closure straight
> away.
> 
> So the question is, are there use cases that fall into category (b)?

Yes. Definitely.

But since I seem to be in the minority of caring about the name, let me propose 
the following which was influenced by Larry Garfield's most recent post.  Since 
it seems that people want the convenience of a short notation to get a closure, 
how about this:

function foo{}

foo::function  — Returns name of function
foo::fn  — Returns closure for function 

Since using `fn` creates anonymous function closures it kinda makes sense that 
`::fn` would return a closure.

-Mike

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Rowan Tommins
On Thu, 13 Feb 2020 at 17:06, Mike Schinkel  wrote:

> 1. IF foo::function returns a name string THEN using
> Closure::fromCallable( foo::function ) can provide a closure.
>
> 2. IF foo::function returns a closure THEN how to we get the name string?
>


Right, I'm with you now. However, I think the answer people are suggesting
to "how do we get the name string?" is "why do we need to?"

Or as Chase Peeler more eloquently put it:

> Can anyone think of a use-case where you would want a string name of a
> function and a callable would not be acceptable, besides possibly
debugging
> code that said 'echo "I'm calling ".myfunction::function;'? Everything
that
> I can think of that accepts a function name, also accepts a callable
(e.g.
> array_map), but I could be forgetting something.


There's a Venn diagram, essentially, of:
a) use cases where a Closure would be useful, but a string wouldn't
b) use cases where a string would be useful, but a Closure wouldn't
c) use cases where either a string or a Closure would be useful

If (and it's a genuine open question) all the use cases fall into
categories (a) and (c), we can make the syntax for closures simpler by
skipping the "get name" step and making foo::fn return a closure straight
away.

So the question is, are there use cases that fall into category (b)?


Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Adding a "Stringable" interface to PHP 8

2020-02-13 Thread Nicolas Grekas
Hi Patrick,

thanks for taking the time to explain your vote.


A virtual "stringable" type (that would be similar to "iterable)" would,
> IMHO, be of a bigger benefit if it is to denote the fact that "a variable
> can be transformed to a string".
> By design, when a variable is declared as "iterable", you know you can
> foreach() on it now, but also on other yet-to-be-implemented concepts that
> would support foreach looping. Think about it as if generators would have
> appeared after "iterable" keyword and then, added to it.
>

I don't make a difference between a type and what you call a virtual type:
any type, virtual or not, is some guarantee that a variable can be used is
some specific way,
typically because some methods exist in the object or something else for
special types managed by the engine.
As such, any type implies a behavior.

My understanding of the existing composite types is that they were added
because PHP lacked union types.
We could imagine a future where PHP will support type aliases. That day,
iterable could be strictly equivalent to
array|Traversable|Iterator|ItratorAggregate and everything would be fine.
PHP doesn't need magic types as a feature of the language to provide any
special behaviors.

Of course, this is my interpretation, and the RFC builds on it.

What is the real advantage of adding this to the core, rather than some
> FIG/PSR standard? This would be compatible in both current versions of PHP
> and next ones at the same time.
>

At least the auto and implicit declaration of the interface + the return
type, that makes a big diff.


> public string __toString() {
> throw new \Exception("Foo should not be casted to string, you
> should now...");
> }
>

This concern exists with any interface actually, nothing specific to this
one.

As the vote is open now, I'm going to keep it going until the end.
If it does not pass - or if it passes and you feel strongly about it, we
might want to submit an RFC on top of course.

Thanks again for your explanation,
Nicolas


Re: [PHP-DEV] [RFC]

2020-02-13 Thread Mike Schinkel
> On Feb 13, 2020, at 2:33 AM, Rowan Tommins  wrote:
> 
> On 13 February 2020 03:33:32 GMT+00:00, Mike Schinkel  
> wrote:
>>> On Feb 12, 2020, at 5:47 PM, Rowan Tommins 
>> wrote:
>>> 
>>> On 12/02/2020 03:58, Mike Schinkel wrote:
 Returning a_closure_  instead of a string would be providing a
>> feature we_already_  have instead of one we do_not_  have.
>>> 
>>> 
>>> Not really, because you still need a way to get the fully-qualified
>> name of the function. This is not valid:
>>> 
>>> namespace MyVendor\Something\Foo;
>>> function bar() {}
>>> 
>>> \Closure::fromCallable('bar'); # Error: tries to resolve function
>> '\bar'
>>> 
>> 
>> Why would ::function return a short name instead of the fully-qualified
>> name? 
> 
> 
> I never said it would; the intent of this example was to show what is 
> possible in current PHP, in response to your comment about returning a 
> closure being "a feature we already have".
> The key new feature being proposed is a way to resolve an unqualified 
> function name based on current namespace and imports, without calling the 
> function. The open question is whether the result of that should be expressed 
> as a string or as a Closure object, but in current PHP the feature doesn't 
> exist at all.

Let me clarify for you what I was trying to say.

1. IF foo::function returns a name string THEN using Closure::fromCallable( 
foo::function ) can provide a closure.

2. IF foo::function returns a closure THEN how to we get the name string?

Hence we already have a way to get the closure _if_ ::function returns a name 
string, but we would *not* have a way to get the name string if ::function 
returns a closure.  

IOW, we can already derive a closure if we have a name, but we cannot derive a 
name if we have a closure.

I hope this clarifies what I was trying to say when I said "we already have it."

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



Re: [PHP-DEV] [RFC] token_get_all() TOKEN_AS_OBJECT mode

2020-02-13 Thread Larry Garfield
On Thu, Feb 13, 2020, at 3:47 AM, Nikita Popov wrote:
> Hi internals,
> 
> This has been discussed a while ago already, now as a proper proposal:
> https://wiki.php.net/rfc/token_as_object
> 
> tl;dr is that it allows you to get token_get_all() output as an array of
> PhpToken objects. This reduces memory usage, improves performance, makes
> code more uniform and readable... What's not to like?
> 
> An open question is whether (at least to start with) PhpToken should be
> just a data container, or whether we want to add some helper methods to it.
> If this generates too much bikeshed, I'll drop methods from the proposal.
> 
> Regards,
> Nikita

I love everything about this.

1) I would agree with Nicolas that a static constructor would be better.  I 
don't know about polyfilling it, but it's definitely more self-descriptive.

2) I'm skeptical about the methods.  I can see them being useful, but also 
being bikeshed material.  For instance, if you're doing annotation parsing then 
docblocks are not ignorable.  They're what you're actually looking for.

Two possible additions, feel free to ignore if they're too complicated:

1) Should it return an array of token objects, or a lazy iterable?  If I'm only 
interested in certain types (eg, doc strings, classes, etc.) then a lazy 
iterable would allow me to string some filter and map operations on to it and 
use even less memory overall, since the whole tree is not in memory at once.

2) Rather than provide bikesheddable methods, would it be feasible to take a 
queue from PDO and let users specify a subclass of PhpToken to fetch into?  
That way the properties are always there, but a user can attach whatever 
methods make sense for them.

IMO the laziness would be more valuable, since a struct class can be operated 
on by an external function just as easily as a method, especially if using a 
functional pipeline.

--Larry Garfield

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



Re: [PHP-DEV] [RFC]

2020-02-13 Thread Larry Garfield
On Tue, Feb 11, 2020, at 1:08 PM, Dik Takken wrote:

> On 11-02-2020 19:46, Larry Garfield wrote:
> >
> > I would love a nicer way to reference function names; it's really ugly
> to do functional code in PHP otherwise, or even just dynamic function
> logic within a namespace.  If I never have to write $fn = __NAMESPACE__
> . '\a_func' again, it will be too soon. :-)
> 
> Perhaps Larry can convince us all to go for something like $() by
> posting a fabulous functional programming example?

I walked right into that one, didn't I...


Well, Dik asked me to post a "fabulous functional programming example".  I 
dont' have one, so I'll go with one from the book I'm working on instead. :-)

This is what I have now, assuming all global functions:

$result = Stats::of($string)
->analyze('normalizeNewlines')
->analyze('readingLevel')
->analyze('countStats')
->analyze(fn($s) => wordDistribution($s, 3))
;

I think we are all in agreement that is sub-optimal.  If using functions in the 
`Stats\Analyzer` namespace, you end up with this:

$result = Stats::of($string)
->analyze('\Stats\Analyzer\normalizeNewlines')
->analyze('\Stats\Analyzer\readingLevel')
->analyze('\Stats\Analyzer\countStats')
->analyze(fn($s) => \Stats\Analyzer\wordDistribution($s, 3))
;

Or if you're in that namespace (as I often am) you can do:

$ns = __NAMESPACE__;

$result = Stats::of($string)
->analyze($ns . '\normalizeNewlines')
->analyze($ns . '\readingLevel')
->analyze($ns . '\countStats')
->analyze(fn($s) => \Stats\Analyzer\wordDistribution($s, 3))
;

This is doubleplusungood.

I'll expand the example to use some methods, too, for variety's sake:


$result = Stats::of($string)
->analyze('normalizeNewlines')
->analyze('readingLevel')
->analyze('countStats')
->analyze([$synonymSuggester, 'analyze'])
->analyze([WordCouter::class, 'analyze'])
->analyze(fn($s) => wordDistribution($s, 3))
;


As I understand it, the goal in this thread is to:

1) Make code like the above more statically analyziable by not using strings. 
(That covers a number of areas.)
2) Make code like the above easier to write by using symbols rather than 
strings.

In each case, the analyze() method wants a callable with a specific signature.  
Enforced callable signatures are *absolutely something we desperately need*, 
but are not the scope at the moment.  In this example, then, that a function 
name is a string is incidental; what we care about is that it's callable.  I 
don't have a good example off hand for it actually wanting a string, although 
strings are callables.

So, given this import block:

use Stats\Analyzer\normalizeNewlines;
use Stats\Analyzer\readingLevel;
use Stats\Analyzer\countStats;
use Stats\Analyzer\normalizeNewlines;
use Stats\Analyzer\wordDistribution;
use Stats\Analyzer\Stats;
use Stats\Analyzer\WordCounter;

here's the above example cast into a number of the different proposals floating 
about this thread:

::function

$result = Stats::of($string)
->analyze(normalizeNewlines::function)
->analyze(readingLevel::function)
->analyze(countStats::function)
->analyze([$synonymSuggester, 'analyze'])
->analyze([WordCouter::class, 'analyze'])
->analyze(fn($s) => wordDistribution($s, 3))
;

Analysis: I stand by my earlier statement that ::function is just too damned 
long for this funtionality.  Not when already reserved shorter options exist.

::fn

$result = Stats::of($string)
->analyze(normalizeNewlines::fn)
->analyze(readingLevel::fn)
->analyze(countStats::fn)
->analyze([$synonymSuggester, 'analyze'])
->analyze([WordCouter::class, 'analyze'])
->analyze(fn($s) => wordDistribution($s, 3))
;

Analysis: Same thing, less typing.  

::name

$result = Stats::of($string)
->analyze(normalizeNewlines::name)
->analyze(readingLevel::name)
->analyze(countStats::name)
->analyze([$synonymSuggester, 'analyze'])
->analyze([WordCouter::name, 'analyze'])
->analyze(fn($s) => wordDistribution($s, 3))
;

Analysis: This one gives us unification between classes and functions.  I think 
that would be good, although it's not a hard requirement for the functionality.


Any of the above could be expanded, potentially, to include methods, like so:

::name, for methods, too

$result = Stats::of($string)
->analyze(normalizeNewlines::name)
->analyze(readingLevel::name)
->analyze(countStats::name)
->analyze([$synonymSuggester, analyze::name])
->analyze([WordCouter::name, analyze::name])
->analyze(fn($s) => wordDistribution($s, 3))
;

However, that requires the parser being able to tell the difference between 
analyze::name inside a callable array and not.  That's... potentially 
complicated, since you can also just have an array that contains both objects 
and strings, or objects and callables, especially as objects can also be 
callables with __invoke().


$() or variations thereof

$result = Stats::of($string)

Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-13 Thread Paul M. Jones
Hi Ruud,


> On Feb 13, 2020, at 00:45, Ruud Boon  wrote:
> 
> Hi!
> 
> I really like this RFC. 

Glad to hear it!


> In the the RFC I see that $content will return  php://input using 
> file_get_contents on the fly. Can we add the possibility to get a reference 
> to the stream as well?

By "get a reference" I presume you mean "an open file handle" (a la `return 
fopen('php://input', 'rb')`).

In which case: maybe? I can see where that would be useful for extremely large 
request bodies in a memory-constrained environment.

But the question becomes: is that needed frequently-enough across a wide-enough 
range of PHP developers to warrant inclusion in this RFC? I don't recall seeing 
any userland implementation from my research provide such a thing. That makes 
me think it's a comparatively infrequent need.

If many others disagree with that assessment, I'm happy to entertain the 
possibility of adding something like it to ServerRequest.


-- 
Paul M. Jones
pmjo...@pmjones.io
http://paul-m-jones.com

Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp

Solving the N+1 Problem in PHP
https://leanpub.com/sn1php

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



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-13 Thread Paul M. Jones
Hi Niklas,

> On Feb 12, 2020, at 12:20, Niklas Keller  wrote:
> 
> I think the request / response API is entirely fine being solved in
> userland instead of in php-src. However, since you already made such a
> proposal, I want to give some feedback:

Re: userland, I gave a counterargument in my reply to Mark Randall.

Even so, thanks for providing feedback in spite of that objection; I appreciate 
your time and effort.


> Naming
> 
> I think we shouldn't take over the naming of the super globals, e.g.
> $_GET really contains the query parameters and has nothing to do with
> GET or POST, so $request->getQueryParameter(...) would be a better
> name.

/me nods

Yeah, naming is one of the hard problems. I considered $query as an alternative 
property name for $get, but in the end, the `$_GET => $get` symmetry was too 
great to ignore. If others here feel that $query is a better name for `$_GET` 
than $get, I will submit to consensus on that point.

Using a getQueryParameter() method strikes a little too close to PSR-7, and 
thereby to charges of favoritism. But let's say we do use a method instead of a 
property here, call it getQuery(); then, of the following ...

$foo = $request->getQuery()['foo'];
// vs
$foo = $request->query['foo'];

... the latter (using a property) looks and feels more appropriate to me. Thus, 
the RFC specifies properties over methods for ServerRequest.


> Type Safety
> 
> I think the API should be type safe. Currently $request->get['key']
> can be null | string | string[] | ... Most parameters only appear a
> single time, so a method returning the first parameter value or null
> could be used instead.

This sounds a little like using `$_REQUEST` instead of `$_GET`, `$_POST`, and 
`$_COOKIES`. Using the "first" parameter would then depend on the order in 
which the superglobals get entered into the ServerRequest object, and/or we're 
in the business of reading and honoring the `variables_order` INI setting, at 
which point the logic starts sounding rather involved.

So while I do get the desire for type-safety, I'd prefer to avoid all that 
intricacy, and go with something much closer to what PHP itself already does. 
That is, read $get for $_GET, $post for $_POST, etc., and just go with what is 
stored there.


> API Issues
> 
> I don't see any reason to keep specials such as
> $_SERVER['HTTP_X_REQUESTED_WITH'] vs. $request->requestedWith, which
> is just another HTTP header.

I get that; $requestedWith in 1.x was a boolean $xhr, to let you know if 
`$_SERVER['HTTP_X_REQUESTED_WITH'] === 'XmlHttpRequest'`. It struck me that 
there might be different values in the future, and so moved to just 
$requestedWith instead. I am not attached to that particular property; if 
others agree, I am OK with removing it.


> If there's $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] => $request->method
> and $_SERVER['REQUEST_METHOD'] => $request->method, how can I get the
> original  (actual) method?

The $method property is a calculated value: if there is a method override on a 
POST, $method is the override; otherwise, it is the "actual" method. So:

- $request->server['REQUEST_METHOD'] is the original (actual) method,
- $request->server['HTTP_X_METHOD_OVERRIDE'] is the override method, and
- $request->method is the "calculated" value between them.

You can see the code here: 
https://github.com/pmjones/ext-request/blob/2.x/php_request.c#L147-L175


> Given 'echo $content; => $response->setContent($content);', shouldn't
> this rather be something like `addContent()`?

That looks like poor describing on my part in the RFC. It is more true to say 
that these are equivalent:

echo $content;

// =>

$response->setContent($content);
$responseSender->send($response);

I will try to make that more apparent in the RFC.

> How does streaming responses work? There's ServerResponseSender, but I think 
> this should
> be part of the Response API.

Here's an example:

$fh = fopen('/path/to/file.ext', 'rb');
$response->setContent($fh);
// ...
$responseSender->send($response);

When the ServerResponseSender calls $response->getContent() and detects a 
resource, it calls rewind() on that resource, then fpassthru(). That should 
stream through nicely.

For more information, please see the ServerResponseSender methods at 
 under the sendContent() 
bullet:

• If the content is a resource, it is sent using rewind() and then fpassthru().

• If the content is a callable object or closure, it is invoked, and then its 
return value (if any) is echoed as a string; note that object returns will be 
cast to string at this point, invoking the __toString() method if present.

• Otherwise, the content is echoed as a string; note that objects will be cast 
to string at this point, invoking the __toString() method if present.

There are limitations to that approach, but experience has shown that it covers 
the vast majority of common 

[PHP-DEV] Re: [RFC] Adding a "Stringable" interface to PHP 8

2020-02-13 Thread Patrick ALLAERT
Hi,

> allow using string|Stringable to express string|object-with-__toString()

That goal is expressed in a technical way, rather than a functional one. I
have the feeling that addressing the goal: "Can I represent/cast variable
$str as a string" would address a broader, yet much more useful, scope.

string|Stringable:
1. Denotes a list of types, not a capability as "stringable" would as a
virtual type (like iterable). It somewhat contradicts the principle of
knowing the *type* vs knowing what we can do with it.
2. Is incomplete in terms of what can be "represented as a string".

The Stringable interface used alone tells there is a __toString() method.
Therefor, we should expect it to be used to call the __toString() method
explicitly:

function test(Stringable $object) {
\strtoupper($object->__toString();) // do something with __toString();
}

... in order to be consistent with what interfaces are meant. If mainly
used for string casting capability, then it will only match objects and not
all the other types that can be casted as string.

A virtual "stringable" type (that would be similar to "iterable)" would,
IMHO, be of a bigger benefit if it is to denote the fact that "a variable
can be transformed to a string".
By design, when a variable is declared as "iterable", you know you can
foreach() on it now, but also on other yet-to-be-implemented concepts that
would support foreach looping. Think about it as if generators would have
appeared after "iterable" keyword and then, added to it.

> Adding a new stringable special type (like iterable, callable, etc.) is
not considered in this RFC because it would require adding a new reserved
keyword in the language. This would break BC more heavily and would defeat
goal #2 mentioned previously (ability to polyfill on PHP7.)

It's perfectly fine to add a new reserved keyword in the language, and a
major version is absolutely the best moment for it. Not sure how much more
break would be implied by a keyword, vs the interface.

As it is presented, Stringable alone seems of very little use as compared
to union like "string|Stringable", so using the polyfill in a version of
PHP that does not support union does not seem to make sense.

What is the real advantage of adding this to the core, rather than some
FIG/PSR standard? This would be compatible in both current versions of PHP
and next ones at the same time.

This RFC would also introduce a very new concept, which seems nice at a
first glance, but a bit nasty too:

class Foo {
/** @deprecated */
public string __toString() {
throw new \Exception("Foo should not be casted to string, you
should now...");
}
}

The above would imply that "Foo implements Stringable" unconditionally:
without opt-in, but also without opt-out! It would also be the only one
case of classes declared without "implements" that would still implement an
interface: quite contradictory and hacky!

It would be less "hacky" if a broader concept (let's say "Signature"?)
would exist for checking at runtime the availability of a method without
requiring an interface to be implemented, e.g.:

Option 1: By introducing the "signature" keyword:

signature CanCommit {
public function commit();
}

used like this:

if ($object instanceof CanCommit) {
$object->commit();
}

Option 2: By introducing an extra meaning to keyword "implements":

interface CanCommit {
public function commit();
}

used like this:

if ($object implements CanCommit) { // Checking at runtime that $object's
class would comply to interface CanCommit
$object->commit();
}

If this, or a similar concept would exist, one could just declare a
signature for __toString() and we wouldn't have the incoherence that this
RFC introduces.

Another, also broader, approach would be to implement a global way to check
"castability" to type X:

function foo((string) $stringable) { // Type not enforced, but possibility
of casting checked
}

I'm aware that this RFC addresses a small goal, but accepting lot of small
changes compared to bigger ones with a broader vision could lead to even
more inconsistencies in the core in the longer run.

Regards,
Patrick


Re: [PHP-DEV] [RFC]

2020-02-13 Thread Rowan Tommins
On Thu, 13 Feb 2020 at 12:04, Manuel Canga  wrote:

>
>
> On Thu, 13 Feb 2020 at 08:58, Rowan Tommins 
> wrote:
>
>> On 12 February 2020 23:12:34 GMT+00:00, Manuel Canga <
>> manuelca...@gmail.com> wrote:
>> >El mié., 12 feb. 2020 23:01, Rowan Tommins 
>> >escribió:
>> >In your example, you has the same options:
>> >
>> >>
>> >1. Change import
>> >2. Add namespace:
>> >
>> >['Acme\Global\I18N',\translate::function]
>>
>>
>> There is no collision between 'Foo::translate()' and 'translate()', so
>> there is no reason to change the import. That's true of executing the
>> functions, so it should remain be true of resolving them to strings.
>>
>> There is collision with import which you added.
>


There is no collision. This is perfectly valid PHP code:

namespace Foo;
use \explode;

class Bomb { public static function explode() { return 'Bang! Bang!'; } }

$bangs = explode(' ', Bomb::explode());


There is no ambiguity here, explode(...) refers precisely to the global
function 'explode' which is unrelated to the class method 'Bomb::explode'.
The same applies if I import the function from somewhere other than the
global namespace:

namespace Foo;
use Acme\BetterArrayFunctions\explode;

class Bomb { public static function explode() { return 'Bang! Bang!'; } }

$bangs = explode(' ', Bomb::explode());

Again, there is no ambiguity, explode(...) refers precisely to the function
'Acme\BetterArrayFunctions\explode,  which is unrelated to the class method
'Bomb::explode.

"explode::function" should mean "if I run explode() here, what is the
fully-qualified name of the function that would run?" If there's no
ambiguity of which function would run, there's no ambiguity of what value
::function should return.





> * Here, 'my_function' is only a string. Maybe a global function( without
> namespace  ) or maybe a method or other case. With native array_map is a
> global function. However, you can have a function like this:
>
> function array_map( $method, $array) {
>   \Collection::$method( $array );
> }
>
> In both cases, you could do:
>
> array_map(\my_function::function, [] );
>



In the second case, it would be incorrect to use \my_function::function,
because you do not want the answer to the question "if I run \my_function()
here, what is the fully-qualified name of the function that would run?"

Annotating the argument that way wouldn't be useful for tools, either -
e.g. an IDE like PHPStorm would see ::function and offer "jump to
definition", but in this case it would jump to the definition of the global
function my_function, which is actually irrelevant.




>
>
>> Importantly, it might not work at all, if ::function gives an error if
>> the function doesn't exist.
>>
>>
> ::function only would retrieve string, like as ::class, exists or not. In
> fach, that code might not work at all due to class. What matter if Class
> does't exist ?. ::class doesn't produce error. Look:
> http://sandbox.onlinephpfunctions.com/code/0a8466a00974bc1ffc12b219569ced55753327bd
>



As pointed out elsewhere, an implementation of ::function would need to be
smarter than ::class, because unqualified function calls look first in the
current namespace, then fall back to global scope. For example:

namespace Foo;
function explode() {}

echo implode::function; // Should return 'implode', because that is what
implode() would run
echo explode::function; // Should return 'Foo\explode', because that is
what explode() would run


Regards,
-- 
Rowan Tommins
[IMSoP]


[PHP-DEV] Re: Literal / Taint checking

2020-02-13 Thread Craig Francis
Hi,

While there was a brief discussion about an *is_literal*() method in
August, I'm wondering where I can go next?

Just as a reminder, the main objection seemed to be that Taint checking is
the current solution. For example, those created by Laruence[1],
MediaWiki[2], and Matthew[3]. But this can never be as good at the PHP
engine explicitly stating a variable *only* contains literal values, where
it can be checked at runtime, and be a key part of the development process.

And while I'm using SQL injection in my examples (because it's easy to show
how it can enforce the use of parameterised queries); it would also be
useful to protect against command line injection, and HTML/XSS as well
(e.g. a templating system can only accept HTML as literal strings, and
the user supplied values be provided separately).

I'm assuming this would change the zval structure (to include an
"is_literal" flag?), and it would be more of a PHP 8.0 change, rather than
8.1.

Craig


---

Broken taint check, due to missing quote marks:

$sql = ‘... WHERE id = ’ . mysqli_real_escape_string($db, $_GET[‘id’]);

---

Support for "WHERE ... IN", ideally done via an abstraction, so you don't
need to write this every time:

$sql = '... WHERE id IN (' . substr(str_repeat('?,', count($ids)), 0, -1) .
')';

---

[1] https://github.com/laruence/taint
[2] https://www.mediawiki.org/wiki/Phan-taint-check-plugin
[3] https://psalm.dev/r/ebb9522fea

---




On Thu, 15 Aug 2019 at 19:02, Craig Francis 
wrote:

> Hi,
>
> How likely would it be for PHP to do Literal tracking of variables?
>
> This is something that's being discussed JavaScript TC39 at the moment
> [1], and I think it would be even more useful in PHP.
>
> We already know we should use parameterized/prepared SQL, but there is no
> way to prove the SQL string hasn't been tainted by external data in large
> projects, or even in an ORM.
>
> This could also work for templating systems (blocking HTML injection) and
> commands.
>
> Internally it would need to introduce a flag on every variable, and a
> single function to check if a given variable has only been created by
> Literal(s).
>
> Unlike the taint extension, there should be no way to override this (e.g.
> no taint/untaint functions); and if it was part of the core language, it
> will continue to work after every update.
>
> One day certain functions (e.g. mysqli_query) might use this information
> to generate a error/warning/notice; but for now, having it available for
> checking would be more than enough.
>
> Craig
>
>
>
> public function exec($sql, $parameters = []) {
> if (!*is_literal*($sql)) {
> throw new Exception('SQL must be a literal.');
> }
> $statement = $this->pdo->prepare($sql);
> $statement->execute($parameters);
> return $statement->fetchAll();
> }
>
> ...
>
> $sql = 'SELECT * FROM table WHERE id = ?';
>
> $result = $db->exec($sql, [$id]);
>
>
>
> [1] https://github.com/tc39/proposal-array-is-template-object
> https://github.com/mikewest/tc39-proposal-literals
>


Re: [PHP-DEV] [RFC]

2020-02-13 Thread Manuel Canga
On Thu, 13 Feb 2020 at 08:58, Rowan Tommins  wrote:

> On 12 February 2020 23:12:34 GMT+00:00, Manuel Canga <
> manuelca...@gmail.com> wrote:
> >El mié., 12 feb. 2020 23:01, Rowan Tommins 
> >escribió:
> >In your example, you has the same options:
> >
> >>
> >1. Change import
> >2. Add namespace:
> >
> >['Acme\Global\I18N',\translate::function]
>
>
> There is no collision between 'Foo::translate()' and 'translate()', so
> there is no reason to change the import. That's true of executing the
> functions, so it should remain be true of resolving them to strings.
>
> There is collision with import which you added.



>
>
> >Explain:
> >
> >When you do: [ class, method ] or [ $object, method ]. Method has not
> >namespace, you write it without namespace( like global functions )
>
>
> I think this is where we are thinking differently. A method name is not
> "like a global function", it's just a name; it doesn't belong in the same
> category.
>
> You might have any number of classes that use the same method name, but
> with completely different parameters and purpose, so "a method named foo"
> isn't a useful concept outside some specific class or interface.
>
> On the other hand, you can only have one function with a particular
> fully-qualified name, and the proposed feature is a way of referencing that.
>
>
Function as callable is different as regular function. Example:

http://sandbox.onlinephpfunctions.com/code/99408213d1ed740f60471646f16f9765d7efa93e

namespace MyProject;

function my_function() {
  //
}

my_function(); // it calls to \MyProject\my_function

array_map('my_function', [] ); //*

* Here, 'my_function' is only a string. Maybe a global function( without
namespace  ) or maybe a method or other case. With native array_map is a
global function. However, you can have a function like this:

function array_map( $method, $array) {
  \Collection::$method( $array );
}

In both cases, you could do:

array_map(\my_function::function, [] );





>
>
> >Other example:
> >
> >$class = \MyClass::class;
> >$method = \method::function;
> >
> >and...
> >
> >$class = '\MyClass';
> >$method = 'method';
> >
> >$obj = new $class();
> >$obj->$method();
> >
> >Both are the same, but first is more semantic.
>
>
> This isn't semantic at all - it works only because \method::function
> happens to return the string you want, but so does \method::class; neither
> is actually labelling it as what it is, which is a method within class
> \MyClass.
>
> Importantly, it might not work at all, if ::function gives an error if
> the function doesn't exist.
>
>
::function only would retrieve string, like as ::class, exists or not. In
fach, that code might not work at all due to class. What matter if Class
does't exist ?. ::class doesn't produce error. Look:
http://sandbox.onlinephpfunctions.com/code/0a8466a00974bc1ffc12b219569ced55753327bd

If class doesn't exist, nothing happend.


Thank, Rowan. You points of view are very interesting.


Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-13 Thread Ekin B.
Hi all,

> On February 13, 2020 1:52 PM Côme Chilliet 
>  wrote:
> 
>  
> Le mercredi 12 février 2020, 19:20:56 CET Niklas Keller a écrit :
> > Naming
> > 
> > I think we shouldn't take over the naming of the super globals, e.g.
> > $_GET really contains the query parameters and has nothing to do with
> > GET or POST, so $request->getQueryParameter(...) would be a better
> > name.
> 
> I think this remark is really on point.
> GET and POST are HTTP methods and not ways of passing data. You can have 
> query parameters on any request, and you can have POST data with a lot of 
> other HTTP methods, as is commonly used in REST APIs.
> 
> I do not like the name getQueryParameter at first sight, but I do not like 
> get() and post() for getting values from $_GET and $_POST.
> I would expect a method named post to actually post something, not just get a 
> value.
> 
> -- 
> Côme Chilliet
> FusionDirectory - https://www.fusiondirectory.org
> 
> --

I agree that this is indeed on point.
Personally I would like $request->getQueryParameter() and $request->getBody() 
over $request->get() and $request->post().
In the former case you are asking for the parameters in the query string (query 
component of the URI) and the latter is to get the request body. These method 
names make it very clear what you're asking for.

What kind of bothers me in general about this RFC is that... we are talking 
about Request and Response and these are standard HTTP components, yet the RFC 
is about providing wrappers for existing global PHP variables and functions. It 
does not try to model these components as they are in their standard, nor aim 
to do so.

This is why I believe it's better to leave it to userland implementations. 
Besides the fact that they are widely adopted, they attempt to follow the 
specification they are providing. 

Regards,
Ekin H. Bayar 
https://ekins.space 
https://heap.space

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



Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

2020-02-13 Thread Côme Chilliet
Le mercredi 12 février 2020, 19:20:56 CET Niklas Keller a écrit :
> Naming
> 
> I think we shouldn't take over the naming of the super globals, e.g.
> $_GET really contains the query parameters and has nothing to do with
> GET or POST, so $request->getQueryParameter(...) would be a better
> name.

I think this remark is really on point.
GET and POST are HTTP methods and not ways of passing data. You can have query 
parameters on any request, and you can have POST data with a lot of other HTTP 
methods, as is commonly used in REST APIs.

I do not like the name getQueryParameter at first sight, but I do not like 
get() and post() for getting values from $_GET and $_POST.
I would expect a method named post to actually post something, not just get a 
value.

-- 
Côme Chilliet
FusionDirectory - https://www.fusiondirectory.org

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



Re: [PHP-DEV] Re: Changing the generated name for anon classes

2020-02-13 Thread Nikita Popov
On Fri, Feb 7, 2020 at 2:35 PM Nikita Popov  wrote:

> On Thu, Feb 6, 2020 at 9:08 PM Andrea Faulds  wrote:
>
>> Hi,
>>
>> Nikita Popov wrote:
>> > Hi internals,
>> >
>> > Based on a suggestion by Nicolas Grekas,
>> > https://github.com/php/php-src/pull/5153 changes the generated name for
>> > anonymous classes to include the name of the parent class or first
>> > interface. So instead of just class@anonymous, you'll see something
>> like
>> > EventHandler@anonymous in error messages, for example.
>> >
>> > There's a minor BC break here, for code checking for a "class@anonymous
>> "
>> > prefix, which should be easy to rectify by checking for "@anonymous"
>> > instead.
>> >
>> > What do people think about doing this change?
>> >
>> > Regards,
>> > Nikita
>> >
>>
>> Perhaps it would make sense to include the namespace used by the code
>> which defines/instantiates the class? That might make it easier, when
>> looking at a mysterious anonymous class using var_dump() deep in a big
>> project perhaps, to find out where it came from.
>>
>
> That would be a possible alternative. This is similar to what we do for
> closures.
>
> As we need the generated name to be reasonably concise, we can only do one
> or the other though. I don't know which one is more useful... Maybe Nicolas
> wants to chime in.
>

I've scrolled through anon class uses in popular composer packages, and
that convinced me that parent/interface is probably the most useful
information here. Adding the namespace prefix leaves you with something
like "Amp\class@anonymous", which doesn't really tell you anything at all,
while adding the interface gives you "Amp\CancellationToken@anonymous",
which is fairly meaningful. Many more examples like this.

Nikita


[PHP-DEV] [RFC] token_get_all() TOKEN_AS_OBJECT mode

2020-02-13 Thread Nikita Popov
Hi internals,

This has been discussed a while ago already, now as a proper proposal:
https://wiki.php.net/rfc/token_as_object

tl;dr is that it allows you to get token_get_all() output as an array of
PhpToken objects. This reduces memory usage, improves performance, makes
code more uniform and readable... What's not to like?

An open question is whether (at least to start with) PhpToken should be
just a data container, or whether we want to add some helper methods to it.
If this generates too much bikeshed, I'll drop methods from the proposal.

Regards,
Nikita