Can someone please explain what PHP "with" does?
Example begins:
Say I have a class:
\App\fa_batch
What is the difference between this statement:
$w = (with (new \App\fa_batch))
// uses 'with'
// returns App\fa_batch
and this statement?
$n = (new \App\fa_batch)
// does not use 'with'
// also returns App\fa_batch
Context / Background Info:
I'm having trouble finding documentation for with, maybe because the PHP.net, stack overflow and google search engines considers php "with" keyword such a common search phrase.
If context helps, I came across this usage of the word with from this answer:
https://stackoverflow.com/a/33222754/5722034
with is not a keyword, it's a laravel function. The extra space between with and ( is a red herring.
The 5.2 docs include it in miscellaneous helpers. The source is available on github as well
https://laravel.com/docs/5.2/helpers#miscellaneous
with() is a helper function that just returns the object.
A normal use case I've seen is when you're cloning an object, it allows you to chain onto that clone:
$object = new Object();
with(clone $object)->doSomethingWithoutAffectingTheOriginal();
In the use case you've provided, there is no difference. with() is completely redundant if you've wrapped the creation of the instance in parentheses.
Thanks to the answers by various posters, I've realised it is a function in Laravel. Here is the Laravel source: Taken from vendor/laravel/framework/src/Illuminate/Support/helpers.php
if (! function_exists('with')) {
/**
* Return the given object. Useful for chaining.
*
* #param mixed $object
* #return mixed
*/
function with($object)
{
return $object;
}
}
From that terse comment there, I understand it is used for chaining, e.g. queries together. (I use the term 'understand' loosely.)
with is not a PHP keyword.
Also take a look at the language reference page.
tldr
The with function has been used to chain methods, but is no longer required. Since php 5.4 you can simply write (new MyObject)->myMethod() - this was not possible prior to v5.4:
Example: https://3v4l.org/57dc0#v5.3.29
More detailed answer
The with was a workaround to use the instance without assigning it to a variable:
$instance = new A;
A->doSomething();
Using the with function (works prior to v5.4 - example):
with(new A)->doSomething();
Since v5.4 you can simply write:
(new A)->doSomething();
Related
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.
I'm using the Facebook library with this code in it:
class FacebookRestClient {
...
public function &users_hasAppPermission($ext_perm, $uid=null) {
return $this->call_method('facebook.users.hasAppPermission',
array('ext_perm' => $ext_perm, 'uid' => $uid));
}
...
}
What does the & at the beginning of the function definition mean, and how do I go about using a library like this (in a simple example)
An ampersand before a function name means the function will return a reference to a variable instead of the value.
Returning by reference is useful when
you want to use a function to find to
which variable a reference should be
bound. Do not use return-by-reference
to increase performance. The engine
will automatically optimize this on
its own. Only return references when
you have a valid technical reason to
do so.
See Returning References.
It's returning a reference, as mentioned already. In PHP 4, objects were assigned by value, just like any other value. This is highly unintuitive and contrary to how most other languages works.
To get around the problem, references were used for variables that pointed to objects. In PHP 5, references are very rarely used. I'm guessing this is legacy code or code trying to preserve backwards compatibility with PHP 4.
This is often known in PHP as Returning reference or Returning by reference.
Returning by reference is useful when you want to use a function to
find to which variable a reference should be bound. Do not use
return-by-reference to increase performance. The engine will
automatically optimize this on its own. Only return references when
you have a valid technical reason to do so.
PHP documentation on Returning reference
A reference in PHP is simply another name assigned to the content of a variable. PHP references are not like pointers in C programming, they are not actual memory addresses, so they cannot be used for pointer arithmetics.
The concept of returning references can be very confusing especially to beginners, so an example will be helpful.
$populationCount = 120;
function &getPopulationCount() {
global $populationCount;
return $populationCount;
}
$countryPopulation =& getPopulationCount();
$countryPopulation++;
echo "\$populationCount = $populationCount\n"; // Output: $populationCount = 121
echo "\$countryPopulation = $countryPopulation\n"; //Output: $countryPopulation = 121
The function getPopulationCount() defined with a preceding &, returns the reference to the content or value of $populationCount. So, incrementing $countryPopulation, also increments $populationCount.
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.
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.
I've recently become familiar with Reflection, and have been experimenting with it, especially getDocComment(), however it appears that it only supports /** */ comment blocks.
/** foobar */
class MyClass{}
$refl = new ReflectionClass('MyClass');
// produces /** foobar */
echo $refl->getDocComment();
-Versus-
# foobar
class MyClass{}
$refl = new ReflectionClass('MyClass');
// produces nothing
echo $refl->getDocComment();
Is it not possible to capture this without resorting to any sort of file_get_contents(__FILE__) nonsense?
As per dader51's answer, I suppose my best approach would be something along these lines:
// random comment
#[annotation]
/**
* another comment with a # hash
*/
#[another annotation]
$annotations
= array_filter(token_get_all(file_get_contents(__FILE__)), function(&$token){
return (($token[0] == T_COMMENT) && ($token = strstr($token[1], '#')));
});
print_r($annotations);
Outputs:
Array
(
[4] => #[annotation]
[8] => #[another annotation]
)
DocComments distinguish themselves by saying something about how your classes are to be used, compared to regular comments that could assist a developer in reading the code. That's also why the method isn't called getComment() instead.
Of course it's all text parsing, and someone just made a choice in docComments always being these multiline comments, but that choice has apparently been made, and reading regular comments is not something in the reflection category.
I was trying to do just a you a few days ago, and here is my trick. You can just use the php internal tokenizer ( http://www.php.net/manual/en/function.token-get-all.php ) , and then walk the array returned to select only the comments, here is a sample code :
$a = token_get_all(file_get_contents('path/to/your/file.php'));
print_r($a); // display an array of all tokens found in the file file.php
Here is a list of all tokens php recognize : http://www.php.net/manual/en/tokens.php
And the comment you will get by this method include ( from php.net site ) :
T_COMMENT : // or #, and /* */ in PHP 5
Hope it helps !
AFAIK, for a comment to become documentation it is needed to start with /** not even with standard multi-line comment.
A doc comment as the name implies, is a documentation comment, not a standard comment, otherwise when you are grabbing comments for apps such as doxygen it will try to document any commented code from testing/debuggung, etc, which often gets left behind and is not important to the user of the API.
As you can read here in the first User Contributed Note:
The doc comment (T_DOC_COMMENT) must begin with a /** - that's two asterisks, not one. The comment continues until the first */. A normal multi-line comment /*...*/ (T_COMMENT) does not count as a doc comment.
So only /** */ blocks are given by this method.
I don't know any other method with php to get the other comments as using file_get_contents and filter the comments with e.g. a regex