C H A P T E R  5

Cutting Edge

This chapter will introduce the new features of PHP 5.3. These new features include name spaces, closures, the new text format known as nowdoc, and the goto statement. This final innovation is sort of a blast from the past, still as much despised as it was when the first fully procedural languages, such as Pascal, started to gain popularity among programmers. Regular use of the goto statement is still very much frowned upon; one could even argue that its use is a deadly sin among programmers. The controversy was started by the famous paper “Go To Statement Considered Harmful” (Edsger Dijkstra, 1968), and the goto statement has been considered suspect ever since. Having an option, however, is never bad. Programming is not a religion; the goals are simplicity, clarity, and efficiency. If the goto statement can help programmers reach these goals, using it makes perfect sense.

The goto statement, controversial as it might be, is not the most important new feature of PHP 5.3. Namespaces are by far the most important new feature. Important, too, are anonymous functions, also known as closures or lambda functions, which enable a whole slew of the new programming methods without polluting the global namespace.

There is also new document format, called nowdoc, which is similar to heredoc, but more versatile for certain situations. PHP 5.3 is also the first version containing standard the PHP library (SPL) as an integral part of the language. In earlier versions, SPL was an extension. Last but not least, there are PHP archives, known as phar, which enable users to create files similar to Java JAR archives, which contain the entire application.

Namespaces

Namespaces are a standard feature of many programming languages. The problem solved by namespaces is the following: one of the very frequently used methods of communication among different subprograms is communicating through global variables. Many programming libraries have global variables used by a multitude of other routines. As the language grows and the number of different programming libraries grows, the probability of clashing variable names grows exponentially. Namespaces help with compartmentalizing the global namespace and avoiding the variable name clashes, which could lead to strange and unpredictable bugs. PHP did not have namespaces until version 5.3. The need for namespaces arose because of the growth of the language itself. Namespaces are syntactical objects that can contain classes, functions, or constants. They are ordered hierarchically, and can contain sub-namespaces.

Namespace syntax is extremely simple and easy to follow. Listing 5-1 consists of three files that demonstrate how to define namespaces and how to use them. The first file, domestic.php, defines class animal and initializes its instances to the value dog. The second file, wild.php, also defines the same class animal, this time in the namespace wild, and initializes its instances to the string tiger. Finally, script5.1.php shows how to use it.

Listing 5-1. Using Namespaces

domestic.php :

<?php
class animal {
    function __construct() {
        $this->type='dog';
    }
    function get_type() {
        return($this->type);
    }
}
?>
wild.php :
<?php
namespace wild;
class animal {
    function __construct() {
        $this->type='tiger';
    }
    function get_type() {
        return($this->type);
    }
}
?>
script5.1.php :
#!/usr/bin/env php
<?php
require_once('domestic.php'),
require_once('wild.php'),
        $a=new animal();
        printf("%s ",$a->get_type());
        $b=new wildanimal();
        printf("%s ",$b->get_type());
        use wildanimal as beast;
        $c=new beast();
        printf("%s ",$c->get_type());
?>

The execution produces the expected result, as shown in the following:

./script5.1.php
dog
tiger
tiger

The namespace wild is defined in the file wild.php. Without defining the namespace, our class produces a completely different result. Once namespace is defined, a class can only be addressed by using namespaceclass convention. It is also possible to import the namespace into the local name space by using use statement and to alias it with a more convenient name. Namespaces define blocks of statements. If there is more than one namespace in the file, it must be enclosed in curly brackets, as in Listing 5-2.

Listing 5-2. A File with Multiple Namespaces

animals.php:
<?php
namespace animalwild {
  class animal {
      static function whereami() { print __NAMESPACE__." "; }
      function __construct() {
        $this->type='tiger';
      }
      function get_type() {
          return($this->type);
      }
  }
}

namespace animaldomestic {
  class animal {
      function __construct() {
          $this->type='dog';
      }
      function get_type() {
          return($this->type);
      }
  }
}
?>

Here we can also see sub-namespaces, separated by the backslash character “.” There is also a constant __NAMESPACE_, which will contain the current namespace name. It's very similar to the other PHP special constants, such as __FILE__ or __CLASS__. Listing 5-3 shows how to use it in a script.

