Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for enumerated options fro properties and method arguments #557

Closed
MarkBaker opened this issue Aug 5, 2012 · 36 comments
Closed
Milestone

Comments

@MarkBaker
Copy link

PHPDocumentor doesn't support listing of enumerated values for a property or for a method argument. I suggest that this would be a useful addition to doc blocks;

/*
 * Object State
 *
 * @var string
 * @options=["open", "closed", "pending"] 
 **/ 
private $_state;
/**
 * Set Object State
 *
 * @param string $plotType
 * @options=["open", "closed", "pending"] 
 **/
public function setPlotType($plotType = '') {
    ...
}

While @options might not be the best tag to use, or this syntax could be simplified (and might need modification if the list of options was to be a list of valid constant values), it seems to me that it would be a useful addition to the doc block because the alternative is documenting it in the general block comments. A formal syntax of some description would simplify this and provide a standardised display of the valid options

@boenrobot
Copy link
Contributor

IMHO, it's a better practice to define (class) constants, and then explicitly clarify in the description that acceptable values are one of said constants.

But disregarding that bit... Consider scenarios with multiple arguments, where you have multiple @param tags, followed by one @options. What does @options apply to? The first argument, or the last one specified by @param?

I think it would make much more sense to somehow embed enumerations within the type specification. The pair "[]" is already in use for array specifiers, so either "{}" or "()" should be used, e.g.

/**
 * Set Object State
 *
 * @param string("open", "closed", "pending") $plotType
 **/
public function setPlotType($plotType = '') {
    ...
}

or

/**
 * Set Object State
 *
 * @param string{"open", "closed", "pending"} $plotType
 **/
public function setPlotType($plotType = '') {
    ...
}

Even assuming you accept this variation, I would bet that this wouldn't be trivial to implement (although I don't know for sure, @mvriel would have to be the one to say that), especially considering that constants and other scalar values should also be valid enumarations... So it would probably be pushed for 2.1.

@mvriel
Copy link
Member

mvriel commented Aug 5, 2012

I was thinking about this issue and perhaps we should expand the scope and think about that. If you take a step back you'd consider that we have a definition of a boundary; something describing the limits of the given data type.

My initial idea would be that we can approach this from two angles:

  1. have a new element that defines boundaries for an @var or @param tag or
  2. expand the current @var or @param's type to include boundary information (imo: @options might be too abstract)

With boundaries I do not just mean a limited enumeration but also a value range (i.e. [0..3]), array structure or other type of information that limits the possible amount or structure of values contained in the @var or @param.

Downsides:

  1. a @var or @param may have more than 1 type (i.e. string|int) or even an array with composed type (i.e. (int|string)[]); how do we designate which to apply the boundary to?
  2. A boundary might get too complex (rigid array structure for example) to include in the Type information

In either case we might need a good way of presenting boundaries and existing standards may help out with that

@mvriel
Copy link
Member

mvriel commented Aug 5, 2012

p.s. if I were to implement this myself I'd consider it for 2.1+; if this item is contributed then I'd be happy to include it in 2.0

@MarkBaker
Copy link
Author

In all the cases where I'd be using this (at the moment), the option set would be a series of pre-defined class constants, and I do currently identify the set of options in the description. It was merely a question raised on SO this morning that made me think of an actual tag that would allow them to be defined, and where it would then be easier to link each option to the actual const definition in the docs, or to clarify the description in a structured manner.

Logically, (thinking of my suggested @options tag) if there were multiple @params each with their own @options, I'd anticipate alternate @param and @options tags so each @options referred explicitly to the previous @param

Equally, @param string{"open", "closed", "pending"} $plotType would work... it provides a precise structural definition.

There's also a couple of instances I can think of where a valid value would be a float within a range of -1.0 to 1.0... I hadn't considered using a bounds definition for that, but it is a logical extension from an enumerated set of options.

@boenrobot
Copy link
Contributor

There are already array specifiers, right? So there's no need to worry about that bit.

It's only a matter of specifiers for scalar types (which should extend to those that are part of array specifiers). The "{}" notation would work fine, even for numerical representations, e.g.

@param int{PHP_INT_MIN...-1,1...PHP_INT_MAX} $multiplier
function multiply($multiplier)

Would define $multiplier as expecting (basically) any integer other than 0. Although this here illustrates a new possible extension - a way to explicitly blacklist values rather then whitelist them... perhaps with "!"? Like

