Very simple question as the title says.
I want PHP to behave rather than give me a error, it might just return another null to me when I called a method on a null object.
PHP on elsewhere looks like it doesn't care anything.
It returns null if you get a non-existed key from a array:
$foo = ['foo'=>'foo'];
var_dump($foo['bar']);
It returns null even if the array is null:
$foo = null;
var_dump($foo['bar']);
But it suddenly becomes serious to an object!
You should check the error, without saying that disable the report.
if ($foo != null) {
var_dump($foo['bar']);
}
// or
if(isset($foo['bar'])) {
var_dump($foo['bar']);
}
Related
I am using PHP Phan to scan through some code and ensure PHP 7 compatibility before upgrade. It is reporting an issue with the following...
if(!empty($values->custom_field['section'][0]['value'])):
Expected an object instance when accessing an instance property, but saw an expression $values with type null
I am not sure what is causing the error. How can I resolve it?
$values is an object, since it needs to have a custom_field property. For some reason your tool believes $values to be null in that instance.
Why that should be the case, I do not know. I have seen this happen with code such as,
$values = null;
if (SOMETHING THAT SHOULD ALWAYS HAPPEN) {
$values = functionReturningObject();
}
/*
if (null === $values) {
throw new RuntimeException('Impossible error!');
}
*/
if (empty($values->property)) {
...
}
In the above case, sometimes explicitly testing the object for nullity or objectness is enough to remove the warning.
In some cases, the warning is actually correct:
$values = null;
switch ($flag) {
case 0:
$values = ...;
break;
case 1:
$values = ...;
break;
case 2:
$values = ...;
break;
}
In the above case, the tool is warning you that in the unforeseen default case, however unlikely that might be, $values will be null.
The function empty() doesn't care whether or not its parameter is defined or makes sense. empty returns false if $values is not defined or null, but also when it's not an object or when it is an object without the custom_field property. And if that property exists but it's not an array it also returns false. If it is an array but doesn't have the key section it again returns false.
PhpStan shows this message because it thinks that $values is null. It's possible that this is correct, you would have to check the code to find where $value is defined/assigned. But since it is used in empty it will not cause runtime problems. If $values is always null then the check just makes your code more complex.
I have a class that has a method that expects a response from an API service in array format. This method then converts the response array into an object by casting (object)$response_array. After this the method attempts to parse the contents of the object. There is a possibility that the returned array could be empty. Before parsing the contents of the object in my class method, I perform a check for null or empty object in an if...else block. I would like to use an equivalence comparison operator like if($response_object === null){} and not if(empty($response_object)){}.
Below is how my class looks like
<?php
class ApiCall {
//this method receives array response, converts to object and then parses object
public function parseResponse(array $response_array)
{
$response_object = (object)$response_array;
//check if this object is null
if($response_object === null) //array with empty content returned
{
#...do something
}
else //returned array has content
{
#...do something
}
}
}
?>
So my question is - is this the right way to check for empty object, without using the function empty() and is it consistent? If not then how can I modify this code to get consistent results. This would help me know if null and empty mean the same thing in PHP objects. I would appreciate any answer where I can still use an equivalent comparison like this ===
It is not the right way to check for an empty object. If you call your function parseResponse with an empty array, the if condition will still be false.
So, if you would put echo in the if-else code like this:
class ApiCall {
//this method receives array response, converts to object and then parses object
public function parseResponse(array $response_array)
{
$response_object = (object)$response_array;
//check if this object is null
if($response_object === null) { // not doing what you expect
echo "null";
}
else {
echo "not null";
}
}
}
Then this call:
ApiCall::parseResponse(array()); // call with empty array
... will output
not null
The same happens if you test for empty($response_object). This used to be different in a distant past, but as from PHP 5.0 (mid-2004), objects with no properties are no longer considered empty.
You should just test on the array you already have, which is falsy when empty. So you can just write:
if(!$response_array) {
echo "null";
}
else {
echo "not null";
}
Or, if you really want an (in)equality, then do $response_array == false, making sure to use == and not ===. But personally, I find such comparisons with boolean literals nothing more than a waste of space.
All of the following would be working alternatives for the if condition:
Based on $response_array:
!$response_array
!count($response_array)
count($response_array) === 0
empty($response_array)
Based on $response_object:
!get_object_vars($response_object)
!(array)($response_object)
Note that get_object_vars could give a different result than the array cast method if $response_object were not a standard object, and would have inherited properties.
Look at this example
$ php -a
php > $o = (object)null;
php > var_dump($o);
class stdClass#2 (0) {
}
php > var_dump(!$o);
bool(false)
So, it is not good idea to compare object with null in your case. More about this: How to check that an object is empty in PHP?
We've got variable that for some reason we think would be an array, but it happens to be null.
$var = null
We try to get a value from this variable.
$value = $var['key']
This doesn't throw an error, my intuition is that it would though. What instead happens is that $value is now also null. Is there a particular reason that the above line doesn't throw an error?
There is "almost duplicate": Why does accessing array index on boolean value does not raise any kind of error?
the code there looks like:
$var = false;
$value = $var['key'];
and the answer is - it's just document
Accessing variables of other types (not including arrays or objects implementing the appropriate interfaces) using [] or {} silently returns NULL.
So in this string (I am talking about your case, $var = null, but with boolean would be the same explanation, just replace NULL to boolean)
$var['key']
$var is the variable of type NULL, and accessing variable of type NULL (other type that array or object) using [] silently returns NULL.
You can use this kind of fallback
function _get($from, $key)
{
if(is_null($from))
{
trigger_error('Trying to get value of null');
return null;
}
return $from[$key];
}
Change
$value = $var['key'];
to
$value = _get($var, 'key');
discussing with a friend of my work, we discover something weird about PHP. Let's get the following code:
<?php
$leo = false;
$retorno = $leo[0];
var_dump($retorno);
The return of var_dump() is NULL. Now, the thing is, why is returning NULL, if we are trying to access a bool as array?
The correct behavior isn't throw an exception telling us, that we are trying to access a non-array object as array (in this case a boolean var)?
what you guys think about that?
Since you are trying to access not a string, but a boolean it returns NULL. As from the manual:
Note:
Accessing variables of other types (not including arrays or objects implementing the appropriate interfaces) using [] or {} silently returns NULL.
It's NULL because $leo[0] isn't $leo. You haven't assigned the bool or string to $leo[0], therefore it's empty, and ultimately results in being NULL.
If you were to put:
$retorno = $leo;
Or
$leo[0] = false;
Then you would get the result you are expecting.
$leo = false;
$retorno = array($leo);
var_dump($retorno[0]);
Try this
I have a function in PHP, which has some arguments default to null, so that I can easily call it with less than the full number of arguments.
The problem is, that when I use a null-defaulted argument directly, I get the given argument, but when I try to copy that value to another variable, the variable only gets the default value of null.
It looks like this:
// inside my MySQLI wrapper class...
public function bind(&$stmt, $types = "", &$arg1, &$arg2 = null, &$arg3 = null /* this goes up to 20; it's auto-generated by another script */)
{
echo "dumping...";
var_dump($arg1); // var_dump shows value from function call (string(0))
var_dump($arg2); // ditto
echo "...dumped";
if ($arg2 != null) $foo = $arg2; var_dump($foo); echo "foo"; // var_dump shows that $foo is NULL
/* ... */
}
I call the function like this, from another script:
(It's a dummy script dealing with trucks and cars.)
$make = "";
$model = "";
$year = 0;
$license = "";
list($error, $message) = $mysql->bind($stmt, "", $make, $model, $year, $license);
My bind() function is a wrapper to MySQLI's bind_param() and bind_result() functions.
I've only included the top couple lines, because it's failing at that point already, before it even gets to the actual logic.
Right now, it just looks like it's a bug in PHP, because this doesn't follow what I know about how variables, arguments, default arguments, and references work.
Furthermore, this problem only appears to manifest itself in my real code, and doesn't appear in my simple php file that I coded up to test this.
Further info:
$foo gets assigned NULL, when $arg2 is an empty string, "", and properly gets assigned when it is a non-empty string. Empty strings are still valid strings, so why is PHP doing this?
The problem is the != comparison. What happens is that PHP type-juggles at least one of your variables, and as such, "" != null evaluates to false. The table part-way down this page shows what will happen for comparisons between different types. A type-strict form !== is needed:
if ($arg2 !== null)
$foo = $arg2;