Listing 5-3. Using Sub-namespaces in a Script

<?php
require_once('animals.php'),
use animalwildanimal as beast;
$c=new beast();
printf("%s ",$c->get_type());
beast::whereami();
?>

The function whereami was made static, so it can only be called in class context, not an object context. The syntax for calling a function in the class context is class::function($arg). Such calls are not tied to particular object and are called class context calls.

The class animalwildanimal was aliased into beast and its names were imported into the local namespace. Operations such as calling class functions are also allowed on the imported namespaces.

There is also the predefined global namespace. All the normal functions are part of the global namespace. Calling a function phpversion() is completely equivalent to calling the function phpversion() without the “” prefix, as shown here:

php -r 'print phpversion()." ";'
5.3.3

Although creating a local version of the built-in functions is never a good idea, prefixing the function name with “” will make sure that the version being called is one from the global namespace, not the local variety.

Namespaces and Autoload

In previous chapters, you learned about the __autoload function, which is used to load the classes into the program. In other words, the __autoload function can help with automating the require_once directive from Listing 5-3.

The bare bones auto-loading function looks like this:

function __autoload($class) {
    require_once("$class.php");
}

When the class in question contains namespaces, the full path is passed to __autoload function.

Let's modify Listing 5-3 to read like this:

<?php

function __autoload($class) {

    print "$class ";

    exit(0);

}

use animalwildanimal as beast;

$c=new beast();

printf("%s ",$c->get_type());

beast::whereami();

?>

When executed, the result would be the full path:

animalwildanimal

In order to use namespaces with autoload, we should develop a directory hierarchy, replace the backslash characters with the forward slashes, and include the file. Replacing the characters can be done using either the str_replace or preg_replace functions. For simple tasks like this, the str_replace function is cheaper than preg_replace.

Namespaces Conclusion

Namespaces are abstract containers created to hold a logical grouping of object names. They are well-known features common to other languages, and are sometimes called packages or modules. Scripts are getting bigger and more complex every day, which is making inventing new identifiers harder and harder. In this chapter, we've been working with two different classes, both called animal. With such a naming convention, it is practically guaranteed that you will have clashes that introduce nasty bugs. With namespaces, we were able to always refer to the right class and even to alias the class names with more convenient names, as needed.

Namespaces are very new, at least in PHP; very few software packages (additional PHP Libraries) use them, but namespaces are also an essential and very welcome language feature. I have no doubt that you will find this particular feature extremely useful.

Anonymous Functions (Closures)

This is actually not a new feature; it has been available since PHP 4.0.1, but the syntax has become much more elegant. In earlier versions of PHP, it was also possible to create an anonymous function using the create_function built-in function. Anonymous functions are usually very short, and are used as callback routines in many other functions. Here is a sample script that will sum up the values in an array, using the array_reduce() built-in function. The array_map and array_reduce functions are PHP implementations of the Google map-reduce algorithm. Function array_reduce() is called recursively on an array to produce a single-value output.

The syntax for the array_reduce function is very simple: array_reduce($array,callback_function). The callback function has two arguments: the first is returned by the previous iteration; the second is the current array element. Listing 5-4 shows the script.

Listing 5-4. The array_reduce Function

<?php
$y = 0;
$arr = range(1, 100);

// $sum=create_function('$x,$y','return($x+$y);'),
$sum = function ($x, $y) {
    return ($x + $y);
};
$sigma = array_reduce($arr, $sum);
print "$sigma ";
?>

The anonymous function was created and stored into the variable $sum. Commented out is the old way of doing things, using the create_function solution. The new way is much more elegant. Both methods function identically, producing the same output.

Also, anonymous functions can be returned from the function as a return value. PHP rules of visibility prevent the variable from the outer scope from being visible in the internal, which means that the arguments from the external function cannot be accessed in the internal function. To access the argument from the enclosing function in the function being returned, we have to use a global variable. The whole thing would look like this:

function func($a) {
    global $y;
    $y = $a;
    return function ($x) {
        global $y;
        return $y + $x;
    };
}

That would return an anonymous function that depends on a global variable. The term “closure” comes from Perl, which has different scope rules that enable somewhat different uses. In PHP, closures are primarily used for creating short callback functions and to prevent wasting a global name on something that is not really necessary. This new way of creating anonymous functions, though syntactically elegant, is nothing really new.

Nowdoc

Nowdoc is a new way of inserting free form text into the script. It looks almost like a heredoc but with one essential difference: nowdoc is not further parsed, which makes it ideal for inserting PHP code or even SQL commands. Oracle RDBMS, for instance, has internal tables with names starting with “V$.” Before PHP 5.3, each and every dollar sign in the queries had to be “escaped” with a backslash, like this:

$FILE="select
           lower(db_name.value)  || '_ora_' ||
           v$process.spid ||
           nvl2(v$process.traceid,  '_' || v$process.traceid, null ) ||
           '.trc'
       from
       v$parameter db_name
       cross join v$process
       join v$session
       on v$process.addr = v$session.paddr
       where
           db_name.name  = 'instance_name' and
       v$session.sid=:SID and
       v$session.serial#=:SERIAL";

Without the nowdoc syntax, this query had to be written exactly like that, which is tedious and ugly. The nowdoc syntax allows queries like this to be entered without the ugly backslash characters. The heredoc syntax looks like this:

$FILE= = <<<EOT
select
           lower(db_name.value)  || '_ora_' ||
           v$process.spid ||
           nvl2(v$process.traceid,  '_' || v$process.traceid, null ) ||
           '.trc'
       from
       v$parameter db_name
       cross join v$process
       join v$session
       on v$process.addr = v$session.paddr
       where
           db_name.name  = 'instance_name' and
       v$session.sid=:SID and
       v$session.serial#=:SERIAL;
EOT;

The new newdoc syntax looks like this:

$FILE = <<<'EOT'
select
           lower(db_name.value)  || '_ora_' ||
           v$process.spid ||
           nvl2(v$process.traceid,  '_' || v$process.traceid, null ) ||
           '.trc'
       from
       v$parameter db_name
       cross join v$process
       join v$session
       on v$process.addr = v$session.paddr
       where
           db_name.name  = 'instance_name' and
       v$session.sid=:SID and
       v$session.serial#=:SERIAL;
EOT;

The only differences are the single quotes around the ending identifiers and the removed backslash characters escaping the dollar signs. Everything else is exactly the same.

images Note Rules for the “end of text” identifier are exactly the same; there must not be any preceding spaces or spaces trailing the semicolon character.

To see the difference, let's take a look at the code snippet shown in Listing 5-5.

Listing 5-5. The Difference Between heredoc and nowdoc

<?php
class animal {
    public $species;
    public $name;
    function __construct($kind,$name) {
        $this->species=$kind;
        $this->name=$name;
    }
    function __toString() {
        return($this->species.'.'.$this->name);
    }
}

$pet = new animal("dog","Fido");
$text = <<<'EOT'
    My favorite animal in the whole world is my {$pet->species}.
    His name is {$pet->name}.
    This is the short name: $pet
EOT;

print "NEWDOC: $text ";
$text = <<<EOT
    My favorite animal in the whole world is my {$pet->species}.
    His name is {$pet->name}.
    This is the short name: $pet
EOT;
print "HEREDOC: $text";

The same text is first defined as PHP 5.3 newdoc text and then as the usual and well-known heredoc text. The output clarifies the difference between the two ways for string specification within the script:

NEWDOC:
    My favorite animal in the whole world is my {$pet->species}.
    His name is {$pet->name}.
    This is the short name: $pet
HEREDOC:
    My favorite animal in the whole world is my dog.
    His name is Fido.

    This is the short name: dog.Fido

The first version, new in PHP 5.3, doesn't interpret anything. Embedded variable references, variables themselves, and even special characters are shown exactly as they appear in the text. That's the beauty of the nowdoc format. The old heredoc version interprets everything: variable references, variable names, and special characters. This feature is primarily intended for inserting PHP or other code into the scripts. Something like the following would be much harder with heredoc:

<?php
$x = 10;
$y = <<<'EOT'
    $x=$x+10;
EOT;
eval($y);
print "$x ";
?>

