PHP Conditional > how to know what didn't match? - php

if i have statement:
$a = 1;
$b = 2;
$c = 3;
if($a == 1 && $b == 2 && $c == 3)
{
echo 'correct';
}
else
{
echo 'what variable's weren't matched';
}
Is there any way of knowing what didn't watch instead of writing everything separately?
Cheers!

No. Your expression was turned into a boolean, so apart from checking the equality(s) again you cannot find out which triggered the "false".

You need to test each individually, but you could do something like this:
$a = 1;
$b = 2;
$c = 3;
$a_matched = $a == 1;
$b_matched = $b == 1;
$c_matched = $c == 1;
if($a_matched && $b_matched && $c_matched)
{
echo 'correct';
}
else
{
if (!$a_matched) echo 'a did not match!';
if (!$b_matched) echo 'b did not match!';
if (!$c_matched) echo 'c did not match!';
}
but that's less clear than just:
$a = 1;
$b = 2;
$c = 3;
if($a == 1 && $b == 2 && $c == 3)
{
echo 'correct';
}
else
{
if (!$a == 1) echo 'a did not match!';
if (!$b == 2) echo 'c did not match!';
if (!$c == 3) echo 'b did not match!';
}

Actually, heh, I take back my comment. You can rely on the boolean short-circuiting to set a variable indicating the last part of the conditional which was true:
if (($x = 'a') && $a == 1 && ($x = 'b') && $b == 2 && ($x = 'c') && $c == 3) {
echo "correct\n";
} else {
echo "$x is wrong\n";
}
Note, I would never write this in production code because it's goofy and very hard to understand what's supposed to be going on. But fun to fiddle with, at least.

Nope! That's not possible. You can make life a lot simpler by using arrays, though:
$results = array(1, 2, 4);
$expected = array(1, 2, 3);
$count = count($results);
$wrong = array();
for($i = 0; $i < $count; $i++) {
if($results[$i] !== $expected[$i]) {
$wrong[] = $i;
}
}
if(count($wrong) > 0) {
echo "There were wrong ones. They were at positions: " . implode(', ', $wrong);
} else {
echo "All good!";
}
For example.

Related

Need better simpler solution for conditional link

I have three condition/variable combination e.g. below called amounts:
$a = 15000; $b = 10000; $c = 5000;
or
$a = 10000; $b = 15000; $c = 0;
or
$a = 12000; $b = 0; $c = 15000;
etc.
At least each $a or $b or $c above is not 0 (zero).
If the amount of each not 0 (zero) it have its own associated array e.g. if $b == 0 then $b_array will not set/created, assume all is not 0(zero) then below arrays are created:
$a_array = array('id'=>1);
$b_array = array('id'=>2);
$c_array = array('id'=>3);
If $a / $b / $c is not 0 (zero) then if $b or $c not zero it needs to be linked to $a or $b (if not zero) as below:
if($a != 0 && $b != 0 && $c != 0){
$b_array['id_link'] = $a_array['id'];
$c_array['id_link'] = $a_array['id'];
} elseif ($a != 0 && $b != 0 && $c == 0){
$b_array['id_link'] = $a_array['id'];
} elseif ($a != 0 && $b == 0 && $c != 0){
$c_array['id_link'] = $a_array['id'];
} elseif ($a == 0 && $b != 0 && $c != 0){
$c_array['id_link'] = $b_array['id'];
}
The result for conditional statement above seems correct as you can check at the php sandbox
Is there any better idea for the conditional code and is there a missing condition (error handling). Any idea or solutions is greatly appreciated. Thanks!!
If I understand your question correctly, instead of checking for every combination possible, just get the first non zero number and assign it's id as id_link to all of them like below:
<?php
$id_link = -1;
if($a !== 0){
$id_link = $a_array['id'];
}else if($b !== 0){
$id_link = $b_array['id'];
}else if($c !== 0){
$id_link = $c_array['id'];
}
$a_array['id_link'] = ($b_array['id_link'] = ($c_array['id_link'] = $id_link));
Online Demo
(The brackets in the expression are added just for readability since they are redundant in case of PHP)
Update:
If you wish to leave the array with it's corresponding variable without the id_link key, then you can just use another 3 if conditions to take care of it.
<?php
$id_link = -1;
if($a !== 0){
$id_link = $a_array['id'];
}else if($b !== 0){
$id_link = $b_array['id'];
}else if($c !== 0){
$id_link = $c_array['id'];
}
if($a !== 0){
$a_array['id_link'] = $id_link;
}
if($b !== 0){
$b_array['id_link'] = $id_link;
}
if($c !== 0){
$c_array['id_link'] = $id_link;
}
Online Demo

