Getting around duplicating code in complex if/else statements - php

I come across this problem all the time: you have a series of if/else statements, where the intended result can come from two completely different branches, and you end up duplicating the code across both. Here's an example:
if (condition1) {
return error
} else {
if (condition2) {
return intendedResult
} else {
if (condition3) {
return error
} else {
return intendedResult
}
}
}
I have this problem in a PHP script at the moment, where the intended result is approximately 200 lines of PHP queries, HTML and additional if/else statements. Is this the prime example of when you should use a function? And return all that code in a concatenated string?
EDIT:
Thanks for all your replies. I can see that my logic would need tidying up. If I gave you a real-world example, could you help me restructure my logic? I think it's a little more complicated than my pseudo-code.
I pull two dates, $lift_deadline and $show_guide_close from a database, and depending on today's date's relation to those, do the following:
if ($lift_deadline > $today) {
echo "No access until " . $lift_deadline;
} else {
if ($lift_deadline !== "0000-00-00") {
if ($today > $show_guide_close) {
$use_date = $show_guide_close;
} else {
$use_date = $lift_deadline;
}
echo "HTML Table"; // Intended result goes here, using $use_date
} else {
if ($show_guide_close > $today) {
echo "No access until " . $show_guide_close;
} else {
$use_date = $show_guide_close;
echo "HTML Table"; // Intended result also goes here
}
}
}

Well part of the solution is certainly making intendedResult code into a separate method, but just reoganizing the conditions can help:
if ($condition1) {
return 'error';
}
if (!$condition2 && $condition3) {
return 'error';
}
return $this->intendedResult();
This could be further simplified to:
return ($condition1 || $condition3) ? 'error' : $this->intendedResult();
But that might not be as readable, and doesnt really illustrate my point, which is as Tom mentions, to flatten your control structure

Yes, functions are one way to simplify code and make it easier to read. It might be also worth looking into classes and exceptions.

In simple instances I use a switch statement for stuff like this
switch(true)
{
case (condition1):
break;
case (condition2):
break;
default:
}

Related

Mapping Woocommerce order statuses using IF statements

