I would like to check if a key exist in one of the objects :
array (size=2)
0 =>
object(stdClass)[1631]
public 'label' => string 'Monsieur' (length=8)
public 'value' => string '1' (length=1)
public 'selected' => boolean true
1 =>
object(stdClass)[1633]
public 'label' => string 'Madame' (length=6)
public 'value' => string '2' (length=1)
In the example I have one array who contain two objects, the first one contain 'selected' key. I would like to return true if one of them contain 'selected' key. If the objects not contain 'selected' key I would like to return false.
I can have more than two objects. This is only for the example. Is there a function for this?
You can do this work using simple loop
$res = false;
foreach($arr as $item){
if (isset($item->selected))
$res = true;
}
Check result in demo
Note that if your array is large, you need to break loop when finding target key to prevent additional checking
Also you can do this work using array_filter()
$res = !!array_filter($arr, function($item){
return isset($item['selected']);
});
For a start, you don't have an array of arrays there, you have an array of objects.
Simply use property_exists to check if a key is in that object - however note, that it will return true even if value is null.
var_dump(property_exists($array[1], 'key'));
or if you want to test using arrays (docs):
var_dump(array_key_exists((array) $array[1], 'key'));
or as a function
function checkInArray($array, $key)
{
$found = array_filter($array, function($el)
{
return (property_exists((array) $el, $key));
}
return (!empty($found) ? true : false)
}
if (checkInArray($yourArray, 'selected')) {
# do something
}
Related
I am working on an API which receives a PHP object of $POST data. I am trying to check wether the 'smsPhoneNumber' inside customFields exists but not sure how to do this.
I am currently able to check for 'email' using:
if ( property_exists( $data, 'email' ) ) {
return true;
}
Question: How to check if 'smsPhoneNumber' exists?
--
var_dump:
object(stdClass)[1515]
public 'email' => string 'email#email.com'
public 'customFields' =>
array (size=2)
0 =>
object(stdClass)[1512]
public 'name' => string 'Firstname'
public 'value' => string 'james'
1 =>
object(stdClass)[1514]
public 'name' => string 'smsPhoneNumber'
public 'value' => string '077'
You could use an array_filter to get the custom field you want.
$phoneFields = array_filter($data->customFields, function($field) {
return $field->name === 'smsPhoneNumber';
});
This will only return objects in the array that have a name property equal to smsPhoneNumber.
if (!count($phoneFields)) {
// Phone not found
}
// or
if ($phone = current($phoneFields)) {
echo "The first phone number found is " . $phone->value;
}
The drawback of using array_filter() to search for the subarray values is:
array_filter() will not stop once it finds a match; it will keep iterating even after a match is found until it reaches the end of the array.
You should use a technique that allows an early break/return.
I recommend a simple foreach() with a break.
$foundIndex = null;
foreach ($data->customFields as $index => $customFields) {
if ($customFields->name === 'smsPhoneNumber') {
$foundIndex = $index;
// or $wasFound = true;
// or $smsNumber = $customFields->value;
break;
}
}
This will prove to be very efficient and easy to read/maintain.
easy question but i can't find a solution.
I have an array:
array
0 =>
array
1 => string '25' (length=2)
1 =>
array
1 => string '27' (length=2)
And i need to get:
array
0 => string '25' (length=2)
1 => string '27' (length=2)
Yea if course i could do:
foreach($result as $each) {
$resultIds[]=$each[1];
}
But i am pretty sure i saw this week somewhere a function for it something like...
array_something('current',$result);
What will loop over the array as foreach and return the first element so the result will be the same as the foreach solution. But i can't find it or remember it.
*What is the name of the function ? *
You can use array_map or array_walk
example of array_map
<?php
function first($n)
{
return $n[1];
}
$arr = array(
array(1, 2, 4),
array(1, 2, 3,),
);
var_export($arr);
// call internal function
$arr = array_map('current', $arr);
var_export($arr);
// call user function
$arr = array_map('first', $arr);
Please read manual here
$resultIds = array_map(function($arrEle) {
return $arrEle[0];
}, $result);
array_map takes a function which gets passed each of the elements of the array in turn, it is called for each array element.
The function then needs to return whatever you want in the new array, in this case you are wanting the second element of the child array so we return $arrEle[1];
after the whole array has been iterated over it returns the new array.
My project is in cakePHP but I think this is an aspect of native PHP that I am misunderstanding..
I have an afterFind($results, $primary = false) callback method in my AppModel. On one particular find if I debug($results); I get an array like this
array(
'id' => '2',
'price' => '79.00',
'setup_time' => '5',
'cleanup_time' => '10',
'duration' => '60',
'capacity' => '1',
'discontinued' => false,
'service_category_id' => '11'
)
In my afterFind I have some code like this:
foreach($results as &$model) {
// if multiple models
if(isset($model[$this->name][0])) {
....
The results of the find are from my Service model so inserting that for $this->name and checking if(isset($model['Service'][0])) should return false but it returns true? if(isset($model['Service'])) returns false as expected.
I am getting the following PHP warning:
Illegal string offset 'Service'
so what's going on here? why does if(isset($model['Service'][0])) return true if if(isset($model['Service'])) returns false?
UPDATE:
I still don't know the answer to my original question but I got around it by first checking if $results is a multidimensional array with
if(count($results) != count($results, COUNT_RECURSIVE))
Use array_key_exists() or empty() instead of isset(). PHP caches old array values strangely. They have to be manually unset using unset()
isset() does not return TRUE for array keys that correspond to a NULL value, while array_key_exists() does.
String offsets provide a mechanism to use strings as if they were an array of characters:
$string = 'abcde';
echo $string[2]; // c
$model is indeed a string for all keys except discontinued.
As for the isset($model['Service'][0]) return value, I'm a bit surprised. This is a simplified test case:
$model = '2';
var_dump(isset($model['Service'])); // bool(false)
var_dump(isset($model['Service'][0])); // bool(true)
There must be a reason somewhere. Will have a dig..
I need to remove an element form a deeply nested array of unknown structure (i.e. I do not know what the key sequence would be to address the element in order to unset it). The element I am removing however does have a consistent structure (stdObject), so I can search the entire multidimensional array to find it, but then it must be removed. Thoughts on how to accomplish this?
EDIT: This is the function I have right now trying to achieve this.
function _subqueue_filter_reference(&$where)
{
foreach ($where as $key => $value) {
if (is_array($value))
{
foreach ($value as $filter_key => $filter)
{
if (isset($filter['field']) && is_string($filter['field']) && $filter['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
unset($value[$filter_key]);
return TRUE;
}
}
return _subqueue_filter_reference($value);
}
}
return FALSE;
}
EDIT #2: Snipped of array structure from var_dump.
array (size=1)
1 =>
array (size=3)
'conditions' =>
array (size=5)
0 =>
array (size=3)
...
1 =>
array (size=3)
...
2 =>
array (size=3)
...
3 =>
array (size=3)
...
4 =>
array (size=3)
...
'args' =>
array (size=0)
empty
'type' => string 'AND' (length=3)
...so assuming that this entire structure is assigned to $array, the element I need to remove is $array[1]['conditions'][4] where that target is an array with three fields:
field
value
operator
...all of which are string values.
This is just a cursor problem.
function recursive_unset(&$array)
{
foreach ($array as $key => &$value) # See the added & here.
{
if(is_array($value))
{
if(isset($value['field']) && $value['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
unset($array[$key]);
}
recursive_unset($value);
}
}
}
Notes : you don't need to use is_string here, you can just make the comparison as you're comparing to a string and the value exists.
Don't use return unless you're sure there is only one occurrence of your value.
Edit :
Here is a complete example with an array similar to what you showed :
$test = array (
1 => array (
'conditions' =>
array (
0 => array ('field' => 'dont_care1', 'value' => 'test', 'operator' => 'whatever'),
1 => array ('field' => 'dont_care2', 'value' => 'test', 'operator' => 'whatever'),
2 => array ('field' => 'nodequeue_nodes_node__nodequeue_subqueue.reference', 'value' => 'test', 'operator' => 'whatever'),
3 => array ('field' => 'dont_care3', 'value' => 'test', 'operator' => 'whatever')
),
'args' => array (),
'type' => 'AND'
));
var_dump($test);
function recursive_unset(&$array)
{
foreach ($array as $key => &$value)
{
if(is_array($value))
{
if(isset($value['field']) && $value['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
unset($array[$key]);
}
recursive_unset($value);
}
}
}
recursive_unset($test);
var_dump($test);
One way to solve this was to extend your recursive function with a second parameter:
function _subqueue_filter_reference(&$where, $keyPath = array())
You'd still do the initial call the same way, but the internal call to itself would be this:
return _subqueue_filter_reference($value, array_merge($keyPath, array($key)));
This would provide you with the full path of keys to reach the current part of the array in the $keyPath variable. You can then use this in your unset. If you're feeling really dirty, you might even use eval for this as a valid shortcut, since the source of the input you'd give it would be fully within your control.
Edit: On another note, it may not be a good idea to delete items from the array while you're looping over it. I'm not sure how a foreach compiles but if you get weird errors you may want to separate your finding logic from the deleting logic.
I have arrived at a solution that is a spin-off of the function found at http://www.php.net/manual/en/function.array-search.php#79535 (array_search documentation).
Code:
function _subqueue_filter_reference($haystack,&$tree=array(),$index="")
{
// dpm($haystack);
if (is_array($haystack))
{
$result = array();
if (count($tree)==0)
{
$tree = array() + $haystack;
}
foreach($haystack as $k=>$current)
{
if (is_array($current))
{
if (isset($current['field']) && is_string($current['field']) && $current['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
{
eval("unset(\$tree{$index}[{$k}]);"); // unset all elements = empty array
}
_subqueue_filter_reference($current,$tree,$index."[$k]");
}
}
}
return $tree;
}
I hate having to use eval as it SCREAMS of a giant, gaping security hole, but it's pretty secure and the values being called in eval are generated explicitly by Drupal core and Views. I'm okay with using it for now.
Anyway, when I return the tree I simply replace the old array with the newly returned tree array. Works like a charm.
I have one array that contains some settings that looks like basically like this:
$defaults = array(
'variable' => 'value',
'thearray' => array(
'foo' => 'bar'
'myvar' => array('morevars' => 'morevalues');
);
);
On another file, i get a string with the first level key and it's childs to check if there is a value attached to it. Using the array above, i'd get something like this:
$option = "thearray['myvar']['morevars']";
I need to keep this string with a similar format to the above because I also need to pass it to another function that saves to a database and having it in an array's format comes in handy.
My question is, having the array and the string above, how can i check for both, existance and value of the given key inside the array? array_key_exists doesn't seem to work below the first level.
You could use a simple function to parse your key-string and examine the array like:
function array_deep_exists($array, $key)
{
$keys = preg_split("/'\\]|\\['/", $key, NULL, PREG_SPLIT_NO_EMPTY);
foreach ($keys as $key)
{
if ( ! array_key_exists($key, $array))
{
return false;
}
$array = $array[$key];
}
return true;
}
// Example usage
$defaults = array(
'variable' => 'value',
'thearray' => array(
'foo' => 'bar',
'myvar' => array('morevars' => 'morevalues')
)
);
$option = "thearray['myvar']['morevars']";
$exists = array_deep_exists($defaults, $option);
var_dump($exists); // bool(true)
Finally, to get the value (if it exists) return $array where the above returns true.
Note that if your array might contain false, then when returning the value you'll have to be careful to differentiate no-matching-value from a successful false value.
You need to eval this code, and use isset function in an eval string, and don't forget to add $ character in right place before code eval
example:
eval("echo isset(\$defaults['varname']['varname2']);")
this will echo 0 or 1 (false or true) You can do anything in eval, like a php source