I have the following array($post_options), it can appear in various guises, the key is dynamic:
It might be like this:
array(1) { [95]=> string(2) "25" }
It might be like this, the key can be anything:
array(1) { [05]=> string(2) "" }
I want to add a control statement that controls upon whether or not the value in the first key element has a value.
I have this code:
if (!isset($post_options[0])) {
// value is empty
var_dump($post_options);
}
else {
// value has value
echo 'Option Selected';
}
But this is not working, it returns true when the value is set and not set. What is the solution here? Thanks
So if the array appears like this (the value of the first key is empty):
array(1) { [05]=> string(2) "" }
I want to var_dump(); in this case
Depending on your exact requirements, there are three alternatives.
array_key_exists($key, $array)
This is the simplest option. It returns true if the array has the given key, and otherwise returns false.
isset($array[$key])
Slightly more strict than array_key_exists since it also requires that the value assigned to the key is not null.
!empty($array[$key]) (note the !) This is the strictest option, as it requires the value to not be any empty value (i.e., not null, false, 0, '0', etc).
There's some other options, again, depending on exact requirements. It looks to me that you are looking for the !empty option, since it will (in particular) reject empty strings.
If you don't know the first key of array - use array_keys, for example, to get all keys of your array.
$ar = array('95' => 'val');
$keys = array_keys($ar);
$first_item = $ar[$keys[0]];
var_dump($first_item); // outputs: string(3) "val"
Another option can be a current function, which will return you current element of an array. Considering that you don't move array pointer, code can be:
$ar = array('95' => 'new_val', '02' => 'val2');
$cur = current($ar);
var_dump($cur); // outputs: string(7) "new_val"
After that you can use standard emptyfunction to check:
if (empty($cur))
or
if (empty($first_item))
try this
if (!isset($post_options[0])) { // value is empty
if(!empty($post_options[0])) {
var_dump($post_options);
}
}
isset checks whether the array position exists or not, not whether it cointains or it doesn't contain a value.
You better have a look at the empty function to do this
if (empty($post_options[0])) {
// value is empty
var_dump($post_options);
} else {
// value has value
echo 'Option Selected';
}
hope this helps
Related
I am trying to get a certain value out of an array.
Example of the array is:
array(2) {
["error"]=>
array(0) {
}
["result"]=>
array(1) {
["open"]=>
array(1) {
["12345-AAAAA-66AAKK"]=>
array(14) {
["inf"]=>
Usually when I want a certain value I would use:
$datawanted=$data[result][open][value];
However, in this case the first array is a variable that always changes (12345-AAAAA-66AAKK), I need to find the value of that.
I tried getting this with reset() and key[0] but this not give the wanted result.
Is there a way to get the output of the first element in the result array?
You can use array_search: http://php.net/manual/de/function.array-search.php
Example:
foreach ($array['result']['open'] as $dynamicKey => $item) {
if ($key = array_search('Value you are looking for', $item) {
$datawanted=$array['result']['open'][$dynamicKey][$key];
}
}
$data[result][open] is not a correct way to access array items.
The token result looks like a constant. PHP searches for a constant named result, cannot find one and triggers a notice. Then it thinks "I guess the programmer wanted to write 'result' (a string, not a constant). I'll convert it as string to them." and uses 'result' instead.
It works but it's a horrible practice. It dates from the prehistory of PHP, 20 years ago and it's not recommended.
After you fix your code to correctly denote the keys of an array, the next step is to pick one of the many PHP ways to access values in the array.
You can get the first value of an array without knowing its key ($data['result']['open']['12345-AAAAA-66AAKK']) by using the function reset():
$datawanted = reset($data['result']['open']);
Or you can use the function array_values() to get only the values of the array (the keys are ignored, the returned array have the values indexed from zero) then your desired data is at position 0 on this array:
$values = array_values($data['result']['open']);
$datawanted = $values[0];
Another option, if you don't need to keep $data for further processing, is to use the PHP function array_shift() to remove the first value from the array and return it. Be warned that this function modifies the array it receives as argument:
$datawanted = array_shift($data['result']['open']);
If you need to process all the values of $data['result']['open'] (and you probably do) then the best way is to use the foreach PHP statement. It allows you to access both the key and the value of each element of the array:
foreach ($data['result']['open'] as $key => $value) {
// $key is '12345-AAAAA-66AAKK'
$datawanted = $value;
}
I recently tried to create an array with multiple Strings, representing the AcceptLanguage header. I need to push another user-specified language to the start of the array, to make it max priority.
So far I have
function getRequestLangs(){
//get languages from browser
$accLangs = explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
$requestedLanguages = array();
foreach($accLangs as $key => $lang){
$lang = substr($lang,0,2);
// p is a quality param, we won't need it, since the
// preferred languages are already sorted by default
if($lang != 'p='){
array_push($requestedLanguages,$lang);
}
}
// we only need each language once, this function keeps the order
return array_unique($requestedLanguages);
}
Now I want to add the user-specified language as first key (in case the language is not supportet, I may fall back to another accepted language)
//language from path, pushed as first index (highest priority)
if(isset($_GET['lang']) && $_GET['lang'] != ""){
$requestedLanguages = array_unshift($requestedLanguages,$_GET['lang']);
}
var_dump($requestedLanguages) before array_unshift:
array(2) {
[0]=> string(2) "de"
[2]=> string(2) "en"
}
var_dump($requestedLanguages) after array_unshift:
int(3)
I think it might have to do with the index-hole between 0 and 2, but that is only a guess.
[EDIT]
i need more caffeine...
//wrong:
$requestedLanguages = array_unshift($requestedLanguages,$_GET['lang']);
//right:
array_unshift($requestedLanguages,$_GET['lang']);
array_unshift mutates the supplied array and returns the new number of elements in the array after the item was prepended to it, so the int(3) is telling you that there are now three items in the array.
http://uk3.php.net/manual/en/function.array-unshift.php
This is a weird one, so bear with me. Asking you guys really is my last resort.
To be clear, I'm using Kohana 3.3, although I'm not even sure that's related to the problem.
I'm using a cookie to track read items on a website. The cookie contains a json_encoded array. Adding to that array isn't a problem, objects are added every time a new item is read. An item in the array contains an object with the last_view_date and a view_count For the sake of updating the view count, I need to check whether the item has been read already using array_key_exists and then add to the view count. Here's how I'm setting the cookie:
// Get the array from the cookie.
$cookie_value = Cookie::get_array('read_items');
// Update the view_count based on whether the id exists as a key.
$view_count = (array_key_exists($item->id, $cookie_value)) ?
$cookie_value[$item->id]['view_count'] + 1 : 1;
// Create the item to be added to the cookie.
$cookie_item = array(
'last_view_date' => time(),
'view_count' => $view_count
);
// Push $cookie_item to the cookie array.
Cookie::push('read_items', $item->id, $cookie_item);
I've added two methods to Kohana's Cookie class, Cookie::push and Cookie::get_array, used in the code above:
class Cookie extends Kohana_Cookie {
public static function push($cookie_name, $key, $value)
{
$cookie_value = parent::get($cookie_name);
// Add an empty array to the cookie if it doesn't exist.
if(!$cookie_value)
{
parent::set($cookie_name, json_encode(array()));
}
else
{
$cookie_value = (array)json_decode($cookie_value);
// If $value isn't set, append without key.
if(isset($value))
{
$cookie_value[$key] = $value;
}
else
{
$cookie_value[] = $key;
}
Cookie::set($cookie_name, json_encode($cookie_value));
}
}
public static function get_array($cookie_name)
{
return (array)json_decode(parent::get($cookie_name));
}
}
Now, here's my problem. Running a var_dump on $cookie_value outputs the following:
array(1) {
["37"]=>
object(stdClass)#43 (2) {
["last_view_date"]=>
int(1359563215)
["view_count"]=>
int(1)
}
}
But when I try to access $cookie_value[37], I can't:
var_dump(array_key_exists(37, $cookie_value));
// Outputs bool(false);
var_dump(is_array($cookie_value));
// Outputs bool(true);
var_dump(count($cookie_value));
// Outputs int(1);
var_dump(array_keys($cookie_value));
// Outputs:
// array(1) {
// [0]=>
// string(2) "37"
// }
Added debugging code:
var_dump(isset($cookie_value["37"]));
// Outputs bool(false).
var_dump(isset($cookie_value[37]));
// Outputs bool(false).
var_dump(isset($cookie_value[(string)37]));
// Outputs bool(false).
I hope it's clear enough.
Take a look at json_decode. Currently, you're casting the result to an array. If you pass true as the second parameter to json_decode, you'll get an array back instead of a stdObject.
The problem may also be related to you checking int vs string keys. You could test by running this code on your server:
<?php
$one = array("37" => "test");
$two = array(37 => "test");
var_dump(array_key_exists(37,$one)); // true or false?
var_dump(array_key_exists(37,$two)); // true
?>
Access the value using:-
$cookie_value["37"]
"37" (key) is in string format.. You are specifying it as integer ($cookie_value[37])
I'm used to perl's map() function where the callback can assign both the key and the value, thus creating an associative array where the input was a flat array. I'm aware of array_fill_keys() which can be useful if all you want to do is create a dictionary-style hash, but what if you don't necessarily want all values to be the same? Obviously all things can be done with foreach iteration, but what other (possibly more elegant) methods exist?
Edit: adding an example to clarify the transformation. Please don't get hung up on the transformation, the question is about transforming a flat list to a hash where we can't assume that all the values will be the same.
$original_array: ('a', 'b', 'c', 'd')
$new_hash: ('a'=>'yes', 'b'=>'no', 'c'=>'yes', 'd'=>'no')
*note: the values in this example are arbitrary, governed by some business logic that is not really relevant to this question. For example, perhaps it's based on the even-oddness of the ordinal value of the key
Real-world Example
So, using an answer that was provided here, here is how you could parse through the $_POST to get a list of only those input fields that match a given criteria. This could be useful, for example, if you have a lot of input fields in your form, but a certain group of them must be processed together.
In this case I have a number of input fields that represent mappings to a database. Each of the input fields looks like this:
<input name="field-user_email" value="2" /> where each of this type of field is prefixed with "field-".
what we want to do is, first, get a list of only those input fields who actually start with "field-", then we want to create an associative array called $mapped_fields that has the extracted field name as the key and the actual input field's value as the value.
$mapped_fields = array_reduce( preg_grep( '/field-.+/', array_keys( $_POST ) ), function( $hash, $field ){ $hash[substr( $field, 6 )] = $_POST[$field]; return $hash; } );
Which outputs:
Array ( [date_of_birth] => 1 [user_email] => 2 [last_name] => 3 [first_name] => 4 [current_position] => 6 )
(So, just to forestall the naysayers, let me agree that this bit of compact code is arguably a lot less readable that a simple loop that iterates through $_POST and, for each key, checks to see if it has the prefix, and if so, pops it and its value onto an array)
I had the exact same problem some days ago. It is not possible using array_map, but array_reduce does the trick.
$arr = array('a','b','c','d');
$assoc_arr = array_reduce($arr, function ($result, $item) {
$result[$item] = (($item == 'a') || ($item == 'c')) ? 'yes' : 'no';
return $result;
}, array());
var_dump($assoc_arr);
result:
array(4) { ["a"]=> string(3) "yes" ["b"]=> string(2) "no" ["c"]=> string(3) "yes" ["d"]=> string(2) "no" }
As far as I know, it is completely impossible in one expression, so you may as well use a foreach loop, à la
$new_hash = array();
foreach($original_array as $item) {
$new_hash[$item] = 'something';
}
If you need it in one expression, go ahead and make a function:
function array_map_keys($callback, $array) {
$result = array();
foreach($array as $item) {
$r = $callback($item);
$result[$r[0]] = $r[1];
}
return $result;
}
This is a clarification on my comment in the accepted method. Hopefully easier to read. This is from a WordPress class, thus the $wpdb reference to write data:
class SLPlus_Locations {
private $dbFields = array('name','address','city');
public function MakePersistent() {
global $wpdb;
$dataArray = array_reduce($this->dbFields,array($this,'mapPropertyToField'));
$wpdb->insert('wp_store_locator',$dataArray);
}
private function mapPropertyToField($result,$property) {
$result[$property] = $this->$property;
return $result;
}
}
Obviously there is a bit more to the complete solution, but the parts relevant to array_reduce() are present. Easier to read and more elegant than a foreach or forcing the issue through array_map() plus a custom insert statement.
Nice!
A good use case of yield operator!
$arr = array('a','b','c','d');
$fct = function(array $items) {
foreach($items as $letter)
{
yield sprintf("key-%s",
$letter
) => "yes";
}
};
$newArr = iterator_to_array($fct($arr));
which gives:
array(4) {
'key-a' =>
string(3) "yes"
'key-b' =>
string(3) "yes"
'key-c' =>
string(3) "yes"
'key-d' =>
string(3) "yes"
}
I'm trying to check that user's submitted data, from $_POST, has at least the same elements that my passed array has. I'm doing it because I will use those elements later by calling $_POST['element'] and I don't like errors about that element doesn't exist (isn't set). :)
I don't want to use something like isset($_POST['x'], $_POST['y'], $_POST['z']) because each time I need to rewrite $_POST and it seems unreadable as well.
I tried to use in_array(array('x', 'y', 'z'), $_POST), but it doesn't work (it returns false when it should return true). Any ideas how to make that work? :) I'm sure that I have empty strings as $_POST['x'], $_POST['y'] and $_POST['z']. I even tried to change values of hose three $_POST elements to something other than empty string - still... doesn'y work as expected. :(
Thanks in an advice! :)
Edit:
Just found out that in_array() checks values, not keys. Then, I tried to do like this...
in_array(array('title', 'slug', 'content'), array_keys($_POST))
Still, it returns false. How does it comes so? ;/
Edit #2:
Okay, here are results of debugging...
Incoming $_POST:
array(3) {
["title"]=>
string(0) ""
["slug"]=>
string(0) ""
["content"]=>
string(0) ""
}
Result of array_keys($_POST):
array(3) {
[0]=>
string(5) "title"
[1]=>
string(4) "slug"
[2]=>
string(7) "content"
}
Result of in_array(array('title', 'slug', 'content'), array_keys($_POST)):
bool(false)
The question... why is it false? I did all correct, as much as I know.
Edit #3:
At the end, I created my own method called Arr::keys_exists($keys, $array).
in_array() checks to see if a value exists in an array, not a key. If you want to check to see if a key exists, then you'd want something like...
in_array('x', array_keys($_POST));
or the simpler...
array_key_exists('x', $_POST);
If you want to check for many keys at once:
$required_keys = array('x'=>1, 'y'=>1, 'z'=>1);
$missing_keys = array_diff_key($required_keys, $_POST);
$missing_keys_count = count($missing_keys);
Because in_array checks if the needle is in the array exactly. See example #3 of the manual-page. array_key_exists cannot work with a key as first argument because array's aren't valid with arrays as keys.
You want something like all_in_array(array $needles, array $haystack); or array_all_keys_exists(array $keys, array $search); which returns whether all elements are in the array. You can probably implement something like this yourself, or ask for more help here.
First of all:
I don't want to use something like isset($_POST['x'], $_POST['y'], $_POST['z']) because each time I need to rewrite $_POST and it seems unreadable as well.
You should never change one of the super globals ;)
However, in_array() searches for values and not for keys
in_array(array('x', 'y', 'z'), array_key($_POST))
function getPost( $index, $default = '' )
{
if ( isset( $_POST[ $index ] ) )
{
return $_POST[ $index ];
}
return $default;
}
If you want to ensure the presence of multiple keys, then array_diff might be applicable:
!array_diff(array('title', 'slug', 'content'), array_keys($_POST))
You might also be interested in array_intersect_uassoc.
in_array(array('x', 'y', 'z'), $_POST), but it doesn't work (it returns false when it should return true)
No, it shouldn't. Read the manual of in_array.
Checks if a value exists in an array
Instead you'd like to check array keys. Get all the keys with array_keys and then use in_array.
With in_array you can test only one value at a time, though, not a whole array of values like you're trying to do.
In other words, if you do:
in_array(array('title', 'slug', 'content'), array_keys($_POST))
It will to find one element of the keys array containing an array with title, slug and comment, which is not what you want.
#Eric was right, try this -
in_array(array('title', 'slug', 'content'), array(array_keys($_POST)))
You don't understand in_array.
$a = array(
'x' => 1
);
echo in_array(array('x', 'y', 'z'), $a); // false
$a['an array'] = array('x', 'y', 'z');
echo in_array(array('x', 'y', 'z'), $a); // true