I don't understand... I'm doing something and when I do print_r($var); it tells me that I have an array, so naturally I think I have an array yet when I do
if(is_array($xml->searchResult->item))
it returns false
I use this array with foreach(); in documentation it says that foreach() won't work with anything else but array, so assuming that this is an array that I'm working...
plus, if I try to access it via
echo $xml->searchResult->item[3];
i will get 4th element of my array
print_r will also print objects as though they are arrays.
well, is_array() returns true if your variable is an array, otherwise, it returns false. In your case, $xml->searchResult->item seems not to be an array. What is the output for
var_dump($xml->searchResult->item)
? Another hint: You can determine the type of a variable via gettype().
is_array() returns true only for real php arrays. It is possible to create a "fake" array by using the ArrayAccess class. That is, you can use normal array semantics (such as item[3]) but it is not a real array. I suspect your $item is an object. So use
if($x instanceof ArrayAccess || is_array($x))
Instead.
plus, if I try to access it via echo $xml->searchResult->item[3]; i will get 4th element of my array
That's right, the first element is always 0 unless you specifically change it.
The manual does mention that foreach works on objects as well, and it will iterate over properties.
In your case, the situation is slightly different because I guess you're using SimpleXML, which is yet another special case. SimpleXMLElement has its own iterator, which I assume is hardcoded as it doesn't seem to implement any of SPL's Iterator interfaces.
Long story short, some objects can be used as an array, but they are not one.
Just be careful to check what has been returned by your array. You might have an object with class or stdClass which is empty and you cannot get element from it.
Related
var_dump(is_a([], "array"));
The above code displays "false".
But,
echo gettype([]);
Displays "array".
Am I doing something wrong or missing out on something here?
is_a() function checks if the object is of this class or has this class as one of its parents
To check if something is an array, you should use is_array().
Based on the question and what has been described in the comments, it sounds like you're looking for a way to identify if something (i.e an array or object) is iterable.
In PHP, this can be achieved with is_iterable(), which will return true if the passed-in parameter supports iteration via foreach.
From the docs:
Verify that the contents of a variable is accepted by the iterable
pseudo-type, i.e. that it is either an array or an object implementing
Traversable
In the case of the array you mentioned in the question:
is_iterable([]));
Outputs:
bool(true);
To create an empty JSON object I do usually use:
json_encode((object) null);
casting null to an object works, but is there any other preferable way and/or any problem with this solution?
Recommended method
json_decode ("{}") will return a stdClass per default, using the below should therefor be considered safe/portable and correct.
json_encode (new stdClass);
Your solution could work..
The documentation specifies that (object) null will result in an empty object, some might therefor say that your code is valid and that it's the method to use.
PHP: Objects - Manual
If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created. If the value was NULL, the new instance will be empty.
.. but, try to keep it safe!
Though you never know when/if the above will change, so if you'd like to be 100% certain that you will always will end up with a {} in your encoded data you could use a hack such as:
$empty = json_decode ("{}");
$result = json_encode($empty); // "{}"
Even though it's tedious and ugly I do assume/hope that json_encode/json_decode is compatible with one another and always will evaluate the following to true:
$a = <something>;
$a === json_decode (json_encode ($a));
If you use objects as dynamic dictionaries (and I guess you do), then I think you want to use an ArrayObject.
It maps into JSON dictionary even when it's empty. It is great if you need to distinguish between lists (arrays) and dictionaries (associative arrays):
$complex = array('list' => array(), 'dict' => new ArrayObject());
print json_encode($complex); // -> {"list":[],"dict":{}}
You can also manipulate it seamlessly (as you would do with an associative array), and it will keep rendering properly into a dictionary:
$complex['dict']['a'] = 123;
print json_encode($complex); // -> {"list":[],"dict":{"a":123}}
unset($complex['dict']['a']);
print json_encode($complex); // -> {"list":[],"dict":{}}
If you need this to be 100% compatible both ways, you can also wrap json_decode so that it returns ArrayObjects instead of stdClass objects (you'll need to walk the result tree and recursively replace all the objects, which is a fairly easy task).
Gotchas. Only one I've found so far: is_array(new ArrayObject()) evaluates to false. You need to find and replace is_array occurrences with is_iterable.
Well, json_encode() simply returns a string from a PHP array/object/etc. You can achieve the same effect much more efficiently by doing:
$json = '{}';
There's really no point in using a function to accomplish this.
UPDATE
As per your comment updates, you could try:
$test = json_encode(array('some_properties'=>new stdClass));
Though I'm not sure that's any better than what you've been doing.
json_encode($array, JSON_FORCE_OBJECT) will do it too. see https://www.php.net/manual/en/function.json-encode.php
I'm using json_encode to dump an array and I'm getting different results using array() and SplFixedArray. It gives me array as it should when I use array(), but gives me an object when I use an SplFixedArray. Is there a reason for this?
This is what is returned when I use a normal array():
[{"firstName":"Bo","middleName":"N","lastName":"Higgs"},
{"firstName":"Bob","middleName":"D","lastName":"Superstar"}]
And when I use a SplFixedArray it gives me:
{"0":{"firstName":"Bo","middleName":"N","lastName":"Higgs"},
"1":{"firstName":"Bob","middleName":"D","lastName":"Superstar"}}
The two string are exactly the same, SplFixedArray only has a little different way of storing it, as it is a FIXED array. simple demo
Also be sure to read the manual. If you initiate SplFixedArray (it is a class, not a function) you get an object in return. The manual:
http://php.net/manual/en/class.splfixedarray.php
To create an empty JSON object I do usually use:
json_encode((object) null);
casting null to an object works, but is there any other preferable way and/or any problem with this solution?
Recommended method
json_decode ("{}") will return a stdClass per default, using the below should therefor be considered safe/portable and correct.
json_encode (new stdClass);
Your solution could work..
The documentation specifies that (object) null will result in an empty object, some might therefor say that your code is valid and that it's the method to use.
PHP: Objects - Manual
If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created. If the value was NULL, the new instance will be empty.
.. but, try to keep it safe!
Though you never know when/if the above will change, so if you'd like to be 100% certain that you will always will end up with a {} in your encoded data you could use a hack such as:
$empty = json_decode ("{}");
$result = json_encode($empty); // "{}"
Even though it's tedious and ugly I do assume/hope that json_encode/json_decode is compatible with one another and always will evaluate the following to true:
$a = <something>;
$a === json_decode (json_encode ($a));
If you use objects as dynamic dictionaries (and I guess you do), then I think you want to use an ArrayObject.
It maps into JSON dictionary even when it's empty. It is great if you need to distinguish between lists (arrays) and dictionaries (associative arrays):
$complex = array('list' => array(), 'dict' => new ArrayObject());
print json_encode($complex); // -> {"list":[],"dict":{}}
You can also manipulate it seamlessly (as you would do with an associative array), and it will keep rendering properly into a dictionary:
$complex['dict']['a'] = 123;
print json_encode($complex); // -> {"list":[],"dict":{"a":123}}
unset($complex['dict']['a']);
print json_encode($complex); // -> {"list":[],"dict":{}}
If you need this to be 100% compatible both ways, you can also wrap json_decode so that it returns ArrayObjects instead of stdClass objects (you'll need to walk the result tree and recursively replace all the objects, which is a fairly easy task).
Gotchas. Only one I've found so far: is_array(new ArrayObject()) evaluates to false. You need to find and replace is_array occurrences with is_iterable.
Well, json_encode() simply returns a string from a PHP array/object/etc. You can achieve the same effect much more efficiently by doing:
$json = '{}';
There's really no point in using a function to accomplish this.
UPDATE
As per your comment updates, you could try:
$test = json_encode(array('some_properties'=>new stdClass));
Though I'm not sure that's any better than what you've been doing.
json_encode($array, JSON_FORCE_OBJECT) will do it too. see https://www.php.net/manual/en/function.json-encode.php
I'm working with an object fed back from a class. For some reason, the class spits out an object with numbered properties (0, 1, 2, etc.). I need to check if the object is empty. The standard trick, empty(get_object_vars($obj)), won't work, because get_object_vars returns an empty array even when the object has (numbered) properties.
For reference, the object I'm working with is the one returned by the legislatorsZipCode method of the PHP interface for Sunlight's API. You can see a print_r of a sample response here.
Judging by the code, the author made the mistake of casting a numerically indexed array to an object. This makes getting object properties by name impossible, though you should still be able to foreach over it. You can also simply cast it back to an array: $results = (array) $obj;. Then, count the array.
This appears to work:
if (current($obj) === false)
echo "is empty\n";
It probably is doing an implicit cast to an array.