Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streams
Kind regards
Niels
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
Niels
This seems quite reasonable to me overall. My one question is regarding the writer version. Why is that not a static method, too? I would have expected that to be a "named constructor" just like the reader.
--Larry Garfield
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsThis seems quite reasonable to me overall. My one question is regarding the writer version. Why is that not a static method, too? I would have expected that to be a "named constructor" just like the reader.
--Larry Garfield
Hi Larry
XMLReader already had these static methods that act as named constructors, but XMLWriter has no named constructors at the moment.
The XMLWriter::openMemory() and XMLWriter::openUri() functions are instance methods that must be called after doing "new XMLWriter".
If these two existing functions were static methods instead, I would've made XMLWriter::openStream() static too.
So IOW, for consistency I followed the model of the existing XMLWriter methods.
While it is possible to do the magic trick that XMLReader uses to have the open methods on XMLWriter both static and non-static, this is quite hacky and was only done to XMLReader for BC reasons.
Kind regards
Niels
Le 23 avr. 2024 à 21:23, Niels Dossche dossche.niels@gmail.com a écrit :
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsThis seems quite reasonable to me overall. My one question is regarding the writer version. Why is that not a static method, too? I would have expected that to be a "named constructor" just like the reader.
--Larry Garfield
Hi Larry
XMLReader already had these static methods that act as named constructors, but XMLWriter has no named constructors at the moment.
The XMLWriter::openMemory() and XMLWriter::openUri() functions are instance methods that must be called after doing "new XMLWriter".
If these two existing functions were static methods instead, I would've made XMLWriter::openStream() static too.
So IOW, for consistency I followed the model of the existing XMLWriter methods.While it is possible to do the magic trick that XMLReader uses to have the open methods on XMLWriter both static and non-static, this is quite hacky and was only done to XMLReader for BC reasons.
That’s odd. The inconsistency was introduced (or at least sanctioned) in PHP 8.0. In PHP 7, XMLReader::open() and XMLReader::XML() already worked when used both as static and non-static methods, but triggered a deprecation warning when called statically. The deprecation warning was removed in 8.0, regardless of the differing semantics when called statically and non-statically, and regardless of the the inconsistency with corresponding XMLWriter methods.
Another point: when called statically on a subclass, both XMLReader::open()
and XMLReader::XML()
return an object of type XMLReader
, not of the subclass: https://3v4l.org/lCOAvJ
For that reason, they are unusable as static methods on a subclass. The new openStream()
method should work on instances, so that it will be usable on subclasses. (And for the same reason, I think it was a mistake to undeprecate XMLReader::{open,XML}()
as static methods in 8.0.)
—Claude
Le 23 avr. 2024 à 21:23, Niels Dossche dossche.niels@gmail.com a écrit :
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsThis seems quite reasonable to me overall. My one question is regarding the writer version. Why is that not a static method, too? I would have expected that to be a "named constructor" just like the reader.
--Larry Garfield
Hi Larry
XMLReader already had these static methods that act as named constructors, but XMLWriter has no named constructors at the moment.
The XMLWriter::openMemory() and XMLWriter::openUri() functions are instance methods that must be called after doing "new XMLWriter".
If these two existing functions were static methods instead, I would've made XMLWriter::openStream() static too.
So IOW, for consistency I followed the model of the existing XMLWriter methods.While it is possible to do the magic trick that XMLReader uses to have the open methods on XMLWriter both static and non-static, this is quite hacky and was only done to XMLReader for BC reasons.
That’s odd. The inconsistency was introduced (or at least sanctioned) in PHP 8.0. In PHP 7, XMLReader::open() and XMLReader::XML() already worked when used both as static and non-static methods, but triggered a deprecation warning when called statically. The deprecation warning was removed in 8.0, regardless of the differing semantics when called statically and non-statically, and regardless of the the inconsistency with corresponding XMLWriter methods.
Another point: when called statically on a subclass, both
XMLReader::open()
andXMLReader::XML()
return an object of typeXMLReader
, not of the subclass: https://3v4l.org/lCOAvJ https://3v4l.org/lCOAvJ
For that reason, they are unusable as static methods on a subclass. The newopenStream()
method should work on instances, so that it will be usable on subclasses. (And for the same reason, I think it was a mistake to undeprecateXMLReader::{open,XML}()
as static methods in 8.0.)
This is a good point indeed, good catch!
I agree it should be an instance method then to avoid this problem.
It also makes me wonder why the static form is the canonical form shown in the manual (https://www.php.net/manual/en/xmlreader.open)... We should probably show the instance method as the recommended one.
I also checked whether it's possible to return "static" instead of "XMLReader" for the existing static functions, but that's not possible in the general case because we won't know with which arguments to call the constructor...
Anyway, I'm going to update the RFC for this.
—Claude
Kind regards
Niels
On Mon, Apr 22, 2024 at 8:43 PM Niels Dossche dossche.niels@gmail.com
wrote:
Hi internals
I'm opening the discussion for my RFC "Add openStream() to
XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streams
Not sure this needs an RFC. Its a sensible addition and the explanations
make sense. :+1: from me.
Kind regards
Niels
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
Niels
Hi internals
It's been over two weeks since I opened the discussion.
Please raise any last concerns now.
I'd like to start voting next week Monday.
Kind regards
Niels
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsHi internals
It's been over two weeks since I opened the discussion.
Please raise any last concerns now.
I'd like to start voting next week Monday.Kind regards
Niels
Please include some examples of what a full usage would look like with the new additions. I'm not super experienced with those libraries right now, but the "create the object, THEN populate it with its data source" pattern feels very weird to me. (Though at least it's consistent now rather than as it was before, thanks.)
--Larry Garfield
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsHi internals
It's been over two weeks since I opened the discussion.
Please raise any last concerns now.
I'd like to start voting next week Monday.Kind regards
NielsPlease include some examples of what a full usage would look like with the new additions. I'm not super experienced with those libraries right now, but the "create the object, THEN populate it with its data source" pattern feels very weird to me. (Though at least it's consistent now rather than as it was before, thanks.)
--Larry Garfield
Hi Larry
I added minimal examples for both.
The streams I used are just the memory and output streams for simplicity so that it can be tested on its own.
Kind regards
Niels
Hi Niels,
Am 10.05.2024 19:38 schrieb Niels Dossche dossche.niels@gmail.com:
> >> >>> Hi internals >>> >>> I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}". >>> RFC link: https://wiki.php.net/rfc/xmlreader_writer_streams >>> >>> Kind regards >>> Niels >> >> Hi internals >> >> It's been over two weeks since I opened the discussion. >> Please raise any last concerns now. >> I'd like to start voting next week Monday. >> >> Kind regards >> Niels
Hi Marc
Haven't looked at the implementation but it feels weird to call an openStream method on an already opened stream on already instantiated object. What does it open?
I'm guessing this question is about the naming of the method?
The way I saw it is that you open the XMLReader/XMLWriter to the stream, but I can see how this could be confusing.
What about the names XMLReader->fromStream and XMLWriter->toStream ?
And what happens on calling openStream in a middle of reading/writing an XML document.
What happens on calling openStream stream after calling open - does it read/write from/to both?
What will happen is the same thing that already happens when you call $xmlWriter->openUri for example when it was already opened: from then on forward it will start writing only to the new uri. So when you call $xmlWriter->openStream($newstream) then it will start writing to the $newstream from then on forward, not to two streams at the same time.
Similarly, for XMLReader, when you call an open method again it will start reading from the last provided source from that point forward.
Best,
Marc
Kind regards
Niels
Kind regards Niels
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
Niels
Hi internals
The main complaint that kept coming up in internal communication was the choice of instance methods instead of static methods.
This has been brought up in this thread too.
I switched back to using static methods, and they're now called XMLReader::fromStream($stream) and XMLWriter::toStream($stream).
They return the static type, which means that they'll be compatible with child classes that inherit from XML{Reader,Writer}.
The child constructor will in that case be called with no arguments (i.e. it'll do new static()
internally).
The RFC text has been updated to reflect this change. New RFC text version is 0.10.0.
Kind regards
Niels
Le 18 mai 2024 à 01:13, Niels Dossche dossche.niels@gmail.com a écrit :
Hi internals
I'm opening the discussion for my RFC "Add openStream() to XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsHi internals
The main complaint that kept coming up in internal communication was the choice of instance methods instead of static methods.
This has been brought up in this thread too.
Hi,
Now you have a complaint because of the choice of static methods instead of instance methods... :-)
You are introducing an inconstancy for subclasses, because:
-
As noted in an earlier message, the existing open-like methods (XMLReader::XML() and XMLReader::open()) don’t work statically on subclasses (they create an instance of the base class, not of the subclass). You must use them as instance methods.
-
On the other hand, the method you are going to introduce won’t work as instance method. You must use it statically.
Please, if you want to make the new method static only, fix first the existing ones, so that they also work statically (on subclasses).
(But again, I prefer that all those methods work on instances, as it was the case before PHP 8. They shouldn’t have been switched to static-but-broken-for-subclasses without discussion.)
—Claude
On Tue, May 21, 2024 at 12:58 PM Claude Pache claude.pache@gmail.com
wrote:
Le 18 mai 2024 à 01:13, Niels Dossche dossche.niels@gmail.com a écrit
:Hi internals
I'm opening the discussion for my RFC "Add openStream() to
XML{Reader,Writer}".
RFC link: https://wiki.php.net/rfc/xmlreader_writer_streamsKind regards
NielsHi internals
The main complaint that kept coming up in internal communication was the
choice of instance methods instead of static methods.
This has been brought up in this thread too.Hi,
Now you have a complaint because of the choice of static methods instead
of instance methods... :-)You are introducing an inconstancy for subclasses, because:
As noted in an earlier message, the existing open-like methods
(XMLReader::XML() and XMLReader::open()) don’t work statically on
subclasses (they create an instance of the base class, not of the
subclass). You must use them as instance methods.On the other hand, the method you are going to introduce won’t work as
instance method. You must use it statically.Please, if you want to make the new method static only, fix first the
existing ones, so that they also work statically (on subclasses).(But again, I prefer that all those methods work on instances, as it was
the case before PHP 8. They shouldn’t have been switched to
static-but-broken-for-subclasses without discussion.)
Fixing the existing ones would be a potential BC break, depending on
whether or not instance usage is completely eliminated.
The reason why many of us recommended static methods here is that they
would act as named constructors, and reduce the potential for cases where a
new stream is read from or written to mid-flight. Essentially, the usage
becomes:
$reader = XMLReader::fromStream($streamHandle);
// read the stream
and
$writer = XMLWriter::toStream($streamHandle);
// write to the stream
My understanding is that the implementations will allow for subclassing.
Having these as instance methods means that subclasses would need to
potentially add handling to ensure the instance is not in an invalid state
(e.g., by switching streams mid-flight), which would add far more edge
cases to handle.
--
Matthew Weier O'Phinney
mweierophinney@gmail.com
https://mwop.net/
he/him
Le 21 mai 2024 à 21:00, Matthew Weier O'Phinney mweierophinney@gmail.com a écrit :
(But again, I prefer that all those methods work on instances, as it was the case before PHP 8. They shouldn’t have been switched to static-but-broken-for-subclasses without discussion.)
Fixing the existing ones would be a potential BC break, depending on whether or not instance usage is completely eliminated.
Yes, of course. But there exist options that don’t make the API even more inconsistent than it already is. I hereby propose:
-
XMLReader::fromUrl()
as replacement for(new XMLReader)->open()
-
XMLReader::fromString()
as replacement for(new XMLReader)->xml()
… which would make me happy. (The old, inconsistently-named, instance-and-semi-broken-static methods could be kept for BC and marked as soft-deprecated in the manual.)
—Claude
Le 21 mai 2024 à 21:00, Matthew Weier O'Phinney mweierophinney@gmail.com a écrit :
(But again, I prefer that all those methods work on instances, as it was the case before PHP 8. They shouldn’t have been switched to static-but-broken-for-subclasses without discussion.)
Fixing the existing ones would be a potential BC break, depending on whether or not instance usage is completely eliminated.
Yes, of course. But there exist options that don’t make the API even more inconsistent than it already is. I hereby propose:
XMLReader::fromUrl()
as replacement for(new XMLReader)->open()
XMLReader::fromString()
as replacement for(new XMLReader)->xml()
… which would make me happy. (The old, inconsistently-named, instance-and-semi-broken-static methods could be kept for BC and marked as soft-deprecated in the manual.)
—Claude
Okay, that seems reasonable to me and I can do that.
I'll make them return static and do "new static()" like I proposed with the new static method.
For XMLWriter, I suppose we also want the static counterparts:
-
XMLWriter::toMemory()
for(new XMLWriter)->openMemory()
-
XMLWriter::toUri()
for(new XMLWriter)->openUri()
If that sounds good I'll update the RFC.
Niels
Okay, that seems reasonable to me and I can do that.
I'll make them return static and do "new static()" like I proposed with the new static method.For XMLWriter, I suppose we also want the static counterparts:
XMLWriter::toMemory()
for(new XMLWriter)->openMemory()
XMLWriter::toUri()
for(new XMLWriter)->openUri()
If that sounds good I'll update the RFC.
Niels
I've now updated the RFC to include this kind of change; except I used the term Url instead of Uri.
See the new subsection "Consistency" for what I propose.
Niels