PHP autocomplete parameters - php

I don't know if it's a IDE question or if there's a way to do this with PHP configuration or something.
I want to know if it's possible to create a autocomplete/intellisense feature for a parameter. For example:
function sayALetter($letter){
echo $letter;
}
Now when I call this function, I want to have some autocomplete options for the $letter parameter. (a, b, c, d). In other words, I want to control which values this parameter can receive.
It's possible or I'm talking crazy?

It's been a while, but there is a way (sort of). The thing you need is an IDE that can give hints (eg. PhpStorm). It does not prevent passing on different values tho:
function letters($letters = "ab"|"ad"|"bf"|"ah"|"bj"|"al"|"cn"|"oc") {
return $letters;
}

There are IDEs that give you hints as to what parameters a function expects. This is done via a special comment format just before the function.
Even when writing your own functions, if you stick to the format, the documentation of a function's parameters is done in seconds, and it will instantly be visible to you when you type in the name of the function in another part of the code.
They also have autocomplete, filling in the function's parameter variable names from the definition of your function.
If you type in /** on a line and hit return on a line just before your function definition, your IDE should fill in the skeleton for your function documentation (parameters and return types).
/**
* This function bars foos
* it returns an array in some cases
* otherwise it returns FALSE.
* #param string foo being barred
* #return mixed array of barred foos or FALSE
*/
public function foobar($foo)
{....
This is very useful, since your IDE can now give you hints inside the function regarding the parameters, i.e. what methods/properties are available for the parameter.
However, since php doesn't really have types, you'll still need to make sure that you're getting what you're expecting inside your function.
This is just your IDE helping you out, PHP itself doesn't care.

Related

In phpDoc, is it neccessary to define parameter type?

an old fashioned example:
/**
* #param string $a - test parameter
*/
public function test($a)
{
}
but now that Php has types, I would write:
/**
* #param $a - test parameter
*/
public function test(string $a)
{
}
since it has a parameter, so adding "string" to phpdoc is verbose.
"Necessary" depends on what you're using to parse the annotation (if anything)*
If this is PHPDocumentor itself, you'll want to stick with the standard that it prescribes. Even if it works without the type now, there's no guarantee that a future version will, and as mentioned in Alex Howansky's answer, the type is currently defined as mandatory. From their manual:
With the #param tag it is possible to document the type and function of a single argument of a function or method. When provided it MUST contain a Type to indicate what is expected; the description on the other hand is OPTIONAL yet RECOMMENDED in case of complicated structures, such as associative arrays.
PHPStorm (at least the version I have in front of me) acts a bit strangely if you leave out the type-hint in a parameter. If I use
* #param $a Some useful comment about my parameter
then I get a warning about Undefined class Some. Apparently it's taking the first word other than the #param annotation and the variable name, and assuming that's the type. I can't find a reference to this behaviour in the phpdoc manual (providing the type after the variable), so that could itself be non-standard. Interestingly, if the first character after the variable name is a hyphen (as in the example in your question), then the warning is supressed.
I've seen a lot of code recently that leaves out the annotations entirely, and relies on the language's internal type-hinting (both parameter and return) to do the job. This is perfect, as long as you don't need to add a description to any of them. PHPStorm will warn you about missing parameter annotations the moment you provide any (but not all) of them, which means if you want to provide a comment for one then you'll need to add the rest, commented or not.
You mention verbosity in your question, and if all you're concerned about is human readability then by all means leave out the type. Phpdoc itself has a standard, but you're absolutely not bound by it. It's your code, ultimately. But if you're shipping a package that other developers might use, or if any of your toolchain (from IDE, through static analysis, to documentation generation itself) aren't happy with the non-standard usage, then you'll have to weigh up the decision again. Either way it comes down to whether you're the only one (person or machine) reading your code; if you're not, then stick with the standards, even if it means typing a few extra characters.
--
* This can include things that actually do affect the way the code runs - PHP allows you to fetch these annotations with the getDocComment methods in the Reflection API. Use-cases for this tend not to include #param annotations (more often it'll be something package specific like Doctrine's ORM annotations), which are almost exclusively used for documentation, but I don't want to over-generalise and say that this can't have an effect on your code's actual functionality.
The phpDocumentor docs state that the Datatype field is required for #param. Those docs are quite old, but I would expect apps which consume tags to still abide by that requirement. Lately, I've tended to skip the #param tag completely when I have an explicit typehint present.
PHPCS will alert if you leave it out but have a typehint, like in your example:
/**
* #param $arg The arg.
*/
public function foo(int $arg) {
PHPStan will alert if you have a #param tag type and a typehint that don't match, like this:
/**
* #param string $arg The arg.
*/
public function foo(int $arg) {

How to use mixed parameter type in my own functions?

I want to define a PHP 7 function that takes a parameter of mixed type. (What I want is the equivalent of a generic type parameter in C#; if there's a better way to emulate that in PHP 7, please let me know.)
My code is as follows.
<?php
declare (strict_types = 1);
function test (mixed $s) : mixed {
return $s;
}
// Works
echo gettype ('hello');
// Does not work
echo test ('hello');
?>
When I run this code, I get the following.
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of mixed, string given, called in mixed.php on line 11 and defined in mixed.php:4
Stack trace:
#0 mixed.php(11): test('hello')
#1 {main}
thrown in mixed.php on line 4
If I comment out the call to test(), the code runs fine, so apparently it's at least okay for me to use the mixed parameter type in the function declaration.
I know built-in PHP functions such as gettype() can take mixed parameters, though I don't know if they are internally using strict typing.
I see that "mixed" is also used as a pseudo-type in PHP documentation, so I might misunderstand the purpose of "mixed" as a PHP keyword, but what I'm seeing here at least implies to me that it is a legitimate keyword. Am I simply using it in a way it isn't intended for?
Finally, I realize I could circumvent all this by simply not specifying the parameter type, but I'd like to be consistent by specifying all my parameter and return types.
Thank you and please let me know if I can provide any additional information.
FYI mixed is not a Type. (Refer to the Documentation). It is only a pseudo type: a Hint that any Type might be passed to or returned from a Method... or perhaps for a variable which was loosely typed as mixed for any reason...
Unlike in C#, what you are trying to achieve might be tricky in PHP especially with strict_types set to true.
However, you can achieve a nearly similar effect without Strict Typing - in which case your Methods may accept any Type so long as you don't supply any Type Hints. Though For C# Programmers, that's bad - yet, that is the juice of PHP.
UPDATE 2021
Mixed type has been introduced in PHP8. It can be used exactly as shown in the question.
To indicate that the function also accepts null the ?-operator works for this also as mentioned on http://php.net/manual/de/functions.returning-values.php#functions.returning-values.type-declaration
But this is only usable if the code hasn't to be backward compatible because this feature is only available on PHP >= 7.1
As you can see on https://wiki.php.net/rfc/mixed-typehint there as RFC for adding mixed for type hinting. So actually there seem to be no chance to defined a correct type hint for parameters that accept more the one type.
So a phpDoc comment could be a solution (and it's also backward compatible).
Example:
/**
* Functiondescription
* #author FSharpN00b
* #param mixed $s
* #return mixed
**/
function test ($s){
return $s;
}

PHP type hinting - code vs. annotations

PHP 5 can do some (limited) type hinting, however, it seems to me that in real-world projects, types are usually described in doc comments. For example, instead of this:
/**
* Test method
*/
function test(SomeType $param1) {
...
}
there will more commonly be
/**
* Test method
*
* #param SomeType param1
*/
function test($param1) {
...
}
What are the advantages and disadvantages of the two approaches? And if I'm right in the assumption that the PhpDoc method is more common, why is that? Why don't people utilize the built-in language feature more?
Edit: the third option is to use both approaches combined:
/**
* Test method
*
* #param SomeType param1
*/
function test(SomeType $param1) {
...
}
However, I personally haven't seen this used too often (looked at libraries like Symfony or PHPUnit) and this also seems like doing some work for not much additional benefit to be honest. Maybe that's why it isn't seen more often.
First thing: PHP typehints have different ability to hint than PHPDoc. Differences are (at least):
Scalar types. Before PHP 7.1, you can not hint scalar types, while nothing prevents you from hinting
/**
* #param string $param Param description
*/
Array of hinting. In PHPDoc you can hint, that parameter (or return value) is array of something. It would be:
/**
* #param ClassName[] $param Param description
*/
and meaning of this is - array of instances of ClassName. This is extremely useful when it comes to return type (because IDE then may do substitutions for methods on iteration of that array, and, therefore, you'll know that you're doing correct thing or not). However, in PHP you can only typehint it as
function functionName(array $param) { /*...*/ }
so it won't be possible to realize what are actual elements of array. For your information there is a corresponding RFC for typehinting as array of some elements, which is currently rejected - but may be in future such possibility will appear in PHP.
But, on the other hand, using PHP typehints is still different thing and normally you should do both - so, if it's possible to hint somehow in PHP (like for array sample above) - do it, and add PHPDoc block as well. PHP typehint allows you to enforce behavior on language level, while PHPDoc is only "information" source, it serves only information goal and can not prevent of passing illegal argument type.
Personally I would use both.
First option is good for controling what objects are you passing to the method. Second usually can be added automaticaly by any modern IDE and it makes your code more readable.

What does #param mean in a class?

What does the #param mean when creating a class? As far as I understand it is used to tell the script what kind of datatype the variables are and what kind of value a function returns, is that right?
For example:
/**
* #param string $some
* #param array $some2
* #return void
*/
IsnĀ“t there another way to do that, I am thinking of things like: void function() { ... } or something like that. And for variables maybe (int)$test;
#param doesn't have special meaning in PHP, it's typically used within a comment to write up documentation. The example you've provided shows just that.
If you use a documentation tool, it will scour the code for #param, #summary, and other similar values (depending on the sophistication of the tool) to automatically generate well formatted documentation for the code.
As others have mentioned the #param you are referring to is part of a comment and not syntactically significant. It is simply there to provide hints to a documentation generator. You can find more information on the supported directives and syntax by looking at the PHPDoc project.
Speaking to the second part of your question... As far as I know, there is not a way to specify the return type in PHP. You also can't force the parameters to be of a specific primitive type (string, integer, etc).
You can, however, required that the parameters be either an array, an object, or a specific type of object as of PHP 5.1 or so.
function importArray(array $myArray)
{
}
PHP will throw an error if you try and call this method with anything besides an array.
class MyClass
{
}
function doStuff(MyClass $o)
{
}
If you attempt to call doStuff with an object of any type except MyClass, PHP will again throw an error.
I know this is old but just for reference, the answer to the second part of the question is now, PHP7.
// this function accepts and returns an int
function age(int $age): int{
return 18;
}
PHP is entirely oblivious to comments. It is used to describe the parameters the method takes only for making the code more readable and understandable.
Additionally, good code practice dedicates to use certain names (such as #param), for documentation generators.
Some IDEs will include the #param and other information in the tooltip when using a hovering over the relevant method.
#param is a part of the description comment that tells you what the input parameter type is. It has nothing to do with code syntax. Use a color supported editor like Notepad++ to easily see whats code and whats comments.

Is it necessary to validate function parameters or not?

When i write down a function is a good practice to validate all the parameters of the function like this:
<?php
/**
* foo - Test function
*
* #param int $paramA
* #param str $paramB
* #param array $paramC
*
* #return something
*/
function foo($paramA, $paramB, $paramC) {
// verify all parameters
if(!is_int($paramA)) {
return 0; // or error msg
}
if(!is_string($paramB)) {
return 1; // or error msg
}
if(!is_array($paramC)) {
return 2; // or error msg
}
// some code in function scope that uses parameters
// and saves the results in $result
return $result;
}
or should i rely on the user that will use the function and assume that he knows what he is doing and forget about parameter validation?
Personally i prefer to validate all the parameter of the function and return error codes for consistency of the code and make my life easier afterwords.
Thank you in advance.
I think the answer is: it depends
It depends on who you are writing your code for. If you're looking for the most generalized answer, then yes, you should.
If your script will only ever be used by you and you know in your heart of hearts that you will always use it correctly, then you will (probably) be safe if you don't.
If your script is part of an API that will be distributed to many, many people, then you most definitely want to add error checking and provide good fall back error messages for people.
If you are part of a small team that will all be using the same code, I would also suggest that validating your arguments according to your particular context would be a good idea.
If it is an internal function that only you will be using, it is probably okay to not validate every single parameter like that. If it is a function that has parameters that depend on user input (for example, you get information through $_GET, and then pass that to a function), then it needs to be validated.
Never rely on a user or anyone else besides yourself to know what they are doing. Sometimes it can be helpful to validate things like this if you are writing code that you can re-use later (like if you were writing your own framework to use across all of your PHP projects). But if it is just one application-specific function that only you can call with parameters that only you define, I wouldn't worry about it.
Why validate your parameters:
Sometimes we really need a certain datatype for an operation. If you give me a string that is not representative of an integer and you use that as a search for a primary key in a database (usually an int), then you will have trouble.
It makes fixing your code easier. When you are checking parameters, you can throw individual exceptions and give messages that are very descriptive. This makes it easier to fix your code when something breaks, because you know exactly what went wrong.
Some tips on type checking:
In case you didn't know, is_int is pretty faulty. I think a valid check to see if it is an int is is_numeric($int) && $int==(int)$int.
You can specify types for objects and arrays, like so: function foo($paramA, $paramB, array $paramC).
Really depends on the type-strictness of what you're doing with those parameters.
Since PHP is weakly typed, you can get away with a lot by casting or just letting the implicit type conversion/coercion do it's thing.
And if you're just going to throw a bunch of guard conditions at the head of every function only to return errors, that's really not much different than PHP triggering errors of its own.
I beg to differ. I recently stumbled upon an article about a similar issue (null checks), but it seems to apply for type checking in php as well. I agree with the author.
Write code in a way that makes type checking redundant.
explicitly validate user input and cast the values to the required types as soon as possible.
In some exceptional cases, you can and should use exceptions instead of returning some obscure error numbers.
It is a very good practice to validate function arguments. I suspect you ask this question because on the other hand it makes your functions look longer and uglier. However with args module from NSPL, it is very easy to do. The function from your example will be:
function foo($paramA, $paramB, array $paramC)
{
expects(int, $paramA);
expects(string, $paramB);
// do something
}
// or type check several arguments
function sum($x, $y)
{
expectsAll(numeric, [$x, $y]);
return $x + $y;
}
More examples here.

Categories