@param int{!0,!100} $multiplier
function multiply($multiplier)

would be interpreted as "any integer other then 0 and 100", while

@param int{!PHP_INT_MIN...0} $multiplier
function multiply($multiplier)

would be interpreted as "any non-negative integer".

Damn, this sounds so cool, yet hard...

@mvriel
Copy link
Member

mvriel commented Oct 6, 2012

There is a discussion going on in PHP-FIG where some of these aspects are touched; might be interesting for this issue

@liverbool
Copy link

and associative array?

@boenrobot
Copy link
Contributor

There's a whole other issue (#650) about that, although I guess this here is related as well.

@mvriel
Copy link
Member

mvriel commented Nov 21, 2012

I have not yet forgotten about this issue but am swamped in other stuff to work on

@liverbool
Copy link

+1000 👍

@MarkBaker
Copy link
Author

I can fully understand being swamped

@J7mbo
Copy link

J7mbo commented Apr 10, 2014

Did enum ever make it in?

@mvriel
Copy link
Member

mvriel commented Apr 13, 2014

Hi @J7mbo, they are not included in phpDocumentor2 yet. The discussion on the exact notation and feature set is still on-going

@GameCharmer
Copy link

Hello. It's been a year or so since the last comment. Are there any plans for incorporating something like this?

@mikedfunk
Copy link

+1

@felixfbecker
Copy link

felixfbecker commented Jul 28, 2015

why not combine it with the syntax for union types? You can already use true and false as type, so why not other scalars values? Examples:

 @return array|false Array on success, false on failure

 @var 'open'|'closed'|'pending' $status

 @return 1|0|-1 One if greater, zero if equal, minus one if smaller

This is how TypeScript does it too (I think JavaScript and PHP are very similar in their dynamic nature)

@sybbear
Copy link

sybbear commented Feb 10, 2016

Any ideas when this will be implemented?
Java supports enumeration types, XML also supports for validation, we see enumeration every day - it's a part of our lives. Choose an item from dropdown list, use radio inputs - it's all the same.

In PHP frameworks dependency injectors use strings for registering modules, relations are also accessed via strings sometimes. There are so many uses, when a simple raw string is used nowadays as a parameter. It's year 2016, should not be really that hard to implement such a feature, when we are able to create very complex systems.

