PHP 5.
しかし、
PHP 5.3とPHP6
PHP 5.
PHP 6は正式にUnicodeがサポートされるようになります。Unicodeがサポートされる、
- PHP 5.
x: echo strlen('日本語'); // 9を出力 - PHP 6.
x: echo strlen('日本語'); // 3を出力
マルチバイト文字列の計算が正しく行われるようになるのです。文字列型は文字列とバイナリの両方を保存できるコンテナのようなデータ型になります。アプリケーションは文字列とバイナリを必要に応じて区別しなければならないケースが発生します。文字列型の仕様変更は過去のアプリケーションの動作に大きく影響します。さらに、
PHP 5.
PHP 5.2とPHP 5.3
PHPはマイナーバージョンアップが行われると、
しかし、
PHP 5.
PHP 5.3かPHP 5.2か?
既にアプリケーションを開発し、
これから新規にアプリケーションを開発する場合、
しかし、
もしPHP 5.
PHP 5.
PHP 5.3とフレームワーク
PHP 5.
特にフレームワーク開発者に嬉しい機能は、
PHP 5.3の目玉機能
PHP 5.
- 名前空間のサポート
- レイトスタティックバインディング
- クロージャ
目玉機能呼ぶにはあまりふさわしくありませんが、
今回はこれら3つ
名前空間のサポート
名前空間とは、
名前空間サポートにより追加された機能
- 名前空間を定義するnamespace文
- 名前空間のエイリアスを定義するuse文
- 名前空間名を保存した特殊定数__
NAMESPACE__定数
ソフトウェアを開発する場合に、
今まではクラス名や関数名にプレフィックスを付けて名前の衝突を回避してきました。名前空間機能を使用すると名前の衝突を自由に回避できます。
名前空間の使い方
PHPの名前空間はnamespace文で定義されます。名前空間の区切り文字は
デフォルトの名前空間の名前はなく、
<?php
echo \strlen('abc'); // 3を出力
?>
<?php
namespace my\name\space;
const MY_CONST = 1;
?>
名前空間は最初に定義されなければなりません。PHPは埋め込み型言語ですが、
<html>
<?php
namespace MySpace;
?>
Fatal error: Namespace declaration statement has to be the very first statement in the script in /home/yohgaki/ext/src/php/php-5.3.0/- on line 3
名前空間の宣言は最初の文でなければなりませんが、
<?php
namespace X;
const A = 1;
namespace Y;
const A = 2;
echo \X\A.' '.A; // \を付けるとデフォルトの名前空間からアクセスできる
// \X\A で最初のconst A=1;にアクセス
// Aのみの場合、現在有効な\Y名前空間のA(2つ目のconst A=2)にアクセス
?>
1 2
名前空間の設定はファイル単位です。つまり、
<?php
function bar() { echo __FUNCTION__.PHP_EOL; }
?>
<?php
namespace MySpace;
function bar() { echo __FUNCTION__.PHP_EOL; }
include 'test.php';
bar(); // MySpace\bar()
\bar(); // test.phpのbar()
?>
MySpace\bar bar
出力を見ると
- MySpace\bar
のように、
名前空間だけを知りたい場合もあるでしょう。現在の名前空間名を保存した特殊定数__
<?php
namespace A;
echo __NAMESPACE__.PHP_EOL;
namespace B;
echo __NAMESPACE__.PHP_EOL;
namespace X;
echo __NAMESPACE__.PHP_EOL;
?>
A B X
名前空間名は非常に長くなる場合もあります。\very\long\name\space\name\function()のようにアクセスしなければならないのでは使いづらいです。この問題を解決するために名前空間名を別の名前
<?php
namespace very\long\name\space\name;
function foo() { echo __FUNCTION__.PHP_EOL; }
namespace short;
function foo() { echo __FUNCTION__.PHP_EOL; }
use very\long\name\space\name as X; // エイリアスを定義
X\foo();
foo();
?>
very\long\name\space\name\foo short\foo
名前空間のエイリアス名でアクセスしても、
名前空間を利用するとフレームワーク/
レイトスタティックバインティング
レイトスタティックバインディングは継承により今までのPHPのクラスの静的バインディングの問題を解消する機能で、
追加された機能
staticキーワードをメソッド、
プロパティに利用可能となった (スタティックコールの制御) get_
called_ class関数が追加され、 呼ばれたクラス名が判別可能となった スタティックコールの場合に呼び出される、
特殊メソッドの__ getStatic, __ setStatic, __ callStaticが追加された
以前のPHPはこの機能が無かったため、
レイトスタティックバインディングの使い方
レイトスタティックバインディングの効果は次のコードを理解できます。
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
A
Aクラスのメソッドにアクセスしたい場合もあるでしょう。しかし、
ORマッパーのようなクラスライブラリを実装する場合、
PHP 5.
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // レイトスタティックバインディング
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
B
PHP 5.
static::who(); // レイトスタティックバインディング
は
self::who(); // スタティックバインディング
と書くしかありませんでした。これではBクラスから呼び出しても、
A
になってしまいます。ベースとなるTableクラスを多数の実在するテーブルクラスで継承して利用る場合、
この例では動作が理解できても、
<?php
// 通常のシングルトン。継承不可
class Singleton {
private static $singleton;
final public static function getInstance() {
if (Singleton::$singleton === null) {
$className = __CLASS__;
Singleton::$singleton = new $className();
}
return Singleton::$singleton;
}
}
// 継承可能なシングルトン
class ExtendableSingleton {
protected static $singleton = array();
final public static function getInstance() {
$className = get_called_class(); // レイトスタティックバインディングのクラス名
if (!isset(self::$singleton[$className])) {
self::$singleton[$className] = new $className();
}
return self::$singleton[$className];
}
final protected function __clone() { throw new Exception('Should not clone object'); }
}
class MySingleton extends Singleton {}
class AnotherSingleton extends Singleton {}
$o1 = MySingleton::getInstance();
$o2 = AnotherSingleton::getInstance();
if ($o1 === $o2) {
echo '$o1 === $o2, want diffrent one...', PHP_EOL;
} else {
echo 'expecting this, but it\'s not', PHP_EOL;
}
class StaticMySingleton extends ExtendableSingleton {}
class StaticAnotherSingleton extends ExtendableSingleton {}
$o1 = StaticMySingleton::getInstance();
$o2 = StaticAnotherSingleton::getInstance();
$o3 = StaticMySingleton::getInstance();
if ($o1 === $o2) {
echo '$o1 === $o2, something wrong', PHP_EOL;
} else {
echo 'should be differ', PHP_EOL;
}
if ($o1 === $o3) {
echo '$o1 === $o3', PHP_EOL;
} else {
echo 'something wrong', PHP_EOL;
}
?>
$o1 === $o2, want diffrent one... should be differ $o1 === $o3
期待通りの出力が得られています。
レイトスタティックバインディングにより、
レイトスタティックバインディングはクラスライブラリを作成する開発者にとっては、
次回は残りの目玉機能のひとつである