Do You PHP?    
Search Engine Optimization  php5 powerd  Valid XHTML 1.0!  Valid CSS!  このサイトのはてなブックマーク数 



last updated
2008/12/06

counter hits
since 1999/11/06


PHP6.0.0-devを試してみる - 名前空間のサポート

caution2008/12/04付でリリースされたPHP5.3.0α3から、名前空間のデリミタがバックスラッシュ(\)に変更されました。PHP6でもこのままの仕様となりそうです。

cautionimportキーワードはuseキーワードに変更されました。PHP6でもこのままの仕様となりそうです。

cautionここにある新規機能は、PHP5.3.0から利用可能になる予定です。

次期メジャーバージョンであるPHP6をあれこれやってみます。今回は、名前空間のサポートです。

PHP5での導入も検討された名前空間のサポートですが、PHP6でついに導入される事になりそうです。本家のメーリングリストでは以前から名前空間の仕様決めで盛んに議論されていましたが、Dmitry Stogov氏の提案を軸としたシンプルなものに固まっていったようです。そして2007/07/12、Dmitry Stogov氏によってついに名前空間をサポートするコード一式が本家CVSにcommitされました。2007/07/16現在ではCVSはもちろん、snaps.php.netにあるアーカイブにもそれらのコードが含まれています。

前置きが長くなりましたが、サポートされた名前空間がどんな感じなのか、実際にCVSからソースを取得してbuildしたPHP6-devを使って試した結果をまとめてみました。なお、今回の内容は、[PHPのソースディレクトリ]Zend/tests/ns_*.phptファイルを元に書いています。また、今後正式リリースまでの間に仕様が変わり、ここにある内容が正しくなくなる可能性もありますので、注意してください。

使用した環境

今回の環境は、CentOS4.5+Apache2.2.4+PHP6.0.0-devです。ソースは本家CVSリポジトリから直接取得しています。手順は『Do You PHP? - anonymous cvsからPHPのソースを取得する』を参照してください。また、PHPは以下のようなconfigureオプションを付けてbuildしています。

●PHP6.0.0-devのconfigureオプション
--with-apxs2=/usr/local/apache2/bin/apxs \
--prefix=/usr/local/lib/php6 \
--with-pear=/usr/local/lib/php6/pear \
--with-config-file-path=/usr/local/lib/php6/ini/ \
--with-config-file-scan-dir=/usr/local/lib/php6/ini.d \
--enable-zend-multibyte \
--with-dom \
--enable-filter=shared \
--with-gettext=shared \
--with-mcrypt=shared \
--with-gd=shared \
--with-jpeg-dir \
--with-png-dir \
--with-zlib-dir \
--with-ttf \
--with-freetype-dir \
--enable-gd-native-ttf \
--enable-gd-jis-conv \
--enable-soap=shared \
--enable-pdo=shared \
--with-pdo-sqlite=shared \
--with-sqlite=shared \
--enable-sqlite-utf8 \
--with-openssl=shared \
--with-curl=shared \
--enable-bcmath=shared \
--enable-pcntl=shared \
--enable-sockets=shared \
--with-oci8=shared,/usr/lib/oracle/xe/app/oracle/product/10.2.0/server/ \
--with-pdo-oci=shared,/usr/lib/oracle/xe/app/oracle/product/10.2.0/server/ \
--with-pdo=shared \
--enable-sigchild \
--with-xsl=shared \
--enable-zip=shared

いずれも「--prefix」オプションを付けているため、phpコマンドのパスがデフォルトとは変わっていますが適宜読み替えてください。

名前空間の宣言

名前空間の宣言はキーワード「namespace」を使って以下のように記述します。また、名前空間のデリミタには「::」(コロン2つ)を使います。デフォルトの名前空間は「""」(空文字)です。

●名前空間の宣言
  namespace test::ns1;

宣言する位置ですが、スクリプトファイルの先頭にする必要があります。require_onceやinclude_onceよりも前になります。そうでない場合、「Fatal error: Namespace declaration statement has to be the very first statement in the script in ...」が発生します。また、名前空間を宣言すると、そのファイルで定義されたクラスや関数がその名前空間に属することになります。

