Best way to simplify statement - php

I have the following php code.
Im trying to find out the field name/key that does not exist without using hardcoded static text. Is there a php function that can do this. array_keys_exist is similar to what I want but it only allows for checking of a single key.
ex:
Something like
$keys_to_confirm = ['password','password_old',....];
$user_submitted_input_array = ['password'=>'...', 'somekey'=>'...' ];
bool : all_array_keys_exist($keys_to_confirm,$user_submitted_input_array);
Current code that uses static text to report the missing field/key name
if( isset($input['password']))
{
if( isset($input['password_old'])) )
{
if(isset($input['password_repeat'])) )
{
//good to go!
}
else
{
die('missing form element password_repeat.');
}
}
else
{
die('missing form element password_old.');
}
}
else
{
die('missing form element password.');
}
I had this code but it doesnt say what is missing.
//if the field doesnt exist for some reason lets create a dummy
if( ! isset($input['password'])
OR (!isset($input['password_repeat']))
OR (!isset($input['password_old'])) )
{
die('missing form element.');
}

Try:
foreach( array('password', 'password_repeat', 'password_old') as $key ) {
if( empty($input[ $key ]) ) {
echo 'Missing field: ' . $key;
}
}
You can probably come up with a one liner to do this using array_diff_key, but I think the above is concise enough.

Here's the one liner with array_key_diff. It's not the prettiest but functional.
$keys_to_confirm = array('password' => '','password_old' => '');
$user_submitted_input_array = array('password'=>'...', 'somekey'=>'...');
$validate = array_diff_key($keys_to_confirm, $user_submitted_input_array);
if( empty($validate) ) {
echo 'Passed';
} else {
echo 'Missing field: ' . key($validate);
}

My solution:
if ($field_miss = array_diff_key(array('password', 'password_old', '...'), array_keys($input))) {
echo 'Missing field: ', implode(', ', $field_miss);
}

Related

Multiple IDs in PHP call in WordPress

** I apologize for being unclear - I meant I want "Summit Sponsors" to display once regardless of how many IDs are used. Just for it to be hidden if no IDs are used. Thanks **
I was wondering if anyone knew a clean way to use multiple custom fields in an IF statement.
At the moment I have it spaced out, so each custom field "SponsorHeading#" has it's own if/else statement:
<?php
if(get_post_meta($post_id, 'SponsorHeading1', true)) {
echo '<h2>Summit Sponsors </h2>';
}
else {
echo '';
}
if(get_post_meta($post_id, 'SponsorHeading2', true)) {
echo '<h2>Summit Sponsors </h2>';
}
else {
echo '';
}
?>
and so on for 3 more custom fields. I'd like to have something cleaner like:
<?php
if(get_post_meta($post_id, 'SponsorHeading1', true)) || if(get_post_meta($post_id, 'SponsorHeading2', true)) || if(get_post_meta($post_id, 'SponsorHeading3', true)) {
echo '<h2>Summit Sponsors </h2>';
}
else {
echo '';
}
?>
or something along those lines to clean it up but nothing I've tried has worked.
Any suggestions?
Not 100% sure on if there is a more efficient way to manage this within WordPress’s logic itself, but the simplest solution I can conceive of using the example you give is to put all of the ids into an array & have logic to loop through them like so:
<?php
$fields = array('SponsorHeading1', 'SponsorHeading2', 'SponsorHeading3');
foreach($fields as $field_value) {
if(get_post_meta($post_id, $field_value, true)) {
echo '<h2>Summit Sponsors </h2>';
}
else {
echo '';
}
}
?>
EDIT: Addressing the user edits to the question. So how about this? We loop through the fields, and the value of $has_value changes to TRUE if at least one of the fields is returned by get_post_meta(). And if $has_value is TRUE then act on it:
<?php
$fields = array('SponsorHeading1', 'SponsorHeading2', 'SponsorHeading3');
$has_value = FALSE;
foreach($fields as $field_value) {
if(get_post_meta($post_id, $field_value, true)) {
$has_value = TRUE;
}
}
if ($has_value) {
echo '<h2>Summit Sponsors </h2>';
}
else {
echo '';
}
?>

