Condensing multiple if statements into one with PHP (for Joomla)? - php

Just in case anyone was not familiar with Joomla, countModules is a function built into it. Also keep in mind I am NOT very familiar with PHP.. and I'm rather new to using it. Please try to keep any solutions simple for understanding. Thanks.
My questions is could I condense this:
if($this->countModules('Top1A and Top1B') >= 1) $modCellRow1 = "col2";
if($this->countModules('Top1B and Top1C') >= 1) $modCellRow1 = "col2";
if($this->countModules('Top1A and Top1C') >= 1) $modCellRow1 = "col2";
into this:
if ($this->countModules('Top1A and Top1B') >= 1) || ($this->countModules('Top1A and Top1B') >= 1) || ($this->countModules('Top1A and Top1C')
{
$modCellRow1 = "col2";
}
If you do know Joomla and countModules... or even if you don't, keep in mind I am checking to see if there is anything in each of the module positions rather then counting how many actual modules there are. In other words, I DO need to use AND as an operator. Also, I don't want to include all three because that is another line in my code... for example:
if($this->countModules('Top1B and Top1B and Top1C') >= 1) $modCellRow1 = "col3";
What I'm checking on those other statements is whether there is something in just TWO of the module positions... (I.E. only two of the three that are equal to or greater the one... but not all three).
ADDITIONAL COMMENT / QUESTION:
Would this work then?
$topRow1Count = 0;
foreach(array('Top1A','Top1B','Top1C','Top1D') as $position) {
if ($this->countModules($position)) {$colCount += 1;}
}
$modColCountTopRow1 = "col" . $topRow1Count;
if ($topRow1Count == 0) { $modTopRow1 = " hidden"; }
$topRow2Count = 0;
foreach(array('Top2A','Top2B','Top2C','Top2D') as $position) {
if ($this->countModules($position)) {$colCount += 1;}
}
$modColCountTopRow2 = "col" . $topRow2Count;
if ($topRow2Count == 0) { $modTopRow2 = " hidden"; }
if ($topRow1Count + $topRow2Count == 0) { $topModCont1 = " hidden"; }

Yes it will work. But let's consider performance and readability.
Performance
You are invoking countModules 3 times for the "col2" case, once for the "col3" case assuming you are starting with "col1" it will be 4 invocations,each with multiple "positions" to check for.
Now the countModules() code is pretty optimized, falling back to a single static class that will not query the db at every iteration; but you're still making your program 10 times slower than it should be even in a small site with few modules.
Readability & code quality
You might have read that code should not look like it's copied and pasted. That makes sense at least because it's easier to read code that avoids duplication, additionally it will be less prone to typos.
In the spirit of condensing multiple statements, instead of joining lines, why not consider:
$colCount = 0;
foreach(array('Top1A','Top1B','Top1C') as $position) {
if ($this->countModules($position)) {
$colCount += 1;
}
}
$modCellRow1 = "col" . $colCount;
This will return "col0" if no modules are in any of the positions, "col1" if modules are present only in one and so on.
I wrote it so it's easiest to read,

Related

Better "Randomization" with Simplexml and PHP

I'm working on a 'thought' function for a game i'm working on -- it pulls random strings from an XML file, combines them and makes them 'funny'. However, i'm running into a small issue in that the same couple of items keep getting selected each time.
The two functions I am using are
function randRoller($number)
{
mt_srand((microtime()*time())/3.145);
$x = [];
for($i = 0; $i < 100; $i++)
{
#$x = mt_rand(0,$number);
}
return mt_rand(0,$number);
}
/* RETRIEVE ALL RELEVANT DATA FROM THE XML FILE */
function retrieveFromXML($node)
{
$node = strtolower($node);
$output = [];
$n = substr($node,0,4);
#echo $node;
foreach($this->xml->$node->$n as $data)
{
$output[] = $data->attributes();
}
$count = count($output)-1;
$number = $this->randRoller($count);
return $output[$number];
}
Granted, the "randRoller" function is sorta defunct now because the orginal version I had (Which 'rolled' ten numbers from the count, and then selected the one which got the most number of dice) didn't work as planned.
I've tried everything i can think of to get better results && have googled my brains out to fix it. but still am getting the same repetitive results.
Don't use mt_srand() unless you know what you are doing, since it is called automatically. See the note on http://php.net/manual/en/function.mt-srand.php:
Note: There is no need to seed the random number generator with srand() or mt_srand() as this is done automatically.
Remove (all) the mt_srand() call(s).

Real estate site, trying to only output properties based on type

So I inherited an old site from another developer, and I'm not really a programmer so I'm having some trouble. I've put the code into a Fiddle: https://jsfiddle.net/s6coraf5/
Basically there are different categories of real estate properties and when you click on different pages it's supposed to filter them and only display the ones specific to whatever page you're on. The problem is that no matter what page you're on, it's just displaying everything. I've narrowed down some specific code but can't figure out why it isn't applying it right.
In the php there's:
$select_title = "Unknown";
if ($select_type == "all") { $select_title = "All Listings"; }
if ($select_type == "office") { $select_title = "Office"; }
if ($select_type == "industrial") { $select_title = "Industrial"; }
if ($select_type == "retail") { $select_title = "Retail"; }
if ($select_type == "shoppingcenter") { $select_title = "Shopping Center"; }
if ($select_type == "land") { $select_title = "Land"; }
if ($select_type == "agricultural") { $select_title = "Ranch / Farm"; }
if ($select_type == "investment") { $select_title = "Investment"; }
if ($select_type == "lodging") { $select_title = "Lodging"; }
if ($select_type == "sportsentertainment") { $select_title = "Sports / Entertainment"; }
In the HTML there are various places where those $select_type's are supposed to be applied:
a href="properties.php?select_type=<?php echo $select_type;?>&select_city=<?php echo $select_city;?>&priceForm=<?= $lowPrice;?>,<?= $highPrice; ?>&sqft=<?= $lowSize;?>,<?= $highSize; ?>&sort_type=city, asking_price desc"><font size=4><b>Location,</b></a>
it's only applying the "all" one though on every page. Again, the fiddle has the full php and html which is probably more helpful. I realize it's ugly and bad but maybe someone can see something obvious that I can't.
Thanks in advance for any help anyone can provide.
Based on the PHP code in the fiddle (Which really shouldn't be there since the fiddle is for Javascript), it seems like the problem is that you never use the select_type given in the URL.
Take a look at this line. This is the first time $select_type is used.
if (!isset($select_type)) $select_type = "all";
Thus, $select_type will always be all.
Instead you should either change it to:
if (!isset($select_type)) $select_type = $_GET['select_type'];
Or just add this line before it:
$select_type = $_GET['select_type'];
Your ssql query in your jsfiddle seems like it might be the culprit. I'll put it here to make it easier:
select properties.property_id,selected_subtypes.property_type,properties.listing_type,properties.city,properties.asking_price,memberships.name,properties.membership_id,properties.building_size,memberships.website,properties.sold_price
from selected_subtypes,properties,memberships where (selected_subtypes.property_id = properties.property_id)
and (properties.membership_id = memberships.membership_id)
and (memberships.status = 'Active') and (properties.sold_information = ' ' or properties.sold_information = 'Undisclosed')
and ((selected_subtypes.property_category ='".$select_type."' or '".$select_type."'='all')
or (selected_subtypes.property_type ='".$select_type."'))
and (properties.city = '".$select_city."' or '".$select_city."'='all')
and (properties.asking_price BETWEEN ".$lowPrice." and ".$highPrice.")
and (properties.building_size BETWEEN ".$lowSize." and ".$highSize.")
".$date_sql."
order by ".$sort_type
The query appears to be, in each line, be selecting $select_type OR 'all
This boolean approach will always bring back either of those, so it would bring back "all" every time.
If you want to bring back only the selected type, you'd need to eliminate the "all" within the OR in these rows.
The easiest way to handle this would be to set the value $select_type to be equal to "all" if that is what is selected, or else, the specific type. One way he way I do "all" queries is to set the value to be "1=1" which will always be true.
In other words, modify the query like so (for each of the selected types) to show this (I changed the OR to AND in this case)
AND selected_subtypes.property_type ='".$select_type."'
and then in the php modify the code to be something like this:
if (!isset($select_type)) {
$select_type = "1=1"
}
else {
$select_type = $_GET['select_type'];
}
Another thing to be aware of
This particular code is somewhat vulnerable to SQL injection, so you might want to modify the way that you query the database. I strongly suggest you look into prepared statements, either using mysqli or PDO

Am I bloating my coding with IF statements?

I was wondering, do too many IF statements bloat coding and when is it okay not to use them?
These two examples both work the same and I'm the only one editing / using the script. Am I teaching myself bad habits by not adding the IF statement?
if ($en['mm_place']) {
$tmp = explode(",", $en['mm_place']);
$en['mm_place'] = $tmp[0].", ".$tmp[1]." ".$tmp[2];
}
is the same as...
$tmp = explode(",", $en['mm_place']);
$en['mm_place'] = $tmp[0].", ".$tmp[1]." ".$tmp[2];
EDIT: using #Francis Avila example I came up with this...
if ($en['mm_wmeet']) {
$tmp = explode(",", $en['mm_wmeet']);
for ($i = 0; $i < count($tmp); $i++) {
$en['mm_wmeet'] = $tmp[$i];
}
}
In this particular example, they are not the same.
If $en['mm_place'] is empty, then $tmp will not have three elements, so your string construction will be bogus.
Actually what you need is probably this:
if (!empty($en['mm_place'])) { // depending on whether you know if this is set and must be a string.
$tmp = explode(',', $en['mm_place'], 3);
if (count($tmp)===3) {
$en['mm_place'] = "{$tmp[0]}, {$tmp[1]} {$tmp[2]}";
}
}
Run PHP with E_NOTICE set, and code in such a way that you don't get any notices. PHP requires an extraordinary amount of discipline to use safely and properly because it has so many sloppy misfeatures. Notices will inform you of most bad practices. You will probably end up using lots of if statements.
if they don't serve any purpose then yes, you're bloating.
In this kind of situation, where you are checking if an array element exists before operating on it, you should keep the if-statement in the code. Here it will only throw a notice if the element is missing, but in the future you definitely could have similar code that will crash if the element is not set.
Edit: Actually those two code samples are not the same. if $en['mm_place'] is null or not set, the first sample will leave it as such while the second will replace it with ", "

What is the most efficient way to verify Variables in PHP?

I'm thinking about an application which recieves massive Data from the User.
But this data has to be verified in php:
f.e. $_GET['id'] has to be a number every Element of an array must be a value between a specific range.
so how efficient are functions like is_int($x) or isset($x) ?
Maybe if($x!=null) is faster or (int) x is causing same results.
What is the best way to handle Data that needs to get to Database quick but needs to be verified? Is there any difference in $_GET and $_POST in speed?
Maybe implementing a class doing that improves something?
Maybe for an more concret chance to answer, here a bit inefficent code:
if(isset($_GET["x"]) && $_GET["x"] > 0) { $x = $_GET["x"]; }
if(isset($_GET["y"]) && $_GET["y"] > 0) { $y = $_GET["y"]; }
if(isset($_GET["winWidth"]) && $_GET["winWidth"] > 0) { $winWidth = $_GET["winWidth"]; }
if(isset($_GET["winHeight"]) && $_GET["winHeight"] > 0) { $winHeight = $_GET["winHeight"]; }
if(isset($_GET["a"])) { $a = $_GET["a"]; }
UPDATE:
What about further security functions like:
mysql_real_escape_string($str);
or
stripslashes()
?
Please Stackoverflow, show me the magic :)
Harry
The fastest way to check if something has been posted and whether it's a positive integer:
if (isset($_POST['field']) && ctype_digit($_POST['field']))
mysql_real_escape_string is incredibly slow, compared to addslashes. However, it's definitely more secure.
However, it's normally not necessary to worry about all this too much. We're talking about billionths of a second here.

Can any one give me some advice to make my for loop more efficient?

So I have this for loop with 36 if-queries inside. Any advice on making it more efficient?
You can view the complete code here
Here's a sample of what it looks like:
$numbers = range(1, 36);
shuffle($numbers);
for ($m =0; $m<37; $m++){
if ($numbers[$m] == "1"){
$mirza[$m] = "RUTHIE";
$mage[$m] = "3";
$mquote[$m] = "I get to learn a lot of new things here, like sign language!";
$link[$m] = "http://www.google.com";
}
if ($numbers[$m] == "2"){
$mirza[$m] = "AIDA";
$mage[$m] = "82";
$mquote[$m] = "This is like a club and I know and like all the members. It's good therapy.";
$link[$m] = "/about/";
}
if ($numbers[$m] == "3"){
$mirza[$m] = "AMIRE";
$mage[$m] = "4";
$mquote[$m] = "I am learning how to share and make friends.";
$link[$m] = "/about/";
}
}
Changing your if-s to a switch with appropriate breaks or even at worse if..elseif..etc would mean that not all ifs have to be evaluated.
When you have this much data it really should be in a database (maybe XML or document style) or a text file.
Still, I'll show you a way to improve this by hard-coding all the data in one place and eliminating the need for any if or switch statements. You should AT VERY LEAST change to switch statements, better still hard-code all the data in one place (below), better still get a database or CSV text file storing these values.
$data = array(
array('mirza' => 'RUTHIE', 'mage' => '3', 'mquote' => 'I get to learn a lot of new things here, like sign language!', 'link' => 'http://www.google.com'),
array(......
);
$numbers = range(1, 36);
shuffle($numbers);
for ($m =0; $m<37; $m++){
$index = $numbers[$m];
$mirza[$m] = $data[$index]['mirza'];
$mage[$m] = $data[$index]['mage'];
$mquote[$m] = $data[$index]['mage'];
$link[$m] = $data[$index]['link'];
}
Just to be clear, the 'efficiency' issue here isn't so much speed (though this way is faster). Its that what you have is a nightmare to maintain and change.
You might do better to seriously reconsider the design of your app, specifically making an object with mirza, mage, mquote, link as fields.
Is your problem that you feel you simply have too many "if" statements? Try a switch statement. Technically speaking, your loop is about as efficient as possible (using big-O method of evaluating efficiency).
for ($m =0; $m<37; $m++){
switch($numbers[$m])
{
case 1:
$mirza[$m] = "RUTHIE";
$mage[$m] = "3";
$mquote[$m] = "I get to learn a lot of new things here, like sign language!";
$link[$m] = "http://www.google.com";
break;
case 2:
$mirza[$m] = "AIDA";
$mage[$m] = "82";
$mquote[$m] = "This is like a club and I know and like all the members. It's good therapy.";
$link[$m] = "/about/";
break;
case 3:
$mirza[$m] = "AMIRE";
$mage[$m] = "4";
$mquote[$m] = "I am learning how to share and make friends.";
$link[$m] = "/about/";
break;
}
}
My guess it's already as fast as you may ever need.
The only way to make it faster is to look at sites benchmarking PHP and to adjust this or that to easy the most efficent PHP internals.
Since PHP internals may change over time (with PHP updates), unless you regulary benchmark your code I'd say you have not that much to gain, especially with code that simple.
For example you may try to change
$numbers[$m] == "2"
with
$numbers[$m] === 2
or
$numbers[$m] === "2"
But if you don't benchmark your code (ex. putting it in a function and measure the execution time over 10.000 iterations) you're gonna be blind about improvements. PHP internals speed don't always behave as you expect it.
(the same goes with the answer you got about the switch statement. Try it, but benchmark !)
My advice is to try to work with data structures, and put all these values in an array of the same type as the data structure. That way, if you later need to access the values again with the same number-to-value relationship, you won't have to redefine everything like you have done here. All you would have to do then is to use array indices to access the values.

Categories