August 20, 2008, 09:34:17 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
Pages: [1]
  Print  
Author Topic: PHP Tips and Tricks  (Read 147 times)
SouthDreamZ
Administrator
Newbie
*****
Posts: 39


View Profile
« on: April 18, 2008, 08:12:15 PM »

These are some common PHP and MySQL coding tips.
I believe these are good do's and don'ts, that most experienced coders
would agree with, and not just my opinions.

Note: in my examples, I'm using the new arrays ($_GET/$_POST/$_COOKIE/
$_SERVER) because I'm assuming that you're using at least PHP 4.1.0.
If you have an older version, then use the old, longer arrays
($HTTP_GET_VARS/$HTTP_POST_VARS/$HTTP_COOKIE_VARS/$HTTP_SERVER_VARS).
But you should upgrade because of the file-upload vulnerability in
unpatched versions prior to 4.1.2. That's a tip by itself!

PHP

register_globals
First and foremost, I believe, is the use of register_globals. For
those of you who don't know, register_globals allows you to access
variables from forms and URLs (such as file.php?var=foo) as $var in
your script -- "magically" created global variables.

Unfortunately, this old method continues to be used in most tutorials/
examples.  The PHP developers seem to have realized that
register_globals was a bad idea, though. They discuss Using Register
Globals in the PHP manual and recommend turning them off in php.ini:
Quote:

Note that register_globals is going to be deprecated (i.e., turned off
by default) in the next version of PHP, because it often leads to
security bugs.
...
You should do your best to write your scripts so that they do not
require register_globals to be on

In fact, as of PHP 4.2.0, register_globals is now off by default on
new PHP installations. By writing code that relies on register_globals
being on, you risk having that code not work on some systems! Wouldn't
you rather use the preferred method of accessing variables and have
your code work on all PHP installations?

The proper way to access these variables is via their respective
arrays. So instead of $var, in the above example, you should use
$_GET['var']. Similarly, use $_SERVER['HTTP_USER_AGENT'] instead of
just $HTTP_USER_AGENT.

The main arrays are $_GET, $_POST, $_COOKIE, and $_SERVER, depending
on where the variable came from, obviously. You can read more about
them, and a couple of others, here and here in the manual.

Please access your variables via these arrays!

magic_quotes, addslashes(), and stripslashes()
magic_quotes_gpc, when on, automatically adds slashes to all GET/POST/
COOKIE data so that you don't need to use addslashes() before using
GET/POST/COOKIE data in MySQL queries, etc. (e.g. with
magic_quotes_gpc OR addslashes(), I'm becomes I\\'m). Well,
magic_quotes_gpc is no convenience and just complicates things!

Since magic_quotes_gpc can be on or off, you don't know whether to use
addslashes() or not. You don't want to use addslashes() when
magic_quotes_gpc is on because you'll add too many slashes (e.g. I'm
becomes I\\\\'m), which is bad. Use addslashes() if magic_quotes_gpc
is off, and don't if it's on (you can find out its setting with
get_magic_quotes_gpc()). But you can't use the same code all the time.
One workaround is something such as:

if (!get_magic_quotes_gpc()) { $txt = addslashes($txt); }
Things are further complicated if you want to first manipulate text
that has had magic_quotes_gpc applied. You then have some text that
has slashes added and some that doesn't. The effect of this is: some
text will be wrong whether you use addslashes() or not.

It's easiest to turn off magic_quotes_gpc, which I recommend, and use
addslashes() manually all the time and not worry about the wrong
amount of slashes. This is what it says in the recommended php.ini:
Quote:

magic_quotes_gpc = Off

Input data is no longer escaped with slashes so that it can be sent
into SQL databases without further manipulation. Instead, you should
use the function addslashes() on each input element you wish to send
to a database.

As I said above, if you use addslashes() when magic_quotes_gpc is on,
too many slashes will be added. For inserting I'm into MySQL, you want
it to be I\\'m (and it will come out as I'm). Using addslashes() with
magic_quotes_gpc, however, will give you I\\\\'m. THAT will come out
of MySQL as I\\'m, which is not the original text. Most people assume
that you are supposed to use stripslashes() when retrieving data from
MySQL because otherwise they have slashes in their text. But that's
fixing a problem that should never have occurred. If you have to use
stripslashes() on text from your database, it's because you added too
many slashes when you inserted it. You should never have to use
stripslashes() on text from your database. If you do, you need to fix
the problem at the source, rather than after the fact.

You can turn off magic_quotes_gpc in php.ini or like this in
a .htaccess file:
Code: [Select]
<IfModule mod_php4.c> php_flag magic_quotes_gpc off </IfModule>
If that's not possible, you can put the following code at the top of
all your files (in a require or include). It will strip the slashes
that magic_quotes_gpc added, virtually turning it off.
Code: [Select]
function strip_magic_quotes($arr)
{
foreach ($arr as $k => $v)
{
  if (is_array($v))
   { $arr[$k] = strip_magic_quotes($v); }
  else
   { $arr[$k] = stripslashes($v); }

}

return $arr;

}