PHP improve my show message function

I'd like some help please, if its possible.
I have created two functions in order to display some messages when is set a $_GET after a redirect.Here's the code:
function display(){
if(isset($_GET['cnf_upd']) && $_GET['cnf_upd'] == '1'){
$value = "The update was successful!";
$type = "confirm";
construct_the_div($value, $type);
}
if(isset($_GET['err_upd']) && $_GET['err_upd'] == '1'){
$value = "The Update failed.";
$type = "error";
construct_the_div($value, $type);
}
if(isset($_GET['cnf_del']) && $_GET['cnf_del'] == '1'){
$value = "Deleted completely.";
$type = "confirm";
construct_the_div($value, $type);
}
if(isset($_GET['err_del']) && $_GET['err_del'] == '1'){
$value = "Unable to delete.";
$type = "error";
construct_the_div($value, $type);
}
}
function construct_the_div($value, $type){
// creating a div to display the message results
$div = "<div class=\"{$type}Msg\">\n";
$div .= "<p>{$value}</p>\n";
$div .= "</div><!-- end of {$type}Msg -->\n";
echo $div;
}
What I'd like to make is to try to improve the display function, as it gets longer and longer, so that there whould be only one (or two at most) if statement(s) if possible. So the value of the GET will be dynamicly inside the if condition and also if it has the preffix 'cnf_' it wil be a 'confirmMsg' and if it has the preffix 'err_' it wil be a 'errorMsg'.
Is it possible to make something like this???
function display() {
$messages = array(
'cnf_upd' => 'The update was successful!',
'cnf_err' => 'The Update failed.!',
// ...
// add all error and confirm there
// ...
);
foreach($_GET as $key => $value) {
if(strpos($key, 'cnf_')===0) {
$type = 'confirm';
$value = isset($messages[$key])
? $messages[$key]
: $key;
construct_the_div($value, $type);
}
if(strpos($key, 'err_')===0) {
$type = 'error';
$value = isset($messages[$key])
? $messages[$key]
: $key;
construct_the_div($value, $type);
}
}
}
The approach is not correct, it seems that only one message should occur at once (there cannot be "deleted completely" and "unable to delete" at once).
Try construct the parameters this way: ?msg=upd&msgType=cnf
function display(){
if (isset($_GET['msg']) && isset($_GET['msgType']))
{
$messages = array('cnf_upd'=>'The update was successful!',
'err_upd'=>'The update failed!',
'cnf_del'=>'The deletion was successful!',
'cnf_upd'=>'The deletion failed!',
);
if (isset($messages[$_GET['msgType'].'_'.$_GET['msg']))
construct_the_div($messages[$_GET['msgType'].'_'.$_GET['msg']], htmlspecialchars($_GET['msgType']));
}
there is still much to improve, but for start this is cleaner and safer.
I'm going to propose a different solution. Instead of setting different parameters in $_GET based on the message to be sent, set one parameter and parse its value.
// Start by setting integer constants:
define(CNF_UPD, 1);
define(ERR_UPD, 2);
define(CNF_DEL, 3);
define(ERR_DEL, 4);
Then when you set the value un $_GET, use the constant:
// Build the URL with a deletion error...
header("Location: http://example.com/script.php?msg=" . ERR_DEL);
Finally, use a switch to parse them
if (isset($_GET['msg'])) {
switch ($_GET['msg']) {
case CNF_UPD:
// Updated...
break;
case ERR_UPD:
// failed...
break;
// etc...
default:
// invalid code.
}
}
If you use a pattern of confirm/error/confirm/error for your integer constants, you can determine which it is by taking $_GET['msg'] % 2. Odd numbers are confirmations, evens are errors. There are of course many other ways you could lay this out, I just happen to have typed them in the alternating order you used. You could also do positive integers for confirmations and negatives for errors, for example.
$type = $_GET['msg'] % 2 == 1 ? $confirm : $error;
This is easily expanded to use multiple messages as well. Since they are integer values, you can safely construct a comma-separated list and explode() them when received.
$messages = implode(array(ERR_DEL,CNF_UPD));
header("Location: http://example.com/script.php?msg=$messages");
Unless you can somehow generate $value and $type based on the $_GET parameter (which I can't see how you would do), you could do something like:
$messages = array();
$messages[] = array('id' => 'cnf_upd', 'value' => 'The update was successful!', 'type' => 'Confirm');
$messages[] = array('id' => 'err_upd', 'value' => 'The Update failed.', 'type' => 'error');
...
foreach ($messages as $message) {
if(isset($_GET[$message['id']]) && $_GET[$message['id']] == '1'){
construct_the_div($message['value'], $message['type']);
}
}

Check if multiple strings are empty [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
More concise way to check to see if an array contains only numbers (integers)
PHP checking if empty fields
I have form that submits 10 fields, and 7 of them should be filled, here is how i chek it now in PHP:
if (!$name || !$phone || !$email || !$mobile || !$email || !$state || !$street || ! $city) {
echo '<div class="empty_p">You have empty fields!!!</div>';}
else{
//process order or do something
}
My question is: is there more simple way to do this? Because sometimes I have even more strings to check (12-15)
Another possibility:
$elements = array($name, $email, $mobile);
$valid = true;
foreach ($elements as $element) {
if (empty($element)) {
$valid = false;
}
}
if ($valid) {
// complete
} else {
// alert! some element is empty
}
Something like this?
foreach($_POST as $key => $value)
{
if (empty($_POST[$key]))
{
echo '<div class="empty_p">'.$_POST[$key].' is empty.</div>';
}
}
It's good to be specific about where this data should be expected, e.g. $_POST:
if (!isset($_POST['name'], $_POST['phone'], $_POST['email'], $_POST['mobile'], $_POST['state'], $_POST['street'], $_POST['city'])) {
// something is up
}
You can shorten this code a little bit by creating an array with your required field names:
$required_fields = array('name', 'phone', 'email', 'mobile', 'state', 'street', 'city');
The 'check-for-existence' code can then be simplified to:
foreach ($required_fields as $f) {
if (!isset($_POST[$f])) {
// something is up
}
}
The better way ™
However, you should seriously consider combining both existence and validation / sanitization checks. PHP provides a family of filter functions functions that you can use to validate and/or sanitize your input variables. For example, to get equivalent behavior as above:
$required_fields = filter_input_array(INPUT_POST, array(
'name' => FILTER_UNSAFE_RAW,
'email' => FILTER_VALIDATE_EMAIL,
));
if (is_null($required_fields) || in_array(null, $required_fields, true)) {
// some fields are missing
}
Fields that exist but fail validation will be set to false, so this is how you detect such an event:
foreach ($required_fields as $name => $value) {
if (false === $value) {
// field $name failed validation (e.g. bad email format)
} elseif (!strlen(trim($value))) {
// field is empty
}
}
The best way would be to create some sort of form validator. However you can use this function:
<?php
function isAnyEmpty() {
$total = 0;
$args = func_get_args();
foreach($args as $arg)
{
if(empty($arg)) {
return true;
}
}
return false;
}
$var1 = 1;
$var2 = 'test';
$var3 = '';
if(isAnyEmpty($var1, $var2, $var3)) {
echo 'empty fields!';
}
?>
You could try creating a general validation class that could be reused and be more precise.
Some pseudo code:
<?
class validateFields {
$validators = array(
"name" => array(
"empty" => array(
"rule" => "some regex",
"errorMessage" => "name may not be empty"
),
"noNumbers" => array(
"rule" => "some regex",
"errorMessage" => "No numbers are allowed in the name field"
)
),
"otherVariable" => array(
"atLeast50chars" => array(
"rule" => "some regex",
"errorMessage" => "This field must be at least 50 chars"
)
)
);
public function Validate($post){
$errors = array();
foreach($_POST as $key => $value){
if(!array_key_exists($key, $validators)) {
continue;
}
foreach($validators[$key] as $validator) {
if(!preg_match($validator["rule"], $value) {
$errors[$key] = $validator["errorMessage"];
break;
}
}
}
return $errors;
}
}
?>
Then in your code you could do something like:
$errors = Validate($_POST);
foreach($error as $errorMessage) {
echo $errorMessage . "</br>";
}
Of course you could fancy this up, adding divs with classes right below/beside the concerning input field and load the $errorMessage into there.
I'm sure there's loads of examples out there :)
You can write Foreach loop
foreach($_POST as $key => $value)
{
if (!isset($_POST[$key]) || empty($_POST[$key])
{
echo '<div class="something">You have empty fields!!!</div>';
}
}
<input type="text" name="required[first_name]" />
<input type="text" name="required[last_name]" />
...
$required = $_POST['required'];
foreach ($required as $req) {
$req = trim($req);
if (empty($req))
echo 'gotcha!';
}
/* update */
OK! guys, easy...
You can make it more secure, just with type casting as all we programmers do for out coming data, like $id = (int) $_GET['id'], like $username = (string) addslashes($_POST['username']) and so on...;
$required = (array) $_POST['required'];
And then, what ever comes from post fields let them come, this code just seek what it need.
That is it! Uhh...

Validating multiple fields in one 'small' function in PHP

i want to build a validation function(or even class) in php to check for empty fields in a form.
The thing is that i want to check the fields one after another and if there is an empty one to send "The -field_name- is empty."
If none is empty to continue with the rest of the script...
I have already made it using multiple nested if-else statements....but i was wondering if there is a more compact and programmer friendly way.
I've tried using an array which i pass in a foreach statement and then i use a switch loop.
The nested if-else's:
function no_empties($first_name,$last_name,$username,$password,$password2,$user_email,$user_email2)
{
if ( !empty($first_name) )
{ if ( !empty($last_name ) )
{if ( !empty($username ) )
{if ( !empty($password ) )
{if ( !empty($password2) )
{if ( !empty($user_email) )
{if (!empty($user_email2) )
{return TRUE;}
else{ js_msg("Please retype your email!");return FALSE;};
}
else {js_msg("Please enter a -valid- email!"); return FALSE;};
}
else{js_msg("Please retype your password!");return FALSE;};
}
else {js_msg("Please enter a password!" ); return FALSE;};
}
else {js_msg("Pleas enter a username!"); return FALSE;};
}
else { js_msg("Please enter your last name!"); return FALSE;};
}
else { js_msg("Please enter your first name!"); return FALSE;};
}
The second case i described is this:
$fields_array = array("first name"=>$first_name,"last name"=>$last_name,"username"=>$username,"password"=>$password,"retype password"=>$password2,"email"=>$user_email,"retype email"=>$user_email2);
function TEST($fields_array)
{
foreach ($fields_array as $field_name => $input)
{
switch (empty($input)) :
case TRUE: return $output="The -{$field_name}- field is empty "; break;
case FALSE:return $output= "No field is empty!!! Hooray! "; break;
endswitch;
}
}
It is working but i cannot use it like this:
if ( TEST($fields_array)==TRUE ): echo $output; else: echo $output; endif;
Moreover it would be perfect if the code was in a form that was irrelevant of how many fields each form has. Someone would just enter an array like
$fields = array ("first"=>$first,etc....) .
Any thoughts???????
I usually do it this way, find it cleaner and allows you to chain more errors at once than a single one:
$errors = array();
if(!isset($_POST['field1']) || !is_numeric($_POST['field1']) || $_POST['field1'] < 123){ $errors[] = 'Field1 is missing or has an invalid value'; }
if(!isset($_POST['field2']) || !is_string($_POST['field2']) || strlen($_POST['field2']) < 20){ $errors[] = 'Field2 is missing or is not long enough'; }
if(!isset($_POST['field3']) || !in_array($_POST['field3'], array('valid', 'values'))){ $errors[] = 'Field3 is missing or has an invalid value value not in list of (....)'; }
if(!isset($_POST['field4']) || strtotime($_POST['field4']) == false){ $errors[] = 'Field4 is missing or has an invalid date value'; }
if(count($errors) == 0){
//Process
}

PHP - Validation function to return true|false, AND a message if false

I have a validation function which returns either true or false.
However, I want it to provide info as to what the problem is, when there is one.
Let's say the function is like this:
function is_valid($val) {
$result = true;
if( rule_1_not_met ) $result = false;
if( rule_2_not_met ) $result = false;
return $result;
}
Which is used like this
$val = $_GET['some_param'];
if(!is_valid($val)) $out .= 'Not so helpful feedback.';
...
I thought I could change it like this:
function is_valid($val) {
$result = array(true, array());
if( rule_1_not_met ) $result[1][] = 'Reason 1';
if( rule_2_not_met ) $result[1][] = 'Reason 2';
if(count($result[1]) > 0) $result[0] = false;
return $result;
}
And use it like this:
$val = $_GET['some_param'];
$validation_result = is_valid($val);
if(!$validation_result[0]) $out .= implode('<br/>', $validation_result[1]);
...
My question is
Am I in, for unexpected results with this?
Are there better ways to achieve this?
P.S. Would make this community wiki
You are in the right track but I would like to do this in this way
function is_valid($val,&$mes) {
$result = true;
if( rule_1_not_met ) { $mes[]='message one'; $result = false; }
if( rule_2_not_met ) { $mes[]='Message two'; $result = false; }
return $result;
}
$mes=array();
if(isvalid($val,$mes) ===false) $out .= implode('<br/>', $mes);
In my opinion, your proposed solution works fine. The only problem with it is that you have to remember that $validation_result[0] is the status and $validation_result[1] contains the messages. This might be OK with you but it will be hard to maintain if other people use your code. One thing you can do is when you call your function, you can use array destructuring to at least store the results with meaningful variable names. For example:
[$valid, $errors] = is_valid($val);
if(!$valid) $out .= implode('<br/>', $errors);
For the reason mentioned above, I like Brad Thomas's solution of creating a specialized class that contains the messages and status. Since the properties are named, you don't have to guess how to access the validation information. Also, most good IDEs will autocomplete when you try to access their properties.
I also have an alternate solution. Instead of including a boolean true or false. Just return the array of messages. The caller would just have to check if the returned array has a non-zero number of errors. Here is an example:
function get_errors($val) {
$errors = array();
if( rule_1_not_met ) $errors[] = 'Reason 1';
if( rule_2_not_met ) $errors[] = 'Reason 2';
return $errors;
}
Then the caller would use it like this:
$val = $_GET['some_param'];
$validation_result = get_errors($val);
if (count($validation_result) > 0) $out .= implode('<br/>', $validation_result);
You could use a Result object that encapsulates return data, a message and a status.
i.e.
class Result( $bResult, $sMessage, $mData ) {
public function __construct() {
$this->bResult = $bResult;
$this->sMessage = $sMessage;
$this->mData = $mData;
}
}
In Your code:
$result = new Result(true, 'some helpful message here', null);
$reasons = array();
function is_valid($val)
{
global $reasons;
if ( rule_1_not_met ) $reasons[] = 'Reason 1';
if ( rule_2_not_met ) $reasons[] = 'Reason 2';
if ( count($reasons) == 0 )
return TRUE;
else
return FALSE;
}
if (!is_valid($condition))
{
echo 'Was not valid for these reasons<br />';
foreach($reasons as $reason)
echo $reason, '<br>';
}
else
echo 'Is valid!';
This question is old, and makes a showcase of bad and outdated practices. Using global is frowned upon, and using references in this context is just the same.
Only Cave Johnson's answer makes it straight, but still the usage could be confusing. A better solution would be to write a class, but not as silly one as in the Brad Thomas's answer.
class NumberValidator
{
protected $errors;
public function validate($number)
{
if(!is_numeric($number))
{
$this->errors[] = "The value provided is not numeric";
return false;
}
if($number < 10)
{
$this->errors[] = "The number is less than 10";
return false;
}
return true;
}
public function getErrors()
{
return $this->errors;
}
}
and then it can be used like this
$validator = new NumberValidator();
if($validator->validate($number)) {
/*success*/
}
and then $validator->getErrors() can be used elsewhere

Categories