TalkPHP

TalkPHP (http://www.talkphp.com/forums.php)
-   Absolute Beginners (http://www.talkphp.com/absolute-beginners/)
-   -   Optimization of some code! (http://www.talkphp.com/absolute-beginners/4425-optimization-some-code.html)

Sirupsen 05-22-2009 08:35 PM

Optimization of some code!
 
Hellow dear fellow PHP developers.

I have made a simple portfolio, but also "too simple". It's basically only if() statements, and then it does something - which results in high MySQL traffic - and lot's of useless code (I think at least!)

I've now looked around for a couple of hours in search for a function which I could use, to make this script a lot smaller. But, beeing unsure what to do - and everything I tried went very very wrong, I decided to search for help from more experinced people.

My code looks like this..:

PHP Code:

<?                    
$result 
mysql_query("SELECT * FROM Portfolio ORDER BY id DESC");

while(
$row mysql_fetch_array($result)) {
$id $row['id'];
$thumb $row['thumb'];
$p1 $row['p1'];
$p1d $row['p1d'];
$p2 $row['p2'];
$p2d $row['p2d'];
$p3 $row['p3'];
$p3d $row['p3d'];
$p4 $row['p4'];
$p4d $row['p4d'];
$p5 $row['p5'];
$p5d $row['p5d'];
$p6 $row['p6'];
$p6d $row['p6d'];
$p7 $row['p7'];
$p7d $row['p7d'];
$p8 $row['p8'];
$p8d $row['p8d'];
$p9 $row['p9'];
$p9d $row['p9d'];
$p10 $row['p10'];
$p10d $row['p10d'];
$name $row['name'];
$website $row['website'];

echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p1;
echo 
'" class="option" id="thumb" title="';
echo 
$p1d;
echo 
'" ><img src="';
echo 
$thumb;
echo 
'" / class="thumbs"></a> ';

if(
$p2 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p2;
echo 
'" class="hidden" title="';
echo 
$p2d;
echo 
'" ></a>';
}                        
if(
$p3 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p3;
echo 
'" class="hidden" title="';
echo 
$p3d;
echo 
'" ></a>';
}
if(
$p4 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p4;
echo 
'" class="hidden" title="';
echo 
$p4d;
echo 
'" ></a>';
}
if(
$p5 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p5;
echo 
'" class="hidden" title="';
echo 
$p5d;
echo 
'" ></a>';
}
if(
$p6 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p6;
echo 
'" class="hidden" title="';
echo 
$p6d;
echo 
'" ></a>';
}
if(
$p7 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p7;
echo 
'" class="hidden" title="';
echo 
$p7d;
echo 
'" ></a>';
}
if(
$p8 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p8;
echo 
'" class="hidden" title="';
echo 
$p8d;
echo 
'" ></a>';
}
if(
$p9 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p9;
echo 
'" class="hidden" title="';
echo 
$p9d;
echo 
'" ></a>';
}
if(
$p10 >= "1") {
echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p10;
echo 
'" class="hidden" title="';
echo 
$p10d;
echo 
'" ></a>';
}                                                                     
}
                                     
?>

I'm super emberassed with this code, but as I said - also very unsure how I would do this with a while, do, for, foreach function? Can anyone show me? That would lead me a long way!

allworknoplay 05-22-2009 08:51 PM

I've read somewhere that using SELECT * FROM causes too much CPU usage, so even if it is a pain, I suppose you can make a SELECT call on each column, this way mysql doesn't have to think.

You can probably get away with using mysql_fetch_assoc($result) instead of array, I don't know if it's true, but I heard it was a little faster too...

Also, to replace the if's, you can use switch, it is faster.

Sirupsen 05-22-2009 09:14 PM

Any chance you can show me a small bunch of code with what you exactly mean? :)

allworknoplay 05-22-2009 09:29 PM

Quote:

Originally Posted by Sirupsen (Post 24579)
Any chance you can show me a small bunch of code with what you exactly mean? :)

Sure, here's a snippet, you should be able to figure out the rest based on the pattern..

PHP Code:

<?                    
$result 
mysql_query("SELECT id,thumb,p1,p1d,p2,p2d FROM Portfolio ORDER BY id DESC");

while(
$row mysql_fetch_assoc($result)) {
$id $row['id'];
$thumb $row['thumb'];
$p1 $row['p1'];
$p1d $row['p1d'];
$p2 $row['p2'];
$p2d $row['p2d'];

echo 
'<a rel="shadowbox[';
echo 
$p1;
echo 
'];" href="';
echo 
$p1;
echo 
'" class="option" id="thumb" title="';
echo 
$p1d;
echo 
'" ><img src="';
echo 
$thumb;
echo 
'" / class="thumbs"></a> ';


I'll take a look at your IF statements, a lot is redundant...

sketchMedia 05-22-2009 09:34 PM

Quote:

I've read somewhere that using SELECT * FROM causes too much CPU usage, so even if it is a pain, I suppose you can make a SELECT call on each column, this way mysql doesn't have to think.
Indeed! You should always be careful when using SELECT *.

You need to ask yourself: Do I need all of the columns? more than likely not.

The reason you need to be wary is that getting MySQL to retrieve data it doesn't need is a waste of resources better used elswhere. This waste adds disk I/O, memory and CPU overheads where they are simply not needed, not to mention network overhead and also potentially b0rking up covering indexes (if there are any).

Quote:

You can probably get away with using mysql_fetch_assoc($result) instead of array, I don't know if it's true, but I heard it was a little faster too...
This may be true (haven't tested it) because mysql_fetch_array by default will return both numeric AND associative arrays for the result (unless you pass in the 2nd param), where as mysql_fetch_assoc will only return an associative array.

Quote:

Also, to replace the if's, you can use switch, it is faster.
Whilst I do believe this to be true (it also adds a heap of readability to long conditional statements), this post suggests otherwise: http://www.fluffycat.com/PHP-Design-...-if-VS-switch/

N.B read the comments, its quite intriguing, I'll have to run my own benchmarks.

This brings me nicely to my next point, if a script needs so many if/else's there must be an easier way to do it.

allworknoplay 05-22-2009 09:41 PM

Quote:

Originally Posted by sketchMedia (Post 24582)

This brings me nicely to my next point, if a script needs so many if/else's there must be an easier way to do it.

Agreed. Looking over his IF conditionals, I thought it might be easier to consolidate them but in each one he echo's out a $p1 variable as well as the variable that is related to the IF test itself.

It kinda looks like a pagination script....

allworknoplay 05-22-2009 09:47 PM

I'm also curious what all the p1, p2,p3 is all about...pages?

Sirupsen 05-22-2009 09:47 PM

Cool.

To clear up, this is for a mini-portfolio - so it adds more pictures (the $p1 = picture one url, $p1d = picture one description) - if I choose so from my Admin panel. Which is why I have all the if()'s, so that if those rows are empty, it should not add an empty picture, but just skip that line of code and do NOTHING. :D - but if the row is filled with an url, it should print out the picture to the gallery.

It's in action here.

Sorry if the explanation is messy, just ask if I need to clear something up. :) Cheers

CoryMathews 05-22-2009 09:53 PM

I could not find where you were using $id, $name and $website.

You should change the Selet * to Select col1, col2... however for most smaller sites it really does not matter unless you have a ton of extra columns. There is no need for the extra variables, and a switch would probably be better but it really does not matter on that either. You only need 1 echo to print all the junk instead of the multiples. so something like this would be a bit better.

PHP Code:

<?                    
$result 
mysql_query("SELECT * FROM Portfolio ORDER BY id DESC");

while(
$row mysql_fetch_array($result)) {
$id $row['id'];
$name $row['name'];
$website $row['website'];

echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p1'].'"   class="option" id="thumb" title="'.$row['p1d'].'" ><img src="'.$row['thumb'].'" / class="thumbs"></a> ';

if(
$row['p2'] >= "1")
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p2'].'" class="hidden" title="'.$row['p2d'].'" ></a>';

if(
$row['p3'] >= "1"
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p3'].'" class="hidden" title="'.$row['p3d'].'" ></a>';

if(
$row['p4'] >= "1"
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p4'].'" class="hidden" title="'.$row['p4d'].'" ></a>';

if(
$row['p5'] >= "1"
  echo 
'<a rel="sxadowbox['.$row['p1'].'];" href="'.$row['p5'].'" class="hidden" title="'.$row['p5d'].'" ></a>';

if(
$row['p6'] >= "1"
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p6'].'" class="hidden" title="'.$row['p6d'].'" ></a>';

if(
$row['p7'] >= "1"
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p7'].'" class="hidden" title="'.$row['p7d'].'" ></a>';

if(
$row['p8'] >= "1"
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p8'].'" class="hidden" title="'.$row['p8d'].'" ></a>';

if(
$row['p9'] >= "1")
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p9'].'" class="hidden" title="'.$row['p9d'].'" ></a>';

if(
$row['p10'] >= "1")
  echo 
'<a rel="shadowbox['.$row['p1'].'];" href="'.$row['p10'].'" class="hidden" title="'.$row['p10d'].'" ></a>';                                                                   

}

?>


allworknoplay 05-22-2009 09:55 PM

Quote:

Originally Posted by Sirupsen (Post 24587)
Cool.

To clear up, this is for a mini-portfolio - so it adds more pictures (the $p1 = picture one url, $p1d = picture one description) - if I choose so from my Admin panel. Which is why I have all the if()'s, so that if those rows are empty, it should not add an empty picture, but just skip that line of code and do NOTHING. :D - but if the row is filled with an url, it should print out the picture to the gallery.

It's in action here.

Sorry if the explanation is messy, just ask if I need to clear something up. :) Cheers

I see, I don't think that is the correct DB structure then.

You are basically creating a unique column for each unique type of picture. You should only have 2 columns.

I mean, if you have 1000 pictures, you can't seriously think about having 1000 columns?

There's a limit for columns for mysql tables that in it itself!

Sirupsen 05-22-2009 09:57 PM

How would I do that then Allwork? I suppose their gonna be seperated by a space or something, but how am I gonna sort those out for good? :)
That really sounds like the stuff I'm looking for!

CoryMathews, thanks for your clearing up! Let's see how this ends up :))

allworknoplay 05-22-2009 10:07 PM

Quote:

Originally Posted by Sirupsen (Post 24591)
How would I do that then Allwork? I suppose their gonna be seperated by a space or something, but how am I gonna sort those out for good? :)
That really sounds like the stuff I'm looking for!

CoryMathews, thanks for your clearing up! Let's see how this ends up :))

I'll use Corey's example.

$id = $row['id'];
$name = $row['name'];
$website = $row['website'];

So your table now has just 3 columns.

Each portfolio/picture gets a new row. Not new column.

That way as you loop through the rows, you can base your conditionals on the values you get from the rows, not going through each column and doing IF conditionals..

Back to what Sketch said, "if you're using so many if conditionals, there's gotta be a better way to do it" or something like that...

In this case, it's redesigning your DB structure......

Sirupsen 05-22-2009 10:27 PM

Alright, I get the idea of this!
I suppose I'm gonna do somehting like 5 fields:
1. ID
2. Thumb [0 if this is not the thumb, 1 if this is the thumb]
3. Picture [The picture url, left blank if Thumb == 0]
4. Picture Description [Will be what's in the <a title='' /> in the Thumb]
5. Bound To [The gallery the pictures are bound to, the ID of the thumb]
In the PHP I will only have 2 IF's

Quote:

if [thumb == 1] [
Make a Thumbail, which creates a gallery that pictures can bind to.
]

if [thumb == 0] [
Links those images to the Thumbail that it's [bound to] in the MySQL
]

allworknoplay 05-22-2009 11:08 PM

Quote:

Originally Posted by Sirupsen (Post 24596)
Alright, I get the idea of this!
I suppose I'm gonna do somehting like 5 fields:
1. ID
2. Thumb [0 if this is not the thumb, 1 if this is the thumb]
3. Picture [The picture url, left blank if Thumb == 0]
4. Picture Description [Will be what's in the <a title='' /> in the Thumb]
5. Bound To [The gallery the pictures are bound to, the ID of the thumb]
In the PHP I will only have 2 IF's


Yup, you can make the thumb column of bool type since it's just going to be either 0 or 1.

sketchMedia 05-23-2009 02:47 AM

Quote:

Back to what Sketch said, "if you're using so many if conditionals, there's gotta be a better way to do it" or something like that...
Yep, its a rule I personally stick too. If something turns out fabulously long winded, there is obviously a problem in the design. In those cases, a rethink and a re-factor are in order.

Quote:

1. ID
2. Thumb [0 if this is not the thumb, 1 if this is the thumb]
3. Picture [The picture url, left blank if Thumb == 0]
4. Picture Description [Will be what's in the <a title='' /> in the Thumb]
5. Bound To [The gallery the pictures are bound to, the ID of the thumb]
Do you need the thumb in the DB? I think we can leave PHP out of the processing of this (i.e. serving thumbs or full pictures and all the logic the accompanies it).

Easiest solution (bearing in mind, i quickly hack this together):

Have 2 pictures (I'm assuming you have a full and a thumb of each), name them <picturename>.gif and thumb_<picturename>.gif (or whatever).

Now all we do is prefix 'thumb' to the image to get the thumb:
PHP Code:

 <img src="thumb_<?php echo $row['image']?>.gif" />

And for the full size:
PHP Code:

 <img src="<?php echo $row['image']?>.gif" />

Now there is no need for more DB columns.


With a DB structure like this:
sql Code:
CREATE TABLE `portfolio` (
  `id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
  `image` VARCHAR(25)  NOT NULL,
  `description` VARCHAR(50)  NOT NULL,
  PRIMARY KEY (`id`)
)
ENGINE = MyISAM
CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Test data:
sql Code:
INSERT INTO `portfolio` VALUES (1,'test2.png','This is a test, test number two to be exact!'),(2,'test1.gif','This is a test, test number one to be exact!');

We could crudely output it thus:
PHP Code:

<div id="portfolio">
<h2>Portfolio</h2>
<?php while($row mysql_fetch_assoc($result)):?>
    <a href="<?php echo $row['image']?>">
        <img src="thumb_<?php echo $row['image']?>" />
    </a>
    <p>
        <?php echo $row['description']?>
    </p>
<?php endwhile;?>
</div>

That what you were after?

Sirupsen 05-23-2009 07:32 AM

Sketch, cool idea! I'm gonna work on it in a few minutes. :) I'm very happy for everyones help!

Sirupsen 05-23-2009 08:46 AM

Alright, here is how it all ended up..

I felt like I needed to create a Thumb BOOL, as I have > 1 pictures in one gallery, which are invisible on the page before the thumb is opened, and you can browse them in the Thumbail.


After that, I began the coding part. I realised the hard part was to tell the image which "hidden gallery" it was in, so I decided to use functions, to check that - my first use of functions effectively!

Here's how it all ended up:
PHP Code:

<?                    
                            $result 
mysql_query("SELECT * FROM Portfolio");
                            
                                while(
$row mysql_fetch_array($result)) {
                                
                                        if(
$row['thumb'] == '1') {
                                        
                                            function 
boundToMe($id) {
                                                
$res mysql_query("SELECT * FROM Portfolio WHERE boundTo = '$id' ORDER BY id ASC LIMIT 0,1");                        
                                                while(
$func mysql_fetch_array($res)) {
                                                            echo 
$func['picture'];
                                                }
                                            }
                                            
                                            echo 
'<a rel="shadowbox['.$row['id'].'];" href="';
                                            
boundToMe("".$row['id']."");
                                            echo 
'"   class="option" id="thumb" title="'.$row['pictureDesc'].'" ><img src="'.$row['picture'].'" / class="thumbs"></a> ';
                                        } else {
                                        
                                        function 
WhoAmIBoundTo($bound) {
                                                
$res mysql_query("SELECT * FROM Portfolio WHERE id = '$bound' ORDER BY id ASC LIMIT 0,1");                        
                                                while(
$func mysql_fetch_array($res)) {
                                                            echo 
$func['id'];
                                                }
                                            }
                                            
                                             echo 
'<a rel="shadowbox[';
                                             
WhoAmIBoundTo("".$row['boundTo']."");
                                             echo 
'];" href="'.$row['picture'].'" class="hidden" title="'.$row['pictureDesc'].'" ></a>'
                                        
                                        }
                                    }
                        
?>

I got one question though..!
How do I just make the echo's one long line, with the functions in? I couldn't manage to do that! Like this:

PHP Code:

echo '<a rel="shadowbox[WhoAmIBoundTo("".$row['boundTo']."")']" href="'.$row['picture'].'" class="hidden" title="'.$row['pictureDesc'].'" ></a>'; 

Edit: Fuck, for some reason it bugs when there's > 1 image bound to the thumb.
Edit2: It seems like that the HTML just stops after this PHP, even though theres around 100 lines more HTML. Anyone got an idea of what's going on?! :O
Edit3: It gotta be in the else{ ], since it only runs one of those, and is supposed to do 3 with my current database.
Edit4:
It looks like this when I view the HTML source on my page:
PHP Code:

<a rel="shadowbox[1];" href="http://www.sirup.netau.net/2009-05-21_0944.png" class="option" id="thumb" title="Thumbail!" ><img src="http://www.sirup.netau.net/2009-05-21_1006.png" / class="thumbs"></a

<
a rel="shadowbox[1];" href="http://www.sirup.netau.net/2009-05-21_0944.png" class="hidden" title="Description lalala" ></a

So we can see it does only run the else { } one time, but it should run it two times:

Edit5:
It's fixed! I just cleaned up the code on the couch watching a movie! Macbook ftw.
PHP Code:

<?                    
                $result 
mysql_query("SELECT * FROM Portfolio");
                                    
                    function 
boundToMe($id) {
                        
$res mysql_query("SELECT * FROM Portfolio WHERE boundTo = '$id' ORDER BY id ASC LIMIT 0,1");                        
                        while(
$func mysql_fetch_array($res)) {
                            echo 
$func['picture'];
                        }
                    }
                    
                    function 
WhoAmIBoundTo($bound) {
                        
$res mysql_query("SELECT * FROM Portfolio WHERE id = '$bound' ORDER BY id ASC LIMIT 0,1");                        
                        while(
$func mysql_fetch_array($res)) {
                                    echo 
$func['id'];
                        }
                    }
                            
                while(
$row mysql_fetch_array($result)) {
    
                    if(
$row['thumb'] == '1') {
                                                                        
                        echo 
'<a rel="shadowbox['.$row['id'].'];" href="';
                        
boundToMe("".$row['id']."");
                        echo 
'" class="option" id="thumb" title="'.$row['pictureDesc'].'" ><img src="'.$row['picture'].'" / class="thumbs"></a> ';
                        
                    } else {
                                                                                    
                        echo 
'<a rel="shadowbox[';
                        
WhoAmIBoundTo("".$row['boundTo']."");
                        echo 
'];" href="'.$row['picture'].'" class="hidden" title="'.$row['pictureDesc'].'" ></a>'
                                        
                    }
                }
?>

It seems to work fine! Haven't tested it with more thumbs yet though. :(
I'm just gonna clean up the rest of the code first.
Edit6: Worked great.

Wildhoney 05-23-2009 02:44 PM

You should really try and use sprintf when you have such complex lines of echoes! Otherwise you do often find you create a pretty mess.

php Code:
printf
(
    '<a rel="shadowbox[%s]" href="%s" class="hidden" title="%s"',
    WhoAmIBoundTo($row['boundTo']), $row['picture'], $row['pictureDesc']
);

Sirupsen 05-23-2009 09:43 PM

As I'm currently learning about classes, it'd be super cool if someone had somne time on their hands to make my code to a class, and how to use that class so I get the same output!

I'm referring to this code..:

PHP Code:

                <?                    
                $result 
mysql_query("SELECT * FROM Portfolio");
                    
                    function 
WhoAmIBoundTo($bound) {
                        
$res mysql_query("SELECT * FROM Portfolio WHERE id = '$bound' ORDER BY id ASC LIMIT 0,1");                        
                        while(
$func mysql_fetch_array($res)) {
                                    echo 
$func['id'];
                        }
                    }
                            
                while (
$row mysql_fetch_array($result)) {
    
                    if (
$row['thumb'] == '1') {
                        
                        echo 
'<a rel="shadowbox['.$row['id'].'];" href="'.$row['thumbMax'].'" class="option thumb" title="'.$row['pictureDesc'].'"><img src="'.$row['picture'].'" class="thumbs" alt=""/></a> ';
                    
                    } else {
                                                                                
                        echo 
'<a rel="shadowbox[';
                        
WhoAmIBoundTo("".$row['boundTo']."");
                        echo 
'];" href="'.$row['picture'].'" class="hidden" title="'.$row['pictureDesc'].'"></a>'
                                        
                    }
                }
                
?>



All times are GMT. The time now is 09:47 AM.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0