I have to evaluate a very long condition in PHP, so, to avoid errors and trying to write more readable code, I did the following:
//this returns 1 when true, and nothing when false, although expected TRUE or FALSE
$isNameValid=strlen($dataDecoded['nombre'])>=3;
$isDescriptionValid=(strlen($dataDecoded['descripcion'])>=10) && strlen($dataDecoded['descripcion'])<=300;
$isPriceValid=$dataDecoded['precio'] >0;
$isImageValid=(($dataDecoded['imagen'] != "") && ($dataDecoded['imagen'] != NULL) );
And now, I can make the following:
if($isNameValid==1 && $isDescriptionValid==1 && $isPriceValid==1 && $isImageValid==1)
{
echo "ok";
}
else{
echo "no";
}
It seems to work fine, but maybe is a weird way of doing things. I wanted to avoid the following, which I find more confusing and easy to make a mistake
if(strlen($dataDecoded['nombre'])>=3 && ... && ...)
Is there a better way to do that? Is wrong what I did? Thanks
I don't care for creating extra variables here; this makes code difficult to maintain and unreusable. I'd recommend breaking your validation logic into easy-to-read, maintainable, reusable functions:
function valid($data) {
return validName($data['nombre']) &&
validDescription($data['descripcion']) &&
validPrice($data['precio']) &&
validImage($data['imagen']);
}
function validName($name) {
return strlen($name) >= 3;
}
function validDescription($desc) {
return strlen($desc) >= 10 && strlen($desc) <= 300;
}
function validPrice($price) {
return $price > 0;
}
function validImage($image) {
return $image !== "" && $image != NULL;
}
$dataDecoded = [
"nombre" => "foo",
"descripcion" => "foo bar foo bar",
"precio" => 15,
"imagen" => "foo.png"
];
// now your main code is beautiful:
echo (valid($dataDecoded) ? "ok" : "no") . "\n";
Yes, that is acceptable. However, your variables there are all boolean, so you don't even need the ==1.
if($isNameValid && $isDescriptionValid && $isPriceValid && $isImageValid)
It really depends on how you want to handle it.
Is switch an option or a viable one?
Is ternary if prettier or handy?
From what I see, I'm guessing you have a validation purpose and a operating incoming depending on the validation. Why not create a function or a class that handles your input and validates? And in there, you can have all the dirty code you'd want. On your logical code, you'd just have to do (e.g of a class)
$someClass = new SomeClass();
$someClass->validate($fields);
if ($someClass->isValidated()) ...
This way, you'd actually follow some standards whereas the purpose of it would be to work as a validator for (all of? depends on your needs) your data
E.g of ternary ifs
$isNameValid = count($dataDecoded['nombre'])>=3 ? true : false;
$isDescriptionValid = count($dataDecoded['descripcion']) >= 10 && count($dataDecoded['descripcion']) <= 300 ? true : false;
$isPriceValid = count($dataDecoded['precio']) > 0 ? true : false;
$isImageValid = empty($dataDecoded['imagen']) === false ? true : false;
if ($isNameValid && $isDescriptionValid && $isPriceValid && $isImageValid) ...
Related
I have two (and sometimes) three variables which determine if I should run a specific code. The problem is that any of them can be true or false and sometimes this leads to messy codes.
For three variables, there are 8 possible scenarios that I have to check. Like this:
if($var_a && $var_b && $var_c) {
// Do this (A)
} else if(!$var_a && $var_b && $var_c) {
// Do this (B)
} else if($var_a && !$var_b && $var_c) {
// Do this (C)
} else if(!$var_a && !$var_b && $var_C) {
// Do this (D)
}
... and so on.
Is there any way to use nesting and make this code less messy? It gets confusing at times to keep track of so many possibilities.
It might be easier to understand what I am saying with an example of two variables.
if($var_a && $var_b) {
// Do this (A)
} else if($var_a && !$var_b) {
// Do this (B)
} else if(!$var_a && $var_b) {
// Do this (C)
}
Is there any way to combine these conditions together so that I don't have to use so many && and if else conditions? This will make things less confusing for me when I have to deal with three (may be more) variables.
I guess you should try something like lookup map with bitwise map, in your case, it can be something like this:
$bitOne = $var_a ? 1 : 0;
$bitTwo = $var_b ? 2 : 0;
$bitThree = $var_c ? 4 : 0;
$resultKey = $bitOne | $bitTwo | $bitThree;
$map = [
7 => function() { return 'All are true'; },
3 => function() { return 'var_a and var_b are true'; },
6 => function() { return 'var_b and var_c are true'; },
// and so on
];
$result = $map[$resultKey];
If you extract the common variable (or an arbitrary choice in this case), you can produce a more layered approach, although the combinations will still mount up and it looks more code, it should be clearer...
if($var_a) {
if(!$var_b) {
// $var_a && !$var_b
}
else {
// $var_a && $var_b
}
}
else {
if($var_b) {
// !$var_a && $var_b
}
}
I'm using this in my code but I think it can be improved and can be done a simpler way?
if($phaseOne == true && $phaseTwo == true && $phaseThree == true) {
}
You can do it like this:
if($phaseOne && $phaseTwo && $phaseThree) { ... }
Or use ternary operator, if you're trying to define a variable on the basis of these conditions like this:
$var = ($phaseOne && $phaseTwo && $phaseThree) ? true : false;
Hope this helps!
Assuming you have an array with an arbitrary number of logical variables:
$logical = array($phraseOne,$phraseTwo,....);
$allTrue = array_reduce($logical, function ($x,$y) {return $x && $y;},true);
if($allTrue) {
}
Do just:
if($phaseOne && $phaseTwo && $phaseThree)
You don't need to compare it against true.
if ($phaseOne && $phaseTwo && $phaseThree) {
}
This occurs because the result of any comparison is a boolean:
var_dump(1 == 1); // bool(true)
var_dump(1 == 2); // bool(false)
Also if you variable contains a number, it can be used directly:
if (1) {
// This will be executed
}
if (0) {
// This will not be executed
}
Zero will be always be treated as false, any other number (positive or negative) will be true.
Unless you need to check each variable as explicitly identical to a boolean or variable, (see this stack overflow thread)
I'd do it this way
if ($phaseOne && $phaseTwo && $phaseThree) {}
Otherwise, I'd do it this way
if ($phaseOne === true && $phaseTwo === true && $phaseThree === true) {}
Try with this:
($phaseOne && $phaseTwo && $phaseThree) ? {//do something} : '';
Although I think it is arbitrary, controlversial, trivial, and won't preach the use of this, just for fun and learning - here's some typical php variable type juggling that will work also and takes up the least space... efficient in terms of source code length.
if($phaseOne*$phaseTwo*$phaseThree) { ... }
I want to check the GET variables are not empty, I tried ways but they didn't work.
So I had the code like this:
$u = isset($_GET["u"]);
$p = isset($_GET["p"]);
if ($u !== "" && $p !== "") {
//something
} else {
//do something
}
The I checked the code by sending create.php?u=&p=, but the code didn't work. It kept running the //do something part. The I tried:
echo $u;
echo $p;
It returned 1 and 1. Then I changed it to:
if ($u !== 1 && $p !== 1 && $u !== "" && $p !== "") {
//something
} else {
//do something
}
But it continued to run //do something.
Please help.
You can just use empty which is a PHP function. It will automatically check if it exists and whether there is any data in it:
if(empty($var))
{
// This variable is either not set or has nothing in it.
}
In your case, as you want to check AGAINST it being empty you can use:
if (!empty($u) && !empty($p))
{
// You can continue...
}
Edit: Additionally the comparison !== will check for not equal to AND of the same type. While in this case GET/POST data are strings, so the use is correct (comparing to an empty string), be careful when using this. The normal PHP comparison for not equal to is !=.
Additional Edit: Actually, (amusingly) it is. Had you used a != to do the comparison, it would have worked. As the == and != operators perform a loose comparison, false == "" returns true - hence your if statement code of ($u != "" && $p != "") would have worked the way you expected.
<?php
$var1=false;
$var2="";
$var3=0;
echo ($var1!=$var2)? "Not Equal" : "Equal";
echo ($var1!==$var2)? "Not Equal" : "Equal";
echo ($var1!=$var3)? "Not Equal" : "Equal";
echo ($var1!==$var3)? "Not Equal" : "Equal";
print_r($var1);
print_r($var2);
?>
// Output: Equal
// Output: Not Equal
// Output: Equal
// Output: Not Equal
Final edit: Change your condition in your if statement to:
if ($u != "" && $p != "")
It will work as you expected, it won't be the best way of doing it (nor the shortest) but it will work the way you intended.
Really the Final Edit:
Consider the following:
$u = isset($_GET["u"]); // Assuming GET is set, $u == TRUE
$p = isset($_GET["p"]); // Assuming GET is not set, $p == FALSE
Strict Comparisons:
if ($u !== "")
// (TRUE !== "" - is not met. Strict Comparison used - As expected)
if ($p !== "")
// (FALSE !== "" - is not met. Strict Comparison used - Not as expected)
While the Loose Comparisons:
if ($u != "")
// (TRUE != "" - is not met. Loose Comparison used - As expected)
if ($p != "")
// (FALSE != "" - is met. Loose Comparison used)
You need !empty()
if (!empty($_GET["p"]) && !empty($_GET["u"])) {
//something
} else {
//do something
}
Helpful Link
if ($u !== 1 && $p !== 1 && $u !== "" && $p !== "")
why are you using "!==" and not "!=".
to always simplify your problem solve the logic on paper once using the runtime $u and $p value.
To check if $_GET value is blank or not you can use 2 methods.
since $_GET is an array you can use if(count($_GET)) if you have only u and p to check or check all incoming $_GET parameters.
empty function #Fluffeh referred to.
if($_GET['u']!=""&&$_GET['p']!="")
Hope it helps thx
In you code you should correctly check the variable existence like
if ($u != NULL && $p != NULL && $u != 0 && $p != 0) {
//something
} else {
//do something
}
Wow! I was so dumb... isset returns a boolean. I fixed my problem now. Thank you for answering anyway :)
This fixes:
$u = $_GET["u"];
$p = $_GET["p"];
What I'm doing is, if I haven't got an ID in either $_POST or $_SESSION then redirecting. Preference is given to $_POST. So I have this:
$bool = 0;
if (isset($_POST['id'])) {
$bool = 1;
} elseif (isset($_SESSION['id'])) {
$bool = 1;
}
if (!$bool) {
...//redirect
}
Is there a quicker way to write this, APART from just removing the braces?
if(!( isset($_POST['id']) || isset($_SESSION['id']) ))
redirect();
(not sure if I understand how what's given to $_POST is preference).
You could just do:
$has_id = isset($_POST['id']) || isset($_SESSION['id']);
if (!$has_id) {
// redirect
}
(I'd recommend you to give your variables more descriptive names than just $bool.)
Although if you aren't using the variable for anything else, you could just do:
if (!isset($_POST['id']) && !isset($_SESSION['id'])) {
// redirect
}
if (isset($_POST['id']) || isset($_SESSION['id'])) {
$bool = 1;
}
This will do it, simples
$bool = (isset($_POST['id']) || isset($_SESSION['id'])) ? 1 : 0; // if isset, 1
($bool == 1?header(Location: www.whatever.com):null;
Using Conditional Operator, you can achieve this in one line statement
Example:
c = (a == b) ? d : e;
I'm creating an edit page which should get called this way:
users.php?action=edit&id=5
This is my code for this:
} elseif (isset($_GET['action']) && $_GET['action'] == 'edit' && isset($_GET['id']) && is_numeric($_GET['id']) && $_GET['id'] > 0) {
As you see it's long. First a check with isset is needed. I know you can leave that out, but that way I'll get PHP notices when error reporting is set to 'E_ALL'.
I can create a function to make it shorter but that way I'll need to create too many functions as I have such code on different places in my scripts, each requiring different information.
Is there any way to make this code shorter?
Thanks!
Since action and id both are probably going to be used might as well set them at the top of the script:
$action = !empty($_GET['action'])?$_GET['action']:false;
$id = !empty($_GET['id'])?$_GET['id']:false;
switch ($action) {
case 'edit':
if ($id !== false) {
//processing here
}
break;
default:
echo 'No known action was passed through';
}
The initial variable declaration uses the ternary operator which is a shortened if/else as an fyi.
Extra Information
I prefer this method as appose to insane if/elseif/else statements, given that it is much easier to read and you do not have to think about your logic nearly as much, so it would make it less prone to errors.
You could write a function that takes an array of keys:
function check_get_params($keys) {
foreach ($keys as $key) {
if (! isset($_GET[$key]) ) {
return false;
}
}
return true;
}
Then your line above would be:
} elseif (check_get_params(array('action', 'id')) && $_GET['action'] == 'edit' && is_numeric($_GET['id'])) {
which would be cleaner as:
} elseif (check_get_params(array('action', 'id'))) {
if ($_GET['action'] == 'edit' && is_numeric($_GET['id'])) {
I would check parameters first:
$action = (isset($_GET['action']) && !empty($_GET['action'])) ? $_GET['action'] : false;
$id = (isset($_GET['id']) && !empty($_GET['id'])) ? $_GET['id'] : false;
settype($id, 'int'); // "123" became 123(int)
And then go with:
} elseif ($action && $id && $action == 'edit' && $id > 0) {
// here we are
}