in many languages I can do something like this:
function f(a = 0, b = 0, c = 0)
{
// Do something
}
f(b=3, c=4);
Can I do something like this in PHP?
Thank you very much indeed!
No, unfortunately you can't "step over" arguments in PHP, so default values are only possible at the end of the list.
So you can write this:
function foo($a=0, $b=0) {}
foo(42);
Here $b will have its default value but $a won't, as we provided one value as input.
However there's no way of providing a value for $b without also providing one for $a - we have to provide the value for $b as the second parameter, and PHP has no keyword we can use in place of the first parameter to say "use default".
There is talk of adding named parameters to a future version of PHP, similar to your non-PHP example.
You can simulate this a bit with some changes to your code, though; a couple of ideas:
treat null as meaning "use default", and write $a = is_null($a) ? 42 : $a
make your functions take an associative array as their only parameter, and take values from it as though their keys were parameter names
Indeed.
function foo($bar = "test") {
echo "I want ".$bar;
}
In PHP this is not possible: see the PHP Manual. Function parameters are always evaluated from left to right.
However,
f($b=3, $c=4);
is possible, but does something different as you will expect: before the function f() is called, the arguments are evaluated (variable $b and $c get assigned with the values 3 and 4 resp.) and then the function is called as
f(3,4)
As side effect, the variables $b and $c are set to the new values.
Related
Hello I'm writing an article allowing to bypass a filter that allows only base_convert except that there is something I discovered recently is that when we write this syntax in php:
"system"("id")
the function is interpreted, do you have a technical explanation for this?
Thanks to you !
Functions in PHP aren't first-class objects. What does that mean? When you want to pass around a function, for example as callback to array_map, you cannot just pass the function itself like so:
function my_callback() { ... }
array_map(my_callback, $some_array)
my_callback here is interpreted as a constant, and barring its existence, a bare string. (This works in other languages where functions are first class objects.) You can only pass the function by name, which means you pass a string that contains the name of the function:
array_map('my_callback', $some_array)
PHP will then look up the globally registered function with the name "my_callback" and use it.
This means inside array_map it must look something like this:
function array_map($callback, $array) {
$callback($array); // let's ignore the "mapping" part…
}
So, a variable can hold the name of a function, and "calling" that variable which holds the name of a function actually calls that function.
Now, we know that a variable can just as well be replaced with a literal of the same value:
$a = 1;
$b = 2;
$c = $a + $b;
is the same as:
$c = 1 + 2;
The same happens to hold for calling-strings-with-names-of-functions:
'my_callback'($array)
Note that this only works since PHP 7, where the PHP parser got a huge revamping. Before, $f() was sort of a special case hack, but the PHP 7+ parser properly follows the variable-is-substitutable-by-literal logic.
Ok, I know what passing by reference is... I don't need that explained.
Say you have a function that takes in an argument by reference:
function foo(&$a){
$a = 1;
}
and you call it:
$a = 0;
foo($a); // Now $a is 1.
You can do the same exact thing passing by value:
function foo($a){
$a = 1;
return $a;
}
and you call it:
$a = 0;
$a = foo($a); // Now $a is 1.
So, what is the point of passing by reference?
To answer my own question from comments posted above and some other research:
Since only a reference to an object is passed to a function in pass-by-reference, it can be particularly useful when trying to conserve memory.
If there is such a case where you would want to alter an entity but return a different one, pass-by-reference can come in handy (although I would rather use multiple functions with return values).
Other than the two cases, I think this approach can cause confusion in large code bases and result in some nasty code.
If you know of any other reasons that I should add please comment and I'll add them here.
Is it possible to pass a variable to function without passing the variables that come before it in the function definition?
For example, if my function looks like this:
function doThis( $v1, $v2, $v3 )
{
echo $v1.$v2.$v3;
}
Can I then call the function with only some of those variables, like doThis("v1",null,"v3") or some other way?
you can use predefined arguments:
function doThis( $v1, $v2 = "hello", $v3 = 1 ) {}
call to this function only with the first argument, the 2nd and 3rd will be "hello",1 by defualt:
doThis(10);
+1 on #Alon post
You can also use an array ..
$array['var1'] = null;
$array['var2'] = "foo";
$array['var3'] = "bar";
doThis($array);
function doThis($theArray){
var_dump($theArray);
}
This way, you can use empty values and N amout of variables.
Yes, you can do doThis("v1",null,"v3"), if you prepare your function to handle that null argument.
For example your example will work just fine.
Or, if it makes sense you can change the order of the arguments so you can set defaults.
You can specify default values in the function definition like so:
function doThis($a, $b=null, $c=null) {
echo $a . $b . $c;
}
doThis("hello", " world"); // yields: hello world
In this function, $a is a required parameter. The other two values are optional.
To appease the commenter below, you can of course still call this function like so:
doThis("hello", null, "world");
and of course, you do not have to provide defaults (but it is a good idea to do so)
The answer is: rework your workflow.
I know you don't like that answer, but honestly, if you are passing more than 3 parameters or if sometimes you don't want to pass part of the beginning parameters, you probably want to rethink what you're doing. Function and method calls should be simple. You are probably doing too much in your function.
General tips:
Use classes if appropriate. This way you can avoid passing some information around because it's stored in the class and your methods have access to it.
Keep methods cohesive. That means your methods and functions should do one thing and do it well.
Put variables you want to pass only sometimes at the back. This allows you to simply not pass them if they have $var=null after it. You then check to see if $var===null before doing something with it.
Much cleaner way is passing an array of variables, as demonstrated by #jflaflamme.
Another way is allowing an arbitrary number of variables like this:
function foo()
{
$arguments = func_get_args();
if(sizeof($arguments))
{
echo implode('', $arguments);
}
}
foo(1, 2, 3, $some_var);
You can also loop trough the array you obtain via func_get_args, check them for their type (if it's a null, array, object - you name it) and then handle them in a way you deem appropriate.
Setting variable values inside a function call - I don't see this a lot, is this considered good practice?
function myUpdate($status){
...
}
myUpdate($status = 'live');
I personally like it because it's more descriptive. I see it more frequently the other way around, ie., assigning a default value in the function definition.
That's a very bad idea, because it's basically code obfuscation. php does not support keyword arguments, and that can lead to weird stuff. Case in point:
function f($a, $b){
echo 'a: ' . $a . "\n";
echo 'b: ' . $b . "\n";
}
f($b='b-value', $a='a-value');
This program does not only output
a: b-value
b: a-value
but also defines the variables $b and $a in the global context. This is because
f($b='b-value', $a='a-value');
// is the same thing as ...
$b = 'b-value';
$a = 'a-value';
f($b, $a);
There are a few good practices one can do to make remembering method arguments easier:
Configure your editor/IDE to show the signature of functions on highlight.
If a function has lots of arguments that describe some kind of state, consider moving it into an *objec*t (that holds the state instead)
If your function just needs lots of arguments, make it take an array for all non-essential ones. This also allows the method caller not to worry at all about the multitude of options, she just needs to know the ones she's interested in.
All kidding aside, seriously why do you use it? You have to realize it's something totally different than assigning a default value. What you're doing here is assigning the value to a variable, and then passing that variable to the function. The result is, that after the function call, the $status varialbe is still defined.
myUpdate( $status = 'live' );
echo $status; // "live"
Even if this is what you want, I'd say it's less descriptive than just splitting it out in two lines.
No, it's not because it's extra code. Try:
myUpdate('live' /*status*/, 42 /*maxTries*/);
Or if you really wanted named parameters, you could use a map:
myUpdate(array(
'status' => 'live'
));
Normally it would kill type safety, but PHP doesn't have any, anyway.
Well, default value is different thing.
// if you call myUpdate without argument, it will have $status with value live
function myUpdate($status = 'live'){
}
Calling this:
myUpdate($status = 'live');
is equivalent to:
myUpdate('live');
with the only difference being that after the call, if you call it like myUpdate($status = 'live'); you will keep the $status var with value live in the scope where you called the function, not inside it.
But IMHO its much more readable to do it like this:
$status = 'live';
myUpdate($status);
What does this code mean? Is this how you declare a pointer in php?
$this->entryId = $entryId;
Variable names in PHP start with $ so $entryId is the name of a variable.
$this is a special variable in Object Oriented programming in PHP, which is reference to current object.
-> is used to access an object member (like properties or methods) in PHP, like the syntax in C++.
so your code means this:
Place the value of variable $entryId into the entryId field (or property) of this object.
The & operator in PHP, means pass reference. Here is a example:
$b=2;
$a=$b;
$a=3;
print $a;
print $b;
// output is 32
$b=2;
$a=&$b; // note the & operator
$a=3;
print $a;
print $b;
// output is 33
In the above code, because we used & operator, a reference to where $b is pointing is stored in $a. So $a is actually a reference to $b.
In PHP, arguments are passed by value by default (inspired by C). So when calling a function, when you pass in your values, they are copied by value not by reference. This is the default IN MOST SITUATIONS. However there is a way to have pass by reference behaviour, when defining a function. Example:
function plus_by_reference( &$param ) {
// what ever you do, will affect the actual parameter outside the function
$param++;
}
$a=2;
plus_by_reference( $a );
echo $a;
// output is 3
There are many built-in functions that behave like this. Like the sort() function that sorts an array will affect directly on the array and will not return another sorted array.
There is something interesting to note though. Because pass-by-value mode could result in more memory usage, and PHP is an interpreted language (so programs written in PHP are not as fast as compiled programs), to make the code run faster and minimize memory usage, there are some tweaks in the PHP interpreter. One is lazy-copy (I'm not sure about the name). Which means this:
When you are coping a variable into another, PHP will copy a reference to the first variable into the second variable. So your new variable, is actually a reference to the first one until now. The value is not copied yet. But if you try to change any of these variables, PHP will make a copy of the value, and then changes the variable. This way you will have the opportunity to save memory and time, IF YOU DO NOT CHANGE THE VALUE.
So:
$b=3;
$a=$b;
// $a points to $b, equals to $a=&$b
$b=4;
// now PHP will copy 3 into $a, and places 4 into $b
After all this, if you want to place the value of $entryId into 'entryId' property of your object, the above code will do this, and will not copy the value of entryId, until you change any of them, results in less memory usage. If you actually want them both to point to the same value, then use this:
$this->entryId=&$entryId;
No, As others said, "There is no Pointer in PHP." and I add, there is nothing RAM_related in PHP.
And also all answers are clear. But there were points being left out that I could not resist!
There are number of things that acts similar to pointers
eval construct (my favorite and also dangerous)
$GLOBALS variable
Extra '$' sign Before Variables (Like prathk mentioned)
References
First one
At first I have to say that PHP is really powerful language, knowing there is a construct named "eval", so you can create your PHP code while running it! (really cool!)
although there is the danger of PHP_Injection which is far more destructive that SQL_Injection. Beware!
example:
Code:
$a='echo "Hello World.";';
eval ($a);
Output
Hello World.
So instead of using a pointer to act like another Variable, You Can Make A Variable From Scratch!
Second one
$GLOBAL variable is pretty useful, You can access all variables by using its keys.
example:
Code:
$three="Hello";$variable=" Amazing ";$names="World";
$arr = Array("three","variable","names");
foreach($arr as $VariableName)
echo $GLOBALS[$VariableName];
Output
Hello Amazing World
Note: Other superglobals can do the same trick in smaller scales.
Third one
You can add as much as '$'s you want before a variable, If you know what you're doing.
example:
Code:
$a="b";
$b="c";
$c="d";
$d="e";
$e="f";
echo $a."-";
echo $$a."-"; //Same as $b
echo $$$a."-"; //Same as $$b or $c
echo $$$$a."-"; //Same as $$$b or $$c or $d
echo $$$$$a; //Same as $$$$b or $$$c or $$d or $e
Output
b-c-d-e-f
Last one
Reference are so close to pointers, but you may want to check this link for more clarification.
example 1:
Code:
$a="Hello";
$b=&$a;
$b="yello";
echo $a;
Output
yello
example 2:
Code:
function junk(&$tion)
{$GLOBALS['a'] = &$tion;}
$a="-Hello World<br>";
$b="-To You As Well";
echo $a;
junk($b);
echo $a;
Output
-Hello World
-To You As Well
Hope It Helps.
That syntax is a way of accessing a class member. PHP does not have pointers, but it does have references.
The syntax that you're quoting is basically the same as accessing a member from a pointer to a class in C++ (whereas dot notation is used when it isn't a pointer.)
To answer the second part of your question - there are no pointers in PHP.
When working with objects, you generally pass by reference rather than by value - so in some ways this operates like a pointer, but is generally completely transparent.
This does depend on the version of PHP you are using.
You can simulate pointers to instantiated objects to some degree:
class pointer {
var $child;
function pointer(&$child) {
$this->child = $child;
}
public function __call($name, $arguments) {
return call_user_func_array(
array($this->child, $name), $arguments);
}
}
Use like this:
$a = new ClassA();
$p = new pointer($a);
If you pass $p around, it will behave like a C++ pointer regarding method calls (you can't touch object variables directly, but that's evil anyways :) ).
entryId is an instance property of the current class ($this)
And $entryId is a local variable
Yes there is something similar to pointers in PHP but may not match with what exactly happens in c or c++.
Following is one of the example.
$a = "test";
$b = "a";
echo $a;
echo $b;
echo $$b;
//output
test
a
test
This illustrates similar concept of pointers in PHP.
PHP passes Arrays and Objects by reference (pointers). If you want to pass a normal variable Ex. $var = 'boo'; then use $boo = &$var;.
PHP can use something like pointers:
$y=array(&$x);
Now $y acts like a pointer to $x and $y[0] dereferences a pointer.
The value array(&$x) is just a value, so it can be passed to functions, stored in other arrays, copied to other variables, etc. You can even create a pointer to this pointer variable. (Serializing it will break the pointer, however.)