[PSR-5] Defining custom types

407 views
Skip to first unread message

Mike van Riel

unread,
Aug 15, 2014, 5:27:33 PM8/15/14
to php...@googlegroups.com
Dear list,

For some time there is a discussion going on in the issue tracker where
we are trying to formulate an answer to the following use cases:

1. Being able to document Laraval Facades (class_alias'ed types)
2. Being able to describe the available properties or methods on an
object deriving from stdClass (such as JSON objects or SOAP objects)
3. Being able to graft additional method and property descriptions on
existing objects (for example: classes with magic methods from libraries)
4. Create a re-usable definition of an associative array's members

In order to solve these use cases (and more) it would be possible to
document pseudo-types using a new tag `@typedef` (as is used, for
example, in [Javascript](http://usejsdoc.org/tags-typedef.html)). You
can find the documentation for the new pseudo-type here:
https://github.com/phpDocumentor/fig-standards/pull/54

The intent was to come to a definition that could be discussed on this
list but we kinda hit a wall in the mean time. Due to scope and
availability.

I would like to know: do you see this as a useful addition that you'd
use? If so: where do you expect a @typedef tag to be defined and where
would the tag be available?

I am explicitly not stating my opinions in this discussion as I would
like clean opinions; if you want to know the complete discussion and
what is considered, please read the above PR and associated issue
(https://github.com/phpDocumentor/fig-standards/issue/7).

Thanks for your time on answering this question and taking the time to
get PSR-5 a step closer to completion.

Mike

Jennifer Hodgdon

unread,
Aug 15, 2014, 5:52:20 PM8/15/14
to php...@googlegroups.com
Looking at the JSDoc @typdef docs page cited below, I do not think
this will be of great use to the Drupal project for use in PHP
documentation. We would tend to define an interface or a class if we
have standard properties to document/use.

And I personally think this would lead to documentation that is less
human-readable. For instance, the JSDoc example defines

* @typedef {(number|string)} NumberLike

and then uses NumberLike in other documentation, such as

* @param NumberLike param_name

I'm not sure what the scope of the @typedef tag is, but it seems like
if it was global rather than local to a file, that in some other file
if you encountered NumberLike, you'd be saying "Huh? What is that?"
(on an API docs display site, presumably it would turn into a link or
have hover properties or something to clue you in).

That said... if other projects have need for it, I don't see a reason
not to add it to the standards, aside from the necessity of docs
parsers supporting it. On the other hand, PSR-5 doesn't seem inclined
to adopt tags that I've suggested that we use a lot in the Drupal
project, so maybe projects that need this could just define their own
custom tag, as we'll have to if we ever adopt PSR-5?

--Jennifer
--
Jennifer Hodgdon * Poplar ProductivityWare
www.poplarware.com
Drupal web sites and custom Drupal modules

Mike van Riel

unread,
Aug 15, 2014, 6:42:16 PM8/15/14
to php...@googlegroups.com
Hello Jennifer,

I am not going to comment on the specifics of the `@typedef` tag just yet until more people have replied (I hope they do); I did want to respond to your last paragraph:


That said... if other projects have need for it, I don't see a reason not to add it to the standards, aside from the necessity of docs parsers supporting it. On the other hand, PSR-5 doesn't seem inclined to adopt tags that I've suggested that we use a lot in the Drupal project, so maybe projects that need this could just define their own custom tag, as we'll have to if we ever adopt PSR-5?
I am sorry if you feel that I would not be 'inclined' to include Drupal's, or your, tags. I can assure you that this is not true. Which tags are considered has nothing to do with Drupal, you or any specific project. I believe that it is out of scope of this specification to include tags used to format the text of the Description of a DocBlock. The only other tag that I recall being mentioned is the `@file` tag which is not rejected nor accepted. I haven't discussed it yet.

If you feel that I am not 'inclined' to consider other tags not covered by the previous paragraph, please refresh my memory because then I have failed to properly make a mental or physical note of it.

And yes, I say 'I' because I am currently the editor for PSR-5 and responsible for drafting the results of discussions in this group and also to filter out topics that I consider unfit for inclusion. I try my best to limit the number of tags; this does mean that including a new tag should have significant value to multiple projects that is not provided in another way.

sun

unread,
Aug 15, 2014, 9:36:53 PM8/15/14
to php...@googlegroups.com
I do think the proposal has merit, but the spec has to guarantee a clear ownership and origin of custom pseudo-types.

The name and signature of the @typedef tag itself is fine and not being questioned.  The question is where and how @typedef can be specified, and what the name and scope of custom pseudo-types can be, especially when considering that a single project may consist of multiple libraries/code bases.

The scope, visibility, name, and ideally also location of custom pseudo-types must be unique.  Pseudo-types should be easily parseable/discoverable by humans (not only by PHPDoc parsers), they should be maintainable.  These are two independent expectations from vastly different angles.

The architectural design of this specification should prevent all remotely possible name clashes (with actual PHP code as well as other pseudo-types) ahead of time; ideally by front-loading a range of very strict and rigid rules for using @typedef, enforcing and resolving all ownership, origin, authority, scope, and naming concerns.

The challenge is mostly of technical nature.  If/when offering this flexibility, we need to ensure that PHPDoc remains to be self-contained, sane, and doesn't result in nasty surprises.

As an attempt to resolve that challenge, I proposed a PR to vastly limit possible usages of @typedef and thus resolve all ownership/origin/authority/naming/discovery concerns by strictly obeying PHP core language/namespace rules.  If anyone has a better idea, that would be welcome.

Mike van Riel

unread,
Aug 16, 2014, 2:06:39 AM8/16/14
to php...@googlegroups.com

On 16-08-14 03:36, sun wrote:
The scope, visibility, name, and ideally also location of custom pseudo-types must be unique.  Pseudo-types should be easily parseable/discoverable by humans (not only by PHPDoc parsers), they should be maintainable.  These are two independent expectations from vastly different angles.

The architectural design of this specification should prevent all remotely possible name clashes (with actual PHP code as well as other pseudo-types) ahead of time; ideally by front-loading a range of very strict and rigid rules for using @typedef, enforcing and resolving all ownership, origin, authority, scope, and naming concerns.

As I see it PSR-5 should not be responsible for describing the discoverability of the `@typedef` tag (as you stated in your PR: one typedef in a file and each typedef should have its own file).

Compare the same thing to PHP: PHP itself does not describe the discoverability of classes, which enabled developers to have varying approaches to directory hierarchies to match their style. It is PSR-0 that adds rules for discoverability for classes. \

I think the same approach should apply with PSR-5: PSR-5 describes the scheme and syntax and a future PSR could describe things like discoverability or coding standards for DocBlocks. By separating these concerns it is easier to adopt PSR-5 and provide people with the flexibility that they need to manage their projects.

Alexander Makarov

unread,
Aug 16, 2014, 8:03:34 AM8/16/14
to php...@googlegroups.com
1. I've never encountered class aliases in practice (should be interesting, will definitely check how Laravel uses these).
2. In case of SOAP we have all the tools to generate classes representing data using WSDL so I don't think @typedef will be useful in this case. For JSON there's more or less common approach http://json-schema.org/. In general I don't think using raw stdClass is a good idea. If you need just data, use arrays.
3. Isn't it covered by @inheritdoc?

/**
  * Does something
  * @property string $a
  * @property string $b
 /*
class A
{
}

/**
  * @inheritdoc
  * @property int $additionalProperty
  */
class B extends A {
}

4. Sounds interesting theoretically but in practice configuration array typically has a high level of nesting and lots of cases where we have variable number of such. Sub-configs for dependencies etc. Not sure how to handle it and if it worth doing at all.

Overall I tend to think that while it's interesting in theory it won't be usable practically.

Chuck Burgess

unread,
Aug 18, 2014, 4:49:12 PM8/18/14
to php...@googlegroups.com
To me, these things seem like they all boil down to "I want my docs to present this "thing" as if it was a documentable _class_, but I don't want to write an actual class".  Many times when I've encountered questions about "how can I document _foo_", it was because the code in question was written with the intent of class-like (or ValueObject-like) behavior, but with non-class code.  The behavior of the code was usually class-like, e.g. a stdClass with properties being referenced in code, an "options" array with a specific list of what "options" are actually available.  PHP obviously allows for such, but I've never really understood why such code _should not_ be written as an actual class.  It would certainly be a class in a strongly typed language, right?  By insisting on _not_ writing an actual class, but wanting to document its aspects as if it were a class, ... it almost always seems to be a code smell to me.

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/0e11c654-6666-4bf2-af8a-da33676a9cf1%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Paul M. Jones

unread,
Aug 18, 2014, 4:53:30 PM8/18/14
to php...@googlegroups.com

On Aug 18, 2014, at 3:48 PM, Chuck Burgess <demon...@gmail.com> wrote:

> To me, these things seem like they all boil down to "I want my docs to present this "thing" as if it was a documentable _class_, but I don't want to write an actual class". Many times when I've encountered questions about "how can I document _foo_", it was because the code in question was written with the intent of class-like (or ValueObject-like) behavior, but with non-class code. The behavior of the code was usually class-like, e.g. a stdClass with properties being referenced in code, an "options" array with a specific list of what "options" are actually available. PHP obviously allows for such, but I've never really understood why such code _should not_ be written as an actual class. It would certainly be a class in a strongly typed language, right? By insisting on _not_ writing an actual class, but wanting to document its aspects as if it were a class, ... it almost always seems to be a code smell to me.

Hear hear.


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

Modernizing Legacy Applications in PHP
http://mlaphp.com



Mike van Riel

unread,
Aug 18, 2014, 5:06:54 PM8/18/14
to php...@googlegroups.com
I agree that 90% of the stuff that was written would have had a much better life as a true object. However: there will always be a difference between theory and practice and practice teaches us that in code people prefer the 'simple' solutions.

Also, there are several use cases that you cannot solve (easily).

Some examples that spring to mind:

- Classes that are defined using class_alias; such as Laravel Facades
- Configuration arrays, such as those used by Zend Framework
- JSON decoded objects and arrays (not without using Symfony Serializer or JMS Serializer)
- SOAP Result objects (without diving into class mappings, which is an order of pain beyond normal SOAP)
- Classes that rely on magic methods and dynamic behaviour based on a state (for example generic Doctrine Repositories)

Can the above issues be solved? Not without a significant investment that goes beyond the willingness of the Lead Devs.

The proposed option should _always_ be a last resort as it will introduce maintainability issues but I can see where the request
is coming from.

(fyi: I am not too keen on this specific feature, but I can definitely see where it is coming from)

Alexander Makarov

unread,
Aug 20, 2014, 3:42:54 AM8/20/14
to php...@googlegroups.com
API results and framework configs are quite deep nested structures. I doubt it will be a good experience defining these via nested array types. If I absolutely have to do it I'd prefer something like XSD schema instead.
Reply all
Reply to author
Forward
0 new messages