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!