Checking user input - php

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
}

Related

Is this a good way of writing long conditions in PHP?

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) ...

PHP Possible ways to write an if

I'm wondering if there is any way to make this code shorter. I'm using 2 if statements and I'm looking to only use one. The things is $user is the session and if you check if $user->userId exists on the same line, the code will error when no session exists. Caused by requesting the userId from an object that does not exist. That's pretty logical but now is there any solution?
if ($user != null) {
if ($user->userId == 1) {
..
}
}
How about using the && operator:
if ($user && $user->userId == 1) {
//...
}
You can add as many sentences as you want, as long as they are properly built, in this case:
if (($user != null) && ($user->userId == 1)) {
or you could simply:
if ($user && ($user->userId == 1)) {
if ($user) just checks if the variable is set, or if it is not null.
You want to use the && operator. It means and
if ($user && $user->userId == 1) {
// do some things
}
You may also want to look into the || operator, it means or.
The && operator will return true ONLY if the two predicates return true.
The || operator will return true as long as one of the predicates return true.

Shortest way to code this php multiple if condition

I am trying to do a query like:
If $_GET['page'] == 'items' AND $_GET['action'] == 'new' OR 'edit'
Here's what I have:
if (isset($_GET['page']) && $_GET['page'] == 'items') {
if (isset($_GET['action']) && $_GET['action'] == 'new' || isset($_GET['action']) && $_GET['action'] == 'edit') {
// This is what Im looking for
}
}
Is this correct, and is this the easiest way to make this query?
You could have done it like this as well:
if (isset($_GET['page']) && $_GET['page'] == 'items') {
if (isset($_GET['action']) && ($_GET['action'] == 'new' || $_GET['action'] == 'edit')) {
}
}
Your way is perfectly fine, although I would almost be tempted to do it the following way. The only reason I suggest this is that your code requires that both action and page are set. If action is not set then there isn't much point checking if the page is == 'items'.
if(isset($_GET['page']) && isset($_GET['action'])) {
if($_GET['page'] == 'items' && ($_GET['action'] == 'new' || $_GET['action'] == 'edit')) {
//do code here
}
}
You may also try in_array like:
if (isset($_GET['page']) && $_GET['page'] == 'items')
{
if ( !empty( $_GET['action'] ) && in_array( $_GET['action'], array( 'new', 'edit' ) )
{
// This is what Im looking for
}
}
That is one of possible solutions
if ( #$_GET['page'] == 'items' && in_array(#$_GET['action'], array('new','edit')))
Everything is ok, but also you can use function:
function paramIs($param, $values) {
$result = false;
foreach ((array)$values as $value) {
$result = $result || isset($_GET[$param]) && $_GET[$param] == $value;
}
return $result;
}
Usage:
if (paramIs('page', 'items') && paramIs('action', array('new', 'edit')))
{
// your code here
}
It will reduce the number of repetitions in your code and encapsulate logic in one place

What is the most succinct way to test if either of two variables are set?

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;

What would you change in my code for best practices/maintenance?

I've got a small snippet of code below and I was curious what types of things you would change with regards to best practices/code maintainablity and so on.
function _setAccountStatus($Username, $AccountStatus)
{
if ($Username == '' || ($AccountStatus != 'Active' || $AccountStatus != 'Banned' || $AccountStatus != 'Suspended')) {
// TODO: throw error here.
}
$c1 = new Criteria();
$c1->add(UsersPeer::USERNAME,$Username);
$rs = UsersPeer::doSelect($c1);
if (count($rs) > 0) {
$UserRow = array_pop($rs);
$UserRow->setAccountStatus($AccountStatus);
try {
$UserRow->save();
} catch ( PropelException $e ) {
return false;
}
return true;
}
return false;
}
I would use the empty() instead of $Username == '' in your if statement. I haven't used propel before, but I would prefer to have this method be on my User object itself with the fetching and saving of the user object performed by a seperate object. Pseudo code would be something like this.
$user = userManager->getUser($username);
$user->setAccountStatus($accountStatus);
$userManager->saveUser($user);
An else clause before the last return false would be prefererred, just to make the code more readable.

Categories