checking data format with a function instead of multiple preg_matches

I'm trying to check the data format of multiple variables, 21 to be precise, with a function instead of using a preg_match for every single variable as they are supposed to be dates, numeric, alphabetic, alphanumeric and not empty and I'm using the following function for multiple data check in a single row, the function seems to return false, is there anything wrong with them?Thanks for any help in advance, here's the code.
<?php
function alphabetic_check(){
$numargs = func_num_args();
$arg_list = func_get_args();
for($n = 0; $n < $numargs; $n++){
$x = preg_match("^[a-zA-Z\s]*$/", $arg_list[$n]);
if($x == false){
return false;
} else if($n == $numargs - 1 && $x == true){
return true;
}
}
}
function numeric_check(){
$numargs = func_num_args();
$arg_list = func_get_args();
for($n = 0; $n < $numargs; $n++){
$x = preg_match("^[0-9]*$/", $arg_list[$n]);
if($x == false){
return false;
} else if($n == $numargs - 1 && $x == true){
return true;
}
}
}
function alphanumeric_check(){
$numargs = func_num_args();
$arg_list = func_get_args();
for($n = 0; $n < $numargs; $n++){
$x = preg_match("^[a-zA-Z0-9\s]*$/", $arg_list[$n]);
if($x == false){
return false;
} else if($n == $numargs - 1 && $x == true){
return true;
}
}
}
function not_empty(){
$n = func_num_args();
$args = func_get_args();
for($i = 0; $i < $n; $i++){
$x = !empty($args[$i]);
if($x == false){
return false;
} else if($i == $n - 1 && $x == true){
return true;
}
}
}
?>
and here's the code for kinda a reservation system I'm developing returning a promt saying that the data format is incorrect even if it is supposed to excecute the code inside the if block...
if(numeric_check($id, $cellphone, $people, $single, $double, $twin, $superior, $suite, $triple, $quadruple, $disabled, $ccn, $ccm, $ccy, $cccvc) && alphabetic_check($fistname, $lastname, $type) && not_empty($id, $user, $firstname, $lastname, $cellphone, $arrival, $departure, $people, $ccn, $ccm, $ccy, $cccvc, $type)){
echo "ok";
} else {
mysqli_close($connection);
echo "
<script type=\"text/javascript\">
window.alert('Data format wrong, retry.');
window.location.replace('control_panel.php');
</script>
";
}
This is the handwritten code that actually works but I was wondering how to squeeze this stuff as above:
if(preg_match("/^[0-9]*$/", $id) && preg_match("/^[a-zA-Z0-9\-\_]*$/", $user) && preg_match("/^[a-zA-Z\s]*$/", $firstname) && preg_match("/^[a-zA-Z\s]*$/", $lastname) && preg_match("/^[\+0-9]{10,}$/", $cellphone) && preg_match("/^[0-9\-]*$/", $arrival) && preg_match("/^[0-9\-]*$/", $departure) && preg_match("/^[0-9]*$/", $people) && $people > 0 && preg_match("/^[0-9]{16}$/", $ccn) && preg_match("/^[0-9]{1,2}$/", $ccm) && preg_match("/^[0-9]{4}$/", $ccy) && preg_match("/^[0-9]{3}$/", $cccvc) && preg_match("/^[a-z]*$/", $type) && !empty($id) && !empty($user) && !empty($firstname) && !empty($lastname) && !empty($cellphone) && !empty($arrival) && !empty($departure) && !empty($people) && !empty($ccn) && !empty($ccm) && !empty($ccy) && !empty($cccvc) && !empty($type)){
echo "ok";
} else {
mysqli_close($connection);
echo "
<script type=\"text/javascript\">
window.alert('Formato dati errato, riprova.');
window.location.replace('pannello.php');
</script>
";
}
Question solved by Mark, here below the working code with some tests:
<?php
function alphabetic_check(){
$numargs = func_num_args();
$arg_list = func_get_args();
for($n = 0; $n < $numargs; $n++){
$x = preg_match("/^[a-zA-Z\s]*$/", $arg_list[$n]);
if($x == false){
return false;
} else if($n == $numargs - 1){
return true;
}
}
}
function numeric_check(){
$numargs = func_num_args();
$arg_list = func_get_args();
for($n = 0; $n < $numargs; $n++){
$x = preg_match("/^[0-9]*$/", $arg_list[$n]);
if($x == false){
return false;
} else if($n == $numargs - 1){
return true;
}
}
}
function alphanumeric_check(){
$numargs = func_num_args();
$arg_list = func_get_args();
for($n = 0; $n < $numargs; $n++){
$x = preg_match("/^[a-zA-Z0-9\s]*$/", $arg_list[$n]);
if($x == false){
return false;
} else if($n == $numargs - 1){
return true;
}
}
}
function not_empty(){
$n = func_num_args();
$args = func_get_args();
for($i = 0; $i < $n; $i++){
$x = !empty($args[$i]);
if($x == false){
return false;
} else if($i == $n - 1){
return true;
}
}
}
$a = "voda";
$b = 17;
$c = "coding101";
$d = NULL;
echo "Alphabetic check: " . (alphabetic_check($a, $b, $c) ? "true" : "false") . "<br /><br />";
echo "Alphanumeric check: " . (alphanumeric_check($a, $b, $c) ? "true" : "false") . "<br /><br />";
echo "Numeric check: " . (numeric_check($a, $b, $c) ? "true" : "false") . "<br /><br />";
echo "Not empty: " . (not_empty($a, $b, $c) ? "true" : "false") . "<br /><br />";
echo "Not empty 2: " . (not_empty($a, $b, $c, $d) ? "true" : "false") . "<br /><br />";
?>
I can see a couple of problems:
None of your preg_matches have an opening delimeter, e.g. you have: preg_match("^[a-zA-Z\s]*$/", this is missing a forward slash at the start, should be: preg_match("/^[a-zA-Z\s]*$/". This applies to all preg_matches so a error is thrown.
You have an incorrectly named variable, you have alphabetic_check($fistname, , should be $firstname as used elsewhere
Fixing those 2 and plugging in some valid data and your functions work fine.
May I suggest a slight change to the functions though that may make them easier toread, for example:
function alphabetic_check(){
$arg_list = func_get_args();
$valid = true;
foreach($arg_list as $arg){
if(!preg_match("/^[a-zA-Z\s]*$/", $arg))
{
$valid = false;
break;
}
}
return $valid;
}
With my version we set a variable, $valid, to be true. If any of the preg_matches fail then we set valid to false and break out the loop. This way there is no need to check if you are on the last arg in the list. As a result you can also change to a foreach loop and no need to count the number of arguments passed in.

Running same code in different conditions in PHP

I am trying to reduce/simplify the following code as it looks to have repeated elements:
<?php
if ($condition == true) {
if ($a > $b*0.5) {
echo "successful";
}
else {
echo "missed";
}
}
else {
if ($a > $b) {
echo "successful";
}
else {
echo "missed";
}
}
I don't want to use functions because if I did, I would have to define all the database things again.
<?php
if ( (condition1 && ($a > $b*0.5)) || (!condition1 && ($a > $b)) ) {
echo "successful";
else {
echo "missed";
}
?>
Your Code is missed Two (Semicoloumns)}.
Try By this
<?php
$a == 2;
$b == 4;
if ($a == 2 && $a > $b*0.5) {
echo "Suuccess";
}elseif($a != 2 && $a > $b){
echo "Suuccess";
}else{
echo "Fails";
}
In order to simplify your conditions, if the output is boolean (so only two outcomes possible) you could go with either one as default and only change it to the other depending on your decisions.
<?php
$outcome = false;
if($condition1 && ($a > ($b * 0.5))) {
$outcome = true;
}
else if($a > $b) {
$outcome = true;
}
if($outcome) {
echo "succesful";
}
else {
echo "missed";
}
This also combines the technique proposed by Sofyan Thayf to use boolean operators to merge conditions.
Another approach is to put the condition into a function and return early if succesful and have a missed fallthrough like
<?php
function decide($a, $b, $condition1) {
if($condition1 && ($a > ($b * 0.5)))
return true;
if($a > $b)
return true;
return false;
}
if(decide($a, $b, $condition1)) {
echo "succesful";
}
else {
echo "missed";
}
Both approaches enable you to extract the "same code" (being the echo) and IMHO add to readability and extensibility.
<?php
$factor = $condition ? 0.5 : 1;
if ($a > $b * $factor) {
echo "Hit";
}
else {
echo "Miss";
}
Could be further reduced using two ternary operators:
echo $a > $b * ($condition ? 0.5 : 1)
? 'Hit'
: 'Miss';
Ternary operators are useful shorthand for if/else conditionals.

Logical operators equation in php

i have a problem with my function which should combine logical operators according to data in array:
$arr = array(
0 => array(false, "or"),
1 => array(false, "or"),
2 => array(true)
);
the equation should be:
false or false or true
($arr[0][0] $arr[0][1] $arr[1][0] $arr[1][1] $arr[2][0])
And the result: true
But something wrong happens in function and it returns false.
What am i missing?
var_dump( arrayBoolValidation($arr) );
function arrayBoolValidation (array $arr) {
$num = count($arr);
$status = $arr[0][0];
for($i = 1; $i < $num; ++$i) {
if ($arr[$i-1][1] == "and") {
$status = filter_var($status, FILTER_VALIDATE_BOOLEAN) and filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN);
} else if ($arr[$i-1][1] == "or") {
$status = filter_var($status, FILTER_VALIDATE_BOOLEAN) or filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN);
}
}
return $status;
}
It's an operator precedence issue. and is not the same as &&. Look at http://php.net/manual/en/language.operators.precedence.php
= has higher priority than and, so $a = $b and $c; equals to $a = $b;.
You must use extra brackets ($a = ($b and $c);) or better use &&. Same thing about or (use ||).
Assuming that all conditions have to be evaluated:
Note: I have added the case when no operator is defined.
[...]
if (!isset($arr[$i-1][1])) {
$status = $status || $arr[$i][0]; // default: OR, && else
} else if ($arr[$i-1][1] == "and") {
$status = $status && $arr[$i][0];
} else if ($arr[$i-1][1] == "or") {
$status = $status || $arr[$i][0];
}
[...]
Change the following inside your loop:
if ($arr[$i-1][1] == "and") {
$status = (filter_var($status, FILTER_VALIDATE_BOOLEAN) and filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN));
} else if ($arr[$i-1][1] == "or") {
$status = (filter_var($status, FILTER_VALIDATE_BOOLEAN) or filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN));
}
You'll see the extra brackets.
If you don't put them, you set $status to filter_var($status, FILTER_VALIDATE_BOOLEAN), which will always be the same as the first entry (false in this case).
I think there is something wrong in loop
try,
for($i = 1; $i <=$num; ++$i) {

Elegant way to shorten if statement

Any ideas how to shorten if statment in an elegant way.
My if statement:
if(getfoo1() == getfoo2() && getfoo2() == 1)
{
}
EDIT:
I'm looking for something like:
if(getfoo1() == getfoo2() ==1)
{
}
But I suppose we can't do this.
$a = getfoo1();
$b = getfoo2(); // less operations, while it not produces duplicate calls
if($a == $b && $b == 1){
// do something
}
$variable = ((getfoo1() == getfoo2() && getfoo2() == 1) ? $value1 : $value2);
More elegant, combined:
$a = getfoo1();
$b = getfoo2();
$variable = (($a == $b && $b == 1) ? $value1 : $value2);
Since we don't know the possible return values from the functions, if you assume they are integers then you can say:
$a = getfoo1();
$b = getfoo2();
if (($a * $b) === 1) { // strict equality for the win
echo 'hi';
}
The result would only be true iff both $a AND $b are 1.
Another way:
$both = array(getfoo1(), getfoo2());
// use array_diff_assoc so it checks multiple occurrences of the same value
$diffCount = count(array_diff_assoc($both, array(1, 1)));
if ($diffCount === 0) {
echo 'hi';
}
Since anyway getfoo2() == 1 must be true, a better approach is to first check whether getfoo2() is equal to 1. If it false no matter about 2nd condition. But If you first check getfoo1() == getfoo2() and and then check getfoo2() == 1 you have to check 2 conditions all the times.
Therefore go for
$a = getfoo1();
$b = getfoo2();
if($b == 1 && $a == $b)
{
// logiv
}
else
{
}
Try this.
$a = getfoo1();
$b = getfoo2();
if( intval($a && $b) === 1) {
echo 'hi';
}

Categories