Skip to content
December 17, 2011 / J A Burrows

What to Look for in PHP 5.4.0

PHP 5.4.0 will arrive soon. The PHP team is working to bring to some very nice presents to PHP developers. In the previous release of 5.3.0 they had added a few language changes. This version is no different. Some of the other changes include the ability to use DTrace for watching PHP apps in BSD variants (there is a loadable kernel module for Linux folks). This release features many speed and security improvements along with some phasing out of older language features (Y2K compliance is no longer optional). The mysql extensions for ext/mysql, mysqli, and pdo now use the MySql native driver (mysqlnd). This release also improves support for multibyte strings.

Built-in Development Server

In the past, newcomers to PHP needed to set up a server. There was no built in server like a few other languages/web frameworks already had. If developing on *nix, a server needed to be set up with the right modules and the the files to tested needed to be copied over to the document root. Now, you can just run PHP with some options to get a server:

$ php -S localhost:1337

It runs in the current directory, using index.php or index.html as the default file to serve. A different document root can be specified as either an absolute or relative path:

$ php -S localhost:1337 -t /path/to/docroot

The server will log requests directly to the console. Interestingly, this server will not serve your static files unless your script return false. Existing frameworks will need to be modified to add in functionality that is commonly in rewrite rules. This is really all that is needed:

// If we're using the built-in server, route resources
if (php_sapi_name() == 'cli-server') {
  /*
   * If the request is for one of these image types, return false.
   * It will serve up the requested file.
   */
  if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"]))
    return false;
}
// Process the rest of your script

One of the inconveniences of the server is lack of support for SSL. Granted, it is meant for development purposes only. However, some projects I’ve worked on required testing with SSL. Perhaps there will be demand for this once it’s out there.

An Overview of Traits

Traits are bits of code that other objects can use. Traits allow composing objects and they promote code reuse. The Self programming language, one of the precursors to the JavaScript language, introduced them. JavaScript, strangely, does not directly implement traits; instead it allows one to extend objects directly with other objects.

In PHP (and other languages), traits cannot be instantiated, only used to compose other objects. Traits do not imply inheritance, they just add methods to classes. They can be used with inheritance and interfaces. Traits could be used as standard implementations of interfaces, then one could easily compose classes that comply with certain interfaces.

Here is an example, demonstrating a simple use of traits:

<?php
/**
 * Define a trait called runner
 */
trait runner {
  // Does all the work
  public function run() {
    echo "Run, ".$this->name().", run!\n";
  }
  // Gets the name of the runner
  // Must be implemented by the class using the trait.
  abstract public function name();
}
/**
 * Define a class that uses the runner trait
 */
class runningPerson {
  // Use the runner trait
  use runner;
  // Used to store the person's name
  protected $name; // Constructor, assigns a name to the person
  public function __construct($name) {
    $this->name = $name;
  }
  // Retrieves the name of the person, required by runner trait
  public function name() {
    return $this->name;
  }
}
$gump = new runningPerson("Forrest");
$gump->run();

When a class implements a method that is also defined in a trait it uses, the method in the trait takes precedence and overrides the class method. If two traits implement the same method, the conflict needs to be resolved using the insteadof keyword, or given a new signature (only visibility and name can be changed) using the as keyword.

<?php
/**
 * Define traits with conflicting function names
 */
trait A {
  public function do_something(){
    echo "In A::do_something():\n";
    for($i = 0; $i < 10; $i++) {
      echo $i." ";
    }
    echo "\n";
  }
}
trait B {
  public function do_something(){
    echo "In B::do_something():\n";
    echo "Something else.\n";
  }
}
/**
 * Define a class using both traits
 * Prefers one over the other
 */
class ExampleA {
  use A, B {
    B::do_something insteadof A;
  }
}
/**
 * Define a class using both traits
 * Renames a function to use both
 */
class ExampleB {
  use A, B {
    A::do_something insteadof B;
    B::do_something as something_else;
  }
}

//Run examples
$testA = new ExampleA();
$testB = new ExampleB();
$testA->do_something();
$testB->do_something();
$testB->something_else();

More examples reside at the current PHP documentation for traits. If that documentation is lacking in substance, Wikipedia’s article on traits links plenty of background info.

Changes to Anonymous Functions

In PHP 5.3.x, working with anonymous functions needed a work around when stored in an array. The function needed to be stored in a temporary variable before it could be called. For instance:

$functions = array();
// assign an anonymous function to an array element
$functions['anonymous'] = function () {
  echo "Hello, the parser needs to make up a name for me...\n";
};
// to call it you had to do this:
$temp = $functions['anonymous'];
$temp();

