PHP入門 - その他
文字列をPHPスクリプトとして実行する(eval)
eval() は引数で指定した文字列を、PHPスクリプトとみなして実行します。
$str = 'echo "Hello!\n";'; eval($str);
スクリプトの末尾にデータを埋め込む
__halt_compiler()は、PHPスクリプトの解釈(コンパイル)を中止します。PHPスクリプトの末尾にデータを埋め込む際に利用されます。末尾データの先頭は、__COMPILER_HALT_OFFSET__ で参照できます。
$fp = fopen(__FILE__, "r");
fseek($fp, __COMPILER_HALT_OFFSET__);
echo stream_get_contents($fp); // ABCDEFG...が出力される
__halt_compiler();ABCDEFG
HIJKLMN
名前空間(namespace)
PHP5.3 で名前空間の機能が追加されました。例えば、下記のファイル構成で、A社が作成した foo ライブラリと、B社が作成した bar ライブラリでクラス名や関数名が重複していると、test.php からこれらを使用することができません。
test.php
lib
foo.php
bar.php
この問題を解決するため、namespace を用いて名前空間を指定します。foo.php、bar.php を下記の様に作成します。lib と foo の間はバックスラッシュ(\)です。
namespace lib\foo;
class MyClass { function __construct() { echo "MyClass of foo\n"; } }
function MyFunction() { echo "MyFunction of foo\n"; }
const MyConst = "MyConst of foo\n";
namespace lib\bar;
class MyClass { function __construct() { echo "MyClass of bar\n"; } }
function MyFunction() { echo "MyFunction of bar\n"; }
const MyConst = "MyConst of bar\n";
こうすると、MyClass, MyFunction, MyConst などの名称は、lib\foo\MyClass, lib\foo\MyFunction, lib\foo\MyConst などのように参照することが可能となります。
require "lib/foo.php"; require "lib/bar.php"; $obj1 = new lib\foo\MyClass(); $obj2 = new lib\bar\MyClass(); lib\foo\MyFunction(); lib\bar\MyFunction(); echo lib\foo\MyConst; echo lib\bar\MyConst;
use as を用いることで、名前空間に別名をつけることができます。下記の例では、lib\foo に対して foolib という別名をつけています。as 以降は省略可能です。
require "lib/foo.php";
require "lib/bar.php";
use lib\foo as foolib;
use lib\bar; // use lib\bar as bar; と解釈される
$obj1 = new foolib\MyClass();
foolib\MyFunction();
echo foolib\MyConst;
$obj2 = new bar\MyClass();
bar\MyFunction();
echo bar\MyConst;
namespace { ... } の形式で名前空間を指定することもできます。名前を省略するとグローバル名前空間となります。
namespace lib\foo {
function func() { echo "lib\\foo\\func()\n"; }
}
namespace lib\bar {
function func() { echo "lib\\bar\\func()\n"; }
}
namespace {
lib\foo\func();
lib\bar\func();
}
namespace, __NAMESPACE__ は、現在の名前空間を示します。
namespace lib\foo {
function func() { echo "lib\\foo\\func()\n"; }
}
namespace lib\bar {
function func() { echo "lib\\bar\\func()\n"; }
}
namespace lib {
namespace\foo\func(); // lib\foo\func()
namespace\bar\func(); // lib\bar\func()
echo __NAMESPACE__; // lib
}
宣言(declare)
declare は、プログラム全般に関わる宣言を指定します。下記の2つの記述方法があります。
declare(ticks=1) {
// この箇所に記述したプログラムに対して有効
}
declare(ticks=1);
// ファイルの末尾までのプログラムに対して有効
ticks=N は、処理系が N個の命令を実行する毎に、register_tick_function() で指定した関数を実行します。
declare(ticks=10);
register_tick_function(function() { echo "X"; });
for ($i = 0; $i < 100; $i++) {
echo "o"; // ooooXooooXooooXooooX....と表示される
}
encoding は、スクリプトのエンコーディングを指定します。
declare(encoding='UTF-8');
// UTF-8で記述されたプログラム...
トレイト(trait)
英語の trait は「特性」という意味を持ちます。クラスが複数の機能(特性)を継承するための仕組みです。下記の例では Foo トレイトと Baa トレイトを宣言しておき、これを Baz クラスが継承しています。
trait Foo {
public function hello() {
echo "Foo::Hello!\n";
}
}
trait Baa {
public function bye() {
echo "Baa::Bye!\n";
}
}
class Baz {
use Foo, Baa;
}
$baz = new Baz();
$baz->hello(); // => Foo::Hello!
$baz->bye(); // => Baa::Bye!
複数のトレイトが同じ名前のメソッドを持つ場合エラーとなりますが、instead of を用いて Baa::hello の代わりに Foo:hello を使用することを宣言できます。また、as を用いて Baa::hello を Baa::baaHello という名前で継承することもできます。
trait Foo {
public function hello() {
echo "Foo::Hello!\n";
}
}
trait Baa {
public function hello() {
echo "Baa::Hello!\n";
}
}
class Baz {
use Foo, Baa {
Foo::hello insteadof Baa;
Baa::hello as baaHello;
}
}
$baz = new Baz();
$baz->hello(); // => Foo::Hello!
$baz->baaHello(); // => Baa::Hello!
as private を宣言することにより、利用可能なスコープをクラス内に制限することができます。
trait Foo {
public function hello() {
echo "Foo: Hello!\n";
}
}
class Baz {
use Foo {
hello as private;
}
function greet() {
$this->hello();
}
}
$baz = new Baz();
$baz->greet(); // => Foo::Hello!
test.php
lib