PHP Performance – isset() versus empty() versus PHP Notices
I’m cleaning up a lot of PHP code and always program with PHP error_reporting set to E_ALL and display_errors turned on so that I make sure to catch any PHP messages that come up. Since starting on this site, I have fixed literally hundreds (maybe thousands) of PHP Notices about using uninitialized variables and non-existent array indexes.
I have been fixing problems like this where $somevar is sometimes undefined:
if ($somevar)
by changing it to:
if (isset($somevar) && $somevar)
This successfully gets rid of the NOTICEs, but adds some overhead because PHP has to perform two checks. After fixing a lot of this in this manner, I’ve noticed that the pages seem to be generated a little slower.
So, to provide some conclusive results to myself, I wrote up a quick benchmarking script - available at php_empty_benchmark.php. It goes through 1,000,000 tests using each of these methods:
- if ($a) - This generates a notice if $a is not set
- if (isset($a)) - A simple clean way to check if the variable is set (note that it is not equivalent to the one above)
- if (isset($a) && ($a) - The one that I have been using which is equivalent to if($a), but doesn’t generate a notice.
- if (!empty($a)) - This is functionally equivalent to if($a), but doesn’t generate a notice.
It measures the time to perform 1 million tests using a defined percentage of values that are set. It then computes the difference as a percentage of the time taken for the original test (the one that generates the notices). A ‘diff’ of 100 means that the execution time is the same, greater than 100 means that it is faster, and less than 100 means that it is slower. A typical test produced these results:
With NOTICE: 0.19779300689697 With isset: 0.19768500328064 / Diff: 100.05463419811 With both: 0.21704912185669 / Diff: 91.128222590815 With !empty: 0.19779801368713 / Diff: 99.997468735875
In summary, using the if (isset($a) && $a) syntax is about 8-10% slower than generating the PHP Notice. Using !empty() should be a drop-in replacement that doesn’t generate the notice and has virtually no performance impact. Using ifset() also has no performance impact, but is not exactly the same as ‘if($a)’ since isset() will return true if the variable is set to a false value. I included it here, because it often make the code a little more readable than the !empty($a) syntax. For example:
$myvalue = !empty($_REQUEST['myvalue']) ? $_REQUEST['myvalue'] : '';
Versus
$myvalue = isset($_REQUEST['myvalue']) ? $_REQUEST['myvalue'] : '';
Source:
http://www.brandonchecketts.com/archives/php-performance-isset-versus-empty-versus-php-notices
How to grab the mouse position in a browser with jQuery and HTML5
Depending on what your plans are it might become handy to know the mouse position.
The script below gives you the position relative to the page, relative to the browser window and relative to the DIV with the green color.
HTML (index.html)
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="javascript.js"></script>
<link href="style.css" type="text/css">
</head>
<body>
<div id="object"></div>
<div id="page" class="info">Page: <span></span></div>
<div id="client" class="info">Client: <span></span></div>
<div id="container" class="info">Container: <span></span></div>
</body>
</html>CSS (style.css)
* { margin: 0px; border: 0px; padding: 0px; } #object { width: 595px; height: 842px; margin: 10px; background: #cfc; border: 1px solid #666; float: left; } .info { padding-top: 100px; }
JavaScript (javascript.js)
$(function() { $("#object").mousemove(function(e) { var pageCoords = "( " + e.pageX + ", " + e.pageY + " )"; var clientCoords = "( " + e.clientX + ", " + e.clientY + " )"; var cLeft = e.pageX - $(this).offset().left; var cTop = e.pageX - $(this).offset().top; var containerCoords = "( " + cLeft + ", " + cTop + " )"; $("#page span").text("( e.pageX, e.pageY ) - " + pageCoords); $("#client span").text("( e.clientX, e.clientY ) - " + clientCoords); $("#container span").text("( e.clientX, e.clientY ) - " + containerCoords); }).click(function(e) { var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; var containerCoords = "( " + x + ", " + y + " )"; alert("You clicked: ( e.clientX, e.clientY ) - " + containerCoords); }); });
Related links:
http://docs.jquery.com/Tutorials:Mouse_Position
How to modify HTTP headers with PHP header() function
Many examples that show how to use the header() function of PHP.
Hint:
If you want to check your headers, you can use web based tools like: web-sniffer.net, web-browser extensions (e.g. LiveHTTPHeaders, ieHTTPHeaders) or another third-party software tool.
// See related links for more status codes // Use this header instruction to fix 404 headers // produced by url rewriting... header('HTTP/1.1 200 OK'); // Page was not found: header('HTTP/1.1 404 Not Found'); // Access forbidden: header('HTTP/1.1 403 Forbidden'); // The page moved permanently should be used for // all redrictions, because search engines know // what's going on and can easily update their urls. header('HTTP/1.1 301 Moved Permanently'); header('Location: ' . $url); exit(); // Server error header('HTTP/1.1 500 Internal Server Error'); // Redirect to a new location: header('Location: http://www.example.org/'); // Redriect with a delay: header('Refresh: 10; url=http://www.example.org/'); print 'You will be redirected in 10 seconds'; // you can also use the HTML syntax: // <meta http-equiv="refresh" content="10;http://www.example.org/ /> // override X-Powered-By value header('X-Powered-By: PHP/4.4.0'); header('X-Powered-By: Brain/0.6b'); // content language (en = English) header('Content-language: en'); // last modified (good for caching) $time = time() - 60; // or filemtime($fn), etc header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); // header for telling the browser that the content // did not get changed header('HTTP/1.1 304 Not Modified'); // set content length (good for caching): header('Content-Length: 1234'); // Headers for an download: header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="example.zip"'); header('Content-Transfer-Encoding: binary'); // load the file to send: readfile('example.zip'); // Disable caching of the current document: header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Pragma: no-cache'); // set content type: header('Content-Type: text/html; charset=iso-8859-1'); header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/plain'); // plain text file header('Content-Type: image/jpeg'); // JPG picture header('Content-Type: application/zip'); // ZIP file header('Content-Type: application/pdf'); // PDF file header('Content-Type: audio/mpeg'); // Audio MPEG (MP3,...) file header('Content-Type: application/x-shockwave-flash'); // Flash animation // show sign in box header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="Top Secret"'); print 'Text that will be displayed if the user hits cancel or '; print 'enters wrong login data';
Source: http://www.jonasjohn.de/snippets/php/headers.htm
Related links:
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
http://www.web-caching.com/mnot_tutorial/
http://reeg.junetz.de/DSP/node16.html
How to generate a .htaccess and .htpasswd with PHP
Ever had a moment where you needed to secure a directory but didn't have the htpasswd tool available?
The following script simply generates a .htaccess and .htpasswd file to secure a directory.
<!DOCTYPE html> <html> <body> <?php if (!empty($_POST['username']) && !empty($_POST['password'])): ?> <strong>.htaccess</strong><br> <pre> AuthName "Members only" AuthType Basic AuthUserFile /srv/www/domain.tld/.htpasswd require valid-user </pre> Save the above file in the directory you want to secure.<br> <br> <strong>.htpasswd</strong><br> <pre> <?php echo $_POST['username'] . ':' . crypt($_POST['password'], base64_encode($_POST['password'])); ?> </pre> Save the above file as <strong>/srv/www/domain.tld/.htpasswd</strong>.<br> <br> <a href="<?php echo $_SERVER['PHP_SELF']; ?>">« BACK «</a> <?php else: ?> <form method="post"> Username: <input type="text" name="username"><br> Password: <input type="text" name="password"><br> <input type="submit"> </form> </form> <?php endif; ?> </body> </html>
Some useful information about PHP RegEx
This information can be handy with the following PHP functions:
* preg_filter
* preg_grep
* preg_last_error
* preg_match_all
* preg_match
* preg_quote
* preg_replace_callback
* preg_replace
* preg_split
What is a regex?
At its most basic level, a regex can be considered a method of pattern matching or matching patterns within a string. In PHP the most oft used is PCRE or "Perl Compatible Regular Expressions". Here we will try to decypher the meaningless hieroglyphics and set you on your way to a powerful tool for use in your applications. Do not try to understand all this in a single sitting. Instead, take in a little and come back as you grasp various concepts.
Where do I begin?
At the beginning.
Lets create a string.
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // echo our string echo $string; ?>
If we simply wanted to see if the pattern 'abc' was within our larger string we could easily do something like this:
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; echo preg_match("/abc/", $string); ?>
The code above will echo '1'. This is because it has found 1 match for the regex. That means it has found the pattern 'abc' once in the larger string. [[http://www.php.net/preg-match|preg_match()]] will count zero if there is no matches, or one if it finds a match. This function will stop searching after the first match. Of course, you would not do this in a real world situation as php has functions for this such as [[http://www.php.net/strpos|strpos()]] and [[http://www.php.net/strstr|strstr()]] which will do this much faster.
Match beginning of a string
Now we wish to see if the string begins with abc. The regex character for beginning is the caret ^. To see if our string begins with abc, we use it like this:
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // try to match the beginning of the string if(preg_match("/^abc/", $string)) { // if it matches we echo this line echo 'The string begins with abc'; } else { // if no match is found echo this line echo 'No match found'; } ?>
From the code above we see that it echo's the line ''The string begins with abc''. The forward slashes are a delimeter that hold our regex pattern. The quotations are used to 'wrap it all up'. So we see that using the caret(^) will give us the beginning of the string, but NOT whatever is after it.
What if I want case insensitive?
If you used the above code to find the pattern ABC like this:
if(preg_match("/^ABC/", $string))
the script would have returned the message:
No match found
This is because the search is case sensitive. The pattern 'abc' is not the same as 'ABC'. To match both 'abc' and 'ABC' we need to use a modifier to make the search case in-sensitive. With php regex, like most regex, is use 'i' for insensitive. So now our script might look like this:
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // try to match our pattern if(preg_match("/^ABC/i", $string)) { // echo this is it matches echo 'The string begins with abc'; } else { // if not match is found echo this line echo 'No match found'; } ?>
Now the script will find the pattern abc. It would also match any case in-sensitive combination of abc, ABC, Abc, aBc, and so on.
More on [[http://php.net/manual/en/reference.pcre.pattern.modifiers.php|modifiers]] later.
How do I find a pattern at the end of a string?
This is done in much the same way as with finding a a pattern at the beginning of a string. A common mistake made by many is to use the $ character to match the end of a string. This is incorrect and \z should be used. Consider this..
preg_match("/^foo$/", "foo\n")
This will return true as $ is like \Z which is like (?=\z|\n\z). So when a newline is not wanted, $ should not be used. Also $ will match multiple times with the /m modifier whereas \z will not. Lets make a small change to the code from above by removing the caret(^) at the beginning of the pattern and putting \z at the end of the pattern, we will keep the case in-sensitive modifier in to match any case.
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // try to match our pattern at the end of the string if(preg_match("/89\z/i", $string)) { // if our pattern matches we echo this echo 'The string ends with 89'; } else { // if no match is found we echo this line echo 'No match found'; } ?>
The script now will show the line
''The string ends with 89''
because we have matched the end of the string with the pattern 89. Pretty easy stuff so far.
Meta characters
During our first look at regex we did some simple pattern matching. We also introduced the caret(^) and the dollar($). These characters have special meaning. As we saw, the caret(^) matched the beginning of a string and the dollar matched the end of a string. These characters, along with others are called Meta characters. Here is a list of the Meta characters used for regex:
* . (Full stop)
* ^ (Carat)
* * (Asterix)
* + (Plus)
* ? (Question Mark)
* { (Opening curly brace)
* [ (Opening brace)
* ] (Closing brace)
* \ (Backslash)
* | (Pipe)
* ( (Opening parens)
* ) (Closing parens)
* } (Closing curly brace)
We will look at each of these during this tutorial, but it is important that you know what they are. If you wish to search a string that contains one of these characters, eg: "1+1" then you need to escape the the meta character with a backslash like this:
<?php // create a string $string = '1+1=2'; // try to match our pattern if(preg_match("/^1\+1/i", $string)) { // if the pattern matches we echo this echo 'The string begins with 1+1'; } else { // if no match is found we echo this line echo 'No match found'; } ?>
From the code above you will see the script print:
''The string begins with 1+1''
because it found the pattern 1+1 and ignored or escaped the special meaning of the + symbol. If you were to not escape the meta character and use the regex
preg_match("/^1+1/i", $string)
you would not find a match.
If you are looking for a backslash, you need to escape that also. But, we also need to escape the control character too, which is itself a backslash, hence we need to escape twice like this
\\\\
What do the other Meta characters do?
We have already seen the caret **^** and the dollar **$** in action, so now lets look at the others, beginning with the square braces [ ]. These Meta characters are used for specifying a character class.
A what?
A Character Class. This is just a set of characters you wish to match. They can be listed individually like:
[abcdef]
or as a range seperated by a **-** symbol like:
[a-f]
<?php // create a string $string = 'big'; // Search for a match echo preg_match("/b[aoiu]g/", $string, $matches); ?>
Source: http://www.phpro.org/tutorials/Introduction-to-PHP-Regex.html
How to recursive delete files and directories with PHP
This is an example how you could recursive delete directories with PHP.
Keep in mind that you ALWAYS define a root where this function should do its action.
This can seriously remove all your files.
define('UPLOADFILES', dirname(dirname(__FILE__)) . '/uploadfiles'); function recursiveDelete($path) { if (strpos($path, UPLOADFILES) === false) { exit('Trying to remove from wrong path to uploadfiles!'); } if (is_file($path)) { return unlink($path); } elseif ( is_dir($path) ){ $objects = scandir($path); foreach ($objects as $object) { if($object != '.' && $object != '..'){ recursiveDelete($path . '/' . $object); } } reset($objects); return rmdir($path); } }
How to relocate repository root URL of your Subversion working copy
Ever had this issue a administrator changed the location of the repository?
Well, I had
Relocating the URL of the repository is quite simple with svn switch --relocate, here you have some simple steps to fix your working copy.
1. Go into the current working copy.
cd /path/to/your/working/copy
2. Get the current repository root URL.
svn info
3. Now switch the old repository root to the new repository root.
svn switch --relocate http://old_repository_root http://new_repository_root
4. Optionally you can verify if the relocate went successful.
svn info
How to grab the IP address from a remote user in PHP
The following example uses 'HTTP_X_FORWARDED_FOR' to detect if the request was forwarded by a proxy server or not.
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $ip = $_SERVER['REMOTE_ADDR']; } echo $ip;
You could use this info for limiting happenings on your website to a several IP's or maybe an IP range if you need it.
For example you can use preg_match() to check if the IP is within the range you prefer:
if (preg_match('/^(192.168.3.1[0-9]|127.0.0.1|192.168.5.3)$/', $ip)) { echo "IP matches!"; }
jQuery its ‘document ready’ can be written on different ways.
I have seen a lot of scripts already still using a old way of checking if the DOM is ready for action like this:
1 2 3 4 5 | window.onDomReady = myFunction; function myFunction() { alert('hello'); } |
or (which is not smart cause onload waits for even the images to be loaded):
1 2 3 4 5 | window.onload = myFunction; function myFunction() { alert('hello'); } |
jQuery has a nicer way to implement this with the following piece of code:
1 2 3 | $(document).ready(function() { // your code here }); |
However you can write this even a bit shorter than most people already do by using the above code, like this:
1 2 3 | $(function() { // your code here }); |
I hope you find this useful, make something nice with jQuery!