Now, anonymous functions stored in an array can be called directly without first storing them in a temporary variable:

// assume $functions[] is still around.
$functions['anonymous']();

Closures in Classes

Closures defined inside of a class are automatically early bound to the $this variable. If a class method returns a closure, it retains access to the original class that defined it (along with all the public member properties and methods) no matter where it is passed. If assigned to a member property and called as a method, PHP issues a warning if it was called directly. If called as a local variable or by calling the Closure::__invoke() method (which it inherits), PHP issues no warning.

<?php
/**
 * Class that generates closures that reference a public method.
 */
class ClosureTest {
  private $value;

  public function setValue($value) {
    $this->value = $value;
  }

  public function getValue() {
    return $this->value;
  }

  public function getCallback() {
    return function() {
      return $this->getValue();
    };
  }
}

/**
 * Create a class that calls a closure.
 */
class ClosureCaller {
  private $callback;

  public function setCallback($callback) {
    $this->callback = $callback;
  }

  public function doSomething() {
    // Since this is a member variable, call Closure::__invoke().
    echo $this->callback->__invoke() . "\n";
  }
}

// Set up a class to generate closures that reference itself
$test = new ClosureTest();
$test->setValue(42);
$closure = $test->getCallback();
echo $closure() . "\n";

// Test calling a closure from another class
$testCaller = new ClosureCaller();
$testCaller->setCallback($test->getCallback());
$testCaller->doSomething();

Closures allow changing what object scope $this is bound to by calling the bindTo() method and passing in the new object to use as $this.

Currently, no consensus exists around letting closures bound to an object access the private and protected methods of that class. Additionally, PHP still needs to iron out the details around binding closures to static classes. One can find more details about closures, $this, and Closure::bindTo() at https://wiki.php.net/rfc/closures/object-extension

Outlook

There are a lot of established projects that may not immediately start taking advantage of these features, unless the community sees an obvious benefit to drastically changing their projects. When PHP 5.3.0 was released with namespace support and anonymous functions, new frameworks sprung up like Laravel (anonymous functions), FLOW3 (namespaces), Lithium (namespaces), and Symfony2 (namespaces). After PHP 5.4.0 is released, I’m sure new frameworks (or new versions, like Symfony2 vs. Symfony) will spring up around using traits to compose functionality and using the new $this functionality in closures defined in classes. The built in server definitely has some potential for making it easier for developers to debug their apps. It’s just a matter of time before frameworks start taking advantage of it.

Reference

PHP 5.4.0 Release Candidate 2 News

About these ads

13 Comments

Leave a Comment
  1. Lukas / Dec 21 2011 6:16 am

    Thx. nice write up. didn’t realize the part about static files with the build in server. btw .. towards the end your spell checker tricked you into writing “Symphony” instead of “Symfony”.

  2. Taylor Otwell / Dec 21 2011 8:03 am

    Thanks for the overview. I’m looking forward to seeing how the PHP community makes use of traits.

    • Jill Burrows / Dec 21 2011 12:51 pm

      You’re welcome. I’m curious to see what will happen with traits, too. They’re pretty powerful.

  3. Shane / Dec 21 2011 9:08 am

    FYI your link from hackernews is broken – has the wrong date.

    • Jill Burrows / Dec 21 2011 12:50 pm

      When I fixed the spelling issue using the iPhone app, it used a past revision and changed the permalink. Fixed now.

  4. Bryan Helmig / Dec 21 2011 1:20 pm

    If you want to test SSL locally, check out stunnel.

  5. s0ak / Dec 21 2011 3:39 pm

    Zend is ruining the language I really liked…

  6. Mohamed Shiraz / Dec 22 2011 9:11 pm

    Excellent write-up.. yes, very powerful and useful features

  7. Szczepan Hołyszewski / Dec 28 2011 12:15 pm

    I don’t really get the purpose of the insteadof keyword. It seems redundant. Can this keyword be used to say something semantically different than “a::b insteadof *any* clashing b”?

  8. Grigor Gatchev / Dec 30 2011 10:22 am

    I can’t see a starting part of the code in the runner trait example – have you missed it, or I lost it somehow? :-)

    • Jill Burrows / Dec 30 2011 11:52 am

      Grigor, I moved it back to a prior revision. It should be whole again. I’m not sure what happened to it.

  9. Hari K T K T / Jan 6 2012 9:27 am

    Wow good one . Ya 5.4 framework has already begun :) , see https://github.com/auraphp

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 2,118 other followers

%d bloggers like this: