PHP

You are currently browsing the PHP category.

Check if PHP is using HTTPS (SSL)

Posted on December 9th, 2011 by Wayne May in PHP | 0 comments

I had to come up with a way to check if PHP is running in SSL mode today. This will work on both Apache, Nginx and IIS

1
2
3
4
5
6
7
8
9
10
11
12
function is_ssl()
{
    $secure_connection = false;
 
    if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'
        || $_SERVER['SERVER_PORT'] == 443) 
    {
        $secure_connection = true;
    }
 
    return $secure_connection;
}

I found this little nifty function on StackOverflow

Detecting a Multi-Dimensional Array in PHP

Posted on December 9th, 2011 by Wayne May in PHP | 0 comments

I recently had to find a quick way to check if an array is a multi-dimensional array, only to find that there are no PHP built-in function to do this. Here is a quick and easy way to do it:

1
2
3
4
function is_multi_array( array $arr )
{
    return is_array($arr[key($arr)]);
}

This can easily be used in the following context:

6
7
8
9
10
$a = array("dimension1" => array("dimension2" => "I like it") );
if( is_multi_array( $a ) )
{
    echo $a['dimension1']['dimension2'];
}

PHP Safe Redirect Function

Posted on December 8th, 2011 by Wayne May in PHP | 0 comments

I see PHP code every day making use of the header function. Its the standard way to make redirects in PHP, but will fail if ANY output was sent to the browser before its called. There is a safer way to do this, which use JavaScript and meta redirects as a fail safe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    /**
     * Do a Safe Redirect
     *
     * This function will first try to do a server-side redirect, if it is not possible, if will fall back to a
     * Javascript redirect, if that fails, it will try a HTML redirect.
     * @param $url
     */
    function safe_redirect($url, $method = 'PHP')
    {
        try
        {
            if (!headers_sent())
            {
                //If headers are not sent yet... then do a php redirect
                @header('Location: '.$url);
                exit;
            } else throw new Exception();
        }
        catch( Exception $ex )
        {
            //If headers are sent... do a JavaScript redirect...
            //if javascript disabled, do html redirect.
            echo '<script type="text/javascript">';
            echo 'window.location.href="'.$url.'";';
            echo '</script>';
            echo '<noscript>';
            echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
            echo '</noscript>';
            exit;
        }
    }

Basically, this will check to see if headers were sent, if not, it will allow for a PHP header redirect, If output were set, it will make use of JavaScript, and, as a backup if JavaScript is not installed, it will cause a meta redirect.

PHP use Backticks as Execution Operators

Posted on December 7th, 2011 by Wayne May in PHP | 0 comments

PHP use backticks as execution operators, which will return the output of to be assigned to a variable. Any code between backticks will be executed as a shell command – the backtick operator is identical to shell_exec()

One example where I found this useful was to get the fully qualified domain name of a server. I could do something like:

1
$fqdn = shell_exec('hostname --fqdn');

or using backticks, I can so something like:

1
$fqdn = `hostname --fqdn`;

