!is_null() not working as expected - php

dispatch_address_postcode
isn't mandatory and it will still run even if it's blank:
if (!is_null($_POST['personal_info_first_name']) &&
!is_null($_POST['personal_info_surname']) &&
!is_null($_POST['personal_info_email']) &&
!is_null($_POST['personal_info_telephone']) &&
!is_null($_POST['dispatch_address_country']) &&
!is_null($_POST['dispatch_address_first_name']) &&
!is_null($_POST['dispatch_address_surname']) &&
!is_null($_POST['dispatch_address_address']) &&
!is_null($_POST['dispatch_address_town']) &&
!is_null($_POST['dispatch_address_postcode']) &&
!is_null($_POST['dispatch_address_county']) &&
( ($_POST['payment_method'] == "Pay by credit card.") ||
(
($_POST['payment_method'] == "Pay by new credit card.") &&
!is_null($_POST['card_number']) &&
!is_null($_POST['expiration_date']) &&
!is_null($_POST['security_code'])
)
)
)
What gives?

"dispatch_address_postcode isn't mandatory and it will still run even if it's blankā€¦"
Just look at that sentence again. If the field is not mandatory, it is perfectly okay if the code runs if the field is blank. If a field isn't mandatory, don't test it as mandatory.
The real problem is though, is_null only tests if the variable is null. POSTed values will never be null, if they're empty they will be '' (an empty string). All your !is_null tests will always be true, and you will get a warning if the variable isn't set (something you don't want to happen). The more appropriate test would be !empty.
Even more appropriate tests would include a test if the value appears to be valid (does email look like an email address, does telephone have at least x digits in it?). You should also loop through the fields to make your code more readable, endless nested and chained if conditions are no joy to look at.
$mandatoryFields = array('foo' => 'email', 'bar' => 'telephone');
foreach ($mandatoryFields as $field => $rule) {
if (empty($_POST[$field]) || !validateByRule($_POST[$field], $rule)) {
raiseHell();
}
}

It looks like you're trying to make sure all post variables are submitted. Would you like help with that?
Using !empty() may not be the answer to your specific question, but it would definitely help with what it looks like you're trying to do.
empty() returns TRUE if the $_POST key isn't set, if its an empty array, or even if its an empty string, so using !empty() is a good way to make sure that the user has filled in the information.

Try writing your own is_valid function and use that rather than is_null.
For example (and this is by no means comprehensive):
function is_valid(&$array, $key, $required=false) {
if(!array_key_exists($array))
return false;
$value = trim($array[$key]);
if(empty($value) && $required)
return false;
return true;
}
Use like so:
if(is_valid($_POST, 'personal_info_first_name', true) && ...)

!is_null($_POST['personal_info_first_name']) && !isset($_POST['personal_info_first_name'])

use array_key_exists('card_number', $_POST) && !empty($_POST['card_number'])

Edit: Please consider this before a downvote. I'm leaving this here to serve as a "what not to do". I would delete it because it's bad, but then nobody would learn from my mistakes.
DO NOT DO THIS - read the comments for great info on why this is bad
My answer is going to be wildly different, but I am a wildly different guy...
I JUST found that this will work. Instead of all that isset and things, just assign the variables programmatically! I think I have some refactoring to do... y'know on all my code...
if (!is_array($_POST)){exit "$_POST isn't an array";}
foreach ($_POST as $param => $value){
${$param} = secure($value);
}
//now you have a set of variables that are named exactly as the posted param
//for example, $_POST['personal_info_first_name'] == $personal_info_first_name
if ($payment_method == "Pay by credit card."){
//do stuff that you were gonna do anyways
} else if ($payment_method == "Pay by new credit card.") {
if ($card_number && $expiration_date && $security_code){
//do stuff that you were gonna do anyways
} else {
exit("info missing for credit card transaction");
}
} else {
exit("unknown payment method")
}
function secure($input){
//sanitize user input
}
If you use this code, then it doesn't matter what is null and what isn't within the foreach because anything that's null just won't be made. Then you can use nicer looking code (and probably faster code) to check for anything that is required.

Related

PHP If a variable equals this or this

I have this if statement in my PHP:
if($_SESSION['usrName']!='test1'){
header('location:login.php');
}
But i want it to be something like this:
if($_SESSION['usrName']!='test1' or 'user'){
header('location:login.php');
}
But i cant figure out how to do it in PHP code. I have tried this:
if($_SESSION['usrName']!='test1','user'){
header('location:login.php');
}
And this:
if(($_SESSION['usrName']!='test1')||($_SESSION['usrName']!='user')){
header('location:login.php');
}
Can anybody help please?
You have to replace the || with &&. Because you only want to redirect when both conditions are true.
if(($_SESSION['usrName']!='test1') && ($_SESSION['usrName']!='user')){
header('location:login.php');
}
if (!in_array($_SESSION['usrName'], array('test1', 'user')) {
header('location:login.php');
}
This checks if variable $_SESSION['usrName'] is not in list of strings to simplify additional allowed user.
As others have said, you need to be careful with your boolean logic - (NOT X) || (NOT Y) is equivalent to NOT (X AND Y), whereas what you want is NOT (X OR Y) which is equivalent to (NOT X) AND (NOT Y).
For this particular situation, there are also a couple of other options, although none as neat as the invalid syntaxes you tried.
First, there is in_array(), which is easy to read, but not very efficient if you use it a lot with long lists (for a simple case like this, it's not worth worrying about performance, though):
$allowed_users = array('test1', 'user');
if ( ! in_array($_SESSION['usrName'], $allowed_users ) { ... }
Or, you can build a hash with the usernames as keys; this is more efficient as the list grows, because PHP can check for a key without looping through the whole list:
$allowed_users = array('test1' => true, 'user' => true);
if ( ! array_key_exists($_SESSION['usrName'], $allowed_users) ) { ... }
// Or, if you don't mind PHP raising a few notices about accessing undefined keys
if ( ! $allowed_user[ $_SESSION['usrName'] ] ) { ... }
Finally, you can use a switch statement, with the labels falling through, and a default case acting as the "else":
switch ( $_SESSION['usrName'] )
{
case 'test1':
case 'user':
// These users are allowed :)
break;
default:
header('location:login.php');
}
Which, if any, of these you choose to use will depend on how you expect the code to grow in future, but they're useful tricks to know.
Your last attempt is almost correct.
However...
if (var != something || var != something-else)
...will always be true, because one of those conditions will always match. Even if it's equal to one side, it won't be equal to the other.
When you're testing two negatives like that, you need to use AND (&&) instead of OR (||).
if (($_SESSION['usrName']!='test1') && ($_SESSION['usrName']!='user'))
This will match if it's not equal to one, and also not equal to the other.
Currently, you're checking if either one of conditions are true. The last condition will evaluate to true if either one of the conditions are correct. I assume you're trying to check if both the the conditions are true. In that case, you'll need && instead of ||.
Try:
if( ($_SESSION['usrName'] != 'test1') && ($_SESSION['usrName'] != 'user') ) {
header('location:login.php');
}
You need to do something like:
if($_SESSION['usrName'] != 'test1' and $_SESSION['usrName'] != 'user'){
header('location:login.php');
}
The first attempt of yours is equivalent to:
if(($_SESSION['usrName']!='test1') or 'user'){
header('location:login.php');
}
Second seems like invalid syntax
Third is almost right, you just need to replace || with and or &&, as anything will be unequal to either 'user' or 'test1'

PHP if status and !isset or !isset

I'm trying to match a condition where if the user status is 10 and ANY POST variables are not set it triggers an error:
if ($_SESSION['status']=='10' && !isset($_POST['a']) || !isset($_POST['B'])) {}
I can not use && conditions for any !isset as one variable may be set though another might not. I only want the condition to match if one or more variables are not set AND the status==10.
When testing if a $_POST variable !isset, I remove an input element from the page via a browser web tool (e.g. Firebug). When the form is submitted with the variable missing it's still passing validation incorrectly.
I am also seeking a PHP if grouping condition.
If you are looking for absolutely any PHP variables, I'd recommend this:
if (($_SESSION['status'] == 10) && (count($_POST) > 0)) {
You can then get the list of _POST var keys using array_keys($_POST).
If you are looking for a specific:
if (($_SESSION['status'] == 10) && (isset($_POST['A']) || isset($_POST['b']))) {
The order of the brackets is important. You can separate groups of logical statements with brackets.
Is that was what you were looking for?
$status = $_SESSION['status'];
if($status == '10'){
if(!isset($_POST['a']) or !isset($_POST['B'])){
//Triggers error.
}else{
//Another
}
}
Try making it a function:
function checkAllVars($dataVars, $requestVars) {
foreach($dataVars as $varname) {
if(!isset($requestVars[$varname])) {
return false;
}
}
return true;
}
$dataVars = array (
"varName1",
"varName2",
"varName3",
"varName4",
);
$allVarsSet = checkAllVars($dataVars, $_REQUEST);
you might be looking for
if($_SESSION['status']=='10' && (!isset($_POST['a']) || !isset($_POST['B']))){}
^ ^
which means if status = 10 and (if not set 'a' or not set 'B' or they can be both not set) do something
or you might be looking for
if(($_SESSION['status']=='10' && !isset($_POST['a'])) || ($_SESSION['status']=='10' && !isset($_POST['B']))){}

if-clause addings empty

i have the following if-clause:
if(empty($var)){
$errors[]="Failure";
}
this is for a form that will be display an errormessage when a user has made no entries. i would like to hide this field when a user has made something specific so that he cant see this input field. this div will only being displayed when another variable is set. because of the "empty" problem i got the errormessage even when there is no inputfield. so my question is:
how can i add further terms to that clause that it will be like:
if(empty($var) only when $var2===true ){
$errors[]="Failure";
}
i already tried to use && but this doesn't work the correct way. thats why i'm asking and thought maybe there is another way. thanks to all.
Try:
if(empty($var) AND $var2) {
$errors[]="Failure";
}
If $var is empty and $var2 is TRUE it will be inside the if condition. did you mean something like that
Probably $var2 is 1 and not true, because in other case this need to work
if(empty($var) && $var2===true){
$errors[]="Failure";
}
Try
if(empty($var) && $var2==true){
$errors[]="Failure";
}
== instead of === or check for logical bugs.

PHP - If something is the case, do nothing

Is this a proper way to say: if something is the case, do nothing?
if ( ($hostNameInfo == $hostNameInput) && ($hostAddressInfo == $hostAddressInput) )
{
return;
}
Update:
I'm not inside a function. :(
So the return is just nonsense.
Here is more code:
//if the input fields are equal to database values, no need to update and waste resources,hence, do nothing:
if ( ($hostNameInfo == $hostNameInput) && ($hostAddressInfo == $hostAddressInput) )
{
//do nothing
}
//If, however, (they are NOT equal and) input fields are not empty:
elseif (!empty($hostNameInput) && (!empty($hostAddressInput)))
{
//do something.
}
Thanks in advance,
MEM
For do nothing you simply can type:
function relax() {
;
}
if (($hostNameInfo == $hostNameInput) && ($hostAddressInfo == $hostAddressInput)) {
relax();
}
Maybe you should do the opposite, do something if your condition is not verified
if($hostNameInfo != $hostNameInput || $hostAddressInfo != $hostAddressInput) {
// do something
}
I assume you're inside a function in which case it does what you expect, although multiple return statements within a function can lead to confusion and a lack of readability. (Apparently I was wrong.)
Instead, I prefer to let all conditional blocks (my description for the code between in the if's {...} block) contain the relevant code, i.e., write the conditional check in such a way that the total condition evaluates to true when additional processing (sub-flow) is needed:
if ($hostNameInfo != $hostNameInput || $hostAddressInfo != $hostAddressInput) {
// do stuff, else skip
}
Furthermore, you can extract the conditional statement in order to improve both readability and simplicity of control flow:
$hostInfoEqualsInput = ($hostNameInfo == $hostNameInput && $hostAddressInfo == $hostAddressInput);
if (!$hostInfoEqualsInput) {
...
}
UPDATE (based on updated question). Consider this instead:
$fieldsAreFilled = (!empty($hostNameInput) && !empty($hostAddressInput));
$hostInfoEqualsInput = ($hostNameInfo == $hostNameInput && $hostAddressInfo == $hostAddressInput);
if ($fieldsAreFilled && !$hostInfoEqualsInput) {
...
}
ERGO
Minimize branch rate and avoid empty blocks by writing conditions you want to be met, not all the exceptions you want to ignore (subjective).
You're talking about best practices here..
One of best practice things is that routine shall have single exit point, though it is widely discussed and is up to developer/style.
UPDATE:
New answer, since the question was changed:
Don't see any reason to add additional checks if the code should run only under some circustances. To make the code more readable, you should stuck to whatever you accept as easy-maintainable, like this (or something similar):
// Do something only if required
if (($hostNameInfo != $hostNameInput) || ($hostAddressInfo != $hostAddressInput)) &&
!empty($hostNameInput) && !empty($hostAddressInput))
{
echo 'place some code here';
}
A native do_nothing() function would be very nice and readable sometimes.
To avoid stressing alerts from syntax checkers & linters, that go crazy when you have an empty if block, I use:
echo(null);
The other possibility is to throw a new exception, which you can later catch in your application.
UPDATE: not inside the function this is probably a bad idea.

I need to check if multiple items are set and not empty in PHP

Below is a snippet of PHP that I need to get working, I need to make sure that 3 items are not set already and not === ''
I have the part to make it check if not set but when I try to see if the values are empty as well (I might not even be thinking clearly right now, I might not need to do all this) But I need to make sure that redirect, login_name, and password are all not already set to a value, if they are set to a value I need to make sure that the value is not empty.
Can someone help, when I add in check to see if values are empty, I get errors with my syntax, also not sure if I should have 5-6 checks like this in 1 if/else block like that, please help
I need to check the following:
- $_GET['redirect'] is not set
- $_REQUEST['login_name'] is not set
- $_REQUEST['login_name'] is not != to ''
- $_REQUEST['password'] is not set
- $_REQUEST['password'] is not != to ''
if (!isset($_GET['redirect']) && (!isset($_REQUEST['login_name'])) && (!isset($_REQUEST['password']))){
//do stuff
}
UPDATE
Sorry It is not very clear, I was a bit confused about this. Based on Hobodaves answer, I was able to modify it and get it working how I need it. Below is the code how I need it, it works great like this... So if that can be improved then that is the functionality that I need, I just tested this.
if (!isset($_GET['redirect'])
&& empty($_GET['redirect'])
&& isset($_REQUEST['login_name'])
&& !empty($_REQUEST['login_name'])
&& isset($_REQUEST['password'])
&& !empty($_REQUEST['password'])
) {
echo 'load user';
}
if this was loaded then it will run the login process
login.php?login_name=test&password=testing
If this is loaded then it will NOT run the login process
login.php?login_name=test&password=
if (!isset($_GET['redirect'])
&& !isset($_REQUEST['login_name'])
&& empty($_REQUEST['login_name'])
&& !isset($_REQUEST['password'])
&& empty($_REQUEST['password'])
) {
// do stuff
}
This is exactly what you describe, (not != empty === empty). I think you should edit your question though to explain what you're triyng to do, so we can suggest better alternatives.
Edit:
Your updated question can be simplified as:
if (empty($_GET['redirect'])
&& !empty($_REQUEST['login_name'])
&& !empty($_REQUEST['password'])
} {
// load user
}
A more maintainable solution would be storing each key in an array, and then foreach over it and check if isset or empty. You're not very DRY with your current solution.
The implementation would look someting like:
<?php
$keys = array('login_name', 'password');
foreach($keys as $key)
{
if(!isset($_REQUEST[$key]) || empty($_REQUEST['key'])
// Show error message, kill script etc.
}
// Dot stuff
?>
If a global variable is not set, that is the same as being empty. Thus:
!is_set(($_REQUEST['username'])) is the same as empty($_REQUEST['username'])
So based on your update, you can simplify to:
if (empty($_GET['redirect'])
&& !empty($_REQUEST['login_name'])
&& !empty($_REQUEST['password'])
) {
echo 'load user';
}
please read!
Sorry, the previous answer I gave will not give you what you want. Here is why:
If you use !_REQUEST['password'], it will return true if the password is empty or if it is not set. However if you use if($_REQUEST['password']) it will pass the conditional anytime that global variable is set, even if it is empty.
Therefore I recommend:
$no_redirect = (!$_GET['redirect']);
$login_name = (!$_REQUEST['login_name']) ? false : true;
$password = (!$_REQUEST['login_name']) ? false : true;
if($no_redirect && $login_name && $password) {
echo 'load user';
}
Sorry for the previously bad info.
You could create an array
$array = array(
$_GET['redirect'],
$_GET['redirect'],
$_REQUEST['login_name'],
$_REQUEST['login_name'],
$_REQUEST['password'],
$_REQUEST['password']
);
foreach($array as $stuf)
{
if(!empty($stuff) && $tuff !=0)
//do something
}

Categories