In Woocommerce, I am trying to map orders statuses with the following code:
function my_map_status ($status) {
if ($status == "wc-processing") {
return "WAA";
} else {
return $status;
}
if ($status == "wc-cancelled") {
return "WAC";
} else {
return $status;
}
}
But only the first one works.
How can I make it work for both?
The first IF ELSE statement is taking every possibility. Instead use an IF ELSEIF ELSE structure:
function my_map_status ($status) {
if ($status == "wc-processing") {
return "WAA";
} elseif ($status == "wc-cancelled") {
return "WAC";
} else {
return $status;
}
}
It should better work.
The reason it's not getting beyond the first if is that it has an else that just returns - so, if you think it through logically you will see that if $status is not wc-processing then return (and quit function) - in other words, it never gets beyond the first if.
Instead, you might like to consider using switch/case, which makes for much easier reading than multiple if/elseifs, like this:
switch ( $status ) {
case "wc-processing":
return "WAA";
break;
case "wc-cancelled":
return "WAC";
break;
default:
return $status;
}
(in case you're wondering about the break - although not strictly necessary in this case (as the function will be exited with the return) it is good practice IMHO to always remember to use it every time you write a switch structure. More info on the page below.)
Further reading: http://php.net/manual/en/control-structures.switch.php

How to use include or require_once on If else statement on php?

I have two file if.php and index.php, I want to use if.php to store the if condition form if statement. But it seems not working. Is it possible to do it? thank you
if.php
<?php
if(Three == 3) {
//do something
}
?>
index.php
<?php
require_once 'if.php';
else{
//do something
}?>
Update:
Beacase I have a lot of index.php(such as index1.php ,index2.php,index3.php.........................index731.php)
If I need to keep update for if statement.....
First day needto add if(One == 1) , Second day need to add if(One == 1, Two== Three)
so If I need to add value in if statement, I need to change a lot of page!!!!!!
but finally ,I find solution.
if.php
<?php
if(Three == 3) {
$session_admin =true;
}
?>
index.php
<?php
require_once 'if.php';
if($session_admin ==true){
//do something
}else{
//do something
}?>
Each PHP file is compiled individually and it must be syntactically correct. It is not possible to start a control structure, function or class in a file and close it in a different file.
It is, however, possible to return a value from an included file. You can use it to implement the behaviour you want like this:
File if.php:
<?php
if (Three == 3) {
// do something
return true;
} else {
return false;
}
File index.php:
<?php
if (require_once 'if.php') {
// do something (or nothing)
} else {
// do something else
}
However, I do not recommend this approach. The best approach is to encapsulate the test in a function:
File if.php:
function testSomething() {
if (Three == 3) {
// do something
return true;
} else {
return false;
}
}
File index.php:
require_once 'if.php';
if (testSomething()) {
// do something
} else {
// do something else
}
Its wrong way to use if else statement , blew code may help you:
index.php
<?php
if($value == 1) {
include_once('first_file.php');
}else{
include_once('second_file.php');
}
// ** OR **
switch($value){
case '1': include_once('first_file.php');break;
case '2': include_once('second_file.php');break;
}
?>
first_file.php
// put here the code that you want run when $value == 1
second_file.php
// put here the code that you want run when $value == 2

if and else both are true in my php codes

i wonder that both if and it's else are true.
i got $apple_id_num from the input select form and it is a number but in string type like "7" and it is how many ids that user wants.so i convert it to integer
now i want to check if it is not more that what i have available in my database.
but statements under conditions ($num_rows<$id_num) and if ($num_rows>=$id_num) both are running.
what i'm doin wrong?
here is my code:
function getAppleID($apple_id_num)
{
$sqli=new mysqlii();
$apple_ids=$sqli->SelectFromDB($apple_id_num);
$num_rows=$sqli->num_rows;
$id_num=(int)$apple_id_num;
if ($num_rows>=$id_num){
$this->printAppleID($apple_ids,$num_rows);
//$sqli->updateRows();
echo"else if running";
return $apple_id_num;
} else if ($num_rows<$id_num)
echo "if statement was rungning";
}
Try this code. always write intended code. Sometimes you may miss a } :P
Use elseif in place of else if.
function getAppleID($apple_id_num)
{
$sqli=new mysqlii();
$apple_ids=$sqli->SelectFromDB($apple_id_num);
$num_rows=$sqli->num_rows;
$id_num=(int)$apple_id_num;
if ($num_rows>=$id_num) {
$this->printAppleID($apple_ids,$num_rows);
//$sqli->updateRows();
echo"else if running";
return $apple_id_num;
} elseif ($num_rows<$id_num) {
echo "if statement was rungning";
}
}

if statement running regardless of true false

