Late Static Bindings

PHP version 5.3 was a significant improvement: namespace support, closures, the intl library, and late static bindings.

Here is a practical example: making a static call to a __construct() method.

Sample code

  1. The __construct() method returns $this, the class instance.
  2. The new() static method makes a static call possible.
namespace Nevvix\Helper;

class L10n {

    protected $locale;

    public function __construct($locale) {
        $this->locale = $locale;
        return $this;
    }

    static public function new($locale) {
        return new static($locale);
    }

    public function currency($value, $currency = NULL) {
        $fmt = numfmt_create($this->locale, NumberFormatter::CURRENCY);
        $currency = $currency ?: numfmt_get_symbol($fmt, NumberFormatter::INTL_CURRENCY_SYMBOL);
        return numfmt_format_currency($fmt, $value, $currency);
    }
}

Object Oriented usage

$L10n = new L10n('en_US');
echo $L10n->currency(1000), PHP_EOL;
echo (new L10n('en_US'))->currency(1000), PHP_EOL;

Results:

$1,000.00
$1,000.00

Static call usage

$L10n = L10n::new('en_US');
echo $L10n->currency(1000), PHP_EOL;
echo L10n::new('en_US')->currency(1000), PHP_EOL;

Same results.

Difference

  1. The __construct() returns $this, so you can chain methods from it if you wrap the new call in parentheses.
    • (new L10n($html))->currency()
  2. When you call the static new() method, you can chain directly after it without parentheses.
    • L10n::new($html)->currency()

Practicality

A static call is useful when you have a helper library that is available globally: in your application code, but also embedded in an HTML template.

Dependency injection

I want the object-oriented functionality to be able to inject in other class methods:

namespace Nevvix\ProjectManager\App;

use Nevvix\Helper\L10n;

class Invoice {

    public function __construct(...) {
        ...
        return $this;
    }

    public function currency(L10n $L10n, $locale, $number) {
        return $L10n->currency($number);
    }
}
$invoice = new Invoice();
echo $invoice->currency('en_US', 1000);
$1,000.00

Templates

I want to call L10n methods on demand in a template from another part of the application.

<!DOCTYPE html>
<html>
    <head>
        <title><?= _('Market Prices'); ?></title>
    </head>
    <body>
        <table>
            <tr>
                <th><?= _('USD'); ?></th>
                <th><?= _('GBP'); ?></th>
            </tr>
            <tr>
                <td><?= L10n::new('en_US')->currency($number); ?></td>
                <td><?= L10n::new('en_GB')->currency($number); ?></td>
            </tr>
        </table>
    </body>
</html>