With the new nowdoc format, inserting SQL, PHP code and dynamic execution just got a lot easier. Nowdoc is not a replacement for heredoc format, which is still very useful for applications that need simple templating and don't require the full power of the Smarty engine. Smarty is the most popular template engine used with PHP. It has many options and possibilities, and is far more complex than the new nowdoc format. Nowdoc is just an aid to utilize when it's necessary to insert code as a string into a PHP script.

Local goto Statements

PHP 5.3 introduced the highly controversial local goto statement (where the adjective “local” means that it is not possible to jump out of the routine or into a loop). In some languages, most notably C, it is also possible to do “non-local goto” or “long jump,” but that is not possible with PHP. The limitations for the local goto statement are the same as with the other languages: no jumping into the loop and no jumping outside of the current subroutine.

The goto statement is provided as an option of last resort, not as something that should be used regularly. The syntax is extremely simple. Listing 5-6 illustrates a while loop rewritten to use a goto statement instead:

Listing 5-6. A goto Statement Sample

<?php
$i=10;
LAB:
    echo "i=",$i--," ";
    if ($i>0) goto LAB;
echo  "Loop exited ";
?>

Labels are terminated by a colon. This little script produces the expected output:

i=10
i=9
i=8
i=7
i=6
i=5
i=4
i=3
i=2
i=1
Loop exited

I have no real example of goto statement, because I haven't had the need for it. I expect this to be the least used of all new features in PHP 5.3. It is, however, nice to know that it is there, should it ever be needed. Once again, using goto statements is frowned upon among programmers. However, programming, as mentioned earlier, is not a religion; there are no dogmas or punishments for the sins against programming style. The ultimate goals are efficiency and clarity. If goto serves that purpose, it is a welcome option.

Standard PHP Library

The Standard PHP Library (SPL) is a set of classes, similar to the Standard Template Library (STL) in C++. SPL contains classes for standard-programming structures such as stacks, heaps, doubly linked lists, and priority queues, which can be extremely useful. The SplFileObject class was briefly mentioned in Chapter 1. The documentation for the SPL can be found here: http://us3.php.net/manual/en/book.spl.php.

The first class to show is SplMaxHeap. Basically, numbers are inserted into an object of the class SplMaxHeap, in a random order. When the numbers are retrieved, they are sorted in descending order. There is a completely identical class SplMinHeap, which sorts its element in the ascending order. Listing 5-7 contains the script.

Listing 5-7. SplMaxHeap script

<?php
$hp = new SplMaxHeap();
for ($i = 0;$i <= 10;$i++) {
    $x = rand(1, 1000);
    print "inserting: $x ";
    $hp->insert($x);
}
$cnt = 1;
print "Retrieving: ";
foreach ($hp as $i) {
    print $cnt++ . " :" . $i . " ";
}
?>

These classes can be extended and implemented for dates or strings or whatever data type. When this script is executed, the result looks like this:

./ttt.php
inserting: 753
inserting: 770
inserting: 73
inserting: 760
inserting: 782
inserting: 982
inserting: 643
inserting: 924
inserting: 288
inserting: 367
Retrieving:
1 :982
2 :924
3 :782
4 :770
5 :760
6 :753
7 :643
8 :367
9 :288
10 :73

Random numbers, generated by the rand function, are inserted into $hp in random order. When retrieved, they are sorted in descending order. This class can be used as is, like in the previous example, or can be extended. In case the class is extended, the child class is expected to implement the method compare. Listing 5-8 gives an example.

Listing 5-8. Extending the Class

<?php
class ExtHeap extends SplMaxHeap {
    public function compare(array $var1,array $var2) {
        $t1=strtotime($var1['hiredate']);
        $t2=strtotime($var2['hiredate']);
        return($t1-$t2);
    }
}

$var1=array('ename'=>'Smith','hiredate'=>'2009-04-18','sal'=>1000);
$var2=array('ename'=>'Jones','hiredate'=>'2008-09-20','sal'=>2000);
$var3=array('ename'=>'Clark','hiredate'=>'2010-01-10','sal'=>2000);
$var4=array('ename'=>'Clark','hiredate'=>'2007-12-15','sal'=>3000);

$hp=new ExtHeap();
$hp->insert($var1);
$hp->insert($var2);
$hp->insert($var3);
$hp->insert($var4);
foreach($hp as $emp) {
    printf("Ename:%s Hiredate:%s ",$emp['ename'],$emp['hiredate']);
}
?>

