I have the following piece of code and inside the function field_has_input(), I would like to assign the element's key to the errors[]
i.e. errors[]=$key instead of errors[]=$field
The function field_has_input($field) gets called from check_all_fields($_POST)
Hopefully someone can help out.
function field_has_input($field)
{
global $errors;
if(!isset($field) || empty($field))
{
$errors[]=$field;
}
}
function check_all_fields($_POST)
{
global $errors;
foreach($_POST as $key => $value)
{
echo $_POST[$key] . "<br />";
field_has_input($_POST[$key]);
}
//exit;
var_dump($errors);
return $errors;
}
I would suggest you dispense with the field_has_input() function entirely, and just do the work inside the other loop. Otherwise, you would need to be passing the $key into the inner function. In its current simplicity it is totally unnecessary and adds complexity.
function check_all_fields($_POST)
{
global $errors;
foreach($_POST as $key => $value)
{
// empty() calls isset() implicitly...
if (empty($value)) {
$errors[] = $key;
}
}
//exit;
var_dump($errors);
return $errors;
}
Further, I would recommend not using the global errors, but instead passing it to the function. Because $_POST is a superglobal, it is unnecessary to pass it as a parameter to your function. Pass only $errors instead.
function check_all_fields($errors) {
// $_POST is already available here...
foreach($_POST as $key => $value)
{
if (empty($value)) {
$errors[] = $key;
}
}
return $errors;
}
If you must use an inner function, such as if the actual work to be done in field_has_input() is more complex than just checking empty(), pass the $key and check $_POST[$key] inside the function
function field_has_input($key, $errors) {
if (empty($_POST[$key])) {
$errors[] = $key;
}
}
If you want to get an array of values consisting of the $_POST keys that are empty, you can do that with just one line:
$errors = array_keys( array_diff_key( $_POST, array_filter($_POST) ) );
array_filter will remove false, null or empty string values
array_diff_key will compare the original full post array to the filtered version and return only the keys that have been filtered.
array_keys will create an array of values using the array keys of the given array
Example, if:
$arr = array (
'name' => 'Bob'
,'company' => ''
,'state' => 'CA'
,'phone' => ''
);
$errors = array_keys( array_diff_key( $arr, array_filter($arr) ) );
var_dump($errors);
// output:
array(2) {
[0]=>
string(7) "company"
[1]=>
string(5) "phone"
}
Related
I've created an array that contains a form data (the form and php scripts are in a single php file).
I need to create a function to specify which one of the array elements are empty.
This is my code:
if(isset($_POST['submit'])){
$data=array("username"=>$_POST['username'],
"email"=>$_POST['email'],
"password1"=>$_POST['password1'],
"password2"=>$_POST['password2'],
"gender"=>$_POST['gender']);
check($data);
}
function check(){
if(isset($_POST['username']) && isset ($_POST['email']) && isset ($_POST['password1'])){
echo 'ok';
}
else{
echo 'missing';
}
}
Hi #Sina you didn't pass the param $data in the function definition.
<?php
if (isset($_POST['submit'])) { //only if form is submitted
$data = array(
'username' => $_POST['username'],
'email' => $_POST['email'],
'password1' => $_POST['password1'],
'password2' => $_POST['password2'],
'gender' => $_POST['gender']
);
check($data);
}
/**
* #description: validates the form data
* #return none
* #params array($data)
*/
function check($data) {
foreach ($data as $key => $value) {
if (empty($value)) {
echo ucwords($key)." is empty.<br/>";
}
}
}
?>
Thanks & Regards,
Vivek
Just use foreach :
function check($data)
{
foreach($data as $key => $value)
{
echo $key . isset($data[$key]) ? ' Ok' : ' Missing';
}
}
Edit : Fixed function with parameter
There are different ways of solving this, you can use foreach with empty() and a second array to contain the empty elements list.
Follow these steps:
Use foreach to get the values
Read index value and check if (empty($_POST[$key]))
If it's empty, either echo it or save it in a second array to use it later.
The following implementation is one suggestion but have a read at this good article on security and validations.
$_POST exists?
define a list of keys ( to iterate )
do validations in loop ie.isset(),is_null(),empty(),striptags/slash, sanitize etc.
Example:
if(empty($_POST)) {
// handle error ie. redirect
}
// define required keys or as constants using define();
$post_keys = array(
'username',
'email"'
'password1',
'password2',
'gender'
);
foreach($post_keys as $k => $v) {
// _isValid() is optional
// ie. or revalidate email format, empty string, blah etc.
// if(!isset($_POST[$k]) || !_isValid($k, $v)) { .. }
if(!isset($_POST[$k]) {
// handle error
}
}
// everything ok, do stuffs ie.$_POST['username'];
Hope this helps.
I am using the following code to validate integer input fields in my form:
if (isset($_POST['MaxiVegXP']) && ctype_digit($_POST['MaxiVegXP']))
{
$MaxiVegXP = $_POST['MaxiVegXP'];
} else {
$MaxiVegXP = FALSE;
}
I have another 20 or so similar form input fields. Is there a quicker way of doing this with a PHP loop? I'd rather not do the above for another 20 input fields :-)
I would do something like #Simply Dread, but with a slight improvement, so I could explicitly indicate which fields needed to be fixed:
$validFields = array('field1' => true, 'field2' => true, 'field3' => true, ..., 'fieldN' => true);
foreach ($validFields as $field => $valid) {
if (!isset($_POST[$field]) && !ctype_digit($_POST[$field])) {
$validFields[$field] = false;
}
}
With this information, I can now show errors on the appropriate fields instead of only saying that there is a problem.
You could iterate over all fields for example:
foreach ($_POST as $key=>$value){
if (isset($_POST[$key]) && ctype_digit($_POST[$key])) {
$$key = $value;
} else {
$$key = FALSE;
}
}
But I would instead put the code in a function and call the fuction excplicitly for every post variable:
function isDigit($value) {
if (isset($value) && ctype_digit($value)) {
return true;
}
return false;
}
$MaxiVegXP = isDigit($_POST["MaxiVegXP"]) ? $_POST["MaxiVegXP"] : false;
An option would be to create an array of the field names and loop over it. Doing it this way will ensure all fields have to be set and are digits. Check the validate variable afterwards and you'll know if it was successful. :-)
$fieldArray = array('fieldOne', 'fieldTwo', 'fieldThree');
$validate = true;
foreach ($fieldArray as $field) {
if (!isset($_POST[$field]) && !ctype_digit($_POST[$field])) {
$validate = false;
}
}
Is there a quicker way of doing this with a PHP loop?
there's a quicker to do this without a PHP loop:
I would use filter_input_array. This code will assign null to the value if it does not pass the filter. It's quite practical, you just have to add the name of the variable and it's desired filter in the array.
$vars = filter_input_array(INPUT_POST,array (
'MaxiVegXP'=>FILTER_VALIDATE_INT,
'myVar'=>FILTER_DEFAULT,
// or FILTER_VALIDATE_INT. you can also define validator callbacks if need be
));
here you define the keys you wish to get from the input ($_POST in this example, but you can use INPUT_GET to get variables from the $_GET superglobal). You can also define more advanced options in the array to define a min or max range for your inputs, for instance
$vars = filter_input_array(INPUT_POST,array (
'MaxiVegXP'=>array(
'filter'=>FILTER_VALIDATE_INT,
'options'=>array('min_range'=>1, 'max_range'=>10),
),
));
the usefulness is that you don't have to verify manually for each key if they exist and what type they're of, filter_input_array takes care of that once you've defined your array of accepted value
I'm trying to run a foreach loop to check if one of the required fields in a form is empty, and output the missing fields through an error array. Each of the variables is assigned to a $_POST variable.
However, once I call the function:
fields_empty($requiredFields, $fieldErrors);
It only runs once, and not looping through the error. Here's the full source code:
$requiredFields = array(
"First Name"=>$fname,
"Last Name"=>$lname,
"Email"=>$email,
"Password"=>$pass1,
"Confirm Password"=>$pass2,
"Country"=>$country,
"Address 1"=>$addr1,
"City"=>$city,
"State"=>$state,
"Postal Code"=>$pcode,
"Phone Number"=>$phone
);
$fieldErrors = array();
function fields_empty($requiredFields, $fieldErrors) {
global $fieldErrors;
foreach($requiredFields as $name => $field) {
if (empty($field)) {
array_push($fieldErrors, "$name is required.<br>");
return true;
}
}
}
fields_empty($requiredFields, $fieldErrors);
print_r($fieldErrors);
Output in browser:
Array (
[0] => First Name is required.
)
Also, this only happens when it's in a function. If I execute it without a function, it shows all the missing fields.
Remove return from your function. What return does is terminate the function and return whatever is passed with the return, here its set to true. Removing return will keep the loop running.
function fields_empty($requiredFields, $fieldErrors) {
global $fieldErrors;
foreach($requiredFields as $name => $field) {
if (empty($field)) {
array_push($fieldErrors, "$name is required.<br>");
}
}
}
I have a method to check whether a key is in a nested associative array:
private function checkKeyIsInArray($dataItemName, $array) {
foreach ($array as $key=>$value) {
if ($key == $dataItemName) return true;
if (is_array($value)) {
checkKeyIsInArray($dataItemName, $value);
}
}
return false;
}
It always returns true, regardless of the keys I include or do not include. Here is my test array:
Array
(
[0] => Array ( [reset_time] => 2013-12-11 22:24:25 )
[1] => Array ( [email] => someone#example.com )
)
Please, what am I doing wrong? If I search for "reset_time" the method returns true (as I expect); when I search for "reset_expired" the method also returns true (which is incorrect).
Your method is almost works. But there is few issues.
Comparsion numeric values and strings. In first round method has 0 as key and 'email' as value. 0 == 'email' always returns true.
You should use $this when calling object member function.
You should return value of recursive function.
Your rewrited method.
class check
{
private function checkKeyIsInArray($dataItemName, $array)
{
foreach ($array as $key => $value)
{
// convert $key to string to prevent key type convertion
if ((string) $key == $dataItemName)
return true;
if (is_array($value))
// $this added
// return added
return $this->checkKeyIsInArray($dataItemName, $value);
}
return false;
}
public function myCheck($dataItemName, $array)
{
return $this->checkKeyIsInArray($dataItemName, $array);
}
}
$check = new check();
$array = array(array('reset_time' => 123, 'email' => 123));
var_dump($check->myCheck('reset_time', $array)); // true
var_dump($check->myCheck('reset_expired', $array)); // false
var_dump($check->myCheck('0', $array)); // true
I have updated your own code, there was some minor issue.please check.
function checkKeyIsInArray($dataItemName, $array) {
foreach ($array as $key=>$value) {
## here $key is int and $dataItemName is string so its alway comes true in ur case
if ("$key" == $dataItemName) {
return true;
}
else if (is_array($value)) {
$returnvalue=checkKeyIsInArray($dataItemName, $value);
## once a matching key found stop further recursive call
if($returnvalue==true){
return true;
}
}
}
return false;
}
Given a multi-dimensional array that you don't necessarily know the structure of; how would one search for a key by name and change or add to it's contents? The value of the key could be either a string or an array and the effects should be applied either way--I had looked at array_walk_recursive, but it ignores anything that contains another array...
Does this work?
function arrayWalkFullRecursive(&$array, $callback, $userdata = NULL) {
call_user_func($callback, $value, $key, $userdata);
if(!is_array($array)) {
return false;
}
foreach($array as $key => &$value) {
arrayWalkFullRecursive($value);
}
return true;
}
arrayWalkFullRecursive($array,
create_function( // wtb PHP 5.3
'&$value, $key, $data',
'if($key == $data['key']) {
$value = $data['value'];
}'
),
array('key' => 'foo', 'value' => 'bar')
);
Array keys in PHP are ints and strings. You can't have an array array key. So yeah, array_walk_recursive() is what you want.