Preparing for PHP 5.4

PHP 5.4 which is set to be released in late 2011 has several changes and enhancements from PHP 5.3. Roughly, these changes are:

  • Array dereferencing and notation
  • Traits
  • New and Deprecated Functionality
  • Closure changes
  • Upload Progress, Built-in HTTP server
  • Miscellaneous Changes

A very useful addition to PHP 5.4 is array dereferencing and an alternate JSON-like notation.

Arrays

Dereferencing

You can now call a function which returns an array and immediately access values from it.

in PHP 5.3 and below you had to assign an array to a variable before using values from it. $result = foobar(); print $result[0];

in PHP 5.4 you can access values without assigning the variable print foobar()[0];

Notation

PHP arrays can now be created similarly to JSON arrays with square brackets [] $array_1 = ['a', 'b', 'c', 8, 9, 10]; $array_2 = ['a', 'dog' => 'snoopy', 'c', 'cat' => 'garfield', 7 => 12]; Of course, the PHP '=>' operator is not used in JSON.

The older PHP notation is still legal, namely: $array_1 = array('a', 'b', 'c', 8, 9, 10); $array_2 = array('a', 'dog' => 'snoopy', 'c', 'cat' => 'garfield', 7 => 12);

Traits

Although used in many other programming languages, I must admit that traits are new to me.

Traits are designed as a method for ("horizontal") code reuse that does not require inheritence. This allows for more reused functionality while still enforcing single inheritence in PHP. Heirarchy remains flatter than if multiple inheritance where allowed. Traits help eliminate code duplication.

In PHP 5.4, trait is a reserved keyword. The best way to learn about traits is to see them in action. Example:

<?php class A extends B { function e() { echo "foo"; } function f() { echo "bar"; } } class C extends D { function e() { echo "foo"; } function f() { echo "bar"; } } ?>

In this scenario, classes A and C extend different parent classes (assume B and D are not related). They both implement two identical functions, e and f.

With traits, you can change the above example into:

<?php trait g{ function e() { echo "foo"; } function f() { echo "bar"; } } class A extends B { use g; } class C extends D { use g; } ?>

Now we have a trait, g, which has both the e and f function. In our classes we can "use g;". From this simple example, you can see that we have eliminated duplicate code.

To invoke method e or f, you would do so as if they were methods defined within our class: $a = new A(); $a->e(); //foo $a->f(); //bar

Now you are probably asking, why would I use a trait over say a static class? One reason is that with a trait you can use the parent:: operator.

<?php trait g{ function e() { parent::e(); echo "foo"; } } class A extends B { use g; } class B { function e(){ echo "baz"; } } ?> $a = new A(); $a->e(); //bazfoo

Invoking function e, calls the trait function e, which then calls the parent class of A, B. So B->e() is invoked. Followed by the remainder of g->e()

What if you override a trait method? <?php trait g{ function e() { parent::e(); echo "bar"; } } class A extends B { use g; function e(){ echo "meow meow"; } } class B { function e(){ echo "baz"; } } ?> $a = new A(); $a->e(); //meow meow

In this example, A->e() is implemented and invoked instead of g->e().

Multiple traits:

<?php trait g{ function e() { echo "bar"; } } trait h{ function i() { echo "king"; } } class A{ use g, h; } ?> $a = new A(); $a->e().$a->i(); //barking

We are using both traits g and h.

What we have conflicting method names? Imagine that you have a situation like that below:

<?php trait g{ function e() { echo "bar"; } } trait h{ function e() { echo "king"; } } class A{ use g, h; } ?>

In this situation, PHP will not try to guess which version of e you want to use. This will be a fatal error!

The solution to this dilemna is to explicitly tell PHP which method you want to use. To use trait g's version of e, you would define:

class A{ use g, h{ g::e insteadof h; } } $a->e(); //bar To use trait h's version instead: class A{ use g, h{ h::e insteadof g; } } $a->e(); //king Ok, great. But what if you want to use both? Then you choose one and pick an alias for the other. class A{ use g, h{ g::e insteadof h; h::e as e2; } } $a->e(); //bar $a->e2(); //king

Traits can get more complex. Without going into further depth, traits can also:

  • use other traits (nesting)
  • have abstract methods
  • use static variables and methods
  • have their visibility set (public, protected, private, final) on a per class basis

New and Deprecated Functionality

New Functionality

int http_response_code([int $response_code]) //get current HTTP response code //if parameter passed, than set HTTP response code header_register_callback()
php.ini

default_charset is now UTF-8

Deprecated Functionality

session_register() session_unregister() session_is_registered() import_request_variables() //variable break and continue statements break $var; continue $var; //however fixed values still work //example: break 2; continue 3;

php.ini

deprecated register_globals register_long_arrays safe_mode allow_call_time_pass_reference define_syslog_variables highlight.bg session.bug_compat42 session.bug_compat_warn y2k_compliance magic_quotes

Closure $this support

The simplest explanation I have found is on stackoverflow

In PHP 5.3 if you tried the following:

<?php class A { private $value = 1; public function getClosure() { return function() { return $this->value; }; } } $a = new A; $fn = $a->getClosure(); echo $fn(); //Fatal error: Using $this when not in object context

You would receive a fatal error. This is not the case in PHP 5.4.

<?php class A { private $value = 1; public function getClosure() { return function() { return $this->value; }; } } $a = new A; $fn = $a->getClosure(); echo $fn(); //1

Upload Progress and Built-in Server

Built in webserver

The CLI (Command Line Interface) will have a built-in webserver for use with development only. //example $ cd ~/public_html $ php -S localhost:8000

Upload Progress

<form action="upload.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="<?php echo ini_get(" session.upload_progress.name");="" ?="">" value="foobar" /> <input type="file" name="file1"> <input type="submit"> </form> With the hidden form element, you can poll the server multiple times for file progress. In the example about, you would check $_SESSION["upload_progress_foobar"]

Miscellaneous Changes

E_ALL now includes E_STRICT

//PHP 5.3 error_reporting(E_ALL ^ E_STRICT); //PHP 5.4 equivalent error_reporting(E_ALL); This is a nice change.

Indirect method call through array

An array of form `array('class_name', 'method_name') can now be used to call a function.

class Foo { public function bar($name) { echo $name; } } $f = array('Foo','bar'); echo $f('Bertrand'); //Bertrand

I am not crazy about this addition, but then again I have never used is_callable. Too much magic for my liking.

More Information

There are other subtle improvements in PHP 5.4. The full list is available at http://www.php.net/releases/NEWS_5_4_0_alpha1.txt. Another interesting link shows the full list of nominated changes for PHP 5.4 and the voting results.

Let me know of any upcoming PHP features that you think are great and that I may have missed.

taxonomy: 

Add new comment