Chris, thank you for picking this back
up! This is the sort of thing we should be discussing, according
to a majority of our membership. :-)
- 1.1: The description of Opaque and Hierarchical URIs need
examples. From the descriptions in the bullet points... I have no
idea what they are. :-) It's not until 2 paragraphs later ("For
example, a HTTP client...") that i have any idea what you're
talking about.
- 1.2: I'm not comfortable with leaving setters up to
implementations. If these objects are intended to be immutable,
say so and ban post-constructor changes. If not, then we do need
to standardize the manipulation operations as well. Otherwise if
I need to touch even a single property I'm suddenly coupled to a
particular implementation. Reading through the rest of the spec,
I think a value object makes sense along with a SHOULD NOT to
discourage (but not forbid) adding mutators.
- Providing the meat of the implementation as part of the docblock
is inconsistent with what we did in PSR-3 and what is being
discussed for PSR-Cache. I'm not against it necessarily; Drupal
does that a lot, for instance. But I know not everyone likes
that. (Fabien in particular is not a fan, IIRC.) I think a lot
of the extensive details, like the charts and samples, should be
pulled out to spec sections rather than baked into the interfaces.
- "URIs in string form have the syntax": the example here
specifically says hierarchical-part, which implicitly excludes
opaque URIs. From my read of the RFC, however, opaque URIs should
have the same special meaning for ? and # and such. So shouldn't
that be "body" or something?
Hm, no, reading the RFC they use hier-part too. That's silly. :-)
- The docblocks on toDecodedString() and toEncodedString() are
very good, however, as they relate specifically to the behavior of
that method. Nicely done!
- For getScheme(), are you sure that's case-insensitive? I
thought schemes were case sensitive, in that
http:// and
HTTP://
were different things.
- Should geScheme() return NULL, or empty string? Because if the
scheme isn't there, isn't that the same as it being an empty
string? (NULL is a byatch to code around, so I try to avoid it
whenever I can.)
- Is my understanding correct that getHierarchicalPart() on
"http://example.com/gir/zim?dib=dab" would be
"
example.com/gir/zim"? An example here could help, especially
since HTTP is likely to be the most common URI used. That would
slightly duplicate the big docblock at the top, but as stated
above I think it's best to break that part out of the interface to
the RFC proper. (A consistent example for all of the getters
would be good.)
- The docblock for getQueryAsArray() implies that it does not
support nested arrays. That's extremely common in PHP for form
handling, so I think we want to be clear on how that should be
handled. "It can't be" is an answer that would torpedo this
spec's usefulness. :-( It should also explicitly say that in case
of no query, array() is returned rather than NULL.
- I don't understand why I'd want the preceding // on the
hierarchical part in getHierarhicalPart(). Is that what the RFC
says to do? Because I don't know how useful I'd find that as a
developer.
- Is it possible to break getUserInfo() into getUser() and
getPassword()? Or in addition to? Or is it expected that a using
system needs to parse those out of the UserInfo string itself?
(As long as it wouldn't violate the spec, I'd prefer to include
those extra methods for ease of use.)
- getPath() should explicitly specify if the path includes the
leading / or not. Even if the RFC says, we should reiterate here
because that's where people will look to say "Wait, am I going to
get a / back or no?"
- In the normalize() docblock, I'd pair the examples up with their
before/after forms rather than having a before list and after
list. Same for resolve() and relativize(). The examples are
good, but better organization would make them clearer.
- The resolve() and relativize() methods have a lot of
conditionals in their docblocks. That to me is a code smell. See
below.
- UnexpectedValueException 's docblock should have a single line
short summary. The rest of the text should be a longdesc. Also,
"if a value does not match with a set of values" took me 3 reads
to understand. :-) It looks like it's copied from the base PHP
exception. Given that it's only used in one place,
getQueryAsArray(), I think we can make it much more explicit:
InvalidQueryString extends \UnexpectedValue Exception.
On the whole, this reads like a direct port of the RFC to PHP. I
therefore really really like it. :-) The language is overall very
precise and to the point, which is good. And it lays a good
foundation for getting back to to the HTTP work, which I think is
going to be some of our most important PSRs. Well done, Chris!
The only significant pushback I'd offer is that it feels like
HierarhicalUriInterface needs to be split into two: A complete URI
interface and a relative URI. That would, I think, greatly
simplify the descriptions (and therefore implementations) of
resolve() and relativize(). That would also then replace
isAbsolute() with simply an instanceof check.
If there's a specific reason why they can't be split let me know,
because it feels to me like they should. There's too much
conditional logic embedded in those descriptions otherwise.
--Larry Garfield