It's simple as that, in PHPStorm the following scenario would be handy:

  1. Type: $object->do('
  2. A dropdown with options is open, navigate with key arrows:
    ['create'] @return Model
    -> ['save'] @return bool
    ['delete'] @return bool
  3. Press enter and get result: $object->do('save');

@DannyvdSluijs
Copy link

DannyvdSluijs commented Jan 29, 2018

@mvriel I came across this issue on CodeTriage as this issue was almost over 2 years old. And it seems to me that time has proven the issue to be not that desired that anyone in the OSS community started working on it (or any alternatives)

I know there is no native support for enumerations available in PHP (or even planned to be; currently there is an RFC in draft since '15). Alternatively there is the SPL Enum offering a close to native approach.

In addition the examples in the opening post could be upgraded to use objects (implementing a enum type using one of the available libraries ) to avoid having a string type as function parameter.

Most importantly having an @options might look like a solution to the problem but it will not enforce any type checking in the PHP runtime, giving a false sense of code quality, whereas an object oriented approach together with type hinting will. And as a bonus effect it can reduce duplication if the same enumeration is used more than one time.

IMHO the issue can be closed, that said the remark of @felixfbecker in 125731809 seems like a more natural approach which is still very close to the current @param and @return annotations. Still would not fixes the type checking as opposed of the enum object.

@jaapio
Copy link
Member

jaapio commented Jan 31, 2018

Before closing this issue I want to make @ashnazg aware of this question. If this is not added to the psr-5 standard phpdocumentor will not support this.

Moving this to our psr-5 project.

@jaapio jaapio added this to the PSR milestone Jan 31, 2018
@numediaweb
Copy link

Six years later.. Any progress on this issue?

@jaapio
Copy link
Member

jaapio commented May 22, 2018

Asking is answering the question...

@numediaweb
Copy link

In PSR-5 it is possible to specify elements types for an Array:

/**
 * Initializes this class with the given options.
 *
 * @param array $options {
 *     @var bool   $required Whether this element is required
 *     @var string $label    The display name for this element
 * }
 */
public function __construct(array $options = array())
{
    <...>
}

@anurbol
Copy link

anurbol commented May 23, 2018

PHPDocumentor definitely should support this. PHP apps may become very complex, there are already many things we have to memorize, no need to keep memorizing possible string argument values for tens/hundreds of functions. psr-5 has an abandoned status anyway, so there is no reason to wait for it to be released.

@jaapio
Copy link
Member

jaapio commented May 23, 2018

It doesn't our team is preparing to pick up the discussion on psr-5 again.

@anurbol
Copy link

anurbol commented May 23, 2018

@jaapio that's a good news! I think many people just gave up on this (desired, but not a critical), but they still hoping for it to be implemented. I can speak for myself, I almost switched to node.js/typescript world because of this "little" issue (5 years ago I hated JS for it's messy language, now it's been improved significantly, leaving PHP far behind it)

@ashnazg
Copy link
Member

ashnazg commented Jun 5, 2018

I'm very unconvinced on this one. Making a class be your enumerator object seems to me to be the correct approach, both in code and in documenting things. This approach is already supported, and has been back into 1.x.

PHP allowing this behavior (without a proper Enum object) is one of its tradeoffs, and I don't think we can make a doc-only construct for every occasion where "I only want to use strings in my code, but I want my docs to look like these are strict typed thingamabobs".

@anurbol
Copy link

anurbol commented Jun 6, 2018

These type of issues are the reason why I gave up with PHP after 11 years and moved to node.js + Typescript. PHP is moving too slow for 2018

@gareth-ib
Copy link

gareth-ib commented Aug 10, 2018

wow this is a really long time to not do this feature...
If PHP implemented RFC types this would be built in... but they still haven't decided on a good way to do that, so it would be nice if PHPDoc could at least support the idea.

Some sort of concept that would potentially be forward compatible with RFC types being added to php when the figure it out?

    /**
     * @var objectConstants|\Path\To\ClassHoldingStrings
     */
    public $stringFromConstants;
    /**
     * @param objectConstants|\Path\To\ClassHoldingStrings  $param
     */
    public function valueSetter($param) {
        $this->value = $param;
    }

@jaapio
Copy link
Member

jaapio commented Aug 10, 2018

The thing is not to implement this feature but to maintain al non php constructs in phpdocumentor. We are all looking for a way to fake enum behavior in php. And there are a few good user land implementations on packagist.org following the approach of @ashnazg.

You are now talking about class constants. But remember that class constants are not just string types. It can be an array to. And maybe in the future other complex types.

It is not the task of phpdocumentor to add new language constructs. I think an library in php should fix this issue. If there is a need to add some documentation part to support that library we are happy to provide support. But for now it isn't on our priority list. As it wasn't the last six years.

We already have enough missing features that are added to php. Let us focus on that first before we start making new things in the application.

This issue is open for future reference. And at some point we will start implementing a solution.

@gareth-ib
Copy link

yeah I agree there shouldn't be hacks added into phpdoc.. but there must be some sort of concept that can logically solve this concept of needing a param to be a restricted list string, somehow

@Roy-Orbison
Copy link

So now that it's PSR-19 any chance of something sane being suggested to the FIG by someone who can?

I really like the type addendum style, but with | for consistency with other PHPDoc conventions:

@param string{'open'|'closed'|'pending'} $plotType

@AmirrezaNasiri
Copy link

Hi guys, any update on this? 🤐

@JakeQZ
Copy link

JakeQZ commented Oct 6, 2019

@JakeQZ referenced this issue 2 hours ago
Psalm #778

The referenced comment is not properly linked by GitHub (from a large PR and not easy to find o/w), the relevant link is MyIntervals/emogrifier#778 (comment)

@barbu110
Copy link

Anything on this yet?

@mvriel
Copy link
Member

mvriel commented Nov 7, 2020

@ashnazg is this currently in PSR-5/PSR-19? Does this require action?

@quazardous
Copy link

how does it looks like ?

In SF there is something like that:
https://symfony.com/doc/5.x/reference/constraints/Choice.html

So my 2 cents :)

use John\Doe\Foo;
...
/**
* @var string{"bar1", Foo::SPECIAL_BAR, ...Foo:LIST_OF_BARS}
*/
public string $bar;

@phpDocumentor phpDocumentor locked and limited conversation to collaborators Jan 26, 2024
@jaapio jaapio converted this issue into discussion #3648 Jan 26, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests