Context: On our website, we calculate whether an item/order meets the criteria for free shipping using an if statement evaluating if a value - 'ff' - is true. Depending on conditions met it sets the shipping appropriately. We now require the need to evaluate if an item is free shipping with the order of _. To top it off, for other purposes such as external feeds, another condition must apply (weight must = 0 or have no value), for fw to be free freight. Here is the code, that I can't figure out why it is NOT working:
if($r['freeFreight'] == 'ff' || ($r['freeFreight'] == 'fw' && ($r['weight'] == 0 || $r['weight'] == '') ) ) {
$r['shippingStandard'] = 0;
}
Are the conditions overly segregated in the if statement with the sets of ()? Or, are they just incorrectly placed. For example, should it be:
if(($r['freeFreight'] == 'ff') || ($r['freeFreight'] == 'fw' && $r['weight'] == 0 || $r['weight'] == '') ) {
$r['shippingStandard'] = 0;
}
The second of the two seems more logical to me because: if ($r['freeFreight'] == 'ff') - then regardless of the following conditions the statement should return true and set the variable to 0. Is my logic correct? Sorry for this newb question...
Thanks for any help you can offer.
So I think perhaps, based on the answers so far (thanks everybody that has chimed in to help an amateur) - I think I am going to do a trial with:
if( ($r['freeFreight'] == 'ff') || ( $r['freeFreight'] == 'fw' ) && empty( $r['weight'] ) ) {
$r['shippingStandard'] = 0;
}
Planning to run trial with this, if it is fundamentally wrong, please advise.
Try this out?
if( $r['freeFreight'] == 'ff' || ( $r[ 'freeFreight' ] == 'fw' && empty( $r['weight'] ) ) ) {
$r['shippingStandard'] = 0;
}
using empty might be a little cleaner too
if you really want to break it out more, you could do this
if( $r[ 'freeFreight' ] == 'ff' ) {
$r[ 'shippingStandard' ] = 0;
} elseif( $r[ 'freeFreight' ] == 'fw' && empty( $r[ 'weight' ] ) ) {
$r[ 'shippingStandard' ] = 0;
} else {
// Everything else
}
If you want to shorten the variables, and will be using them later:
$freight = $r[ 'freeFreight' ];
$weight = isset( $r[ 'weight' ] ) ? $r[ 'weight' ] : null;
$shipping = $r[ 'shippingStandard' ]; // Or whatever you want the default value to be...
if( $freight == 'ff' || ( $freight == 'fw' && empty( $weight ) ) ) {
$shipping = 0;
}
// ... Later down the file
$r = array(
'freeFreight' => $freight,
'weight' => $weight,
'shippingStandard' => $shipping
);
I really cant tell how the rest of the file looks, like if this is in a function to get shipping, you could simply just return $shipping. Hope this helps. You should be able to move the concepts around to get what you want
your first option should should be identical to the following:
if ($r['freeFreight'] == 'ff') {
$r['shippingStandard'] = 0;
}
elseif ($r['freeFreight'] == 'fw') {
// the dual check for an empty value here is kind of redundant and unneccessary.
// I'd probably just use "if ($r['weight'])" and be done with it
if ($r['weight'] == 0) {
$r['shippingStandard'] = 0;
}
elseif ($r['weight'] == '') {
$r['shippingStandard'] = 0;
}
else {
// $r['shippingStandard'] stays whatever it was before
}
}
else {
// $r['shippingStandard'] stays whatever it was before
}
if that logic looks right to you, then you should be right on and I'd print_r($r) to make sure it's holding what you expect it to be holding. Your parenthesis in the first example is exactly how I would do it.
Related
I am very new to PHP and trying to get an IF statement to work to change the membership level based on the possibility of multiple answers provided in the registration form. However, it's not working. If anyone can help me understand what I am doing wrong/missing that would be a great help. Here is my code. Thank you.
function my_pmpro_checkout_level($level)
{
if ( ! empty( $_REQUEST['registrationlevel']) && $level->id == '1' ) {
if (( $_REQUEST['registrationlevel'] == 'eligibleforlimited' && $_REQUEST['experience'] != 'morethansixyears') || ($_REQUEST['registrationlevel'] == 'eligibleforlimited' && $_REQUEST['timeassesment'] == 'no')) {
$level->id = '3';
} elseif ( $_REQUEST['registrationlevel'] == 'eligibleforprovisional' && $_REQUEST['experience'] != 'noexperience') {
$level->id = '3'}
}
return $level;
}
add_filter("pmpro_checkout_level", "my_pmpro_checkout_level");
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) ...
I have a problem similar to the post:
how to check multiple $_POST variable for existence using isset()?
My issue is, I have a rather large list of checkboxes I need to know if they were checked in order to set the status of $row. it would be exactly like the mentioned script,all and's, except I have and OR thrown in to the works.
if ( isset($_POST['Facial1'])
&& ($_POST['Facial2'])
&& ($_POST['Facial3'])
&& ($_POST['Facial4'])
&& ($_POST['Intra-Oral1'])
&& ($_POST['Intra-Oral2'])
&& ($_POST['Intra-Oral3'])
&& ($_POST['Intra-Oral4'])
&& ($_POST['Intra-Oral5'])
&& ($_POST['Intra-Oral6'])
&& (
(
($_POST['X-Ray1'])
&& ($_POST['X-Ray3'])
)
|| ($_POST['X-Ray5'])
)
)
{
$Status = 1;
} else {
$Status = 0;
}
Each time I run a test, as soon as it gets to an element that is not checked it throws an error: undefined index: xxx. Where xxx is the first none checked item.
Checkboxes that are not checked do not get sent as part of the POST body. Your code needs to use isset:
if ( isset($_POST['Facial1'])
&& isset($_POST['Facial2'])
&& isset($_POST['Facial3'])
&& isset($_POST['Facial4'])
&& isset($_POST['Intra-Oral1'])
&& isset($_POST['Intra-Oral2'])
&& isset($_POST['Intra-Oral3'])
&& isset($_POST['Intra-Oral4'])
&& isset($_POST['Intra-Oral5'])
&& isset($_POST['Intra-Oral6'])
&& (
(
isset($_POST['X-Ray1'])
&& isset($_POST['X-Ray3'])
)
|| isset($_POST['X-Ray5'])
)
)
{
$Status = 1;
} else {
$Status = 0;
}
the isset() allows you to check one variable isset($var) or multiple variables at a time isset($var,$var1,$var2) this will return true is all exists and false if one or more are not set.
Your code is only checking one and then doing well I am not sure what
Try
if ( isset(
$_POST['Facial1'], $_POST['Facial2'], $_POST['Facial3'],
$_POST['Facial4'], $_POST['Intra-Oral1'], $_POST['Intra-Oral2']
$_POST['Intra-Oral3'], $_POST['Intra-Oral4'],
$_POST['Intra-Oral5'], $_POST['Intra-Oral6']
)
&&
(
isset($_POST['X-Ray1'], $_POST['X-Ray3'])
||
isset($_POST['X-Ray5'])
)
)
{
$Status = 1;
} else {
$Status = 0;
}
I hope this is what you intended, its not totally obvious from your code.
if($_SESSION['valueofdie1'] != 0 && $_SESSION['valueofdie2'] != 0 && $_SESSION['valueofdie3'] != 0 && $_SESSION['valueofdie4'] != 0 && $_SESSION['valueofdie5'] != 0)
{
if((($_SESSION['valueofdie1'] == $_SESSION['valueofdie2']) && ($_SESSION['valueofdie2'] == $_SESSION['valueofdie3']||$_SESSION['valueofdie4']||$_SESSION['valueofdie5'])) || (($_SESSION['valueofdie1'] == $_SESSION['valueofdie3']) && ($_SESSION['valueofdie3'] == $_SESSION['valueofdie4']||$_SESSION['valueofdie5'])) || (($_SESSION['valueofdie1'] == $_SESSION['valueofdie4']) && ($_SESSION['valueofdie4'] == $_SESSION['valueofdie5']))
|| (($_SESSION['valueofdie2'] == $_SESSION['valueofdie3']) && ($_SESSION['valueofdie3'] == $_SESSION['valueofdie4']||$_SESSION['valueofdie5'])) || (($_SESSION['valueofdie2'] == $_SESSION['valueofdie4']) && ($_SESSION['valueofdie4'] == $_SESSION['valueofdie5']))
|| (($_SESSION['valueofdie3'] == $_SESSION['valueofdie4']) && ($_SESSION['valueofdie4'] == $_SESSION['valueofdie5'])))
{
if($_POST['choose'] == 'choose 3oaK')
{
$_SESSION['g'] = 5;
$_SESSION['scoretkind'] = $_SESSION['valueofdie1'] + $_SESSION['valueofdie2'] + $_SESSION['valueofdie3'] + $_SESSION['valueofdie4'] + $_SESSION['valueofdie5'];
unset($_SESSION['3oaKBut']);
echo '<input type="hidden" name="choose" value="Clear" onLoad="form.submit();">';
$_POST['sub'] = 'reset';
$_POST['choose'] = '';
}
if(empty($_SESSION['g']))
{
$_SESSION['3oaKBut'] = '<input type="submit" name="choose" value="choose 3oaK">';
echo $_SESSION['3oaKBut'];
}
}
}
if($_SESSION['g'] == 5)
{
echo $_SESSION['scoretkind'];
}
So here is the code we have. We are trying to check if 3 of the 5 die values are equal. If they are equal we echo out a button that allows the user to choose to score his 3 of a kind, which is the total of all of the dice. Everything works except in some cases the 3 of a kind button would echo out when there isnt a 3 of a kind. Halp PLS
I'm sorry I didn't answer your question by actually solving your bug, but I think your code is hard to read and your approach makes it cumbersome to program all the rules.
General advice: Put $_SESSION['valueofdie1'] and the other dice into an array of values. That's much easier to work with. After that, it should be pretty easy to check how many times each value occurs. Even when you keep your approach, you could make variables like $die1, which is already a lot shorter and more readable than $_SESSION['valueofdie1'].
But with an array, you could roughly start like this:
// Put all dice into an array.
$dice = array(
$_SESSION['valueofdie1'],
$_SESSION['valueofdie2'],
etc.... );
// Count how many times each die is rolled.
$diceCount = array();
foreach($dice as $die) {
$count = 0;
if (isset($diceCount[$die])) {
$count = $diceCount[$die];
}
$diceCount[$die] = $count + 1;
}
// Check possible results simply by looking at those counts.
// If one die value is rolled 5 times, it's Yahtzee...
if (array_search(5, $diceCount) !== false) {
echo 'Yahtzee!';
}
if (array_search(4, $diceCount) !== false) {
echo 'Four of a kind';
}
// Full house takes two types.
if (array_search(3, $diceCount) !== false && array_search(2, $diceCount) !== false) {
echo 'Full house';
}
for ($diceCount as $die => $count) {
echo "$count times $die";
}
... etc ...
You'll need to expand this list, and take some other rules into account. After all, a Yahtzee could also count as a Four of a Kind. But by checking all those rules, you can generate a new array of possible combinations, which you can check against the previously chosen options. And the outcome of that determines which options the player can choose.
I have a large group of nested IF statements and I was wondering If anyone had any suggestions on how to optimize for speed, size, and readability.
Below is a sample of ONE of the if statements and its' nested statements. There will be approximately 25-30 of these in the document.
if( $row["inlet_moisture"] > $row["inlet_moisture_high_warning"] ) {
if( $row["inlet_moisture"] > $row["inlet_moisture_high_critical"] ) {
if( $row["inlet_high_critical"] == 0 ) {
if( $row["email_notification"] == 1 ) {
}
if( $row["mobile_notification"] == 1 ) {
}
}
} else {
if( $row["inlet_high_warning"] == 0 ) {
if( $row["email_notification"] == 1 ) {
}
if( $row["mobile_notification"] == 1 ) {
}
}
}
} else if( $row["inlet_moisture"] < $row["inlet_moisture_low_warning"] ) {
if( $row["inlet_moisture"] < $row["inlet_moisture_low_critical"] ) {
if( $row["inlet_low_critical"] == 0 ) {
if( $row["email_notification"] == 1 ) {
}
if( $row["mobile_notification"] == 1 ) {
}
}
} else {
if( $row["inlet_low_warning"] == 0 ) {
if( $row["email_notification"] == 1 ) {
}
if( $row["mobile_notification"] == 1 ) {
}
}
}
}
The idea is; I have a reading (temp/speed/moisture) and I need to check if it hits any of the limits (high warning / high critical / low warning / low critical), if it does I first need to check if I have already sent an alarm for that. If no alarm has been sent I then need to check if the user has requested alarm notification (mobile/email/both)
Currently this works. I Just don't like how heavy it is? Can I improve on this?
Thanks.
this seems to me much more clear, even though you could combine the nested ifs I'd rather prefer this one
if( $row["inlet_moisture"] > $row["inlet_moisture_high_critical"] ) {
if( $row["inlet_high_critical"] == 0 ) {
$message = 'the pertinent message';
}
}
else if( $row["inlet_moisture"] > $row["inlet_moisture_high_warning"] ) {
if( $row["inlet_high_warning"] == 0 ) {
$message = 'the pertinent message';
}
}
else if( $row["inlet_moisture"] < $row["inlet_moisture_low_critical"] ) {
if( $row["inlet_low_critical"] == 0 ) {
$message = 'the pertinent message';
}
}
else if( $row["inlet_moisture"] < $row["inlet_moisture_low_warning"] ) {
if( $row["inlet_low_warning"] == 0 ) {
$message = 'the pertinent message';
}
}
if( $row["email_notification"] == 1 ) {
sendMessage($message, $email);
}
if( $row["mobile_notification"] == 1 ) {
sendMessage($message, $mobile);
}
Premature optimisation is the root of all evil - with what we are dealing with here, no matter what you do it won't have much/any noticable impact on performance.
Having said that, a large amount of if statements can often be replaced with one or more switch structures, although whether this improves performance or readability is debatable. You may also be able to create some functions for repeated bits of code, although this may actually negatively impact performance.
From your comment above... creating variables with nicer names will have pretty much zero impact on performance. If will slightly increase your memory usage, but the processing time impact will be next to zero. And, if you are evaluating the values as booleans, you don't need to convert them to booleans explicitly, because 1 still evaluates to TRUE, and 0 to FALSE. However, if you do want to do it
$email_notification = $row["email_notification"] == 1 ? true : false;
...is unnecessarily long winded, you can do either this:
$email_notification = $row["email_notification"] == 1;
...or...
$email_notification = (bool) $row["email_notification"];
...and it will have the same effect.