
|
View Full Version : How To : Improve Your PHP Programming
giropets 07-21-2004, 01:29 AM Hello everyone,
I've decided that I would make a thread here describing the different things that I do to improve other people's PHP scripts.
Hope you enjoy it and learn a thing or two.
1 - Your PHP Tags
I know some of you prefer to use the short tags when writing PHP scripts <? ?> but this is not always the best way of doing it.
The standard tags <?php ?> are much better as they will work on every server that you write your PHP code on. You may move to a server some day that doesn't allow the short tags or the ASP-style tags and you will have to sit for an hour and update your PHP scripts.
2 - Debugging Your PHP Code
Some of us may run into a problem when programming a PHP script and don't know what's wrong with it. The error_reporting() function in PHP helps you out by telling every error you have on your page. To show all of the errors on the page that you're editing, put this on the second line :
error_reporting(E_ALL);
3 - Debugging Your PHP Code (again)
When you finish editing your 1200-line PHP script, click onto it in your Internet browser, you see an error that says that is on line 561. Don't hit the panic-attack button quite yet, because there is an easy way to find out what line 561 is. Follow these easy steps :
- Open up Microsoft Notepad
- Paste your PHP script into it
- Go to 'Edit' >> 'Go To...' (or Control+G)
- Type in line #561 and hit the enter key
- Your cursor is taken to line #561.
- Look above and below line #561 to see if there is any kind of trouble.
- Fix the error, re-upload the script to your website, and most likely it will work. If there is another error, repeat the above steps. :)
4 - Using Comments
If you have a 1200-line PHP script, it may be quite hard to figure out what's going on all through-out it. The solution to figure out what you're doing is to add PHP-comments.
PHP-comments are different than the <!-- HTML Comments --> as they are not outputted to the user's page (meaning that they are not even going to see it in the source code).
There are three ways to make comments in PHP :
<?php
// The double-backslash is my personal favorite. I add another set after my code so that it looks even, though it is not necessary. //
# The hash-style comment is another way of making a comment.
/* And, this is the final way of making PHP-comments. You can use
multiple
lines
at a time by using this style. */
?>
You can decorate it however you like, you are the only one who may use them.
5 - Indenting Your PHP Codes
I don't personally like to indent my PHP codes, but it helps when reading it. When I do have to, I use the tab key to accomplish this. Example :
<?php
// Settings //
$var1 = "This";
// Showing Variables //
if($var1 == "This"){
echo"You said This";
}else{
echo"You said That";
}
?>
6 - Improving your PHP-File Includes
I'm sure that most of us on here include a PHP file or two for our layouts. Well, what if your layout file was missing ? Wouldn't that look pretty unprofessional to the people on your website ?
In every PHP-script that I write, I make sure that the file exists before it is even included. Here's an example :
<?php
if(!file_exists("layout.inc.php")){exit("Error : LayOut File Missing");}else{include_once("layout.inc.php");}
?>
I'm sure that a small error message will seem better than half a page that is all messed-up looking.
7 - Your MySQL Queries
Sometimes when you're writing a PHP script that includes connections to your MySQL database, you may run into a few problems. Most everyone that had MySQL problems ran a command like this one :
<?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')");
?>
..and they figure out that it's not inserting into their database. Here's the solution to this :
<?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')") or exit("MySQL Error : " . mysql_error());
?>
8 - Combining Alike If-Then Statements
You may have a register page, and want to make sure that everything has been filled-in. You may use many if-then statements like so :
<?php
if(!$_POST[name]){exit("Sorry, but you did not fill-in all of the requested fields.");}
if(!$_POST[email]){exit("Sorry, but you did not fill-in all of the requested fields.");}
?>
You can combine these two lines into one by joining their if-then statements together :
<?php
if((!$_POST[name]) || (!$_POST[email])){exit("Sorry, but you did not fill-in all of the requested fields.");}
?>
Simply, || is the same thing as OR and && is the same as AND.
9 - Using echo or print ?
Most of you may say 'echo is the same thing as print', in which I agree with you all. The echo command is much faster than the print command, and is one less character to type. :) The echo command came later than the print command (I believe), so you make the judement on which to use.
10 - Printing out a Huge Chunk of HTML at a Time
Well, I'm sure that many of us found a way to get around this, but I'd like to share with you a few of the ways you can do it.
1 - Break off your PHP-code, print the HTML, and start your PHP-code up again. (I don't prefer doing this as it looks pretty unprofessional to me).
2 - Adding backslashes to each HTML tag. (It works, but takes forever to do).
3 - Using the echo/print command, but without having to do much work. (I recommend) :
<?php
// Showing a huge chunk of HTML at a time //
echo<<<END
<font face="Verdana" color="Orange" size="3">Large, Orange Text in Font Size 3</font>
<br><br>
More HTML down here..
<br><br>
<div align="Center">Centered text</div>
END;
?>
Well, I have many other things to tell about sprucing up your PHP-code, but I don't want to bore you.
I hope I've helped.
Best Regards,
- Mike.
MaJiD SaeeD Khan 07-28-2004, 08:03 AM Very nice How To , and its not boring at all..your writing style is very interesting and i hope to have more ideas from your mind in the future. Thanx for sharing these tips.
Kar-aK 07-28-2004, 09:44 AM Ild just like to point out something on the echo and print argument. You say "The echo command is much faster than the print command". I'ld like to point out why.
Print has a return value, echo does not.
Consider:
<?php
if (print('foo')) { print('foo printed'); } // Will be true
if (echo('foo')) { echo('foo printed'); } // Will be false
?>
Evidently print will always return logical true (1), unless there is a serious error with PHP and the string does not print. Obviously PHP uses C prototypes but I will convert them into PHP so we can see what is going on.
<?php
function print($stringToPrint) {
system.out($stringToPrint);
return 1;
}
function echo ($stringToPrint) {
system.out($stringToPrint);
}
?>
Hope that helps clear that up.
- Kar
jasonr33 07-28-2004, 09:50 PM The only things I would point out are:
1. Use variable names that make sense.
a) $string is a string, and $string_array is an array for example. $flag is a flag...
2. Put your code into functions as much as possible, and write your functions so they can be used in multiple projects - try not to write code that is proprietary to the project at hand.
a) save your functions in library files that you can use the 'include' command to call them up again in your projects.
giropets 07-28-2004, 10:44 PM Hello again everyone,
Since all of you thought it was not boring, I've decided that I would add a few more to my list.
11 - Multiple Items in the If-Then Statement
As said in #8, you can combine alike if-then statements into one. This also works...
if($this == "that" && $that == "this"){echo"This and that match";}
But from experience, it is best to assign seperate brackets () around them as it does not confuse the code...
if(($this == "that") && ($that == "this")){echo"This and that match";}
12 - Saving Time with Varibles
When using functions, and you want to include a load of settings, you need to include every single of them at a time, as so...
<?php
$time = date("Y-m-d:H.i.s");
$name = "Mike";
$comment = "Just a simple comment";
function show(){
global $time,$name,$comment;
echo"$time - $name - $comment";
}
show();
?>
..But you can save your time by including only one variable instead of three, as so...
<?php
$_SETTINGS[time] = date("Y-m-d:H.i.s");
$_SETTINGS[name] = "Mike";
$_SETTINGS[comment] = "Just a simple comment";
function show(){
global $_SETTINGS;
echo"$_SETTINGS[time] - $_SETTINGS[name] - $_SETTINGS[comment]";
}
show();
?>
..Even though you'll spend a little more time by typing $_SETTINGS[] or just by copying and pasting it.
13 - Shortening exit(); and die(); Functions
If you want to stop the page load, you can use the exit(); or die(); functions. But, if this is all you want to do, then you can shorten it...
exit();
exit;
die();
die;
14 - More Usage of exit; and die;
If you want to stop the page load and show text, you can do this..
echo"You did not finish all of the required fields.";
exit;
...Or...
exit("You did not finish all of the required fields.");
15 - Using arrays to Store Data
Arrays are used to store temporary data in a PHP code. Here's an example...
<?php
$names = array("Mike","Charlie","Amanda","Caroline");
echo $names[0]; // Outputs 'Mike'
echo $names[1]; // Outputs 'Charlie'
echo $names[2]; // Outputs 'Amanda'
echo $names[3]; // Outputs 'Caroline'
?>
That's all I can really suggest for now, some methods of doing things may work better than others, but you're the one to decide what works best.
Best of luck,
- Mike.
Ferneaux 08-05-2004, 08:43 PM Very nicely done giropets.. *cheers* :D
TonyB 08-05-2004, 09:17 PM That's very nice and informative for anyone specially beginners
Some other stuff to keep your code more clean and manageble would be to keep HTML and PHP completly seperate for the most part seperate files for them. So useing functions to call the html keep it much cleaner or a template system. Obviously functions like jasonr33 said specially for database stuff make it much easier.
Heck I've had the same functions for quite a while the same mysql, template and functions files you'd be surprised how much time is saved when all your php scripts use the same set of functions.
websterworld 08-05-2004, 11:38 PM Originally posted by giropets
3 - Debugging Your PHP Code (again)
When you finish editing your 1200-line PHP script, click onto it in your Internet browser, you see an error that says that is on line 561. Don't hit the panic-attack button quite yet, because there is an easy way to find out what line 561 is. Follow these easy steps :
- Open up Microsoft Notepad
- Paste your PHP script into it
- Go to 'Edit' >> 'Go To...' (or Control+G)
- Type in line #561 and hit the enter key
- Your cursor is taken to line #561.
- Look above and below line #561 to see if there is any kind of trouble.
- Fix the error, re-upload the script to your website, and most likely it will work. If there is another error, repeat the above steps. :)
Best Regards,
- Mike.
Well Mike not a bad how-to, but this part IMHO is very wrong.
I strongly suggest that instead of using plain notepad/wordpad or ms-word to code your scripts you get a proper PHP editor such as PHPcoder or the one by Zend. (which is great, I love it. :P )
it has a ton of time saving advantages such as syntax highlighting and line numbering, 'etc.
Eugene
giropets 08-05-2004, 11:39 PM I think I've figured it out the hard way, but thanks for letting me know as I take interest in it.
brainbrian 08-09-2004, 12:37 PM I have recently begun to comment all my closing tags and that is really helping a lot. Like I did in the last two lines of this dummy code below. If there is a lot of stuff contains in the if tags where the opening and closing tags are far apart it helps to know where one starts and ends, as well as telling if your number of brackets match up.
if ($something == "this") {
for($i=0; $i<10; $i++) {
echo $i;
$double[$i] = $i*2;
} // for
} // if
giropets 08-09-2004, 05:03 PM That's actually not a bad idea, I should try using that from now on. ;)
cblc3kw 08-17-2004, 02:49 PM Yes. For clarity you can even do this for nested statements like
for($i = 0; $i < 10; $i++) {
for( ; ; ) {
break;
} // inner for
} // outer for
jasonyates 08-24-2004, 12:09 PM <?php
if(!file_exists("layout.inc.php")){exit("Error : LayOut File Missing");}else{include_once("layout.inc.php");}
?>
I prefer to use a function to do this, for example...
function includeme ($addr)
{
//Check that file exists
if (! file_exists($addr))
{
exit("Error : '$addr' File Missing");
}
//Include File
include($addr);
}
This would go into your functions file which you include, the only down-side is you cant use the function for including your functions file :p
scuba 08-26-2004, 12:59 PM <?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')") or exit("MySQL Error : " . mysql_error());
?>
One step furter is:
<?php
$sql = "SELECT value FROM table";
$query = mysql_query($sql)
or die("You got the error: " . mysql_error() . "with the query: $sql");
?>
You should never make a variable like $_SETTINGS. The _ is there to show that it is a system (php-specific) variable like $_POST, $_GET and $_SERVER. Rather do $settings then!
<?php
$_SETTINGS[time] = date("Y-m-d:H.i.s");
$_SETTINGS[name] = "Mike";
$_SETTINGS[comment] = "Just a simple comment";
function show(){
global $_SETTINGS;
echo"$_SETTINGS[time] - $_SETTINGS[name] - $_SETTINGS[comment]";
}
show();
?>
giropets 08-26-2004, 04:55 PM Thanks for pointing those out, scuba. :) I should try using the SQL lines you done in my code to help debug even better.
Radchenko 08-27-2004, 10:47 PM Just a quick comment:
'&&' and 'AND' aren't exactly the same, they have different precedence. For example:
<PRE>
<?php
$a = "hello\n";
$b = "goodbye\n";
print "First trial\n";
if (print $a && print $b) {
print "Bad\n";
}
print "\nSecond trial\n";
if (print $a and print $b) {
print "Good\n";
}
?>
</PRE>
Returns the following:
First trial
goodbye
1Bad
Second trial
hello
goodbye
Good
Same with OR and ||
eskuek 09-06-2004, 12:17 PM May i know what PHP can be used for?
How powerful is this language?
Thanks!
giropets 09-06-2004, 01:37 PM Well, PHP can be used for a lot of things on the internet.
I programmed a whole entire site with my friend that was a web game with PHP back-end programming.
It is very powerful - just depending on how you want to use it.
eskuek 09-06-2004, 10:00 PM Wouldn't it be better and easier to make a web game using Flash instead of PHP? If not, what advantages does PHP have over Flash?
giropets 09-06-2004, 10:03 PM GiroPets.net is the web game that I made. It includes a few Flash games as well. I recently sold the site (I should get myself a new screen name for WHT)...
intrin 09-07-2004, 02:40 PM thanks for this post
VertexBilly 09-25-2004, 07:26 PM Thanks to everyone that posted ideas and how-to's on this board.
I have succesffully created a few php programs - but my coding was sloppy and hard to change.
On my next few programs I plan on changing that and this post will definitly help me keep my code clean and concise.
Billy
giropets 09-25-2004, 09:30 PM Originally posted by billy79
Thanks to everyone that posted ideas and how-to's on this board.
I have succesffully created a few php programs - but my coding was sloppy and hard to change.
On my next few programs I plan on changing that and this post will definitly help me keep my code clean and concise.
Billy
I can totally relate to that. I code sloppily too and it's hard for me to tab over...I will have to try starting that habbit too.
mikaelhg 10-05-2004, 08:33 AM Also, read the Open Web Application Security Project guide:
http://www.owasp.org/documentation/guide/guide_about.html
Koobi 11-06-2004, 05:43 PM Just a little something to add:
* switch/case is faster than an if condition
* Type cast any foreach arguments to avoid error messages
<?php
//Assume $someArray is the return value of a function
//and it will only be an array if the function
//was successful
$someArray = (array) $someArray;
foreach($someArray as $eachElement)
{
echo $eachElement . '<hr />';
}
?>
* Commas are apaprently faster than periods when it comes to concatenation
* To view the contents of a variable, you can use print_r() which will print the variable out in a human readable format.
* You can use var_dump() or var_export() to view the values and types of a variable. The latter will show the values in a format that can be used within a PHP script directly (i.e. it wont cause any parse errors)
* When using comparison operators, you can either use == or === The latter will check for the type as well as the value and it is faster.
<?php
$boolTrue = TRUE;
$boolFalse = FALSE;
$intOne = 1;
$intZero = 0;
$intOther = 5;
//This evaulates to true
if($intOne == $boolTrue)
{
echo 'Loose checking';
}
//This is false because one is an
//integer, while the other is a boolean
if($intOne === $boolTrue)
{
echo 'Strict checking';
}
?>
* To iterate through an associative array (eg.: $_GET, $_POST, etc.), you can do this:
<?php
//This snippet will strip any tags off all GET arguments
foreach($_GET as $myKey => $myValue)
{
$_GET[$myKey] = strip_tags($myValue);
}
?>
* If you prepend a function with an AT sign (@), it will not spit out any errors. The same applies to user defined functions.
<?php
//This will output an error if the password is wrong
mysql_connect('localhost', 'username', 'wrongPassword');
//This will not display any error messages
@mysql_connect('localhost', 'username', 'wrongPassword');
//Assuming the method myMethod has an error in it,
//it wont spit out any warnings because of the @ prepend
@$myObj->myMethod($myArgument);
?>
Here is an alternative for including files and checking for errors (versus checking if the file exists first)
Sample code:
if(!@include_once("file.inc")) { echo "There was an error including an important file."; exit(0); }
The @ symbol will supress the error thrown by PHP when the file cannot be included. The ! symbol is used to cause the if statement to be true when the the include_once function is false/fails.
SalehJamal 01-08-2005, 12:28 PM giropets, nicly done but it's :
$_SETTINGS['time'] = date('Y-m-d:H.i.s');
$_SETTINGS['name'] = 'Mike';
$_SETTINGS['comment'] = 'Just a simple comment';
why? because your code will bounce few notices about constants not being found..
and since we came about quotes, I will add:
Using Single Quotes VS. Duoble Quotes
some poeple don't know the difference between single and double quotes..
single quotes are faster than double ones because it wont parse variables while the double quotes will look for variables to parse ..
so if you have only hardcoded text, use single quotes but if you have variables use duoble quotes..
example:
$var = 'value';
echo 'this is $var'; //prints "this is $var"
echo "this is $var"; //prints "this is value"
xNexusx 01-12-2005, 06:40 PM Thanks a bunch giro
error404 01-12-2005, 07:26 PM Not bad. Good pointers, though that include code is really quite unreadable, considering your point about readability later on...
Want to also point out that using globals is generally bad practice. Avoid them if you can. For things like settings, or DB pointers they're fine, but try to avoid using them for data that may change through the script's execution. They're a big pain to debug when you run into problems, and just poor design in general. Also, there's nothing there about OO.
Now, for my own points:
Curly braces are unnecessary if you only need to execute a single statement. You *need* to indent things nicely if you do this though, or it's completely unreadable (note that this applies to for, foreach and while statements as well):
if (!$user->loggedin)
error_message("You aren't logged in! You can't access this page.");
or even:
if (!$user->loggedin) error_message("You aren't logged in! You can't access this page.");
If you need more than one statement to be executed in the conditional, you of course need to use the braces.
Ternary conditionals are handy too. A bit confusing at first, but handy once you learn them. They 'return' a value based on the condition given. Here's a simple example:
echo ($user->is_admin) ? "You're an admin!" : "You're not an admin.";
I find this very useful in form processing code where you might use it to assign default values if the input is invalid:
$params['description'] = (preg_match("/^[A-z0-9]{5,30}$/", $_POST['description'])) ? $_POST['description'] : "Default";
Also keep in mind the difference between require() and include(). Generally, it's a good idea to use require() where the code to be included is absolutely required, as the script will die if it can't be included. For things like authentication code, this is definitely important.
Oh, another thing I see a lot that really is quite pointless. Don't use an if construct where it's not required. Generally this is when returning from a function. Granted, this is much more ambiguous in a loosely typed language, but the point stands. Example:
if ($user->loggedin && $user->is_admin) return true;
else return false;
is equivalent to
return ($user->loggedin && $user->is_admin);
And lastly, try to keep your SQL statements in one place. My personal suggestion is to write a DB abstraction class that contains methods such as insert_user() that completely remove any SQL calls from your program logic. This makes things a lot easier to change in the future (all your SQL code is in one place, and you don't have identical SQL in multiple places that all need to be updated), and if you ever need to switch databases, all of your queries and mysql_* or pg_* calls are centralized and can be easily changed. It also reduces the amount of duplicate code you have, and generally leaves less room for errors in input validation etcetera. If you don't use a DB class, at least store your queries in an associative array somewhere and use sprintf to add the parameters at run time.
That's all I've got for now.
error404 01-12-2005, 08:49 PM Well, since the end of my post was about SQL, it's time to rant about database design. It's not really 'PHP programming' as the title suggests, but beginners almost always are interested in using the two together. Other data storage methods are clumsy and much more difficult to implement.
So, without further ado, my attempt at explaining database normalisation. For those who already understand normal forms, please understand that I'm trying to give practical guidelines, not theoretical strict definitions here.
When you're designing your tables (you ARE designing before you implement, aren't you?), you want to keep things fairly normalised. Now, what exactly does that mean?
First, and most importantly, every column in each table should depend on an individual instance of what that table is describing. For example, if you have a comments table and you want this table to also contain information about the user that posted the comment, say the user's name and tagline, you wouldn't actually store the username and tagline inside the comments table. Since I'm not very eloquent at describing this stuff, here's an example:
CREATE TABLE users (
uid INT NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL,
tagline VARCHAR(64) DEFAULT '',
-- ... rest of the fields here
PRIMARY KEY(uid),
UNIQUE(username)
);
CREATE TABLE comments (
cid INT NOT NULL AUTO_INCREMENT,
uid INT NOT NULL, -- in a proper RDBMS (which MySQL is NOT), you'd reference the users table here as a foreign key)
pid INT NOT NULL, -- ditto
comment_body TEXT,
-- ... more fields
PRIMARY KEY(cid),
INDEX(pid)
);
You can think of this concept as reducing duplication. You're already storing the username in a table, so don't store it again in the comments table, just store a reference to the primary key of the user's table. We'll see how to access this in a single query in a few moments.
On with database normalisation concept #2 - don't store multiple values in a single column:
Let's say you have the users table above, and you decide that you want to store every IP address the user has ever logged in under. Now, a novice developer may think that this data belongs in the users table as well, since it depends directly on the user. They might opt to use a VARCHAR or TEXT field and store the values there in some fashion (separated by a delimiter, or perhaps as a serialized array). This is bad practice and leads to all sorts of issues, and also reduces the flexibility of your database. There are two 'correct' ways to accomplish this sort of one to many relationship. The first, and (IMO) correct way in this case is to create a separate table for IPs:
CREATE TABLE user_ips (
uid INT NOT NULL, -- foreign key
ip VARCHAR(15) NOT NULL,
PRIMARY KEY(uid, ip),
INDEX(ip)
);
This can be easily fetched in any combination...and can also easily achieve the reverse ip->user query that's not possible with the other implementation (as well as other ip-related queries).
Now for another similar example to show the other technique. Let's say you're writing something like a blog, where you might have a number of posts as well as a number of categories, where each post can be in an arbitrary number of categories. For this you're going to want a separate table for both posts and categories, and you'd want to create a third table to map the two together (we'll use the users table from above):
CREATE TABLE posts (
pid INT NOT NULL AUTO_INCREMENT,
uid INT NOT NULL, -- again, foreign key definition would go here
post_content TEXT,
-- more...
PRIMARY KEY(pid),
INDEX(uid)
);
CREATE TABLE categories (
cat_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(64),
-- etc...
PRIMARY KEY(cat_id)
);
CREATE TABLE cat_posts_map (
pid INT NOT NULL, -- FK
cat_id INT NOT NULL, -- FK
INDEX(pid),
INDEX(cat_id)
);
Okay, now you're probably wondering how this makes things *easier* since at first glance, it looks like this is going to force you to do half a dozen queries just to get all the information you need for a single post. It's not quite that bad :P.
First, let's take our most recent example -- getting a single post and the categories it's in. What we need to do is map the three tables (posts, users, categories)...well actually four if we count the mapping table...into a single result table. There are two syntaxes for doing this. I'm only going to cover the conditional one, as I think it's easier to understand. If you want to look into the JOIN syntax, you can find it on the JOIN syntax (http://dev.mysql.com/doc/mysql/en/JOIN.html) page.
Now before we give some examples for this, let's populate our database with some data:
INSERT INTO users (username, tagline) VALUES ('user1', 'im a test user');
INSERT INTO users(username, tagline) VALUES ('user2', 'im another test user');
INSERT INTO posts (uid, post_content) VALUES (1, 'test post');
INSERT INTO posts (uid, post_content) VALUES (1, 'another post');
INSERT INTO categories (name) VALUES ('test_cat');
INSERT INTO categories (name) VALUES ('another_cat');
INSERT INTO cat_posts_map (pid, cat_id) VALUES (1, 1);
INSERT INTO cat_posts_map (pid, cat_id) VALUES (1, 2); -- put post 1 in both categories
INSERT INTO comments (uid, pid, comment_body) VALUES (1, 1, 'comment 1');
INSERT INTO comments (uid, pid, comment_body) VALUES (2, 1, 'comment 2, new user');
Alright, so let's get post id 1, and all of it's associated data:
SELECT posts.*, users.*, categories.* FROM posts, users, categories, cat_posts_map
WHERE
posts.pid = 1 AND
posts.uid = users.uid AND
posts.pid = cat_posts_map.pid AND
cat_posts_map.cat_id = categories.cat_id;
The SQL server will join all of the tables together, and you'll get two rows back - each with identical data except for the data from the categories table:
+-----+-----+--------------+-----+----------+----------------+--------+-------------+
| pid | uid | post_content | uid | username | tagline | cat_id | name |
+-----+-----+--------------+-----+----------+----------------+--------+-------------+
| 1 | 1 | test post | 1 | user1 | im a test user | 1 | test_cat |
| 1 | 1 | test post | 1 | user1 | im a test user | 2 | another_cat |
+-----+-----+--------------+-----+----------+----------------+--------+-------------+
This may seem clumsy, but it allows the reverse mapping (get all posts in a single category) just as easily, by changing only a single condition in the query. You may just want a list of categories for that post as well, this query is simple as well (modify what's being selected to just categories.*, remove the users table from the query entirely).
The query to retrieve all the comments for a post is similar:
SELECT comments.* FROM comments, posts -- we only care about the comment data here
WHERE
posts.pid = 1 AND
comments.pid = posts.pid;
This returns all the comments attached to post 1:
+-----+-----+-----+---------------------+
| cid | uid | pid | comment_body |
+-----+-----+-----+---------------------+
| 1 | 1 | 1 | comment 1 |
| 2 | 2 | 1 | comment 2, new user |
+-----+-----+-----+---------------------+
The one other point I wanted to touch on, which doesn't really need examples, is that your columns should never depend on any external data. An example might be storing year-end totals for different products (with each product on a row) in a different column, with separate columns for each year. That'd require adding a new column every year, and you should never EVER modify the DB schema under normal operation (adding and removing fields is fine, but you shouldn't have to do maintenance of this type on the database). This sort of concept should be represented as two tables. I won't give an example, it's not difficult to figure out.
So I hope I didn't just waste an hour of my day. It's not simple stuff, but if you can grasp the concepts, you'll have an easier time designing databases and queries that are more complicated than a simple row/column relationship.
innova 01-25-2005, 06:03 PM in a proper RDBMS (which MySQL is NOT), you'd reference the users table here as a foreign key)
Tsk..tsk.
Do you have something against using InnoDB tables in mysql?
AdamsMedia 03-22-2005, 01:20 PM Originally posted by giropets
<?php
if(!file_exists("layout.inc.php")){exit("Error : LayOut File Missing");}else{include_once("layout.inc.php");}
?>
I'm sure that a small error message will seem better than half a page that is all messed-up looking.
Well erm, this is a rather masssiiive if, dont you think?
if(!file_exists("layout.inc.php")){exit("Error : LayOut File Missing");}else{include_once("layout.inc.php");}
so instead, use the more compact version..
(!file_exists("layout.inc.php")) ? exit("Error : LayOut File Missing") ? include_once("layout.inc.php");
Thats simply (ifstatment) ? true : false;
7 - Your MySQL Queries
Sometimes when you're writing a PHP script that includes connections to your MySQL database, you may run into a few problems. Most everyone that had MySQL problems ran a command like this one :
<?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')");
?>
..and they figure out that it's not inserting into their database. Here's the solution to this :
<?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')") or exit("MySQL Error : " . mysql_error());
?>
This is incorrect, INSERT INTO table ($keys) VALUES ($values) ... $keys must be ` ` and $values must be ' '.
example, `id`,`name` .
Just wanted to point these out - .. :)
Splamoni
www.imgdoc.net - Free Image and Document Hosting!!
SalehJamal 03-22-2005, 04:28 PM Originally posted by splamoni
so instead, use the more compact version..
(!file_exists("layout.inc.php")) ? exit("Error : LayOut File Missing") ? include_once("layout.inc.php");
Thats simply (ifstatment) ? true : false;
you mean:
(!file_exists('layout.inc.php')) ? exit('Error : LayOut File Missing') : include_once('layout.inc.php');
but I am not sure if this is correct because here is what php manual says:
Because include() and require() are special language constructs, you must enclose them within a statement block if it's inside a conditional block.
Example 11-6. include() and conditional blocks
<?php
// This is WRONG and will not work as desired.
if ($condition)
include $file;
else
include $other;
// This is CORRECT.
if ($condition) {
include $file;
} else {
include $other;
}
?>
you are not enclosing the inculde() in a block, but I am not sure about that...
as for
This is incorrect, INSERT INTO table ($keys) VALUES ($values) ... $keys must be ` ` and $values must be ' '.
example, `id`,`name` .
you are NOT obligated to put field names in back quotes `, it's optional..
AdamsMedia 03-22-2005, 06:00 PM Yea i apologize bout that double ? ,
its (if) ? true : false;
But about the ``, you dont have to put `key` etc, but it is better coding standards, plus i was correcting the original which was ' ' which wouldnt work.
And seeming as this is about improving php coding, the `` 's are better to use.
Thanks anyways,
Splamoni
http://www.imgdoc.net/ - Free Online Image and Document Hosting
giropets 03-22-2005, 06:13 PM Most everyone here can probably agree that I'm not the best programmer around, so thanks for your comments about that.
mfonda 03-23-2005, 12:02 AM I would just like to point out that include|require(_once) are language constructs, so you do not need to use ( ) when using them. Instead, just do require_once 'File.php';
Another comment, unless text needs to be parsed(i.e. has \n or variables etc in it), you should always use ' for enclosing strings, instead of "
Also, it is better to do !isset($_POST['name']) instead of !$_POST[name] (do this for any var, not just $_POST).
Also, someone was using globals above, you should try and avoid using globals, its a horrible practice. Instead, pass the values to the array.
joyfield 04-03-2005, 01:55 PM And when you have a massive load on your server knowing how to optimize your script will be important.
The following link will tell you some teqniues.
http://www.php.lt/benchmark/phpbench.php
JonBlower 07-15-2005, 05:44 PM Originally posted by websterworld
get a proper PHP editor such as PHPcoder or the one by zend . (which is great, I love it. :P )
it has a ton of time saving advantages such as syntax highlighting and line numbering, 'etc.
Eugene
You are talking about Zend Studio, right?
richmex 08-03-2005, 08:44 PM Thanks for sharing the PHP expertise. I'm impressed with how PHP is apparently free and developed by folks all over the world (like Linux). When companies have their own software that they sell us along with their hosting (for example regarding forums or databases), and they charge for bandwidth as well, it's not always easy to view their software "upgrades" with suspicion when bandwidth consumption charges subsequently increase. At least with PHP there doesn't tend to be that potential conflict of interest, it would seem.
Might anyone here care to comment on whether PHPbb would be my best bet for creating a membership database, affordably? I'm hoping to gradually fill it up with over 50,000 members (if not more, ideally), and to have considerable data on each one (that they could include and update, in their own language but more often than not in Spanish). Then when I need to find members with certain characteristics, I can search the database and mass-mail the ones who satisfy the criteria.
Ideally I could offer cookies so that they wouldn't have to log in each time they visit, and so that I could tailor the interface precisely for them and folks of their demographics to make it more interesting (and to streamline communications, requiring as few clicks as possible). I'd like to be able to represent in good conscience that the data's secure, too. Unfortunately I'm not a computer programmer as a specialist, but I know html pretty well. I'm tempted to get a hosting account somewhere and gradually learn the ropes with the assistance of the host, but it may be that PHPbb isn't really the most suitable language and I should know that before selecting a host. Affordability is a significant concern though. Any thoughts, friends?
$_patch 01-04-2006, 01:14 PM sometimes, we need to have some randomized values. I just create my own random function to something like this
toss($from,$to)
inside toss is a code that will generate a random number between $from and $to...
so if i need three values, toss(1,3) will return any value from 1 to 3.
roylow 03-07-2006, 08:23 PM A great and useful "How-to", I learned a number of new things.
Why not collect it all in one file and put a link to it on your web-site.
Then people could get all the goodies without a lot of cutting and pasting.
Aleister 03-18-2006, 09:20 PM I have to agree,... not boring at all!
Nice work!
ottoman 03-30-2006, 03:20 AM Thanks a lot for your tips and tutorial.
I have done simple shop and only one page just not totally functioning.After the checkout.Customers fill the required fields and the last page they will send what they have bought.I have changed it for a now as a formular and it comes to my email but has so much code and &&& symbos etc. Actuall it does not send to customers email too.
Could you please help for rebuilding this order.php . Checkout etc functions but just the last actions for order.php does not function. It does not send the photo etc.what they have .I have made test order and comes 5 pages code to my email.
Greetings
AdamsMedia 03-30-2006, 03:45 AM sometimes, we need to have some randomized values. I just create my own random function to something like this
toss($from,$to)
inside toss is a code that will generate a random number between $from and $to...
so if i need three values, toss(1,3) will return any value from 1 to 3.
does this mean you make a function to randomly return 1 2 or 3?
Haha, you could just use $rand = rand(1, 3);
RACKSET 04-05-2006, 03:47 PM does this mean you make a function to randomly return 1 2 or 3?
Haha, you could just use $rand = rand(1, 3);
Or just $rand = rand(3); :-)
Burhan 04-05-2006, 04:25 PM Okay, maybe I should correct some false statements here.
* Commas are apaprently faster than periods when it comes to concatenation
Commas and periods are two very different things. There is only one concatenation operator for PHP, and that is the period (.).
For example, you cannot do this:
$string = 'foo','bar'; # !!! Syntax error!!
I think where the confusion comes in is when people write code like this:
$string = 'foo';
echo $string,'bar';
The reason the above code doesn't error out is because echo is a language construct that takes arguments as a comma separated list. Perhaps its more clear with this example:
echo ($string,'bar');
Which is equivalent to the one posted above. So please, don't think PHP has two concatenation operators -- it doesn't. There is only one. Also, goes without saying, one is not faster than the other.
* When using comparison operators, you can either use == or === The latter will check for the type as well as the value and it is faster.
=== is not faster than ==. Please, tell me where you found this out :)
* switch/case is faster than an if condition
?? How did you figure this one out?
* Type cast any foreach arguments to avoid error messages
This is very bad advice because it will lead to sloppy programming; mainly because PHP won't complain and will turn anything into an array. Instead, use the tools that are provided to you by PHP, namely is_array() (http://php.net/is-array). Your example can be better written as:
$result = someFunction();
if (is_array($result))
{
foreach($result as $foo => $bar)
{
/* ... */
}
}
* If you prepend a function with an AT sign (@), it will not spit out any errors. The same applies to user defined functions.
This is true, but don't use this as an excuse to avoid checking for errors in your code. In my experience, @ creates more problems then it fixes because people don't know how to use it properly.
I haven't had time to read the rest -- but these stood out.
AdamsMedia 04-05-2006, 06:04 PM Or just $rand = rand(3); :-)
Hehe, nope.
Warning: rand() expects exactly 2 parameters, 1 given in /home/imdsm/public_html/dev/test.php on line 3
You must remember that the way rand works, is it takes a value from between "min" and "max":
int rand ( [int min, int max] )
You can view more information about this at http://uk2.php.net/rand
:)
AdamsMedia 04-05-2006, 06:09 PM This is true, but don't use this as an excuse to avoid checking for errors in your code. In my experience, @ creates more problems then it fixes because people don't know how to use it properly.
I agree with you on the above, but would like to add that @ is supposed to be used for functions which are liable to error when there isn't a bug. For example mysql_num_rows(), on some older php versions, will error if there weren't any rows selected by a query. This is a great example of how to properly use the @ prefix:
<?php
$result = mysql_query("select * from table");
$numrows = @mysql_num_rows($result);
/* or a better way to do this, would be to use type casting. */
$result = mysql_query("select * from table");
$numrows = (int)@mysql_num_rows($result);
/* in this case, if there aren't any rows returned, php wont error but instead return 0 instead of false. */
?>
Hope this is of some use to you.
JeanM 07-02-2006, 09:39 AM A lot has been said, and a lot has been corrected, there are still some small things I'd like to point out tho...
1. Heredoc
<?php
// Showing a huge chunk of HTML at a time //
echo<<<END
<font face="Verdana" color="Orange" size="3">Large, Orange Text in Font Size 3</font>
<br><br>
More HTML down here..
<br><br>
<div align="Center">Centered text</div>
END;
?>
Using the heredoc technique as shown above is best to be avoided. It's a lot slower then going in and out of php tags. The reason for this is that php will ignore parts of the file that are not between php tags and since pure html is of no interrest to php you can skip this and make php parse the page faster.
2. Variables
1. Use variable names that make sense.
a) $string is a string, and $string_array is an array for example. $flag is a flag...
Even better would be to use the following technique to write variables:
// boolean
$bIsActive = FALSE;
$bNeedsRefresh = TRUE;
// integer
$iPhoneNumber = 042323232;
$iRandNum = rand(3,6);
// string
$sErrorMsg = 'This is an error';
$sUserName = 'JeanM';
// query
$qUserInfo = mysql_query("SELECT * FROM user WHERE user = '".$sUserName."'");
// array
$aSmilies = array(':D',':(',':P');
$aUserInfo = mysql_fetch_assoc($qUserInfo);
To sum it up:
1. Use the first letter to tell what kind of variable we are dealing with $un -> $sun
2. Don't use short variables like $sun but instead write full names $sun -> $susername
3. Use a case letter whenever a new word starts, this makes it easier to read: $susername -> $sUserName
This makes coding and using variables A LOT easier and it really isn't more work. Yes you will get longer variables but who cares, what matters most is that you still understand your script 6 months after you first created the script.
3. Quotation
Using Single Quotes VS. Duoble Quotes
some poeple don't know the difference between single and double quotes..
single quotes are faster than double ones because it wont parse variables while the double quotes will look for variables to parse ..
so if you have only hardcoded text, use single quotes but if you have variables use duoble quotes..
example:
$var = 'value';
echo 'this is $var'; //prints "this is $var"
echo "this is $var"; //prints "this is value"
While the comment about single quotes being faster than double quotes is true, it is in general good practice to use only single quotes if possible.
// parsing a string
echo 'using single quotes is faster';
// string with a variable
$sPossible = 'possible';
echo "This would be $sPossible";
$sMuchBetter = 'much better';
echo 'But this would be '.$sMuchBetter;
Not only does this make php again parse the page faster (it doesn't have to check each character between double quotes to see if there is a variable present) but it's also a lot cleaner for yourself. For example, you no longer have to worry about using double quotes inside double quotes and, when using a proper php editor as noted above, it colors the variables in the correct way, if you had the variables between double quotes it would just parse them in red, as shown above.
One thing to watch out for (which as been stated before in this thread) is that using linebreaks like \n or \r is not possible within single quotes, in this case you could to the following:
echo "Text with a line break\n"
But even better would be
echo 'Text with a line break'."\n"
3. queries: ` ` vs ' ' vs .. nothing
This is incorrect, INSERT INTO table ($keys) VALUES ($values) ... $keys must be ` ` and $values must be ' '.
example, `id`,`name` .
It is best practice to never use backquotes but instead use column names that are easy to understand and at the same time arent too "general". the reason backquotes are used is to avoid getting an error when for example using the following query:
mysql_query("SELECT * FROM users ORDER BY order");
This will ouput an error because the column name "order" is reserved by mysql (see: http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html). Using `` allows you to still use these words, but using backquotes in every query you make is just not feasable, just stick to using column names that have a prefix or use names that you are sure of are not used my mysql.
innova 07-02-2006, 04:28 PM JeanM,
I agree with what you said, with one exception. The microsoft-like-way of being annoyingly obnoxious with variable names, table names, query names, etc..
$myhouse = 'nice';
$sMyHouse 'nice';
There is no purpose to this whatsoever.
Similarly, in access (offtopic but I think thats where this mess started), you see things like:
tblPerson
qFindPeople
sString
Its silly. As if I didnt know tblPerson was a table, or that qFindPeople was a query. I think you should give variables / objects / etc sensible names, but prefixing them with characters that are supposed to show their purpose is meaningless, redundant, and obnoxious for the 'rest of us'.
My other comment on HEREDOC... I love HEREDOC, because I dont have to worry about quotation rules. I just punch out what I want to put in.. I use it a lot for queries - I dont use it to output html / text.
JeanM 07-02-2006, 05:23 PM I guess it's a matter of preference, but I think that if you work with scripts that include a douzen pages and thousands of lines it's easy to loose track of what variable does what, and with clear naming and stating the type of variable that becomes more clear. For me the capitalized first letters make it easy to read the variables on a page when scanning trough a script that needs to be altered.
Also the heredoc can indeed be used for that purpose, again it's a matter of preference.
Omega-Mark 08-28-2006, 09:06 AM i use dreamweaver to code my PHP. it has colour highlighting automatic indentation. and has a built in ftp. i always upload my entire site to a test folder before showing it publicly.
jacobsd 08-28-2006, 08:29 PM Very Helpful, Thanks
welshboy 09-16-2006, 03:08 PM thanks for the sweet post, because of this ive realised loads of mistakes in my programming and have sorted them out!! thanks once again
WebGuru72 10-13-2006, 11:21 PM very helpful. Thank you all for all the good tips.
One thing I would like to know though..... with sessionstart, how can I have it where it is not in the first thing in the page, I would like to include it in a header but always got errors. any ideas would be great
CodyRo 10-24-2006, 08:01 PM I think you should mention use of variables, don't declare them unless you're going to use it a few times throughout your script.
Also protecting yourself from SQL injections, when / should you cache your work, memcached (http://www.danga.com/memcached/), etc..
I recommend new coders read these Zend tutorial(s) (http://www.zend.com/zend/tut/tut-hatwar.php) (There are three parts) for a good primer.
Aside from that nice little writeup, easy to read and informative.
Also I would usually use the following for a include.
<?php
include_once('config.php') or die('Error!');
?>
*Note*
Keep in mind the difference between include() (http://php.net/include), include_once() (http://php.net/include_once), require_once() (http://php.net/require_once), etc.
Padrone 05-19-2008, 11:46 AM Very nice, Especially for PHP learners
digitalpioneer 05-23-2008, 02:24 PM Make sure you optimize your database structure and use indexes. Cache data in memory as much as possible, however this would only be useful if you're website is very inversive with queries. If it is an average site then use a opt cacher, such as XCache. Preform a crap load of benchmarks to help you eliminate most of the bottlenecks. Google can find you a lot of good tips.
Explizite 05-24-2008, 05:38 PM Combining lines is not necessarily a good idea. Some people get annoyed reading scripts containing combined lines.
rjd22 05-30-2008, 10:45 AM Programming is all about making your own style. Some people use all the PHP rules others just put something together and don't care. Still nice tutorial for people that just began programming PHP
r0rose 06-15-2008, 04:16 PM I agree, however everyone has their own style of programming.
crosenblum 10-11-2009, 11:16 PM Very nice post, i like how good people are really dedicated to their craft.
Nickos 11-28-2009, 08:22 AM Nice stuff.It's for beginners.
After working hours and hours with programming and php your biggest problem will be some stupid mistake you made :) And you will spend next whole day trying to find out what's wrong, then you will give up.Next day in the morning while you are drinking coffee - bang, you nailed the error.The problem was YOU.It's always your mistake :)
aliceandmosee056 03-29-2010, 07:44 PM Thanks man this tutorial was a little over my head, do you know of any more basic tutorials out there I can start with?
Adrian Andreias 03-29-2010, 08:25 PM Move to Python and Django! Sorry, just joking :).
I think the best advice is to use a PHP Framework, like Zend.
icvdm 07-01-2010, 03:22 PM Frameworks do help a lot. They have power and flexibility. As well as giving you the ability to replicate things fairly easily for additional sites. Zend is a good one.
Aran11 08-03-2010, 03:38 PM 5 - Indenting Your PHP Codes
I don't personally like to indent my PHP codes, but it helps when reading it. When I do have to, I use the tab key to accomplish this. Example :
<?php
// Settings //
$var1 = "This";
// Showing Variables //
if($var1 == "This"){
echo"You said This";
}else{
echo"You said That";
}
?>
I would add that a lot of people I know tend to use line breaks to seperate blocks of code and have all elements within the block all on the same line. I guess thats a matter of preference though. Myself I like both depending on the type of script and what makes it easier and faster to edit / update.
7 - Your MySQL Queries
Sometimes when you're writing a PHP script that includes connections to your MySQL database, you may run into a few problems. Most everyone that had MySQL problems ran a command like this one :
<?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')");
?>
..and they figure out that it's not inserting into their database. Here's the solution to this :
<?php
mysql_query("INSERT INTO tableName ('id','name') VALUES('1','Mike')") or exit("MySQL Error : " . mysql_error());
?>
Another way you can do this is:
<?php
mysql_query("INSERT INTO `tableName` SET `id` = '1', `name` = 'Mike'") or die(mysql_error());
?>
10 - Printing out a Huge Chunk of HTML at a Time
Well, I'm sure that many of us found a way to get around this, but I'd like to share with you a few of the ways you can do it.
1 - Break off your PHP-code, print the HTML, and start your PHP-code up again. (I don't prefer doing this as it looks pretty unprofessional to me).
2 - Adding backslashes to each HTML tag. (It works, but takes forever to do).
3 - Using the echo/print command, but without having to do much work. (I recommend) :
<?php
// Showing a huge chunk of HTML at a time //
echo<<<END
<font face="Verdana" color="Orange" size="3">Large, Orange Text in Font Size 3</font>
<br><br>
More HTML down here..
<br><br>
<div align="Center">Centered text</div>
END;
?>
I have to say this is a great way to do it!
Thanks for sharing, very good yet brief overview!
Offshorehosts 12-07-2010, 09:32 PM wow this was very informative, and bookmarked it for future reference. Nice work on the tutorial man.
proyb 12-12-2010, 12:44 PM Another great tip: always use PDO instead of mysql API, it is much easier to code and safer.
proyb 12-12-2010, 12:47 PM Use HTML Purifier if you want to filter out any XSS, code injection, fixed improper HTML syntax or malicious code. It's so simple to filter out all bad codes with just a line of PHP code.
proyb 12-12-2010, 12:51 PM To save time benchmarking,
http: / / net-beta.net / ubench
Backupteddy 12-17-2010, 12:42 AM Great simple tips that can save you hours of debugging because theres less chance of you missing a microscopic flaw because your code is neat.
rallport 12-18-2010, 09:22 AM Including files in your scripts. Apparently using single quotes and include is faster:
include 'my_file.php';
|