Related
I have a variety of arrays that will either contain
story & message
or just
story
How would I check to see if an array contains both story and message? array_key_exists() only looks for that single key in the array.
Is there a way to do this?
Here is a solution that's scalable, even if you want to check for a large number of keys:
<?php
// The values in this arrays contains the names of the indexes (keys)
// that should exist in the data array
$required = array('key1', 'key2', 'key3');
$data = array(
'key1' => 10,
'key2' => 20,
'key3' => 30,
'key4' => 40,
);
if (count(array_intersect_key(array_flip($required), $data)) === count($required)) {
// All required keys exist!
}
If you only have 2 keys to check (like in the original question), it's probably easy enough to just call array_key_exists() twice to check if the keys exists.
if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
// Both keys exist.
}
However this obviously doesn't scale up well to many keys. In that situation a custom function would help.
function array_keys_exists(array $keys, array $arr) {
return !array_diff_key(array_flip($keys), $arr);
}
Surprisingly array_keys_exist doesn't exist?! In the interim that leaves some space to figure out a single line expression for this common task. I'm thinking of a shell script or another small program.
Note: each of the following solutions use concise […] array declaration syntax available in php 5.4+
array_diff + array_keys
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
// all keys found
} else {
// not all
}
(hat tip to Kim Stacks)
This approach is the most brief I've found. array_diff() returns an array of items present in argument 1 not present in argument2. Therefore an empty array indicates all keys were found. In php 5.5 you could simplify 0 === count(…) to be simply empty(…).
array_reduce + unset
if (0 === count(array_reduce(array_keys($source),
function($in, $key){ unset($in[array_search($key, $in)]); return $in; },
['story', 'message', '…'])))
{
// all keys found
} else {
// not all
}
Harder to read, easy to change. array_reduce() uses a callback to iterate over an array to arrive at a value. By feeding the keys we're interested in the $initial value of $in and then removing keys found in source we can expect to end with 0 elements if all keys were found.
The construction is easy to modify since the keys we're interested in fit nicely on the bottom line.
array_filter & in_array
if (2 === count(array_filter(array_keys($source), function($key) {
return in_array($key, ['story', 'message']); }
)))
{
// all keys found
} else {
// not all
}
Simpler to write than the array_reduce solution but slightly tricker to edit. array_filter is also an iterative callback that allows you to create a filtered array by returning true (copy item to new array) or false (don't copy) in the callback. The gotchya is that you must change 2 to the number of items you expect.
This can be made more durable but verge's on preposterous readability:
$find = ['story', 'message'];
if (count($find) === count(array_filter(array_keys($source), function($key) use ($find) { return in_array($key, $find); })))
{
// all keys found
} else {
// not all
}
One more possible solution:
if (!array_diff(['story', 'message'], array_keys($array))) {
// OK: all the keys are in $array
} else {
// FAIL: some keys are not
}
It seems to me, that the easiest method by far would be this:
$required = array('a','b','c','d');
$values = array(
'a' => '1',
'b' => '2'
);
$missing = array_diff_key(array_flip($required), $values);
Prints:
Array(
[c] => 2
[d] => 3
)
This also allows to check which keys are missing exactly. This might be useful for error handling.
The above solutions are clever, but unnecessarily slow. A simple foreach loop over a few keys is much faster.
function array_keys_exist($keys, $array){
foreach($keys as $key){
if(!array_key_exists($key, $array)) {
return false;
}
}
return true;
}
If you have something like this:
$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');
You could simply count():
foreach ($stuff as $value) {
if (count($value) == 2) {
// story and message
} else {
// only story
}
}
This only works if you know for sure that you ONLY have these array keys, and nothing else.
Using array_key_exists() only supports checking one key at a time, so you will need to check both seperately:
foreach ($stuff as $value) {
if (array_key_exists('story', $value) && array_key_exists('message', $value) {
// story and message
} else {
// either one or both keys missing
}
}
array_key_exists() returns true if the key is present in the array, but it is a real function and a lot to type. The language construct isset() will almost do the same, except if the tested value is NULL:
foreach ($stuff as $value) {
if (isset($value['story']) && isset($value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Additionally isset allows to check multiple variables at once:
foreach ($stuff as $value) {
if (isset($value['story'], $value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Now, to optimize the test for stuff that is set, you'd better use this "if":
foreach ($stuff as $value) {
if (isset($value['story']) {
if (isset($value['message']) {
// story and message
} else {
// only story
}
} else {
// No story - but message not checked
}
}
What about this:
isset($arr['key1'], $arr['key2'])
only return true if both are not null
if is null, key is not in array
I use something like this quite often
$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0
or to find the values for the wanted keys
$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
try this
$required=['a','b'];$data=['a'=>1,'b'=>2];
if(count(array_intersect($required,array_keys($data))>0){
//a key or all keys in required exist in data
}else{
//no keys found
}
This is the function I wrote for myself to use within a class.
<?php
/**
* Check the keys of an array against a list of values. Returns true if all values in the list
is not in the array as a key. Returns false otherwise.
*
* #param $array Associative array with keys and values
* #param $mustHaveKeys Array whose values contain the keys that MUST exist in $array
* #param &$missingKeys Array. Pass by reference. An array of the missing keys in $array as string values.
* #return Boolean. Return true only if all the values in $mustHaveKeys appear in $array as keys.
*/
function checkIfKeysExist($array, $mustHaveKeys, &$missingKeys = array()) {
// extract the keys of $array as an array
$keys = array_keys($array);
// ensure the keys we look for are unique
$mustHaveKeys = array_unique($mustHaveKeys);
// $missingKeys = $mustHaveKeys - $keys
// we expect $missingKeys to be empty if all goes well
$missingKeys = array_diff($mustHaveKeys, $keys);
return empty($missingKeys);
}
$arrayHasStoryAsKey = array('story' => 'some value', 'some other key' => 'some other value');
$arrayHasMessageAsKey = array('message' => 'some value', 'some other key' => 'some other value');
$arrayHasStoryMessageAsKey = array('story' => 'some value', 'message' => 'some value','some other key' => 'some other value');
$arrayHasNone = array('xxx' => 'some value', 'some other key' => 'some other value');
$keys = array('story', 'message');
if (checkIfKeysExist($arrayHasStoryAsKey, $keys)) { // return false
echo "arrayHasStoryAsKey has all the keys<br />";
} else {
echo "arrayHasStoryAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasMessageAsKey, $keys)) { // return false
echo "arrayHasMessageAsKey has all the keys<br />";
} else {
echo "arrayHasMessageAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasStoryMessageAsKey, $keys)) { // return false
echo "arrayHasStoryMessageAsKey has all the keys<br />";
} else {
echo "arrayHasStoryMessageAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasNone, $keys)) { // return false
echo "arrayHasNone has all the keys<br />";
} else {
echo "arrayHasNone does NOT have all the keys<br />";
}
I am assuming you need to check for multiple keys ALL EXIST in an array. If you are looking for a match of at least one key, let me know so I can provide another function.
Codepad here http://codepad.viper-7.com/AKVPCH
Hope this helps:
function array_keys_exist($searchForKeys = array(), $inArray = array()) {
$inArrayKeys = array_keys($inArray);
return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys);
}
This is old and will probably get buried, but this is my attempt.
I had an issue similar to #Ryan. In some cases, I needed to only check if at least 1 key was in an array, and in some cases, all needed to be present.
So I wrote this function:
/**
* A key check of an array of keys
* #param array $keys_to_check An array of keys to check
* #param array $array_to_check The array to check against
* #param bool $strict Checks that all $keys_to_check are in $array_to_check | Default: false
* #return bool
*/
function array_keys_exist(array $keys_to_check, array $array_to_check, $strict = false) {
// Results to pass back //
$results = false;
// If all keys are expected //
if ($strict) {
// Strict check //
// Keys to check count //
$ktc = count($keys_to_check);
// Array to check count //
$atc = count(array_intersect($keys_to_check, array_keys($array_to_check)));
// Compare all //
if ($ktc === $atc) {
$results = true;
}
} else {
// Loose check - to see if some keys exist //
// Loop through all keys to check //
foreach ($keys_to_check as $ktc) {
// Check if key exists in array to check //
if (array_key_exists($ktc, $array_to_check)) {
$results = true;
// We found at least one, break loop //
break;
}
}
}
return $results;
}
This was a lot easier than having to write multiple || and && blocks.
$colsRequired = ["apple", "orange", "banana", "grapes"];
$data = ["apple"=>"some text", "orange"=>"some text"];
$presentInBoth = array_intersect($colsRequired,array_keys($data));
if( count($presentInBoth) != count($colsRequired))
echo "Missing keys :" . join(",",array_diff($colsRequired,$presentInBoth));
else
echo "All Required cols are present";
Does this not work?
array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
<?php
function check_keys_exists($keys_str = "", $arr = array()){
$return = false;
if($keys_str != "" and !empty($arr)){
$keys = explode(',', $keys_str);
if(!empty($keys)){
foreach($keys as $key){
$return = array_key_exists($key, $arr);
if($return == false){
break;
}
}
}
}
return $return;
}
//run demo
$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');
var_dump( check_keys_exists($key, $array));
I am not sure, if it is bad idea but I use very simple foreach loop to check multiple array key.
// get post attachment source url
$image = wp_get_attachment_image_src(get_post_thumbnail_id($post_id), 'single-post-thumbnail');
// read exif data
$tech_info = exif_read_data($image[0]);
// set require keys
$keys = array('Make', 'Model');
// run loop to add post metas foreach key
foreach ($keys as $key => $value)
{
if (array_key_exists($value, $tech_info))
{
// add/update post meta
update_post_meta($post_id, MPC_PREFIX . $value, $tech_info[$value]);
}
}
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));
Will return true, because there are keys from $keys array in $myArray
Something as this could be used
//Say given this array
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//This gives either true or false if story and message is there
count(array_intersect(['story', 'message'], array_keys($array_in_use2))) === 2;
Note the check against 2, if the values you want to search is different you can change.
This solution may not be efficient, but it works!
Updates
In one fat function:
/**
* Like php array_key_exists, this instead search if (one or more) keys exists in the array
* #param array $needles - keys to look for in the array
* #param array $haystack - the <b>Associative</b> array to search
* #param bool $all - [Optional] if false then checks if some keys are found
* #return bool true if the needles are found else false. <br>
* Note: if hastack is multidimentional only the first layer is checked<br>,
* the needles should <b>not be<b> an associative array else it returns false<br>
* The array to search must be associative array too else false may be returned
*/
function array_keys_exists($needles, $haystack, $all = true)
{
$size = count($needles);
if($all) return count(array_intersect($needles, array_keys($haystack))) === $size;
return !empty(array_intersect($needles, array_keys($haystack)));
}
So for example with this:
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//One of them exists --> true
$one_or_more_exists = array_keys_exists(['story', 'message'], $array_in_use2, false);
//all of them exists --> true
$all_exists = array_keys_exists(['story', 'message'], $array_in_use2);
Hope this helps :)
I usually use a function to validate my post and it is an answer for this question too so let me post it.
to call my function I will use the 2 array like this
validatePost(['username', 'password', 'any other field'], $_POST))
then my function will look like this
function validatePost($requiredFields, $post)
{
$validation = [];
foreach($requiredFields as $required => $key)
{
if(!array_key_exists($key, $post))
{
$validation['required'][] = $key;
}
}
return $validation;
}
this will output this
"required": [
"username",
"password",
"any other field"
]
so what this function does is validate and return all the missing fields of the post request.
// sample data
$requiredKeys = ['key1', 'key2', 'key3'];
$arrayToValidate = ['key1' => 1, 'key2' => 2, 'key3' => 3];
function keysExist(array $requiredKeys, array $arrayToValidate) {
if ($requiredKeys === array_keys($arrayToValidate)) {
return true;
}
return false;
}
I have this array:
$test = array( "a" => "b",
"c" => array("foo" => "bar",
"3" => "4",
),
"e" => "f",);
I want to create a function that finds the previous value in this array, given a certain value, for example find("bar", $test); should return "b".
This is what I got:
function find($needle, $array, $parent = NULL)
{
//moves the pointer until it reaches the desired value
while (current($array) != $needle){
//if current value is an array, apply this function recursively
if (is_array(current($array))){
$subarray = current($array);
//passes the previous parent array
find($needle, $subarray, prev($array));
}
//once it reaches the end of the array, end the execution
if(next($array) == FALSE){
return;
}
}
//once the pointer points to $needle, run find_prev()
find_prev(prev($array), $parent);
}
function find_prev($prev, $parent = NULL)
{
// in case there is no previous value in array and there is a superior level
if (!$prev && $parent) {
find_prev($parent);
return;
}
// in case previous value is an array
// find last value of that array
if (is_array($prev) && $prev){
find_prev(end($prev), $parent));
return;
} else {
$GLOBALS['pre'] = $prev;
}
}
For pedagogical reasons and since I have devoted some time to this function, it would be great if you could provide any hints about why this isn't working rather than any other simpler solution that you might have.
You have an infinite loop. Your algorithm is a bit complicated for what you want to do. Maybe you should just keep the previous value in a variable and return it when you find the $needle. Here is the corresponding code. I tried to not modify your code as much as I could:
function find($needle, $array, $lastValue = NULL)
{
$previousValue = null;
//moves the pointer until it reaches the desired value
while (current($array) != FALSE) {
$value = current($array);
//if current value is an array, apply this function recursively
if (is_array($value)) {
$subarray = $value;
//passes the previous value as the last value for the embedded array
$value = find($needle, $subarray, $previousValue);
if ($value !== NULL) {
return $value;
}
} else if ($value === $needle) {
//returns the previous value of the current array
if ($previousValue !== NULL) {
return $previousValue;
//returns the last checked value of the parent array
} else if ($lastValue !== NULL) {
return $lastValue;
} else {
return;
}
} else {
$previousValue = $value;
}
next($array);
}
}
$test = array(
"a" => "b",
"c" => array(
"foo" => "bar",
"3" => "4"
),
"e" => "f"
);
$result = find("bar", $test);
if ($result === null) {
print('no previous value');
} else {
$GLOBALS['pre'] = $result;
print($GLOBALS['pre']);
}
You may try TDD to code this kind of algorithm. It could help you.
The function find() calls itself recursively for sub-arrays but it doesn't check if the inner call found something or not and keep searching. This is why the first call to find_prev() runs with $test['b'] as its first parameter (prev() of the last element in $test). You expect it to run with $test['a'].
This question already has answers here:
array_key_exists is not working
(4 answers)
Closed 8 years ago.
I have a matrix¹²³ with the following structure (it's dynamic, may or may not contains those keys (or even more))
array(
"where" => array(
"data_col1": "val1",
"data_col2": "val2"
),
"like" => array(
"data_col3": "val3"
)
);
What I need to do is to find if $var_with_data_col_name exists or not.
Using array_key_exists I can check if "where" or "like" exist, but I couldn't find a way to check inside them for a specific key.
PS:
$var_with_data_col_name would be a variable with one of the following strings:
- data_col1
- data_col2
- data_col3
You can't search for array keys or values in multidimensional arrays directly. Walk through the array and search for it then.
$data_column_1_exists = false;
foreach($array as $key => $value)
{
if(array_key_exists('data_col1', $value)
&& $key == 'where' //optionally check in specific array
)
{
$data_column_1_exists = true;
}
}
You can use this -
function key_exists_level2($arr, $key){
foreach($arr as $level1arr){
if(isset($level1arr[$key])){
return true;
}
}
return false;
}
//And check with
key_exists_level2($arr, $var_with_data_col_name)
Itterate through the "main array" and use the same function for checking the keys of each "sub array"
You can use this code, which gives you the key..which has your $var_with_data_col_name .
$data = array(
"where" => array(
"data_col1" => "val1",
"data_col2" => "val2"
),
"like" => array(
"data_col3" => "val3"
)
);
$key;
$flag = false;
$data_key = 'data_col1';
foreach($data as $our_key => $array){
if(array_key_exists($data_key,$array)){
$key = $our_key;
$flag = true;
}
}
if($flag){
print_r($data[$key]);
}
I'm sure there is already a function out there, more of an exercise for myself!
function recursive_array_key_exists($needle, array $haystack) {
if (array_key_exists($needle, $haystack)) return true;
foreach($haystack as $value) {
if (is_array($value)) {
if (recursive_array_key_exists($needle, $value)) return true;
}
}
return false;
}
Just saw the comment linking to this answer: array_key_exists is not working
I guess mine is basically identical just less code!
I'm looking for some tool to give me a recursive diff of two arrays. What I envision is a web page with two color-coded tree-structures. On each tree, green are parts of the array which match in both arrays, and red is for parts of each that don't match the other. Something like the output of dBug
I have some code that gives me a nested array to populate a report. I'm developing a new method that should be faster, but I need to test the values and also the structure, to make sure it gives output identical to the old method.
Is there something out there that I can use? Or do I need to write this? Or is there another way to accomplish my goals?
There is one such function implemented in the comments of array_diff.
function arrayRecursiveDiff($aArray1, $aArray2) {
$aReturn = array();
foreach ($aArray1 as $mKey => $mValue) {
if (array_key_exists($mKey, $aArray2)) {
if (is_array($mValue)) {
$aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
} else {
if ($mValue != $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
The implementation only handles two arrays at a time, but I do not think that really posses a problem. You could run the diff sequentially if you need the diff of 3 or more arrays at a time. Also this method uses key checks and does a loose verification.
The accepted answer is close to correct, but it doesn't really emulate array_diff correctly.
There are two problems that largely revolve around key matching:
array_diff has a specific behavior where it does not produce a result for an array key that is completely missing from the second array if its value is still in the second array. If you have two arrays $first = ['foo' => 2, 'moo' => 2] and $second = ['foo' => 2], using the accepted answer's function the output will be ['moo' => 2]. If you run the same arrays through array_diff, it will produce an empty array. This is because the above function's final else statement adds it to the diff if the array key is missing, but that's not the expected behavior from array_diff. The same is true with these two arrays: $first = ['foo' => 1] and $second = [1]. array_diff will produce an empty array.
If two arrays have the same values but different keys, it returns more values than expected. If you have two arrays $foo = [1, 2] and $moo = [2, 1], the function from the accepted answer will output all values from $foo. This is because it's doing a strict key matching on each iteration where it finds the same key (numerical or otherwise) in both arrays instead of checking all of the other values in the second array.
The following function is similar, but acts more closely to how you'd expect array_diff to work (also with less silly variable names):
function array_diff_recursive($arr1, $arr2)
{
$outputDiff = [];
foreach ($arr1 as $key => $value)
{
//if the key exists in the second array, recursively call this function
//if it is an array, otherwise check if the value is in arr2
if (array_key_exists($key, $arr2))
{
if (is_array($value))
{
$recursiveDiff = array_diff_recursive($value, $arr2[$key]);
if (count($recursiveDiff))
{
$outputDiff[$key] = $recursiveDiff;
}
}
else if (!in_array($value, $arr2))
{
$outputDiff[$key] = $value;
}
}
//if the key is not in the second array, check if the value is in
//the second array (this is a quirk of how array_diff works)
else if (!in_array($value, $arr2))
{
$outputDiff[$key] = $value;
}
}
return $outputDiff;
}
function array_diff_assoc_recursive($array1, $array2)
{
foreach($array1 as $key => $value){
if(is_array($value)){
if(!isset($array2[$key]))
{
$difference[$key] = $value;
}
elseif(!is_array($array2[$key]))
{
$difference[$key] = $value;
}
else
{
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if($new_diff != FALSE)
{
$difference[$key] = $new_diff;
}
}
}
elseif((!isset($array2[$key]) || $array2[$key] != $value) && !($array2[$key]===null && $value===null))
{
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
Example:
$a = array(
"product_a" => array(
'description'=>'Product A',
'color'=>'Red',
'quantity'=>'5',
'serial'=>array(1,2,3)
),
"product_b" => array(
'description'=>'Product B'
)
);
$b = array(
"product_a" => array(
'description'=>'Product A',
'color'=>'Blue',
'quantity'=>'5',
'serial'=>array(1,2,5)
),
"product_b" => array(
'description'=>'Product B'
)
);
Output:
array_diff_assoc_recursive($a,$b);
Array
(
[product_a] => Array
(
[color] => Red
[serial] => Array
(
[2] => 3
)
)
)
Try this code:
function arrayDiffRecursive($firstArray, $secondArray, $reverseKey = false)
{
$oldKey = 'old';
$newKey = 'new';
if ($reverseKey) {
$oldKey = 'new';
$newKey = 'old';
}
$difference = [];
foreach ($firstArray as $firstKey => $firstValue) {
if (is_array($firstValue)) {
if (!array_key_exists($firstKey, $secondArray) || !is_array($secondArray[$firstKey])) {
$difference[$oldKey][$firstKey] = $firstValue;
$difference[$newKey][$firstKey] = '';
} else {
$newDiff = arrayDiffRecursive($firstValue, $secondArray[$firstKey], $reverseKey);
if (!empty($newDiff)) {
$difference[$oldKey][$firstKey] = $newDiff[$oldKey];
$difference[$newKey][$firstKey] = $newDiff[$newKey];
}
}
} else {
if (!array_key_exists($firstKey, $secondArray) || $secondArray[$firstKey] != $firstValue) {
$difference[$oldKey][$firstKey] = $firstValue;
$difference[$newKey][$firstKey] = $secondArray[$firstKey];
}
}
}
return $difference;
}
$differences = array_replace_recursive(
arrayDiffRecursive($firstArray, $secondArray),
arrayDiffRecursive($secondArray, $firstArray, true)
);
var_dump($differences);
The answer by Mohamad is working good, except that it needs change on the line:
$difference[$newKey][$firstKey] = $secondArray[$firstKey];
with:
$difference[$newKey][$firstKey] = array_key_exists($firstKey, $secondArray) ? $secondArray[$firstKey] : null;
or, if you are using Laravel, with:
$difference[$newKey][$firstKey] = array_get($secondArray, $firstKey);
Otherwise, you will get errors like
PHP error: Undefined index: some_key
when a some_key exists in $secondArray but not in $firstArray
I have a variety of arrays that will either contain
story & message
or just
story
How would I check to see if an array contains both story and message? array_key_exists() only looks for that single key in the array.
Is there a way to do this?
Here is a solution that's scalable, even if you want to check for a large number of keys:
<?php
// The values in this arrays contains the names of the indexes (keys)
// that should exist in the data array
$required = array('key1', 'key2', 'key3');
$data = array(
'key1' => 10,
'key2' => 20,
'key3' => 30,
'key4' => 40,
);
if (count(array_intersect_key(array_flip($required), $data)) === count($required)) {
// All required keys exist!
}
If you only have 2 keys to check (like in the original question), it's probably easy enough to just call array_key_exists() twice to check if the keys exists.
if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
// Both keys exist.
}
However this obviously doesn't scale up well to many keys. In that situation a custom function would help.
function array_keys_exists(array $keys, array $arr) {
return !array_diff_key(array_flip($keys), $arr);
}
Surprisingly array_keys_exist doesn't exist?! In the interim that leaves some space to figure out a single line expression for this common task. I'm thinking of a shell script or another small program.
Note: each of the following solutions use concise […] array declaration syntax available in php 5.4+
array_diff + array_keys
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
// all keys found
} else {
// not all
}
(hat tip to Kim Stacks)
This approach is the most brief I've found. array_diff() returns an array of items present in argument 1 not present in argument2. Therefore an empty array indicates all keys were found. In php 5.5 you could simplify 0 === count(…) to be simply empty(…).
array_reduce + unset
if (0 === count(array_reduce(array_keys($source),
function($in, $key){ unset($in[array_search($key, $in)]); return $in; },
['story', 'message', '…'])))
{
// all keys found
} else {
// not all
}
Harder to read, easy to change. array_reduce() uses a callback to iterate over an array to arrive at a value. By feeding the keys we're interested in the $initial value of $in and then removing keys found in source we can expect to end with 0 elements if all keys were found.
The construction is easy to modify since the keys we're interested in fit nicely on the bottom line.
array_filter & in_array
if (2 === count(array_filter(array_keys($source), function($key) {
return in_array($key, ['story', 'message']); }
)))
{
// all keys found
} else {
// not all
}
Simpler to write than the array_reduce solution but slightly tricker to edit. array_filter is also an iterative callback that allows you to create a filtered array by returning true (copy item to new array) or false (don't copy) in the callback. The gotchya is that you must change 2 to the number of items you expect.
This can be made more durable but verge's on preposterous readability:
$find = ['story', 'message'];
if (count($find) === count(array_filter(array_keys($source), function($key) use ($find) { return in_array($key, $find); })))
{
// all keys found
} else {
// not all
}
One more possible solution:
if (!array_diff(['story', 'message'], array_keys($array))) {
// OK: all the keys are in $array
} else {
// FAIL: some keys are not
}
It seems to me, that the easiest method by far would be this:
$required = array('a','b','c','d');
$values = array(
'a' => '1',
'b' => '2'
);
$missing = array_diff_key(array_flip($required), $values);
Prints:
Array(
[c] => 2
[d] => 3
)
This also allows to check which keys are missing exactly. This might be useful for error handling.
The above solutions are clever, but unnecessarily slow. A simple foreach loop over a few keys is much faster.
function array_keys_exist($keys, $array){
foreach($keys as $key){
if(!array_key_exists($key, $array)) {
return false;
}
}
return true;
}
If you have something like this:
$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');
You could simply count():
foreach ($stuff as $value) {
if (count($value) == 2) {
// story and message
} else {
// only story
}
}
This only works if you know for sure that you ONLY have these array keys, and nothing else.
Using array_key_exists() only supports checking one key at a time, so you will need to check both seperately:
foreach ($stuff as $value) {
if (array_key_exists('story', $value) && array_key_exists('message', $value) {
// story and message
} else {
// either one or both keys missing
}
}
array_key_exists() returns true if the key is present in the array, but it is a real function and a lot to type. The language construct isset() will almost do the same, except if the tested value is NULL:
foreach ($stuff as $value) {
if (isset($value['story']) && isset($value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Additionally isset allows to check multiple variables at once:
foreach ($stuff as $value) {
if (isset($value['story'], $value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Now, to optimize the test for stuff that is set, you'd better use this "if":
foreach ($stuff as $value) {
if (isset($value['story']) {
if (isset($value['message']) {
// story and message
} else {
// only story
}
} else {
// No story - but message not checked
}
}
What about this:
isset($arr['key1'], $arr['key2'])
only return true if both are not null
if is null, key is not in array
I use something like this quite often
$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0
or to find the values for the wanted keys
$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
try this
$required=['a','b'];$data=['a'=>1,'b'=>2];
if(count(array_intersect($required,array_keys($data))>0){
//a key or all keys in required exist in data
}else{
//no keys found
}
This is the function I wrote for myself to use within a class.
<?php
/**
* Check the keys of an array against a list of values. Returns true if all values in the list
is not in the array as a key. Returns false otherwise.
*
* #param $array Associative array with keys and values
* #param $mustHaveKeys Array whose values contain the keys that MUST exist in $array
* #param &$missingKeys Array. Pass by reference. An array of the missing keys in $array as string values.
* #return Boolean. Return true only if all the values in $mustHaveKeys appear in $array as keys.
*/
function checkIfKeysExist($array, $mustHaveKeys, &$missingKeys = array()) {
// extract the keys of $array as an array
$keys = array_keys($array);
// ensure the keys we look for are unique
$mustHaveKeys = array_unique($mustHaveKeys);
// $missingKeys = $mustHaveKeys - $keys
// we expect $missingKeys to be empty if all goes well
$missingKeys = array_diff($mustHaveKeys, $keys);
return empty($missingKeys);
}
$arrayHasStoryAsKey = array('story' => 'some value', 'some other key' => 'some other value');
$arrayHasMessageAsKey = array('message' => 'some value', 'some other key' => 'some other value');
$arrayHasStoryMessageAsKey = array('story' => 'some value', 'message' => 'some value','some other key' => 'some other value');
$arrayHasNone = array('xxx' => 'some value', 'some other key' => 'some other value');
$keys = array('story', 'message');
if (checkIfKeysExist($arrayHasStoryAsKey, $keys)) { // return false
echo "arrayHasStoryAsKey has all the keys<br />";
} else {
echo "arrayHasStoryAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasMessageAsKey, $keys)) { // return false
echo "arrayHasMessageAsKey has all the keys<br />";
} else {
echo "arrayHasMessageAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasStoryMessageAsKey, $keys)) { // return false
echo "arrayHasStoryMessageAsKey has all the keys<br />";
} else {
echo "arrayHasStoryMessageAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasNone, $keys)) { // return false
echo "arrayHasNone has all the keys<br />";
} else {
echo "arrayHasNone does NOT have all the keys<br />";
}
I am assuming you need to check for multiple keys ALL EXIST in an array. If you are looking for a match of at least one key, let me know so I can provide another function.
Codepad here http://codepad.viper-7.com/AKVPCH
Hope this helps:
function array_keys_exist($searchForKeys = array(), $inArray = array()) {
$inArrayKeys = array_keys($inArray);
return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys);
}
This is old and will probably get buried, but this is my attempt.
I had an issue similar to #Ryan. In some cases, I needed to only check if at least 1 key was in an array, and in some cases, all needed to be present.
So I wrote this function:
/**
* A key check of an array of keys
* #param array $keys_to_check An array of keys to check
* #param array $array_to_check The array to check against
* #param bool $strict Checks that all $keys_to_check are in $array_to_check | Default: false
* #return bool
*/
function array_keys_exist(array $keys_to_check, array $array_to_check, $strict = false) {
// Results to pass back //
$results = false;
// If all keys are expected //
if ($strict) {
// Strict check //
// Keys to check count //
$ktc = count($keys_to_check);
// Array to check count //
$atc = count(array_intersect($keys_to_check, array_keys($array_to_check)));
// Compare all //
if ($ktc === $atc) {
$results = true;
}
} else {
// Loose check - to see if some keys exist //
// Loop through all keys to check //
foreach ($keys_to_check as $ktc) {
// Check if key exists in array to check //
if (array_key_exists($ktc, $array_to_check)) {
$results = true;
// We found at least one, break loop //
break;
}
}
}
return $results;
}
This was a lot easier than having to write multiple || and && blocks.
$colsRequired = ["apple", "orange", "banana", "grapes"];
$data = ["apple"=>"some text", "orange"=>"some text"];
$presentInBoth = array_intersect($colsRequired,array_keys($data));
if( count($presentInBoth) != count($colsRequired))
echo "Missing keys :" . join(",",array_diff($colsRequired,$presentInBoth));
else
echo "All Required cols are present";
Does this not work?
array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
<?php
function check_keys_exists($keys_str = "", $arr = array()){
$return = false;
if($keys_str != "" and !empty($arr)){
$keys = explode(',', $keys_str);
if(!empty($keys)){
foreach($keys as $key){
$return = array_key_exists($key, $arr);
if($return == false){
break;
}
}
}
}
return $return;
}
//run demo
$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');
var_dump( check_keys_exists($key, $array));
I am not sure, if it is bad idea but I use very simple foreach loop to check multiple array key.
// get post attachment source url
$image = wp_get_attachment_image_src(get_post_thumbnail_id($post_id), 'single-post-thumbnail');
// read exif data
$tech_info = exif_read_data($image[0]);
// set require keys
$keys = array('Make', 'Model');
// run loop to add post metas foreach key
foreach ($keys as $key => $value)
{
if (array_key_exists($value, $tech_info))
{
// add/update post meta
update_post_meta($post_id, MPC_PREFIX . $value, $tech_info[$value]);
}
}
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));
Will return true, because there are keys from $keys array in $myArray
Something as this could be used
//Say given this array
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//This gives either true or false if story and message is there
count(array_intersect(['story', 'message'], array_keys($array_in_use2))) === 2;
Note the check against 2, if the values you want to search is different you can change.
This solution may not be efficient, but it works!
Updates
In one fat function:
/**
* Like php array_key_exists, this instead search if (one or more) keys exists in the array
* #param array $needles - keys to look for in the array
* #param array $haystack - the <b>Associative</b> array to search
* #param bool $all - [Optional] if false then checks if some keys are found
* #return bool true if the needles are found else false. <br>
* Note: if hastack is multidimentional only the first layer is checked<br>,
* the needles should <b>not be<b> an associative array else it returns false<br>
* The array to search must be associative array too else false may be returned
*/
function array_keys_exists($needles, $haystack, $all = true)
{
$size = count($needles);
if($all) return count(array_intersect($needles, array_keys($haystack))) === $size;
return !empty(array_intersect($needles, array_keys($haystack)));
}
So for example with this:
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//One of them exists --> true
$one_or_more_exists = array_keys_exists(['story', 'message'], $array_in_use2, false);
//all of them exists --> true
$all_exists = array_keys_exists(['story', 'message'], $array_in_use2);
Hope this helps :)
I usually use a function to validate my post and it is an answer for this question too so let me post it.
to call my function I will use the 2 array like this
validatePost(['username', 'password', 'any other field'], $_POST))
then my function will look like this
function validatePost($requiredFields, $post)
{
$validation = [];
foreach($requiredFields as $required => $key)
{
if(!array_key_exists($key, $post))
{
$validation['required'][] = $key;
}
}
return $validation;
}
this will output this
"required": [
"username",
"password",
"any other field"
]
so what this function does is validate and return all the missing fields of the post request.
// sample data
$requiredKeys = ['key1', 'key2', 'key3'];
$arrayToValidate = ['key1' => 1, 'key2' => 2, 'key3' => 3];
function keysExist(array $requiredKeys, array $arrayToValidate) {
if ($requiredKeys === array_keys($arrayToValidate)) {
return true;
}
return false;
}