Just playing around and I found this.
Why the call by reference to $this->newAxis() does not throw an undefined property notice (xAxis property), while the var_dump() does?
public function newXAxis()
{
// var_dump(isset($this->xAxis)); // false
// var_dump($this->xAxis); // Throws the notice
return $this->newAxis($this->xAxis); // Should throw the notice?!
}
protected function newAxis(&$current)
{
// ...
}
Does it have something to do with the passing by reference, thus not accessing the property directly?
Yes, it happens because you pass it by reference. When you pass by value, an attempt is made to actually read the value of the variable - so a notice appears. When you pass by reference, the value does not need to be read.
When you do that, the variable/property is created if it does not exist yet.
From the manual:
If you assign, pass, or return an undefined variable by reference, it
will get created.
<?php
function foo(&$var) { }
foo($a); // $a is "created" and assigned to null
newAxis(&$current)
is pass by reference. that means you are passing a variable.
By default all variables in PHP are undefined.
You define them by just using, e.g.
$a = 1;
As you can see, PHP does not complain here that $a is undefined, right?
Okay ;), see here:
$a = $b;
PHP now complains that $b is undefined.
Like with $a (you define the variable) and $b (the variable is not defined) it is with passing by reference or by value:
$this->newAxis($a);
The variable $a is defined when passed by reference. It carries it's default value NULL. And now the $b example:
var_dump($b);
var_dump takes it's parameters by value. Therefore PHP complains that $b is not defined.
And that's all. I hope it was clear enough.
I'm going on a limb here...
Since you are accessing it as an object (from a class) it won't give you a notice, while when you var_dump something it kind of access it like an array (and since it's empty it throws a notice)
Related
I was expecting to see a notice like PHP Notice: Undefined variable: a, however when I run this code it works perfectly fine. Moreover, the variable becomes NULL. Why?
<?php
function($a = 1) use (&$a) {};
var_dump($a); // NULL <---- Expected a Notice "undefined", got "NULL"
Demo
i think the & operator silently create the variable if it doesn't exist already. seems this page try to explain it:
If you assign, pass, or return an undefined variable by reference, it will get created. , so when you do use (&$a) , & sees that $a doesn't already exist, and create it..
as for undefined, that's not a real type in PHP. (unlike, for example, javascript, which actually have a type called undefined, and a separate type called null)
why null? given that undefined doesn't exist, its the only logical choice for the initial value, what did you expect it to be initialized to?
"If you don't initialize your variables with a default value, the PHP will do a type cast depending on how you are using the variable. This sometimes will lead to unexpected behaviour."
I just noticed the following behavior in my php code and I'm wondering why it's happening.
$array = array();
test_value($array['invalid_index']); // Error -> Notice: Undefined index: invalid_index in ...
test_reference($array['invalid_index']); //No error
function test_value($value){}
function test_reference(&$value){}
I was expecting both test_value and test_reference to throw the undefined index error but strangely the method by reference doesn't throw any error.
Why?
Function parameters by-reference accept variables which haven't been declared previously; they are being declared by passing them as reference. This makes complete sense if you look at typical use cases of by-reference parameters:
$foo = preg_match('/(.)/', 'bar', $baz);
This function returns one value, which will be assigned to $foo. However, this function should also return the matches, which here is the third parameter $baz. Since a function can only return a single value at a time, additional "return" values are being realised by populating variables passed by reference.
If you had to pre-initialise these variables, your code would look like this:
$baz = null;
$foo = preg_match('/(.)/', 'bar', $baz);
echo $baz[0];
This makes code more complicated than necessary; PHP hence doesn't require that such variables "exist" beforehand.
The error first appears with the call to JB_do_house_keeping(). This function gets called at every request!
JBPlug_do_callback('jb_init', $A=false); // **ERROR HERE**
define ('JB_INIT_COMPLETED', true);
================================
Then also with JB_save_session():
JBPLUG_do_callback('house_keeping_critical_section', $A = false); // **ERROR HERE**
Please help! I am stuck here: I am a basic coder trying something new...
There are two ways to pass information to a function in PHP:
as a value (e.g. false, 48, 'foobar')
as a reference to a variable (e.g. $a)
Functions define how they want to receive their arguments. If they expect to receive it as a reference, that means that the changes the function makes to the variable will have an effect in the scope where the function was called.
If you provide a value where the function is expecting a reference, the function won't properly do what you expect.
For instance, array_splice expects its first argument to be a reference, so that you can get the modifications made to the array. But imagine if you did this:
array_splice(array('foo', 'bar'), 1);
You've passed in a value, not a reference. The code that called your function can't get the modified array, because array_splice doesn't return it. The correct way is like this:
$array = array('foo', 'bar');
array_splice($array, 1);
echo count($array); // echoes 1
This is because array_splice takes a reference, and so modifies a variable.
In your case, you're doing this:
JBPlug_do_callback('jb_init', $A=false);
Presumably, JBPlug_do_callback is expecting a reference as its second argument. You are providing a value (= returns a value). It may make no difference to what the function does, but technically it's a breach of PHP's rules. (That's why it's a "strict standards" error: it may well not have a bad effect, but it's technically invalid.)
You can solve this, again, simply by providing what PHP wants: a variable:
$A = false;
JBPlug_do_callback('jb_init', $A);
My assumption followed by question based on the assumption:
Javascript has null and undefined. You can set a variable to be null, implying it has no value, or you can set it to undefined, implying that it isn't known whether it has a value or not - it's just not set at all.
PHP has null, which so far I've used in the same way I'd use null in Javascript. Does PHP have an equivalent of undefined?
Not really, undefined has no counterpart in PHP. Comparing JS's undefined to PHP
s null doesn't really stack up, but it's as close as you're going to get. In both languages you can assign these values/non-values:
var nothingness = undefined;
$nothing = null;
and, if you declare a variable, but don't assign it anything, it would appear that JS resolves the var to undefined, and PHP resolves (or assigns) that variable null:
var nothingness;
console.log(nothingness === undefined);//true
$foo;
echo is_null($foo) ? 'is null' : '?';//is null
Be careful with isset, though:
$foo = null;
//clearly, foo is set:
if (isset($foo))
{//will never echo
echo 'foo is set';
}
The only real way to know if the variable exists, AFAIK, is by using get_defined_vars:
$foo;
$bar = null;
$defined = get_defined_vars();
if (array_key_exists($defined, 'foo'))
{
echo '$foo was defined, and assigned: '.$foo;
}
I don't think there is undefined. Rather than checking if something is undefined as you would in JavaScript:
if(object.property === undefined) // Doesn't exist.
You just use isset():
if(!isset($something)) // Doesn't exist.
Also, I think your understanding of undefined is a little odd. You shouldn't be setting properties to undefined, that's illogical. You just want to check if something is undefined, which means you haven't defined it anywhere within scope. isset() follows this concept.
That said, you can use unset() which I guess would be considered the same as setting something to undefined.
No. It only has "unset", which is not actually a value at all.
undefined is the value you'll get in Javascript when trying to access a property/variable which does not exist. You don't typically set something to undefined.
PHP does not have this mechanism. If you're trying to access a property or variable which does not exist, you will trigger an error of the level E_NOTICE. The script will continue, but the value of the non-existent variable will be substituted by null.
In Javascript you try to access a variable and test whether it you get undefined or not.
In PHP, you use isset($var) to test whether a variable exists before accessing it.
There are some scenarios where the null is a valid value, and there needs to be some other data type to signify the result of an action.
For example, I have a function to get the value of some key in a complex/nested array. The key value can be anything (including null). What should I return in this case if the key path is not valid? Returning null, false, -1, etc. wouldn't make any sense because the key value might be one of these.
What I decided to is define a constant:
define("undefined", "__undefined__");
...
$value = getKeyValue($options, ["section", "subsection", "opt2"]);
if ($value != undefined) {
...
}
What is the correct way to write code that calls a function that accepts a variable pointer and changes the value?
The following works, but my IDE complains that $v is an undefined variable, which it is until the function it calls sets a value:
function foo(&$bar) {
$bar = 12345;
}
foo($v);
Should I initialize $v first to satisfy my IDE? Or is there a better way to do this?
$v = NULL;
foo($v);
When passing a variable by reference to a function, you need to have a reference to the variable from the calling code. To have a reference, the variable needs to exist. To exist, the variable needs to be initialized.
I recommend setting it to a reasonable default value. If the reasonable default is null, then use null. In some cases it may be more reasonable to use '' or 0 depending on what type of value you want the variable to hold.