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>';
Related
i have written this code to receive data from the Android device. it was inserted just one customer data I need to receive multiple customer details if app goes offline. but it was inserting one data into DB in offline mode also.how can i change this for multiple customer data insertions.
function index_post($customerID = false) {
if ($customerID) {
//update the record
$updateData = array();
$allowedparams = array('streetid' => 'streetid', 'name' => 'name', 'mobile' => 'mobile', 'adhaar' => 'adhaar', 'profession' => 'profession', 'address' => 'address', 'pincode' => 'pincode', 'nearby' => 'nearby', 'paddress' => 'paddress', 'isOwned' => 'isOwned');
foreach ($allowedparams as $k => $v) {
if (!$this->IsNullOrEmptyString($this->post($k, true))) {
$updateData[$v] = $this->post($k, true);
}
}
if ($this->model_customer->update($customerID, $updateData)) {
$data = array('status' => true, 'messsage' => 'cusotmer updated succesfully');
$http_code = REST_Controller::HTTP_OK;
} else {
$data = array('status' => false, 'messsage' => 'cusotmer failed to update.');
$http_code = REST_Controller::HTTP_INTERNAL_SERVER_ERROR;
}
} else {
//insert the record
$allowedparams = array('streetid' => 'streetid', 'name' => 'name', 'mobile' => 'mobile', 'adhaar' => 'adhaar', 'profession' => 'profession', 'address' => 'address', 'pincode' => 'pincode', 'cycle' => 'cycle', 'nearby' => 'nearby', 'paddress' => 'paddress', 'isOwned' => 'isOwned');
$requiredParam = array('streetid', 'name', 'mobile', 'cycle');
$insertdata = array();
foreach ($allowedparams as $k => $v) {
if (in_array($k, $requiredParam)) {
//check if its not null
if ($this->post($k) == null || trim($this->post($k)) == '') {
$data = array('status' => false, 'message' => $k . ' parameter missing or empty');
$http_code = REST_Controller::HTTP_BAD_REQUEST;
break;
}
}
$insertData[$v] = $this->post($k, true);
}
if ($customerID = $this->model_customer->create($insertData)) {
$data['customerID'] = $this->_frameCustomer2($this->model_customer->get($customerID)); //you need to put
$http_code = REST_Controller::HTTP_OK;
} else {
$data = array('status' => false, 'message' => 'unable to create customer');
$http_code = REST_Controller::HTTP_INTERNAL_SERVER_ERROR;
}
}
$this->response($data, $http_code);
}
private function _frameCustomer2($c) { //get value from index_get
$data = array();
$data['id'] = $c->id;
$data['name'] = $c->name;
$data['street'] = array('id' => $c->streetid);
$data['creationDate'] = $c->creationdate;
$data['mobile'] = $c->mobile;
$data['adhaar'] = $c->adhaar;
$data['profession'] = $c->profession;
$data['isOwned'] = ($c->isOwned == 1) ? true : false;
$data['address'] = $c->address;
$data['pincode'] = $c->pincode;
$data['status'] = $c->status;
$data['cycle'] = $c->cycle;
$data['balance'] = $c->balance;
$data['creditAvailable'] = $c->creditbalance;
$data['nearby'] = $c->nearby;
$data['accountNumber'] = $c->accountnumber;
$data['permanentAddress'] = $c->paddress;
$data['lastVisit'] = $this->model_customer->lastVisit($c->id);
return $data;
}
and my part of model function is
function create($insertdata = array()) { //new customer insert
if ($this->db->insert('customer', $insertdata)) {
return $this->db->insert_id();
} else {
return false;
}
}
function update($customerID = 0, $updateData = array()) {
$this->db->where('id', $customerID);
if ($this->db->update('customer', $updateData) && $this->db->affected_rows() == 1) {
return true;
} else {
return false;
}
Instead of customer Id, you can ask the mobile developers to send data in the form of array. In both online and offline. In case of online there will be just one element in the request array.
function index_post() {
$request_data = $this->request->body;
foreach($request_data as $key => $value)
{
//Check if customer id is present
if(Customer present)
{
Update the record
} else {
Insert the record
}
}
}
How do I search for 2 values in the same record using in_array()?
For example I want to search for 'AuthorNiceName' value and 'AuthorType' value.
The below code does not work how I would like. It should return "EU TEST" but it returns "CP TEST".
Thanks in advance.
$authors = array(
array(
'AuthorName' => 'John Smith',
'AuthorNiceName' => 'john-smith',
'AuthorType' => 'CP'
),
array(
'AuthorName' => 'Joe Bloggs',
'AuthorNiceName' => 'joe-bloggs',
'AuthorType' => 'EU'
),
);
if (in_array('joe-bloggs', array_column($authors, 'AuthorNiceName')) && in_array('EU', array_column($authors, 'AuthorType'))) {
$authorType = 'CP TEST';
}
else {
$authorType = 'EU TEST';
}
echo $authorType;
UPDATE: My latest code using #Philipp's suggestion which I adjusted slightly. However it doesn't work, if there are other users with the same 'AuthorType' it returns "no match"?
$authors = array( //TODO
array(
'AuthorName' => 'John Smith',
'AuthorNiceName' => 'john-smith',
'AuthorType' => 'CP'
),
array(
'AuthorName' => 'Joe Bloggs',
'AuthorNiceName' => 'joe-bloggs',
'AuthorType' => 'EU'
),
array(
'AuthorName' => 'Matt Bat',
'AuthorNiceName' => 'matt-bat',
'AuthorType' => 'EU'
),
);
$name = 'joe-bloggs';
$type = 'EU';
foreach ($authors as $author) {
if ($author['AuthorNiceName'] == $name && $author['AuthorType'] == 'EU') {
$authorType = 'EU Test';
}
elseif ($author['AuthorNiceName'] == $name && $author['AuthorType'] == 'CP') {
$authorType = 'CP Test';
}
else {
$authorType = 'no match';
}
}
echo $authorType; //returns "not match". it should return "EU Test".
It seems, you should use a loop for what you want
$name = 'joe-bloggs';
$type = 'EU';
foreach ($authors as $author) {
if ($author['AuthorNiceName'] == $name && $author['AuthorType'] == $type) {
// do something
}
}
using in_array with array_column looses the information if the result is from the same column. Using array_search, you could also compare the index of the columns, but this seems like a bad solution...
Update
The problem with your update is, you overwrite the $authorType var, after you set the correct value. You should check, if an value is already set and only then set a new value.
$name = 'joe-bloggs';
$authorType = false;
foreach ($authors as $author) {
if ($author['AuthorNiceName'] == $name && $author['AuthorType'] == 'EU') {
$authorType = 'EU Test';
} elseif ($author['AuthorNiceName'] == $name && $author['AuthorType'] == 'CP') {
$authorType = 'CP Test';
}
}
if ($authorType === false) {
echo 'no match';
} else {
echo $authorType;
}
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
I have an error and that is happening because I'm changing the $item name cause I want it to be uppercase. I've already done it for most of my code but for some reason I'm having some trouble doing so in here.
Here is the code:
public function check($source, $items = array()) {
foreach($items as $item => $rules) {
foreach($rules as $rule => $rule_value) {
$value = $source[$item];
$item = escape($item);
if ($rule === 'required' && empty($value)) {
$error = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($error) . " is required");
} else if(!empty($value)){
switch($rule) {
case 'min':
if(strlen($value) < $rule_value) {
$this->addError(ucfirst($item) . " must be a minimum of {$rule_value} characters.");
}
break;
case 'max':
if(strlen($value) > $rule_value) {
$this->addError(ucfirst($item) . " must be a maximum of {$rule_value} characters.");
}
break;
case 'matches':
if($value != $source[$rule_value]) {
$item = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($item) . ' does not match ' . $rule_value);
}
break;
case 'unique':
$check = $this->_db->get('*', $rule_value, array($item, '=', $value));
if ($check->count()){
$this->addError(ucfirst($item) . ' is already in use!');
}
break;
}
}
}
}
if(empty($this->_errors)) {
$this->_passed = true;
}
return $this;
}
Problematic code is:
if ($rule === 'required' && empty($value)) {
$item = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($item) . " is required");
}
I'm trying to make it so it outputs Password again is required instead of password_again is required. Everything in the switch($rule) statement is working properly but like I said I don't know why it doesn't work at that specific line. Anyone got an idea?
Exact Error: Notice: Undefined index: password confirm in C:\xampp\htdocs\classes\Validate.php on line 13.
What I thought of:
Suppression of the notice. This is good but I would really love it if this can be fixed.
Code Request [Source & Item]:
$validation = $validate->check($_POST, array(
'email' => array(
'required' => true,
'min' => 7,
'max' => 64,
'unique' => 'users'
),
'password' => array(
'required' => true,
'min' => 7,
'max' => 32
),
'password_confirm' => array(
'required' => true,
'matches' => 'password'
)
));
Var Dump Result:
string(5) "email"
Notice: Undefined property: Validate::$addError in C:\xampp\htdocs\classes\Validate.php on line 18
NULL string(8) "password"
Notice: Undefined property: Validate::$addError in C:\xampp\htdocs\classes\Validate.php on line 18
NULL string(16) "password confirm"
Notice: Undefined property: Validate::$addError in C:\xampp\htdocs\classes\Validate.php on line 18
NULL
Notice: Undefined index: password confirm in C:\xampp\htdocs\classes\Validate.php on line 13
New Working Code:
if ($rule === 'required' && empty($value)) {
$error = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($error) . " is required");
}
You're missing an empty check which is why the notice gets displayed when email, password or password_confirm is missing:
if( !empty( $source[$item] ) )
{
$value = $source[$item];
$item = escape($item);
if ($rule === 'required' && empty($value)) {
$item = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($item) . " is required");
} else if(!empty($value)){
switch($rule) {
case 'min':
if(strlen($value) < $rule_value) {
$this->addError(ucfirst($item) . " must be a minimum of {$rule_value} characters.");
}
break;
case 'max':
if(strlen($value) > $rule_value) {
$this->addError(ucfirst($item) . " must be a maximum of {$rule_value} characters.");
}
break;
case 'matches':
if($value != $source[$rule_value]) {
$item = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($item) . ' does not match ' . $rule_value);
}
break;
case 'unique':
// $check = $this->_db->get('*', $rule_value, array($item, '=', $value));
if ( 1 == 1 ){
$this->addError(ucfirst($item) . ' is already in use!');
}
break;
}
}
}
else
{
$this->addError( $item . ' cannot be empty!' );
break;
}
I would recommend a simpler solution.
Full replication as requested:
function escape( $sValue )
{
return trim( $sValue );
}
class test
{
public $aErrors = array();
public function addError( $sError )
{
$this->aErrors[] = $sError;
}
public function check($source, $items = array()) {
foreach($items as $item => $rules) {
foreach($rules as $rule => $rule_value) {
if( !empty( $source[$item] ) )
{
$value = $source[$item];
$item = escape($item);
if ($rule === 'required' && empty($value)) {
$item = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($item) . " is required");
} else if(!empty($value)){
switch($rule) {
case 'min':
if(strlen($value) < $rule_value) {
$this->addError(ucfirst($item) . " must be a minimum of {$rule_value} characters.");
}
break;
case 'max':
if(strlen($value) > $rule_value) {
$this->addError(ucfirst($item) . " must be a maximum of {$rule_value} characters.");
}
break;
case 'matches':
if($value != $source[$rule_value]) {
$item = str_replace(array('_'), ' ', $item);
$this->addError(ucfirst($item) . ' does not match ' . $rule_value);
}
break;
case 'unique':
// $check = $this->_db->get('*', $rule_value, array($item, '=', $value));
if ( 1 == 1 ){
$this->addError(ucfirst($item) . ' is already in use!');
}
break;
}
}
}
else
{
$this->addError( $item . ' cannot be empty!' );
break;
}
}
}
}
}
$_POST[ 'email' ] = '';
$_POST[ 'password' ] = '';
$_POST[ 'password_confirm' ] = '';
$aValidation = $cTest->check( $_POST,
array( 'email' => array( 'required' => true, 'min' => 7, 'max' => 64, 'unique' => 'users' ),
'password' => array( 'required' => true, 'min' => 7, 'max' => 32 ),
'password_confirm' => array( 'required' => true, 'matches' => 'password' ) ));
var_dump( $cTest->aErrors );
var_dump( $aValidation );
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.