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
Related
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
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 obtain the first key of an associative array, without creating a temporary variable via array_keys() or the like, to pass by reference. Unfortunately both reset() and array_shift() take the array argument by reference, so neither seem to be viable results.
With PHP 5.4 I'll be in heaven; array_keys($array)[0];, but unfortunately this of course is not an option either.
I could create a function to serve the purpose, but I can only imagine there is some concoction of PHP's array_* functions that will produce the desired result in a single statement, that I cannot think of or come up with.
So:
$array = array('foo' => 'bar', 'hello' => 'world');
$firstKey = assorted_functions($array); // $firstKey = 'foo'
The reason for the "no reference" clause in my question is only for the fact that I assume array_keys() will be required (if there is a way passing by reference, please fire away)
I'd use key(), but that requires a reset() as I'm not sure where the pointer will be at the time of this operation.
Addendum
I'm following up on a realization I had recently: as I mentioned in the comments, it'll use the memory all the same, so if that's a concern, this question hath no solution.
$a = range(0,99999);
var_dump(memory_get_peak_usage()); // int(8644416)
$k = array_keys($a)[0];
var_dump(memory_get_peak_usage()); // int(17168824)
I knew this, as PHP doesn't have such optimization capabilities, but figured it warranted explicit mention.
The brevity of the accepted answer is nice though, and'll work if you're working with reasonably sized arrays.
Although array_shift(array_keys($array)); will work, current(array_keys($array)); is faster as it doesn't advance the internal pointer.
Either one will work though.
Update
As #TomcatExodus noted, array_shift(); expects an array passed by reference, so the first example will issue an error. Best to stick with current();
You can use reset and key:
reset( $array );
$first_key = key( $array );
or, you can use a function:
function firstIndex($a) { foreach ($a as $k => $v) return $k; }
$key = firstIndex( $array );
array_shift(array_keys($array))
each() still a temporary required, but potentially a much smaller overhead than using array_keys().
What about using array_slice (in combination with array_keys for associative arrays)?
$a = range(0,999999);
var_dump(memory_get_peak_usage());
$k = array_keys(array_slice($a, 0, 1, TRUE))[0];
var_dump(memory_get_peak_usage());
var_dump($k);
$k = array_keys($a)[0];
var_dump(memory_get_peak_usage());
Gives as output (at least with me):
int(36354360)
int(36355112)
int(0)
int(72006024)
int(0)
I'm trying to use in_array or something like it for associative or more complex arrays.
This is the normal in_array
in_array('test', array('test', 'exists')); //true
in_array('test', array('not', 'exists')); // false
What I'm trying to search is a pair, like the combination 'test' and 'value'. I can set up the combo to be searched to array('test','value') or 'test'=>'value' as needed. But how can I do this search if the array to be searched is
array('test'=>'value', 'exists'=>'here');
or
array( array('test','value'), array('exists'=>'here') );
if (
array_key_exists('test', $array) && $array['test'] == 'value' // Has test => value
||
in_array(array('test', 'value'), $array) // Has [test, value]
) {
// Found
}
If you want to see if there is a key "test" with a value of "value" then try this:
<?php
$arr = array('key' => 'value', 'key2' => 'value');
if(array_key_exists('key',$arr) && $arr['key'] == 'value'))
echo "It is there!";
else
echo "It isn't there!";
?>
If I understand you correctly, you're looking for a function called array_search()
It accepts a mixed value, so you can even search for objects - I haven't tried it exactly, but it should work for your use case:
if (array_search(array('test','value'), array(array('test','value'),array('nottest','notvalue'))) !== false) {
// item found...
}
ok..
However I think you'll find this method the most useful:
If you just need to find out if a certain key/value pair is located in an array, the easiest way to do it is like this:
<?php
if (isset($arr['key']) && $arr['key'] == 'value') {
// we have a match...
}
?>
if you need to find something in a more complex pattern, there's no avoid creating a bigger loop.
Separate Keys from Values and use in_array()
$myArray = array('test'=>'value', 'exists'=>'here');
array_keys($myArray)
array_values($myArray)
I want to remove an element from a PHP array (and shrink the array size). Just looking at the PHP docs, it seems this can be done using array_slice() and array_merge()
so I am guessing (off the top of my head) that some combination of array_merge() and array_slice will work. However, array_slice() requires an index (not a key), so I'm not sure how to quickly cobble these functions together for a solution.
Has anyone implemented such a function before?. I'm sure it must be only a few lines long, but I cant somehow get my head around it (its been one of those days) ...
Actually, I just came up with this cheesy hack when writing up this question....
function remove_from_array(array $in, value) {
return array_diff($in, (array)$value);
}
too ugly? or will it work (without any shocking side effects)?
This functionality already exists; take a look at unset.
http://php.net/manual/en/function.unset.php
$a = array('foo' => 'bar', 'bar' => 'gork');
unset($a['bar']);
print_r($a);
output will be:
array(
[foo] => bar
)
There's the array_filter function that uses a callback function to select only wanted values from the array.
you want an unset by value. loop through the array and unset the key by value.
unset($my_array['element']);
Won't work?
This code can be replaced by single array_filter($arr) call
foreach($array as $key => $value) {
if($value == "" || $value == " " || is_null($value)) {
unset($array[$key]);
}
}
/*
and if you want to create a new array with the keys reordered accordingly...
*/
$new_array = array_values($array);