I have tested each method individually with default values and it all seems to work. There is something going on when they are all mixed together.
Here is the code and i'll do my best to write it in an easy to follow way:
Starting with the controller:
if ($active['newcliq'])
{
$newcliqid = $this->create_m->create_keyword($cliq, $cliqid);
if (!$newcliqid) {
echo json_encode(array('success' => false));
} else {
$this->logic_m->change_active($newcliqid, $cliq);
}
}
$active['newcliq'] is true or false and pulled from userdata('active')
Of course, the next thing it runs is create_keyword($cliq, $cliqid) seen below:
$this->db->insert('cliq', $insert);
$newcliqid = $this->db->insert_id();
if ($newcliqid) {
return $newcliqid;
} else {
return false;
}
Again, I have checked it all manually, and I know that $newcliqid is returning the correct insert_id and the overall function is returning the correct value.
So $newcliqid is returned to the controller and goes runs logic_m->change_active seen below:
if (!$this->logic_m->cliqidcheck($cliqid)){
$cliqid = 6;
}
The above line is what is giving me problems. No matter what value, $cliqid is ALWAYS set to 6. Whether cliqidcheck returns true or false.
Here is cliqidcheck($cliqid)
public function cliqidcheck($cliqid)
{
if ((ctype_digit($cliqid)) AND ($this->checkcliqidexist($cliqid)))
{
return true;
} else {
return false;
}
}
I have tested cliqidcheck with manually entered values and it always returns the correct value. In addition, i've flat out removed the cliqidcheck from the change_active model and it works perfectly.
I also echo'ed the variable $newcliqid in the controller and found the correct value.
I am hoping this is just a simple problem that I'm overlooking. Thanks for the help! Please let me know if more info is required.
Instead of verbal explanations, wouldn't be it better to post either the debugging code
var_dump($cliqid);
$tmp = $this->logic_m->cliqidcheck($cliqid);
if (!$tmp) {
$cliqid = 6;
}
var_dump($tmp, $cliqid);
die;
and it's output.
Even without posting it here it will convince you that if statement actually never "running regardless of true false"
Setting full error reporting also helps (with finding typos and such)
ini_set('display_errors',1);
error_reporting(E_ALL);
Also a note on excessive code. This statement
if (condition)
{
return true;
} else {
return false;
}
can (and should, in my opinion) be shortened to
return (condition);
Same goes for insert id. Why not to make it just
return $this->db->insert_id();
without all that windy
if ($newcliqid) {
return $newcliqid;
} else {
return false;
}
which is actually a mere tautology

Right mvc concept, little php code in view

I have one not understood point In MVC pattern. Please help understood.
for example we have table for cars in database, we want obtain and print results from table, but if results are not found (0 rows), in this case print: "We dont have results"
this is models.php
class modesl {
function getCars () {
$res = $this->db->query("SELECT names FROM cars");
if ($res->num_rows == 0) {
return "We dont have results";
}
else {
return $res;
}
}
}
this is views.php
class views {
function loadHTML ($resultFromCars) {
require 'carspage.php';
}
}
this is carspage.php
<html>
<body>
<?php
if (is_object($resultFromCars)) {
while ($row = $resultFromCars->fetch_assoc()) {
echo $row['names']."<br>";
}
}
else {
echo $resultFromCars;
}
?>
</body>
</html>
this is controllers.php
class controllers {
function generatePage () {
$model = new models();
$resultFromCars = $model->getCars();
$view = new views();
$view->loadHTML($resultFromCars);
}
}
This works, but as I know, many php code in view, (that is condition if (is_object) { } else { } ) is not right MVC. tell please for this concret case, what must be change in my architecture (lol), for obtain right MVC concept?
I like the answer provided by Havelock.
I would adjust this even further, by making sure your model already returns the data in an array format (or false, if nothing is found). Therefore, the logic for extracting data from resultset stays in the model, where it really should be.
Your view becomes even simpler then:
<?php
if (!empty($results)) {
foreach ($results as $row) {
echo $row['name'] . "<br />";
}
} else {
echo "Eh, Nothing found...";
}
You seem to have done a good job, just one small thing to improve. As the model is a wrapper for data only, so you should return only data (and no strings, containing error/exception messages). In the case there's no data to return, then return FALSE, as it's done in PHP.
class CarModel {
function getCars () {
$res = $this->db->query("SELECT names FROM cars");
if ($res->num_rows == 0) {
return FALSE; // if that happens, the function will stop execution here, so no "else" is needed
}
return $res;
}
}
And in your view
<?php
if ($resultFromCars === FALSE && !empty($resultFromCars)) {
echo "We don't have results";
}
else { // now you know it's not FALSE, so it must be an object, no need to check whether it is one
while ($row = $resultFromCars->fetch_assoc()) {
echo $row['names']."<br>";
}
}
?>

Categories