PHP Tips, Tricks, & Explanations
This thread is aimed at creating small, quick, and useful PHP code snippets, and to explain how others work. Also, this thread is not aimed at PHP beginners, it is assumed that you remotely known how the language works and what it can do.
Post your own guides / code snippets / explanations below!
Changelog:
Version 1: Sat 6 Aug
Version 2: Sun 7 Aug
*Added Scope, XSS, SQL Injection, and Form Validation write-ups
Version 3: Thurs, 10 Nov
*Added XSS Attacking video
===Explanations===
Understanding Try / Catch:
Try & Catch are known as
Exceptions to the PHP community. In a nutshell, Try & Catch are used as a simple way to use custom errors in PHP. Here is an example:
PHP Code:
//Our function, which throws an error if the given variable is not numeric (a number)
function my_function($variable) {
if (!is_numeric($variable)) {
throw new Exception(" \"<i>$variable</i>\" returned this error because it is not numeric! ");
}
}
//Now we use our function with some different values. One is a number, and one isn't. Just stick all your function calls inside a 'try' to catch errors you define.
try {
echo my_function(1); //1 is numeric
echo my_function("This is a string!"); //This is not numeric
}
//'Catch' the error, so it doesn't go unnoticed
catch (Exception $my_exception) {
$exception_info = $my_exception->getTrace(); //Load some useful information into our $exception_info array
echo $exception_info[0]['function'] . " was the function where the error occured. <br/>"; //Function that returned the error
echo $my_exception->getMessage(); //Message that was returned
}
Double vs Triple Equals (== vs ===)
I have made a
video explaining this here.
The == and === operators don't seem to make any difference; in fact, you might not have even heard of the triple-equals (===) operator. Here's a quick demonstration:
PHP Code:
$var1 = "1";
$var2 = 1;
//So here we have 2 variables; both are different forms of 1. If we use the following code:
if ($var1==$var2) {echo "Double Equals returned they are the same!";}
else {echo "Double Equals said they are different!";}
//...But that's incorrect. "1" and 1 are not equal. One is a string, while the other is an integer. Let's try the same code with a Triple Equals.
echo "<br />"; //Spacing
if ($var1===$var2) {echo "Triple Equals returned they are the same!";}
else {echo "Triple Equals said they are different!";}
//Now it says they're different, which is correct. What Double Equals basically does is translate all the parameters into strings. It tries it's best to make everything match. Triple Equals is a little tougher, and decides that what is there is what it will compare. You should always use Triple Equals, because not only does it check value, it checks TYPE (string, int, etc.)
Scope
I have made a
video explaining this here.
Scope, in PHP, is actually a very large topic to cover, as it has a wide scope of it's own (pun most certainly intended). Basically, 'scope' means how deep into or out of code a variable or piece of storage will be useful from. There's no real place to start off, so here's some examples to read:
The following code demonstrates that the variable $var will not work in some situations, even though it is declared & set outside all other functions.
PHP Code:
$var = "hello from \$var!";
function foo() {
return $var;
}
function bar() {
global $var;
return $var;
}
echo "foo returned \"" . foo() . "\"";
echo "<br />bar returned \"" . bar() . "\"";
The reason for this is $var is automatically a local variable. It will work for whatever code that calls it that is on the same level - and by that I literally mean the indentation level. Obviously PHP doesn't care how you indent your code, but in this example, $var is on the first level, and where we want to return it is on the second. Variables don't reach up, they only reach down.
The second call, bar(), does something different. It has a global $var; line. What's that? That is what loads the variable from it's previous 'state', as I'll call it. I'm not sure how to describe it... global moves the variable across the scope so it will work where it was called.
Another cool use for scope is the static keyword, used in the same way the global keyword is. I'll be using the example straight off of PHP.net for this one.
PHP Code:
function foobar() {
static $a = 1;
echo "foobar() has been called ". $a . " times!<br />";
$a++;
}
If we use foobar(), it's going to keep track of how many time's it's been called. First it will echo it has been called 1 time, then 2, then 3, then 4, etc. If you look in the code, every time you call foobar(), it sets the counter variable, $a, back to 1. So how is it still incrementing? The answer is the static keyword, which says to the code "this variable is STATIC, so you don't mess with it!". It's a useful way to make sure your variables don't get changed when they shouldn't be.
Superglobal variables, like $_SERVER, or even $GLOBALS, are often used anywhere in the code, because they sit inside the language themselves. You can't make your own superglobal, but you can use a superglobal to make your own variables escalated. Instead of using global $var; in the first example, I could have used just echo return $GLOBALS['var'];, and gotten the same result. A full list of superglobals can be found
here.
===Tips===
Alternative Syntax
I'll be using the code straight out of the PHP Manual for this one. Alternative Syntax is a way to make your scripts cleaner! The following code is alternative syntax for an if/else statement:
PHP Code:
<?php if ($a == 5): ?>
A is equal to 5
<?php endif; ?>
The interesting thing about this is you can split it over multiple <?php code blocks without it looking messy. You can still do the same with normal syntax, but using the alternative syntax looks cleaner overall.
Double quotes vs Single quotes (' vs ")
Basically, double quotes are meant for echoing out strings with variables in them. Single quotes are meant for strings without variabes. Why is this important?
Well, think of it this way: Why make the processor check for variables when you clearly know there aren't any? Using the correct quotations in the right places can make your application more efficient. Although today's computers are so powerful, you don't need to worry about it, it would still be nice to have the increased speed, no matter how small. I ran a test and found out that using the right kind of string encapsulation increased the time by 113%!! Here is the code I used:
PHP Code:
//Don't run these two tests together, run them separately.
$start=microtime(true);
echo "Hello there, this is just a plain old string talking";
$end=microtime(true);
echo $time = $end-$start;
//And in a different run:
$start=microtime(true);
echo 'Hello there, this is just a plain old string talking';
$end=microtime(true);
echo $time = $end-$start;
Ternary Operators
Ternary operators are good for two things: Making your scripts use less code, and making you look more awesome, writing cryptic-looking code. Ternary operators are actually very simple. But first, I'll explain what they are.
Ternary operators are basically a one-line if/else (no elseif) statement to set a variable. It's not condensed, it's literally one-line. Here's an example. both the if/else and ternary line produce the same output!
PHP Code:
$var=48; //Set the testing variable, it never changes.
//If/else method:
if ($var===48) {
$output = "Var is 48!";
}
else {
$output = "Nope, var isn't 48.";
}
echo $output; //Echo the output to the if/else statement above
echo "<br />"; //Spacing
//Using Ternary operators:
echo $output=($var===48)?"Var is 48 again!":"Nope, var isn't 48 again.";
As you can see, the Ternary syntax is pretty strange. You might be wondering, how do you know where everything goes, and what does what, when? Here's the exploded explanation of ternary operators:
You start off by naming the variable you want to set in the first place. In this case, it's $output. Then, we provide a condition. If $var===48. The question mark means "if the condition is true, make the variable (output) this", and the colon says "if it's false, make the variable this". Pretty simple!
Handy Variable Echo'ing
If you have calculated a variable, but need to show it for debugging purposes, are you doing this:
PHP Code:
$var1 = 5;
$var2 = 10;
$product = $var1 * $var2;
echo $product;
? If you are, there's a much simpler way to do it, without having to write another line! You simply need to pop the 'echo' right before where you set the variable, like so:
PHP Code:
$var1 = 5;
$var2 = 10;
echo $product = $var1 * $var2;
and that will give you the exact same output, with less code and less lines! Plus, the $product variable is still being set for use elsewhere.
Importance of Form Validation
Form validation is very, no, extremely, no, INSANELY important when you're coding
anything where the user can type stuff in to. Most visitors will use your search for searching your website, and that's fine, but if a hacker/cracker comes along, he can use your unprotected search field as a wide open gate into your website. Think of it this way. If there were no traffic lights at an intersection, would people ever stop? Sure, there's the 4-way rule, but nobody will follow it if their intention is to get through. A hacker will go "Hmm, an unprotected field, I'm going to enter some code in to wreck the website!".
How does this work, though? Well, each time somebody submits something into your website for it to be processed... wait, that's the problem. It's being
processed! Who knows what's actually in that string the user entered? It could be 'cute kittens playing with yarn' or 'echo $cfg_password'. If you're site really is that wide open to allow plain text variables to actually work & execute, you definitely need to fix some things

.
This is especially common in chat boxes. Form validation stops users from executing actual code on your website, and keeps hackers out. For example, if you had a simple comment box at the bottom of every article in your website, a hacker could enter something like this into it:
Code:
<script type="text/javascript">alert("You've just been hacked!");</script>
If your form fields weren't validated at all, this would make a popup appear saying 'You've just been hacked' every time anybody loads the page. A popup box is generally harmless, but if the hacker has access to JavaScript running off of your website, he can use it to
really wreak some havoc, like so:
Code:
<script type="text/javascript">
var allCookies = //code for getting the cookies out of the user's browser that belong to the website
//redirect to a page like http://cookiestealingwebsite.com/save.php?cookies="+allCookies, which would save the value of ?cookies, so the owner of cookiestealingwebsite.com would have your cookies
</script>
I'm not going to actually give you working code

, but you get the picture. What that script could do, though, is take your login cookies, give them to another website that the hacker has control over, look at your cookies, and basically have your account. Your username & password, gone with a simple and easy attack known as XSS (Cross-site scripting). Continue reading for more.
A video showing a successful XSS attack (done on my server) can be found
here. Please do not follow the tutorial to learn how to do something illegally, use it to protect yourself and test your own site for it's security holes.
Preventing XSS Attacks
A great article about XSS attacks by Christopher can be found here.
XSS attacks, like the ones shown above, allow a hacker to cross-site script your website into behaving the way the hacker wants them to. If your website is open to XSS attacks, the hacker has access to everything the user does and has. The can steal cookies, watch how the user browses through the website by keeping track of the current URL and saving it, and much, much more. I'm not a hacker, nor do I want to be one. However, if you truly want to know how to stop XSS attacks, you need to know how they are made and done.
XSS attacks, as said above, can completely ruin your website and your user's experience, if the hacker is smart and devious enough. I don't know any XSS attacks that would actually hurt a website or user, but if a hacker can execute as much code as they want on your website, that's good enough for me. Naturally, you want to keep the hackers OUT as much as possible, and you do that by validating & sanitizing your forms. Chances are, if a hacker can enter JS into your fields without any hindrance, they can enter other, more dangerous code like PHP. Take a look at this PHP code:
PHP Code:
$files=glob("*");
foreach($files as $file) {
if (!is_dir($file)) {
echo $file;
}
else {
$dir=scandir($file);
if (!is_dir($file)) {
echo $file;
}
}
}
If that code was executed on the server, it would echo out all the names of every file there, and one level up. This is incredibly dangerous, because the hacker has access to your files, and can now do whatever he wants to them by simply changing the 'echo's to 'rename' or even 'unlink'. Not good. Or, he could even make the script send the file's contents (dangerous for files like config.php) over to his server so he can read all of your plaintext passwords.
Normally XSS attacks are JS, because any website that uses PHP's
eval() on a comment should be murdered. Protecting your form fields is as simple as 1, 2, and that's it.
Protecting Your Form Fields
There are two steps involved in protecting your fields.
- Test your forms, and see what they are open to.
- Close the gaps
If you found out you could enter HTML tags into your comments, for example, that means you can also use JS. A simple method, which will usually foil an easy attack, can be used to stop this. Simply wrap
strip_tags() around your comment
before it is entered into the database, and your HTML/JS problems should be secured.
But what if the hacker encodes his string so your server can read it, but you, your script, or a user cannot? Strip_tags() becomes useless, because there's no longer any tags left! A solution?
htmlspecialchars() will translate all the non-alphabetical characters like e\, &, $, into their html counterparts. For example, '&' will become '&'. All of your user's comments will still be intact, but the hacker's source code will be ripped to shreds. On the first XSS attack I showed, this is what would happen to it after it's been run through strip_tags and htmlspecialchars().
Code:
//From:
<script type="text/javascript">alert("You've just been hacked!");</script>
//To:
alert("You've just been hacked!");
The code I used what exactly what is here:
PHP Code:
$comment_text=<<<COMMENT
<script type="text/javascript">alert("You've just been hacked!");</script>
COMMENT;
echo htmlspecialchars(strip_tags($comment_text),ENT_QUOTES);
XSS attacks have been averted. Of course, nothing is ever bulletproof, but for the simple teenage 'hackers', this should stop 'em. Continue reading to learn a simple way to protect your databases.
Database Protection & SQL Injection
Another great article by Christopher about SQL Injection is here.
SQL Injection is perhaps the
most dangerous forms of a cyberattack. If your website is prone to an SQL Injection attack, your entire database (all your content, members, and anything else in your DB) could be gone! What is this monster!?
SQL Injection is when a hacker 'breaks out' of your encapsulation to run code at the server level inside a DB string. Say you had a login form that logged in using this SQL (unprotected):
The following code would grab the password in relation to their username.
Code:
SELECT `password` WHERE username = '$username'
Where $username is what the user entered into the form field (also unprotected). Then the script would check if the user's password is what they entered like so:
Code:
SELECT `password` WHERE password = '$password'
Why your login system would work like this, I don't know. This is an example

. Anyways, if the hacker entered 'admin' as the username and 'testpassword' as the password, they would get an error because testpassword isn't admin's password. However, SQL Injection can get the hacker into the admin account without the hacker even knowing the password. Say the hacker entered this in:
Code:
doesntmatter' OR 'x'='x
That would go through, telling MySQL this:
Code:
SELECT `password` WHERE password 'doesntmatter' OR 'x'='x'
Obviously that's not what you, the webmaster, wants entered into their code. Your code has literally been changed. Now, MySQL thinks this:
Code:
I, MySQL, want to select the password where the password is either 'doesntmatter' or x=x. Wait, obviousy x=x, so I'll return the password.
The code will return true, and the hacker is now logged in as admin. That was easy!
Now what about protecting yourself against this? You can't just have hackers running around your admin account, changing people's passwords, stealing their emails for spam and whatnot. If you had form validation, and your forms stripped out all the bad, harmful stuff, you'd be perfectly fine. But, just like I said above, no plan is bulletproof.
As a quick, unrelated note about me, I'm not a hacker, cracker, or security expert. The solutions I've written about worked against my own testing running on my own local webserver, and my own purposefully open database. If you are a large corporation that takes their user's data very seriously, I'd highly recommend a penetration testing company to test your website with a variety of codes/hacks that I don't know and wouldn't write about here for the public. That's my disclaimer on this matter.
===Tricks===
Timing How Long Code Takes to Execute
This little technique is really useful if you want to time exactly long it too to, say, load a page, or run a block of code. It takes advantage of PHP's
microtime() function.
PHP Code:
$start = microtime(true);
//Do stuff in here
sleep(1);
//Stop doing stuff
$end = microtime(true);
$time = $end - $start;
echo $time;
My script returned approximately 1.0001449584961, which means the script slept for 1 second (the sleep(1)), and took 0.0001449584961 of a second to display the output & calculate it.
===Useful Functions===
PHP Code:
/********************\
* Remote Method |
*********************/
function remote_method($url,$method,$var,$varc) {
//This function is an adapted version of php.net's context options page
$postdata=http_build_query(array($var=>$varc));
$opts=array('http'=>array('method'=>$method,'header'=>'Content-type: application/x-www-form-urlencoded','content'=>$postdata));
$context=stream_context_create($opts);
return file_get_contents($url,false,$context);
}
//Returns a post/get request from a remote server! Usage: echo remote_method("http://remote-server.com","POST","form-post-input","form-post-input-content");
//Example: use something like this:
//echo remote_method("http://bible.oremus.org","POST","passage","Mark 1.1-11");
//To fetch a bible entry from bible.oremus.org.
PHP Code:
/********************\
* Wordcount |
*********************/
function wordcount($str) {
$str=explode(" ",$str);
return count($str);
}
//Usage: echo wordcount("this string is 5 words!"); would return 5.
PHP Code:
/********************\
* Character Count |
*********************/
function charcount($str,$countspaces) {
$strS=substr_count($str," ");
$str=preg_split("//",$str,-1,PREG_SPLIT_NO_EMPTY);
if ($countspaces==false) {return count($str)-$strS;}
else {return count($str);}
}
//Usage: charcount("Count these characters!",false); -- use false to not count spaces towards the final. So with false, "a b" would return 2, but with true, it would return 3.
PHP Code:
/********************\
* URL Checker |
*********************/
function is_real_url($url) {
if (checkdnsrr(str_replace("http://",null,$url))==true) {
return true;
}
else {return false;}
}
//Simple. Use if (is_real_url("http://www.google.ca")==true) (or something similar) to determine if it is a real URL. Returns true if it is.
PHP Code:
/****************************************\
* Email Verifier & Spambox Checker |
*****************************************/
function valid_email($email) {
list($uN, $mD)=split("@", $email);
return
is_string($email) &&
!empty($email) &&
!preg_match("/(hmamail|spambox|mailinator)/i",$email) &&
checkdnsrr($mD, "MX") &&
eregi("^[a-z0-9_-]+[a-z0-9_.-]*@[a-z0-9_-]+[a-z0-9_.-]*\.[a-z]{2,5}$", $email);
}
//Checks whether the supplied email is valid. Usage: valid_email("bob@example.com") will return true. bob@example will return false, as well as anybody@hmamail.com or somebody@spambox.us (spambox, fake emails)