This is not as trivial as it looks at first glance. This script is sorting arrays, by a date value. The new compare function will not accept anything that is not an array as an argument. Dates are compared by converting them to the Epoch format. Our extension of the SplMaxHeap will sort the entries from the most recent to the oldest one:

./script5.6.php
Ename:Clark Hiredate:2010-01-10
Ename:Smith Hiredate:2009-04-18
Ename:Jones Hiredate:2008-09-20
Ename:Clark Hiredate:2007-12-15

In addition to the heap, stack, and queue classes, there are also very interesting classes for dealing with files. SplFileObject class was shown in Chapter 1 and will be used again in the database integration chapters. There are, however, more interesting file classes. The next interesting one is SplFileInfo. It returns the file information for the given file:

<?php
$finfo=new SplFileInfo("/home/mgogala/.bashrc");
print "Basename:".$finfo->getBasename()." ";
print "Change Time:".strftime("%m/%d/%Y %T",$finfo->getCTime())." ";
print "Owner UID:".$finfo->getOwner()." ";
print "Size:".$finfo->getSize()." ";
print "Directory:".$finfo->isDir()? "No":"Yes";
print " ";
?>

This class can get creation time, access time, name, owner, and all the information normally provided by the fstat function from the standard C library. Here is the output from this script:

./script5.7.php
Basename:.bashrc
Change Time:02/18/2011 09:17:24
Owner UID:500
Size:631
No

This class is interesting in itself, but is also needed to explain the FileSystemIterator class. This class, also a part of SPL, functions in the same way as Unix find command: it traverses the directory tree and returns an iterator through the results. Listing 5-9 shows the script that will print the names of all sub-directories in the /usr/local directory.

Listing 5-9. Printing Names of Sub-directories in the /usr/local Directory

<?php
$flags = FilesystemIterator::CURRENT_AS_FILEINFO |
              FilesystemIterator::SKIP_DOTS;
$ul = new FileSystemIterator("/usr/local", $flags);
foreach ($ul as $file) {
    if ($file->isDir()) {
        print $file->getFilename() . " ";
    }
}
?>

The flags regulate what will be returned. By setting the CURRENT_AS_FILEINFO flag, we required each iterator entry to be a file information object, a member of the SplFileInfo class. There is also the CURRENT_AS_PATHNAME flag, used to instruct objects of the FileSystemiterator class to return path names instead of the file information. Of course, file information contains the path name and all other available information, so it's the natural thing to call if looking for directories. The SKIP_DOTS flag instructs the iterator to skip the “.” and “..” directories. The output of this script looks like this on my system:

var
libexec
sbin
src
tora
bin
include
skype_static-2.1.0.81
man
lib
share
etc

Note that the output of this script may look different on another system. Windows installations, for example, usually don't have a directory called “/usr/local.” Another useful iterator is Globiterator, which is slightly different from the FileSystemiterator shown above. The Globiterator will go through the file system pattern, like “*.php”. Listing 5-10 gives a brief example of Globiterator class usage:

Listing 5-10. Globiterator class Usage

<?php
$flags = FilesystemIterator::CURRENT_AS_PATHNAME;
$ul = new Globiterator("*.php", $flags);
foreach ($ul as $file) {
    print "$file ";
}
?>

In this case, we are only interested in file names, so the CURRENT_AS_PATHNAME flag was used to do this. Of course, the flag CURRENT_AS_FILEINFO would be equally valid, while the flag SKIP_DOTS would make no sense.

SPL Conclusion

Technically speaking, SPL is not new in 5.3; it existed in 5.2 as well, but as a separate extension. It is, however, an integral part of PHP since version 5.3 and cannot be disabled or uninstalled, without uninstalling the entire PHP language itself. It is a rather large and developing extension with many useful parts. This chapter showed the most useful and practical ones, but there is much more to SPL than this chapter can cover. It is likely to grow, expand, and become even more useful in the future releases. Getting acquainted with SPL can certainly save a lot of effort and trouble with writing scripts. Personally, I find it extremely useful because of the built-in error checking and exceptions.

Phar Extension