Notice that I am using backticks (`) and not single quotes (‘)

Testing if a string is serialized in PHP

Posted on December 7th, 2011 by Wayne May in PHP | 0 comments

PHP offers a way to store arrays and objects through serialization. The problem is, there is no actual PHP function the check if data is serialized. I came up with a dirty little function to help with that:

1
2
3
4
    function is_serial($data)
    {
        return (@unserialize($data) !== false);
    }

unserialize will return FALSE if you pass a value that is not serialized, BUT, it will also throw an E_NOTICE error at the same time. To get around that, I add the suppressor (@) and then I attempt to unserialize the data.

Unlimited number of function parameters in PHP

Posted on December 6th, 2011 by Wayne May in PHP | 0 comments

Every so often I find myself needing to pass an unknown amount of arguments into a function. For example, assume you want to create a function to add a bunch of variables: add( $a, $b, $c, $d, … ) This can easily be done using the PHP function func_get_args().

1
2
3
4
5
6
7
8
9
10
11
    function add()
    {  
        $total  = 0;
        $args = func_get_args();  
 
        foreach ($args as $key => $val)
        {  
            $total += $val;  
        }  
        return $total;
    }

You can then call the function with as many arguments as you want.

1
    echo add( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );

Interfaces vs. Abstract classes in PHP

Posted on December 5th, 2011 by Wayne May in PHP | 1 comment

Many developers do not know the main difference between intefaces 1 and abstract classes 2, since they seem to provide almost the same capabilities.
Hopefully this will help you decide which to use in your application.

When to use Interfaces?
Interfaces allow you to specify which methods a class must provide, without having to know how they are handled.
Methods specified in an interface MUST be implemented in a class.

1
2
3
4
interface SomeInterface
{
  public function doSomething( $variable );
}

When to use Abstract classes?
An abstract class provides structure. It usually defines default implementations.
Methods specified in an abstract class can be ignored in a subclass.

1
2
3
4
5
6
7
abstract class SomeInterface
{
  abstract protected function doSomething( $variable )
  {
    //Put some code here if you like
  }
}

This table attempts to define the difference between Interfaces and Abstract classes.

Feature Interface Abstract class
multiple inheritance: a class can implement several interfaces. A class can only extend one abstract class.
default implementation: An interface can not provide any code at all. An abstract class can provide default code, and parts that can be overridden.
constants: Interface constants work exactly like class constants, however, they can not be overridden. Abstract classes can have their constants overridden by extending classes.
convenience: Interfaces can easily be added to a third party class. Third party classes might have to be rewritten to extend the abstract class.
is-a vs -able or can-do: Interfaces describe the abilities of a class, and not the identity of the class (It defines what the class can do). An abstract class defines the code identity of the descendants. (It defines what the class is). For example: If you defined a Dog as abstract, then Shepherds are descendants of Dogs.
visibility: All declared methods MUST be public. Methods can be public or protected. If the abstract class defines a method as protected, then it can be declared as protected or public in the sub-class.
homogeneity: If various implementations share the same method signatures, the an interface should be used. If subclasses are going to different (heterogeneous), then use interfaces. If various implementations share a common “kind” or behavior, the an abstract class should be used. For example, if sub-classes are going to be similar (homogeneous), use abstract classes.
performance: Interfaces are almost double as slow as abstract classes. Pretty fast.
terseness: Interfaces are typically not designed to share. Shared code can be put in abstract classes.
maintenance: If you add a new method to an interface, then you MUST update all implementations of the interface and add code to implement the new method. If a new method is added to a class, you can provide default implementation for it. All existing code will continue to work without change.

Updated: Dec-05-2011: Added visibility to the table.

Notes:

  1. http://php.net/manual/en/language.oop5.interfaces.php
  2. http://www.php.net/manual/en/language.oop5.abstract.php

Equality vs. Identity in PHP if statements.

Posted on December 5th, 2011 by Wayne May in PHP | 0 comments

From time to time I meet developers that do not know the difference between == (equality) and === (identity) in PHP. Hopefully this post will clear it up for you. Here are a few examples of PHP is statements.

1
2
3
4
5
6
7
8
9
10
11
12
13
    if( 1 == true ) { /* do something */ }
 
    if( 1 === true ) { /* do something */ }
 
    if( true == true ) { /* do something */ }
 
    if( true === true ) { /* do something */ }
 
    if( 1 == 1 ) { /* do something */ }
 
    if( 1 === 1 ) { /* do something */ }
 
    if( 1 === '1' ) { /* do something */ }

Above, I wrote 7 quick and simple if statements. 1) In PHP 0 equates to FALSE, and any other number equates to true. In this statement, 1 IS EQUAL to true; 2) This will fail, since 1 is not EXACTLY the same as true; 3) This will work, since true IS EQUAL to true; 4) This will work, since true is EXACTLY the same as true; 5) This will work, since 1 IS EQUAL to 1; 6) This will work, since 1 is EXACTLY the same as 1; 7) This will fail, since 1 is NOT EXACTLY the same as ‘1’ (integer vs string); You may ask why you need to know this, and how this is relevant to PHP. Here is a good reason: The strpos() function will return an integer number or a boolean false. Lets say your needle is at position 0, the function will return 0. If you used the equality check, this would equate to false, since PHP considers a 0 as false. Consider this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    $string = "This is an example string";
 
    /*
     * This will fail your check, even though, the needle was found.
     */
    $pos = strpos( $string, 'This');
    if( $pos == false )
    {
        echo "This string does not contain the word: This";
    }
 
    /*
     * This will work since if the needle could not be found.
     */
    $pos = strpos( $string, 'Word');
    if( $pos === false )
    {
        echo "This string does not contain the word: Word";
    }

An autoader that use the SPL DirectoryIterator in PHP

Posted on December 4th, 2011 by Wayne May in PHP | 5 comments

In a previous post I showed a simple example on how to use the SPL Autoloader in PHP. In this example I will show you how to make use of the SPL DirecoryIterator to traverse through the filesystem and look for classes to autoload.

The DirectoryIterator 1 provides a class that makes it easy to view the contents of the file system.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?php
final class Autoloader
{
  /**
   * Holds information about all of the class files
   * @var array
   */
  private static $_cached_classes;
 
	/**
	 * Used to Autoload a class
	 *
	 * @param $classname
	 */
  public static function load( $classname )
  {
    if( empty( self::$_cached_classes ) )
    {
      self::build_class_cache();
    }
    if( isset( self::$_cached_classes[ $classname ] ) )
    {
      include self::$_cached_classes[ $classname ];
    }    
  }
 
  /**
   * Builds a list of all the class files in a directory
   * 
   * This will go traverse a directory and build a list of all the php files
   */
  private static function build_class_cache()
  {
    self::$_cached_classes = array( );
 
    // Specify a list of directories to look in
	$search_directories = array( __DIR__ . '/classes/' );
    foreach( $search_directories as $search_directory )
    {
      //Recursively look in the directory specified
	  $directory_iterator = new RecursiveDirectoryIterator( $search_directory );
      $iterator_iterator = new RecursiveIteratorIterator( $directory_iterator, RecursiveIteratorIterator::SELF_FIRST );
 
      foreach( $iterator_iterator as $file )
      {
        //Look for the Class, but filter out some "garbage"
        if( false === strpos( $file->getFilename(), '~' )
          && 0 < strpos( $file->getFilename(), '.php' ) )
        {
          //if a php file is found, add it to the list.
		  self::$_cached_classes[ $file->getBasename( '.php' ) ] = $file->getPathname();
        }
      }
    }
  }
}
spl_autoload_register( array( 'Autoloader', 'load' ) );

So now, when I reference a class, the autoloader will check to see if a “cache” of all the filenames is available. If there is nothing available (usually on the first run), then a “cache” will be built.
After that, if a class name exists in the “cache”, we will include the class file.

Update (1/12/2012):
Thanks to Tommy for bringing to my attention that this made it to Reddit. It looks like I have been getting a bit of heat about the file IO. As pointed out in one of my comments, this is a basic implementation.

In my situation, I write the $_cached_classes variable to memcache after the build_class_cache() is run. From then on, every time a page is loaded, I check memcache to repopulate my $_cached_classes variable. Only when needed, will that variable be rebuild with build_class_cache().

I agree that this may not be the best method, especially with namespaces, but I wanted to bring some attention to the SPL.

Notes:

  1. http://php.net/manual/en/class.directoryiterator.php

Demystifying the PHP spl_autoload_register, spl_autoload and __autoload functions

Posted on December 2nd, 2011 by Wayne May in PHP | 1 comment

PHP has a nifty way to automatically load classes without the need to explicitly include class files. There is also a performance benefit, since only the unnecessary class files are loaded.

The traditional way to autoload in PHP was to make use of the __autoload function. The problem with this function is that it can only be used once. So if another library adds an __autoload function, the first one will be overwritten. PHP 5 changed this with then new SPL (Standard PHP Library) autoloader functions.

Autoload functions are now added to a stack and called in order. To add a new function to the stack simply add the callback function with spl_autoload_register 1. For example:

1
2
3
4
5
function my_autoloader( $classname )
{
  //do something here...
}
spl_autoload_register( 'my_autoloader' );

You can also use a class member to autoload. For example, lets say I wanted to create an Autoloader class, with a load member:

1
2
3
4
5
6
7
8
class Autoloader
{
  public static function load( $classname )
  {
    //do something here...
  } 
}
spl_autoload_register( array( 'Autoloader', 'load' ) );

Callback functions can be unregistered using spl_autoload_unregister 2.

If your current code has an __autoload function and you need to support it for legacy reasons, you must explicitly add the __autoload function to the stack.

If your code has an existing __autoload function then it must be explicitly registered on the __autoload stack. Failing to register it would mean that

1
2
3
4
if( function_exists( '__autoload' ) ) 
{
    spl_autoload_register( '__autoload' );
}

An example of a very simple autoloader:
index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final class Autoloader
{
  public static function load( $classname )
  {
    $classfile = __DIR__ . "/classes/{$classname}.php";
    if( file_exists( $classfile ) )
    {
      include $classfile;
    }
  } 
}
spl_autoload_register( array( 'Autoloader', 'load' ) );
 
$test = ClassLoadedWithAutoloader();

ClassLoadedWithAutoloader.php

1
2
3
4
class ClassLoadedWithAutoloader
{
  //class content
}

In the first file, index.php, I create an object of the class ClassLoadedWithAutoloader, which is in the /classes/ClassLoadedWithAutoloader.php file, but I am never explicitly including it, the autoloader is doing this for me.

Notes:

  1. http://us.php.net/manual/en/function.spl-autoload-register.php
  2. http://us.php.net/manual/en/function.spl-autoload-unregister.php