if (get_magic_quotes_gpc())
{
if (!empty($_GET))    { $_GET    = strip_magic_quotes($_GET);    }
if (!empty($_POST))   { $_POST   = strip_magic_quotes($_POST);   }
if (!empty($_COOKIE)) { $_COOKIE = strip_magic_quotes($_COOKIE); }

}
ereg vs preg
When it comes to the regular expression functions, ereg* and preg*,
the preg functions are the clear choice. The preg functions are
generally twice as fast as their ereg counterpart. They also support
more advanced regular expression operations. I can't think of any
reason why you would need to use the ereg functions.

preg manual page and pattern syntax (long and confusing but pretty
good).

PHP tags
I recommend always using the full PHP open tag, <?php, rather than the
short one, <?. This means also that instead of <?=$var?>, it's better
to use the full <?php echo $var?>. Using the full open tag ensures
that your code will work on all PHP installations, regardless of the
short_open_tag setting.

Alternative control structure syntax
I highly recommend staying away from the if (): ... endif; style
syntax and sticking with curly braces, if () { ... }. This is the
preferred syntax and it makes your code easier to read.

error_reporting
You should probably test your code with error_reporting set to at
least E_ALL & ~E_NOTICE (all errors except notices) so that you aren't
suppressing errors that should be fixed. error_reporting can be set in
php.ini or with the error_reporting() function.

Line breaks
People want to know how they can retain textarea line breaks in HTML.
You should store text in the database in its original format (e.g.
with just newlines) and then use nl2br() to convert newlines to HTML
<br /> tags on display. That's all good, except for one problem with
nl2br(): it doesn't seem to convert \r newlines (edit: this has now
been fixed in PHP 4.2.0).

Windows uses \r\n newlines; *nix uses \n; Mac uses \r.

nl2br() works correctly on text from Windows/*nix because they contain
\n. However, if you get text from a Mac, nl2br() will not convert its
newlines (again, fixed in PHP 4.2.0). To remedy this, I use the
following bit of code to convert \r\n or \r to \n before inserting it
into the database. It won't hurt anything and ensures that nl2br()
will work on the \n only newlines on display. Also, it has the side
effect of saving 1 byte in the database per newline from Windows (by
storing only \n instead of \r\n).
Code: [Select]
$txt = preg_replace('/\r\n|\r/', "\n", $txt);
Strings
1) As a finesse thing, I use single quotes around strings whenever
possible (e.g. strings that don't contain variables, single quotes,
\n, etc.). This is supposed to make less work for the PHP parser.

2) When an array variable isn't in a string, put quotes around string-
literal keys so they are not regarded as constants:
Code: [Select]
// OK
echo $row[$key];

// Wrong, unless key is a constant
echo $row[key];

// Right
echo $row['key'];

// OK, since it's in a string
echo "Text: $row[key]";
3) Remember, you can break out of PHP mode for large sections of HTML.
This is faster than echo'ing and you don't need to escape quotes.

Quotes around numeric data in queries
For numeric columns in MySQL, you shouldn't put quotes around any of
their values in queries. As our resident database guru, MattR, says,
"that is very non-standard and will only work on MySQL." But if it's
unknown data, how do you know that it's numeric and not letters that
will cause an error? You can make sure that only a number is used in
the query by first type-casting the data as int (or float for decimal
numbers):
Code: [Select]
// If id is being passed in the URL
$id = (int) $_GET['id'];

$r = mysql_query("SELECT * FROM table WHERE id=$id");
Then even if id is set to "abc," the worst that can happen is a 0 will
be used in the query. No quotes; no error.

MySQL

Column types and attributes
1) Be familiar with MySQL's column types along with their ranges/
lengths. You should use the smallest column type that will hold the
data that you expect to store. Most of the time, you probably don't
need INT, because MEDIUMINT, SMALLINT, or TINYINT have enough range.
Using a smaller type saves space and speeds things up.

2) Declare all of your columns NOT NULL unless you need to store NULL
values (NULL is not the same as 0 or the empty string). If you need to
store NULL, you'll know. Again, NOT NULL saves space and speeds things
up.

3) Making INT-family columns UNSIGNED will effectively double the
positive range with the same storage requirement. For example,
TINYINT's highest value is 127. TINYINT UNSIGNED's highest value is
255.

Indexes and optimization
1) First, I sometimes see people create tables like this:
Code: [Select]
CREATE TABLE table (

 id INT UNSIGNED NOT NULL AUTO_INCREMENT,

 .....

 KEY (id),

 UNIQUE (id),

 PRIMARY KEY (id)

 )
Do not make a column KEY, UNIQUE, and PRIMARY KEY. In this case, KEY
and UNIQUE don't help anything. The PRIMARY KEY is a key and it is
unique. By specifying 3 indexes, it wastes space and slows down write
operations.

2) Indexes/keys are the key (no pun intended) to fast queries
(especially joins). The 3 types of indexes are PRIMARY, UNIQUE, and
KEY/INDEX (same thing). It's hard to explain when and how to use
indexes, so I'll just point you to some relevant pages in the MySQL
manual: Speed of SELECT queries and How MySQL uses indexes.

3) When you have your indexes setup, use EXPLAIN on SELECT queries to
make sure your indexes are actually being used.
Tags:
Pages: [1]
  Print