Java is a very popular language on the Web. Java has *.jar archives that make it possible for the developers to pack several files into a single archive file and execute it as an application. In version 5.3, PHP created the phar extension with the same purpose. The purpose of this extension is to allow creation and manipulation of PHP archive files. Thus the name: Php Archive.

In Listing 5-1, we had a script that included two additional class files, wild.php and domestic.php. In order to distribute the application, we would need to distribute three files. If there were more classes, the number of files to distribute would grow even larger. The goal is to distribute only two files: the executable script itself and the phar file containing all of the necessary class files. In other words, the new version of the script from the Listing 5-1 will look like Listing 5-11.

Listing 5-11. Listing 5-1 Revised

<?php
include 'phar://animals.phar/wild.php';
include 'phar://animals.phar/domestic.php';
$a=new animal();
printf("%s ",$a->get_type());
$b=new wildanimal();
printf("%s ",$b->get_type());
?>

The trick is in the include directives, which include the file animals.phar and reference the files. How is such a file created? Just as Java has the program called jar, PHP 5.3 distribution comes with the program called phar. To get help, one needs to execute “phar help”. There are quite a few options, all of them very well documented.

Phar archiver is just a PHP script that uses the .phar extension. On most distributions it still doesn't have a manual page, so “phar help” is the best we can get. Now it's time to create our first phar archive. The syntax is very simple:

 phar pack -f animals.phar -c gz wild.php domestic.php

The “pack” argument instructs the “phar” program to create archive with the name given in the “-f” option and to pack the files “wild.php” and “domestic.php”. In order for that to succeed, the php.ini parameter phar.readonly must be set to “off.” Initially, this parameter is set to “on,” which prevents the archives from getting created. The compression algorithm to use is “zip.” Supported algorithms are zip, gz (gzip), and bz2 (bzip2). The default is no compression. With this, we can execute the script in Listing 5-2 without a problem. The output looks as expected:

dog
tiger

That is not all. PHP Archiver can do more than that. If we want to make sure that the archive is not tampered with, we can sign it:

phar sign -f animals.phar -h sha1

That will sign the file animals.phar with the very popular SHA1 algorithm and prevent tampering. Let's, just for fun, add an empty line to the file and try re-executing out the script in Listing 5-3. Here is the result:

