I have been trying to make a custom validation class, but it is bothering me that it only is test thing last element it sees. I need it to test everything I put into it.
<?php
class Valid {
function validate(array $args){
$errors = NULL;
//********************************
//Find each key validation.
//********************************
foreach ($args as $key => $value){
//*********************************
//Check for letters only, a-z, A-Z.
//*********************************
if ($key == 'letters'){
$letters = preg_match('/^\pL+$/u', $value) ? TRUE : FALSE;
$letters_value = $value;
$letters_array[] = $letters;
}
//*********************************
//Check for numbers only, 0-9.
//*********************************
if ($key == 'numbers'){
$numbers = preg_match('/^[0-9]+$/', $value) ? TRUE : FALSE;
$numbers_value = $value;
$numbers_array[] = $numbers;
}
//*********************************
//Check for vaild email address.
//*********************************
if ($key == 'email'){
$email = filter_var($value, FILTER_VALIDATE_EMAIL) ? TRUE : FALSE;
$email_value = $value;
$email_array[] = $email;
}
//*********************************
//Check for empty string.
//*********************************
if ($key == 'empty'){
$empty_it = (trim($value) == FALSE) ? TRUE : FALSE;
$empty_array[] = $empty_it;
}
}
//********************************
//Check if you failed letters only.
//********************************
if ( count($letters_array) != count(array_filter($letters_array)) ) $errors .= 'You can only enter letters a-z or A-Z.<br />';
//********************************
//Check if you failed numbers only.
//********************************
if ( count($numbers_array) != count(array_filter($numbers_array)) ) $errors .= 'You can only enter numbers 0-9.<br />';
//*************************************
//Check if you failed email validation.
//*************************************
if ( count($email_array) != count(array_filter($email_array)) ) $errors .= 'You must enter a vaild e-mail address.<br />';
//*************************************
//Check if you empty string.
//*************************************
if ( count($empty_array) != count(array_filter($empty_array)) ) $errors .= 'You must enter a value for each required field.<br />';
//********************
//Display the errors.
//********************
if ($errors) echo '<h3>Oops..</h3>'. $errors; var_dump($args); die;
}
}
And then I call it like this:
$Validate->validate( array('empty' => $display_name, 'empty' => $password, 'empty' => $password_again,
'empty' => $gender, 'empty' => $month, 'empty' => $day, 'empty' => $year, 'email' => $email, 'letters' => $gender,
'numbers' => $month, 'numbers' => $day, 'numbers' => $year) );
But my result is this:
array(4) { ["empty"]=> string(4) "2013" ["email"]=> string(0) "" ["letters"]=> string(0) "" ["numbers"]=> string(4) "2013" }
Any help?
You cannot reuse keys in arrays. The last key - value pair will overwrite all the previous.
Write an array like:
$Validate->validate(array(
'empty' => array($display_name, $password, $password_again, $gender, $month, $day, $year, $email),
'letters' => array($gender, $month),
'numbers' => array($day, $year).
));
and parse it appropriately:
if (isset($args["key"])) {
foreach ($args["key"] as $value) {
// ...
}
}
// and this for every method to check
array('empty' => $display_name, 'empty' => $password, 'empty' => $password_again,
'empty' => $gender, 'empty' => $month, 'empty' => $day, 'empty' => $year, 'email' => $email, 'letters' => $gender,
'numbers' => $month, 'numbers' => $day, 'numbers' => $year)
This is not a valid hash. Keys must be unique.
You could, however, pass something like this:
array(
array('empty' => $display_name),
array('empty' => $password),
array('empty' => $password_again),
array('empty' => $gender), ...
)
and modify your loop appropriately.
Documentation: http://php.net/manual/en/language.types.array.php
If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten.
Related
I am trying to figue out how to check for empty values of an array with certain exceptions. Here is the array:
[name_first] => Name
[name_last] =>
[email] => blah#blah.com
[address] =>
[country] => USA
There are two empty values - name_last & address. Here is the code:
if (in_array(null, $data)) {
echo 'empty values';
}else{
echo 'ok';
}
It will return false as [address] and [name_last] values are empty. How can I ignore a particular key (let's say - [address])? Basically it is supposed to LOOK like this:
if (in_array(null, $data) **&& key_is_not('address', 'hatever')**) {
echo 'empty values';
}else{
echo 'ok';
}
try this :
$data = array('name_first' => "Name",
'name_last' => "",
'email' => "blah#blah.com",
'address' => "",
'country' => "USA");
foreach ($data as $key => $value) {
if($value=="")
echo "$key is Empty\n";
}
Update
To exclude particular keys from the check, you can do this way :
$data = array('name_first' => "",
'name_last' => "",
'email' => "blah#blah.com",
'address' => "",
'country' => "");
$array = array("name_first","country");
foreach ($data as $key => $value) {
if($value=="" and (!in_array($key, $array)))
echo "$key is Empty\n";
}
$input_array = [
'name_first' => 'Name',
'name_last' => '',
'email' => 'blah#blah.com',
'address' => '',
'country' => 'USA',
];
Filter array ignoring the specific keys, here address and name_last
$ignore_search = in_array('', array_filter($input_array, function($k){
return !in_array($k, ['address', 'name_last']);
}, ARRAY_FILTER_USE_KEY));
Here array_filter will unset the keys specified inside.
Will return boolean depending on match found or not, if you want keys, just change in_array with array_search.
This will check to see if the value is set and the length is greater than 0, not an empty string.
foreach($elements as $key => $data)
{
if(!in_array($key, ['address', 'something']))
{
if(count($data) > 0)
{
//stuff
}
}
}
You can also ignore the key by writing a custom function that will handle the keys exception, this way you are more in control if in any case you want to tweak later:
if (in_array_except(null, $data, array("address"))) {
echo 'empty values';
}else{
echo 'ok';
}
The function will be:
function in_array_except($needle, $haystack, $exception = array(), $strict = false) {
if ($strict) {
foreach($haystack as $needle_field => $item) {
if (!in_array($needle_field, $exception) && $item === $needle)
return true;
}
} else {
foreach($haystack as $needle_field => $item) {
if (!in_array($needle_field, $exception) && $item == $needle)
return true;
}
}
return false;
}
With your current data set:
[name_first] => Name
[name_last] =>
[email] => blah#blah.com
[address] =>
[country] => USA
The output with the sample snippet is:
empty values
Try with array_search() like below::
if (array_search("", $arr)) {
echo 'empty values';
} else {
echo 'ok';
}
** Update **
$array_var = array("11" => 111, "22" => 222, "33" => 333, "44" => 444, "55" => "", "66" => 666);
$new_array_var = array();
foreach ($array_var as $key => $value) {
// echo $key . "==>" . $value . "<br/>";
if (isset($value) && $value != "") {
$new_array_var[$key] = $value;
}
}
echo "<pre>";
echo "OLD : <br/>";
print_r($array_var);
echo "<br/><br/>";
echo "NEW : <br/>";
print_r($new_array_var);
echo "</pre>";
$ignore_array = array("address");
$blank_value_keys = array_keys($data,"");
if(sizeof($blank_value_keys)>0 && sizeof(array_diff($ignore_array,$blank_value_keys)>0){
echo "Empty";
}else{
echo "NOT Empty";
}
Add all the keys to be ignored in ignore array list.
array_keys will return all the keys which have blank values.
Next we are checking if size of array returned by array_keys is greater than 0 and there are more keys in $blank_value_keys than $ignore_array than if loop executes.
Note: array_diff will return all the values available in second array but not in first
The following code cycles through an array of requirements for user submitted data (in this case from a registration form) and outputs repetitive error messages. How to stop the repetitive messages?
if(!empty($_POST)){
$validate = array(
'username' => array(
'required' => true,
'min' => 3,
'max' => 20,
'unique' => 'users'
),
'password' => array(
'required' => true,
'min' => 6
),
'password_confirm' => array(
'required' => true,
'matches' => 'password'
)
);
foreach($validate as $item => $rules)
{
foreach($rules as $rule => $rule_value)
{
$value = $_POST[$item];
$item = htmlentities($item, ENT_QUOTES, 'UTF-8', false);
if($rule === 'required' && empty($value))
{
$errors[] = "{$item} is required <br>";
}
}
if(!empty($errors))
{
foreach($errors as $error)
{
echo $error;
}
}
else
{
echo 'Registration Successful <br>';
}
}}
Output:
username is required
username is required
password is required
username is required
password is required
password_confirm is required
Your loops have gotten a bit mixed up.
foreach($validate as $item => $rules)
{
foreach($rules as $rule => $rule_value)
{
$value = $_POST[$item];
$item = htmlentities($item, ENT_QUOTES, 'UTF-8', false);
if($rule === 'required' && empty($value))
{
$errors[] = "{$item} is required <br>";
}
}
}
// This piece that prints out the errors (if they are present) needs
// to be moved outside the loop that creates the error array.
if(!empty($errors))
{
foreach($errors as $error)
{
echo $error;
}
}
else
{
echo 'Registration Successful <br>';
}
Also, maybe you simplified this code for the purpose of asking the question, but if this is all there is to it, why not just print the error at the time you find it instead of appending it to an array of errors? That way you only have to loop once. You can just use a boolean to see if there were errors.
$has_errors = false;
foreach($validate as $item => $rules)
{
foreach($rules as $rule => $rule_value)
{
$value = $_POST[$item];
$item = htmlentities($item, ENT_QUOTES, 'UTF-8', false);
if($rule === 'required' && empty($value))
{
$has_errors = true;
echo "{$item} is required <br>";
}
}
}
if (!$has_errors) echo 'Registration Successful <br>';
What's the best way to compare both two arrays to each other in a foreach loop ?
I have two arrays, which one holds a boolean values and other one represents the real values.
First one of the arrays is some sort of configuration file where I tell what field is a required one TRUE or an optional FALSE:
$rules = array(
'fieldname1' => TRUE,
'fieldname2' => FALSE,
'fieldname3' => TRUE,
'fieldname4' => TRUE,
'fieldname5' => FALSE,
'fieldname6' => FALSE,
'fieldname7' => TRUE,
'fieldname8' => TRUE
);
And the other array which holds incoming data to be worked out:
$fields = array(
'fieldname1' => 'some value',
'fieldname3' => 'some value',
'fieldname4' => 'some value',
'fieldname7' => 'some value',
'fieldname8' => 'some value'
);
How do I make a check in foreach() loop, so the $fields array is going to compare each of its fieldnameX or (keys/indexes) with the other array named $rules ?
For example: $rules['fieldname1'] is required as it have a bool TRUE. So in foreach($fields as $field), the $field named fieldname1 should not be empty, null or false, if so, show an error.
This is a function I did so far which is not doing exactly what I want:
private function check_field_required_exist( $fields )
{
// Read rules from config to work with them accordingly
$rules = config_item('flow.format')[$fields['format']];
// Run throught the rules
foreach( array_keys($rules) as $field )
{
// Check wheter key existance is failed
if( !array_key_exists($field, $fields) )
{
// Checking failed, terminate the process
die('Required field: "'. $field .'" for requested format: "'.$fields['format'].'" does not exists.');
}
}
// Everything is alright
return TRUE;
}
// Goes through all the rules
foreach($rules as $key => $value)
{
// access all fields that are marked as required i.e key set as TRUE
if ($value)
{
//for those whose value is TRUE, check whether the corresponding field is set or
// whether it is empty (NULL,false)
if(!isset($fields[$key]) || empty($fields[$key]))
{
die('Required field does not exist');
}
}
}
foreach ($fields as $field => $value)
{
if (array_key_exists($field, $rules) && $rules[$field] === true)
{
if (!$value || $value == "" || $value === null)
{
die(); // return false;
}
}
}
return true;
I think that you can play around with the array functions in PHP. First thing I would do is to apply array_filter on your rules array. That way, you will only keep the TRUE values (and their indexes, since array_filter keep the index/value association).
Then I would use array_intersect_key to keep only the fields of interest in your fields var. And again array_filter with a custom callback to perform the verification you want to do.
$requiredField = array();
foreach($rules as $key=>$value) {
if($value == true && (!isset($fields[$key]) || $fields[$key] == "" )) {
$requiredField[] = $key;
}
}
if(count($requiredField) > 0) {
echo implode(',',$requiredField)." Are Required";
die;
}
USING PHP Array Functions:
$rules = array('name' => TRUE, 'phoneNumber' => TRUE, 'age' => FALSE);
$submittedFields = array( 'name' => 'aspirinemaga', 'age' => 38, 'phoneNumber' => '');
$requiredFields = array_keys(array_filter($rules));
$validFields = array_keys(array_filter($submittedFields));
$missingFields = array_diff($requiredFields, $validFields);
Given
$rules = array('name' => TRUE, 'phoneNumber' => TRUE, 'age' => FALSE);
$submittedFields = array( 'name' => 'aspirinemaga', 'age' => 38, 'phoneNumber' => '');
PhoneNumber is wrong here.
$requiredFields = array_keys(array_filter($rules));
This gives you the keys of all rule elements that are TRUE.
$validFields = array_keys(array_filter($submittedFields));
Same here, your definition of what's ok is the same as php truth table for boolean conversion. If you have a more advanced check, you could pass a function name into array_filter (see below).
$missingFields = array_diff($requiredFields, $validFields);
This will get you all the fieldNames that exist in $requiredFields but are not in $validFields.
More advanced validation
$rules = array('name' => 'MORE_THAN_3', 'phoneNumber' => TRUE, 'age' => 'POSITIVE');
$submittedFields = array( 'name' => 'aspirinemaga', 'age' => 38, 'phoneNumber' => '');
$requiredFields = array_keys(array_filter($rules));
function validateField($key, $value){
// get the rule (assuming no submittedFields that have no rule)
$rule = $rules[$key];
switch($rule){
case 'MORE_THAN_3': return strlen($value) > 3; break;
case 'POSITIVE': return $value > 0; break;
}
// in case of TRUE/FALSE
return TRUE;
}
$validFields = array_keys(array_filter("validateField", $submittedFields, ARRAY_FILTER_USE_BOTH));
$missingFields = array_diff($requiredFields, $validFields);
If you wanted to do a more advanced validation, you can integrate that nicely into above solution.
Say you wanted name to be more than 3 characters and age to be positive. Write it into your rules:
$rules = array('name' => 'MORE_THAN_3', 'phoneNumber' => TRUE, 'age' => 'POSITIVE');
$submittedFields = array( 'name' => 'aspirinemaga', 'age' => 38, 'phoneNumber' => '');
Required Fields are still the same (to check if one is missing).
$requiredFields = array_keys(array_filter($rules));
Now your validate function would be something like:
function validateField($key, $value){
// get the rule (assuming no submittedFields that have no rule)
$rule = $rules[$key];
switch($rule){
case 'MORE_THAN_3': return strlen($value) > 3; break;
case 'POSITIVE': return $value > 0; break;
}
// in case of TRUE/FALSE
return TRUE;
}
Pass that into array_filter and add to ARRAY_FILTER_USE_BOTH Flag:
$validFields = array_keys(array_filter("validateField", $submittedFields, ARRAY_FILTER_USE_BOTH));
And your missing Fields stays the same.
$missingFields = array_diff($requiredFields, $validFields);
This will only work in PHP 5.6+ (because ARRAY_FILTER_USE_BOTH). Not tested, should work.
Let's say I wanted to check to see if a variable is empty and then do something... I can do this:
if ( empty($phone) ) { $phone = 'Not Provided'; }
But I want to do that for a bunch of items. So I'm thinking an array and a loop, so something like this:
$optionalFieldsArray = array($phone, $address, $city, $state, $zip);
foreach ($optionalFieldsArray as $value) {
//what goes here????
}
Is this foreach a resonable way to do it, where I could check if $phone, $address, $city, etc. are empty and assign the "Not Provided" string to it when it is?
If so, can someone help me with the syntax that goes inside that loop?
you can do like this:
<?php
$required_vars = array( 'phone', 'address', 'city', 'state', 'zip' );
foreach( $required_vars as $required_var ) {
if( empty( $$required_var ) )
$$required_var = 'Not Provided'; // $$var -> variable with name = value of $var
}
?>
check the above code yourself. then only you can understand how it works. because it is confusing concept.
$optionalFieldsArray = array('phone'=>$phone, 'address'=>$address, 'city'=>$city, 'state'=>$state, 'zip'=>$zip);
foreach ($optionalFieldsArray as $key => $value) {
if ( empty($value) ) { $optionalFieldsArray[$key] = 'Not Provided'; }
}
echo "<pre>";
print_r($optionalFieldsArray);
echo "</pre>";
I'd say something like -
$optionalFieldsArray = array($phone, $address, $city, $state, $zip);
foreach ($optionalFieldsArray as $key => $value) {
if ( empty($optionalFieldsArray[$key]) ) {
$optionalFieldsArray[$key] = 'Not Provided';
}
}
Combine the two code examples you provided, and use strings as keys in the optional array:
$optional = array(
'phone' => $phone,
'address' => $address,
'city' => $city,
'state' => $state,
'zip' => $zip,
);
foreach ($optional as $type => $value) {
if ($value == null) {
echo "The {$type} field is empty!<br>";
}
}
$optionalFieldsArray = array($phone, $address, $city, $state, $zip);
foreach($optionalFieldsArray as $k => $v) {
// you could check for !empty here if you wanted too
$optionalFieldsArray[$k] = empty($v) ? 'Not Provided' : $v;
}
print_r($optionalFieldsArray);
Input Vars:
$phone = "1234567899";
$address = "";
$city = "";
$state = "";
$zip = "";
Output:
Array ( [0] => 1234567899 [1] => Not Provided [2] => Not Provided [3] => Not Provided [4] => Not Provided )
I'm using a wordpress plugin for advanced form design/logic/processing, and one of it's (biggest) downsides is the awkward way it provides form data. Data is given in an array with two or three items for each field.
if it's a hidden field:
$$$n => id - where n is the field's order in the form, and NAME is the name/id.
id => value - where id is the name/id and value is the value.
If it's a visible field:
$$$n => LABEL - where n is the field's order in the form, and LABEL is the human-readable label.
$$$id => LABEL - where id is the name/id of the field
LABEL => value - where value is what I actually want.
I'm trying to write a function that will consume this horrid array and return a simpler one with a single id => value pair for each field.
For example, it will take this (order of fields can't be guaranteed):
array(
'$$$1' => 'command',
'command' => 'signup',
'$$$2' => 'First Name',
'$$$firstname' => 'First Name',
'First Name' => 'John',
'$$$3' => 'Email Address',
'$$$email' => 'Email Address',
'Email Address' => 'john#example.com'
);
And return:
array(
'command' => 'signup',
'email' => 'john#example.com',
'firstname' => 'John'
);
This code works, but feels very awkward. Can you help refine it? Thanks! (My strategy is to ignore everything but the $$$n fields since they're identical for all forms and there's no simple way to tell if a given field is hidden or not.)
function get_cforms_data($cformsdata) {
$data = array();
foreach ($cformsdata as $key => $value) {
if (strpos($key, '$$$') === 0) {
$newkey = substr($key, 3);
if (is_numeric($newkey)) {
$keys = array_keys($cformsdata, $value);
if (count($keys) == 1) {
// must be a hidden field - NAME only appears once
$data[$value] = $cformsdata[$value];
} else {
// non-hidden field. Isolate id.
foreach($keys as $k) {
if ($k == $key) {
// $$$n - ignore it
continue;
} else {
// $$$id
$k = substr($k, 3);
$data[$k] = $cformsdata[$value];
}
}
}
}
}
}
return $data;
}
Here's a working version:
$i=0;
$result = array();
while (array_key_exists('$$$' . ++$i, $arr)) {
$key = $arr['$$$' . $i];
$result[$key] = $arr[$key];
}
It will print:
Array
(
[command] => signup
[First Name] => John
[Email Address] => john#example.com
)
Here's another version. It is much uglier but does exactly what you want (as I interpreted it)
function get_cforms_data($cformsdata) {
$i=0;
$result = array();
$flipped = array_flip($arr);
while (array_key_exists('$$$' . ++$i, $arr)) {
$key = $arr['$$$' . $i];
$realKey = (!preg_match('~^\${3}\d+$~', $flipped[$key])) ?
substr($flipped[$key], 3) : $key;
$result[$realKey] = $arr[$key];
}
return $result;
}
Returns:
Array
(
[command] => signup
[firstname] => John
[email] => john#example.com
)
See it working: http://ideone.com/5mkbx
Here's what I'd probably do, though I don't think it's that much cleaner than yours or NullUserException's:
function get_cforms_data($cforms_data) {
$ret = array();
$label_to_id = array();
$label_or_id_to_value = array();
foreach ($cforms_data as $key => $value) {
if (substr($key, 0, 3) === "$$$") {
if (!is_numeric($id = substr($key, 3))) {
$label_to_id[$value] = $id;
}
} else {
$label_or_id_to_value[$key] = $value;
}
}
foreach ($label_or_id_to_value as $key => $value) {
$ret[isset($label_to_id[$key]) ? $label_to_id[$key] : $key] = $value;
}
return $ret;
}