●namespace01.php
  
<?php
namespace sample::test;

class ClassA {
    private $param;
    public function get() {
        return strlen($this->param);
    }
    public function set($param) {
        $this->param = $param;
    }
}

function FunctionA() {
    return 123;
}

名前空間に属する関数やクラスの呼び出し

名前空間を関数名やクラス名の前に付け、「::」(コロン2つ)を使って繋げます。呼び出し元が同じ名前空間に属している場合、省略が可能です。

●namespace02.php
  
<?php
namespace namespace02;

require_once 'namespace01.php';

class ClassA {
    private $param;
    public function get() {
        return $this->param;
    }
    public function set($param) {
        $this->param = $param;
    }
}

function FunctionA() {
    return 'Hello!';
}

/**
 * 名前空間「sample::test」に属するクラス・関数の呼び出し
 */
$obj = new sample::test::ClassA();
echo get_class($obj) . '<br>';
$obj->set('hoge');
echo $obj->get() . '<br>';
echo sample::test::FunctionA() . '<hr>';

/**
 * 名前空間「namespace02」に属するクラス・関数の呼び出し
 */
$obj = new ClassA();
echo get_class($obj) . '<br>';
$obj->set('hoge');
echo $obj->get() . '<br>';
echo FunctionA();

●namespace02.phpの実行結果
sample::test::ClassA
4
123namespace02::ClassA
hoge
Hello!

現在の名前空間名の取得

新しい定数「__NAMESPACE__」が使えます。

●namespace03.php
  
<?php
namespace example::NameSpace03;

echo __NAMESPACE__;

●namespace03.phpの実行結果
example::NameSpace03

名前空間の別名を付ける

キーワード「import」を使うことで、名前空間に別名を付けたり短縮形が使えるようになったりします。なお、別名に別名を付けることはできません。

●namespace04.php
  
<?php
namespace php6::sample::namespace04;

import php6::sample::namespace04;
import php6::sample::namespace04 as n04;
import n04 as hoge;

class ClassA {
    private $param;
    public function get() {
        return $this->param;
    }
    public function set($param) {
        $this->param = $param;
    }
}

function FunctionA() {
    return 123;
}

$obj = new php6::sample::namespace04::ClassA();
echo get_class($obj) . '<br>';
echo php6::sample::namespace04::FunctionA() . '<hr>';

$obj = new namespace04::ClassA();
echo get_class($obj) . '<br>';
echo namespace04::FunctionA() . '<hr>';

$obj = new n04::ClassA();
echo get_class($obj) . '<br>';
echo n04::FunctionA() . '<hr>';

/**
 * Fatal error: Class 'n04::ClassA' not found in ...
 * となる
$obj = new hoge::ClassA();
echo get_class($obj) . '<br>';
echo hoge::FunctionA() . '<hr>';
 */

クラス名・関数名の衝突

namespace02.phpもそうですが、異なる名前空間に属する同名のクラス・関数が存在する場合、明示的に名前空間を指定してやる必要があります。特に、PHPの組込みクラス/関数と同名のクラス/関数を使いたい場合は注意が必要です。以下は、Exceptionクラスを使った例ですが、PHP組み込みクラスのExceptionと独自定義のExceptionクラスがどう記述した場合にどちらがインスタンス化されるか分かるでしょうか?

●namespace05.php
  
<?php
namespace example::namespace05;

import example::namespace05;

class Exception {
}

$obj = new Exception();
echo get_class($obj) . '<br>';

$obj = new ::Exception();
echo get_class($obj) . '<br>';

$obj = new namespace05::Exception();
echo get_class($obj) . '<br>';

$obj = new example::namespace05::Exception();
echo get_class($obj) . '<br>';

実行結果は次の通りです。

●namespace05.phpの実行結果
example::namespace05::Exception
Exception
example::namespace05::Exception
example::namespace05::Exception

まとめ

PHP6でサポートされる名前空間について見てきました。ようやく、あの長~いクラス名から解放され。。。るんでしょうかね?(^^;



About This Site |  Privacy Policy |  Contact
Copyright © 1999 - 2008 by Hideyuki SHIMOOKA all rights reserved.