./script5.3.php
PHP Warning:  include(phar://animals.phar/wild.php): failed to open stream: phar "/tmp/animals.phar" has a broken signature in /tmp/script5.3.php on line 3
PHP Warning:  include(): Failed opening 'phar://animals.phar/wild.php' for inclusion (include_path='.:/usr/local/PEAR') in /tmp/script5.3.php on line 3
PHP Warning:  include(phar://animals.phar/domestic.php): failed to open stream: phar "/tmp/animals.phar" has a broken signature in /tmp/script5.3.php on line 4
PHP Warning:  include(): Failed opening 'phar://animals.phar/domestic.php' for inclusion (include_path='.:/usr/local/PEAR') in /tmp/script5.3.php on line 4
PHP Fatal error:  Class 'animal' not found in /tmp/script5. 3.php on line 5

Include commands didn't work, our script failed miserably. That means that our scripts can be properly protected from tampering because modified scripts will not pass the signature validation. Phar can also extract files from the archive, and add and delete files. All commands are very simple and straightforward. Here is an example of the list command, which lists the content of the phar archive:

phar list -f animals.phar
|-phar:///home/mgogala/work/book/Chapter5/animals.phar/domestic.php
-phar:///home/mgogala/work/book/Chapter5/animals.phar/wild.php

Not only can phar list, it can also extract and delete archive members, just like its counterparts jar, ar, and tar. The syntax is very similar to the syntax of the list and insert commands. The command “phar delete -f animals.phar -e wild.php” would delete the script “wild.php” from the archive phar add -f animals.phar wild.php would add it back, and the command phar extract -f animals.phar -i wild.php would extract it from the archive. Phar can also work with regular expressions. This command will pack the entire directory into a phar archive named “test.phar”: “phar pack -f test.phar -c zip *.php

Filenames of the included files will be listed on the standard output. Phar can also create an executable script. In order to do that, we have to create so-called “stub.” Stub is script to which the control is transferred when the phar archive is executed. The format of this stub is somewhat specific. Here is our script from Listing 5-1, slightly modified, in order to use as the stub for our phar archive:

<?php
include 'phar://animals.phar/wild.php';
include 'phar://animals.phar/domestic.php';
$a=new animal();
printf("%s ",$a->get_type());
$b=new wildanimal();
printf("%s ",$b->get_type());
__HALT_COMPILER(); ?>

This file will be called “stub.php” and added to our archive as the “stub.” Note the __HALT_COMPILER() function at the end. This function must be there, to terminate the execution of the script. Also, there can be at most one space between the phar delimiter __HALT_COMPILER() and the script terminator (“?>”). Adding the stub is simple:

phar stub-set -f animals.phar -s stub.php

Note that when the file is added as a stub, it will not be shown as the part of the archive if listed by using “phar list.” It will be, however, possible to execute the archive as a PHP script:

php animals.phar
dog
tiger

On Unix-based systems, it also possible to add the “bang” at the beginning of the script, so that the script is executable from the command line. Here is the syntax:

phar stub-set -f animals.phar -s stub.php -b '#!/usr/bin/env php'

In Unix terms, the “#!/usr/bin/env php” is called the “bang” and it enables shell to find the appropriate interpreter to execute the script. The phar archive “animals.phar” can now be executed on the command line, of course, only after being made executable by OS:

./animals.phar
dog
tiger

We have created a fully contained application, which contains all of the classes and the stub needed to execute the archive. Phar program itself is actually a phar archive, which can be executed on the command line:

phar list -f /opt/php/bin/phar
|-phar:///opt/php/bin/phar.phar/clicommand.inc
|-phar:///opt/php/bin/phar.phar/directorygraphiterator.inc
|-phar:///opt/php/bin/phar.phar/directorytreeiterator.inc
|-phar:///opt/php/bin/phar.phar/invertedregexiterator.inc
|-phar:///opt/php/bin/phar.phar/phar.inc
-phar:///opt/php/bin/phar.phar/pharcommand.inc

It is possible to extract all the routines and study them. Phar is open source, just like the entire PHP language, so you are actually encouraged to do so. There is also an application programming interface (API) that enables phar archives to be created and manipulated by a PHP script.

Phar is a very simple yet important program. It will alter the way that PHP applications are distributed and packaged and will also, hopefully, save some space. It is a rather low-profile but extremely important extension available in PHP 5.3 and later. This extension didn't attract nearly as much attention as namespaces or the nowdoc format, but it will have profound impact on the way PHP applications are distributed. The intentions to use phar for scripts like PhpMyAdmin and pgFouine have already been announced.

Phar doesn't affect the script performance because archives are only parsed once. This time on the beginning of the script is minimal and, at least in my experience, doesn't affect the execution time. There is also an important caching mechanism called APC which allows caching of variables and the entire files. Alternative PHP Cache (APC) is an optional module that needs to be installed separately. It is, however, frequently used because of the great performance gains it can provide. In particular, the function apc_compile_file can be used to compile a PHP file to byte code, cache it, and use it as such, greatly increasing the speed. Phar is compatible with the latest APC and phar files can be cached using apc_compile file. APC is not automatically installed on PHP installations, so I will not cover it in detail but those interested in it can find the manual pages here:

http://us3.php.net/manual/en/book.apc.php

Summary

In this chapter, you learned about the important new features of PHP 5.3, such as the namespaces and the new newdoc format. You also learned about SPL, which was promoted to be an integral part of PHP as of PHP 5.3 and the phar extension, very low-key but also very important extension. There is no such thing as the most important point of this chapter. All the tools introduced here are on the proverbial “bleeding edge,” and can be immensely useful. Namespaces will appear more and more frequently and enable more and more elaborate application systems. Phar archives will enable packing of the entire application systems into a single file, thus making the application distribution much easier.

SPL is still developing, but the modules developed so far are extremely promising and useful. Using the PHP 5.2 and earlier version programming style is easy and requires no effort at all. However, PHP as a language is evolving extremely rapidly, and conscientiously restricting myself to the old versions would render my PHP programming skills obsolete and useless, for the large part. Learning the new stuff isn't hard; it's fun. I wholeheartedly recommend it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset