By Katsuhiro Ogawa
もっと知りたい名前空間
2009.12.15 モダンPHP勉強会
presented by
fivestar
with nequal
名前空間概要
名前空間の注意点
名前空間とフレームワーク
名前空間とオートロード
もしLinuxのファイルシステムに
ディレクトリがなかったら?
/
|- hoge.txt
|- bin_ls
|- usr_bin_php
|- usr_bin_mysql
|- usr_local_bin_sl
|- usr_local_bin_php-5.3.1
|- home_fivestar_bin_php-5.3.1
|- var_www_index.php
|- var_www_css_style.css
|- var_www_scripts_phpinfo.php
...
hoge.txtを追加しよう!
名前がかぶるから
my_hoge.txt
とかにしておくか...
それって今のPHPと同じ?
ダウンロードしたzipを展開したら
my_hoge.txtが上書きされた...
(´・ω:;.:...
フレームワークを
使って開発しよう!
File っていうモデル
クラスを作りました
フレームワークの中に
Fileクラスがあった...
\(^o^)/
PHPと名前空間
ファイルシステムには
ディレクトリがあるから、
ディレクトリさえ分けてしまえば
名前は被らないのに...
そんな殺伐としたPHPの世界に救世主が!!
.__
ヽ|・∀・|ノ
|__|
| |
名前空間とは、PHP 5.3.0 から実装された
クラス名や関数名の衝突を避けるための仕組み
PHPと名前空間
<?php
namespace foo\bar;
class MyObject {} // foo\bar\MyObject
function myfunc() {} // foo\bar\myfunc()
const MY_CONST = 1; // foo\bar\MY_CONST
// foo\bar\MyObject の作成
$obj = new MyObject();
// framework\Controller の作成
$controller = new \framework\Controller();
// foo\bar\myfunc() の呼び出し
namespace\myfunc();
// foo\bar\MY_CONST の出力
echo constant(__NAMESPACE__.'\MY_CONST');
名前空間は で宣言
名前空間の区切り文字は (バックスラッシュ)
\
namespace
名前空間が適応されるのは:
クラス
関数
定数
__NAMESPACE__
namespace
定数や 演算子で
現在の名前空間の指定が行える
名前空間名の定義
非修飾名(Unqualified Name)
修飾名(Qualified Name)
完全修飾名(Fully Qualified Name)
先頭に \ をつけて指定すると、
グローバル空間からの絶対指定になる
Foo, Bar
名前空間区切り文字を含まない識別子
名前空間区切り文字を含む識別子
foo\Bar, hoge\fuga\Piyo
名前空間区切り文字を含む識別子のうち、先頭が名前空間セパレータ、
もしくは namespace 演算子で始まるもの
\foo\bar\Baz, namespace\Hoge
インポート / エイリアス
同一ファイル内での名前空間の複数指定
* TIPS *
グローバル空間 = ルートディレクトリ
現在の名前空間 = カレントディレクトリ
に置き換えると理解しやすいです
(ただし、../ のような表現は使えません)
namespace usr\local;
$obj = new bin\Command();
上記の場合はカレントディレクトリからの
相対指定と同じなので、
usr\local\bin\Command クラスが
生成されます
<?php
use foo\Foo;
// foo\Foo
$obj = new Foo();
use MyApplication_MyObject as MyObj;
// MyApplication_MyObject
$obj = new MyObj();
use bar\baz as baz;
// bar\baz\Baz
$obj = new baz\Baz();
// baz\Baz
$obj = new \baz\Baz();
use
を使うことでクラスのインポートや
でクラス/名前空間にエイリアスを作成することができる
インポート/エイリアスの注意点:
use \foo\Foo;
// 既にFooがimportされているので定義できない
class Foo {}
class Bar {}
// 同名のオブジェクトがすでに宣言されているので
// インポートできない
use bar\Bar;
複数指定するならブレスを使う方が推奨される:
<?php
namespace foo;
class MyObject {}
namespace bar;
class MyObject {}
<?php
namespace foo {
class MyObject {}
}
namespace bar {
class MyObject {}
}
<?php
namespace foo {
class MyObject() {}
}
// グローバル空間
namespace {
$obj = new foo\MyObject();
}
名前空間とグローバル空間を同時に指定する:
ネストはできない:
<?php
namespace foo {
namespace bar {
class MyObject {}
}
}
# => Fatal error: Namespace
declarations cannot be nested
同じ名前空間を複数回指定可能:
<?php
namespace {
class MyObject {}
}
namespace foo {
class MyObject {}
}
namespace {
new MyObject();
}
namespace foo {
new MyObject();
}
ただし
ただ、複数の名前空間をひとつのファイルに記述するようなコーディングはできるだけ避けるべきです。 主な使い道としては、複数の PHP スクリプトをひとつのファイルにまとめるときくらいでしょう。
PHPマニュアルより
とのことです
名前解決のルール
文字列によるクラスの指定
クラスは常に現在の名前空間
関数と定数は現在の名前空間
-> 存在しなければグローバル空間
<?php
namespace foo;
#$array = new ArrayObject();
# => Fatal error: Class 'foo\ArrayObject' not found
$array = new \ArrayObject(array(0, 'a', 'b', 'c', 'b'));
$unique = array_unique((array)$array, SORT_STRING);
// 次と同等: \array_unique((array)$array, \SORT_STRING)
fivestar
小川 雄大 / OGAWA Katsuhiro
アシアル株式会社
symfony/Doctrine evangelist
id:Fivestar / twitter:fivestr
symfonyのアドベントカレンダーの翻訳しました
http://www.symfony-project.org/advent_calendar/
ぜひ見てくださいね!
<?php
namepace foo\bar {
class MyObject {}
}
namespace {
$class = 'foo\bar\MyObject';
$object = new $class;
}
ただし次は失敗:
namespace foo\bar;
$class = 'MyObject';
$obj = new $class();
# => Fatal error: Class 'MyObject' not found
use foo\bar\MyObject;
$class = 'MyObject';
$obj = new $class();
# => Fatal error: Class 'MyObject' not found
use foo\bar as fb;
$class = 'fb\MyObject';
$obj = new $class();
# => Fatal error: Class 'fb\MyObject' not found
文字列で指定した場合は必ずグローバル空間から探される
名前解決はコンパイル時に行われるため、
実行時には名前解決は行われない
.....たぶん
<?php
spl_autoload_register(function ($className)
{
echo $className;
}
)
namespace {
new foo\bar\MyObject();
# => 'foo\bar\MyObject'
}
namespace foo {
new bar\MyObject();
# => 'foo\bar\MyObject'
new \MyObject();
# => 'MyObject'
}
名前解決されたクラス名が渡される
useをしただけではクラスはロードされない
use foo\bar\MyObject;
new MyObject();
# => 'foo\bar\MyObject'
class_exists()
namespace foo {
class_exists('bar\MyObject');
# => 'bar\MyObject'
}
namespace {
use foo\bar\MyObject;
class_exists('MyObject');
# => 'MyObject'
}
PHP Standards Working Group
フレームワークやライブラリの開発者やコミュニティのメンバーらがPHPのコーディング規約について議論している
http://groups.google.com/group/php-standards
主なメンバー:
Jonathan H. Wage: Doctrine, symfony
Nate Abele: Lithium(CakePHP)
Matthew Weier O'Phinney: Zend Framework
Paul M. Jones: Solar
David Coallier: PEAR
2009.12.15 現在: 22名
Coding standard for PHP 5.3 and above
名前空間に関するルール
クラス名に関するルール
例外に関するルール
<vendor>\(<package_or_component>\)*<ClassName>
名前空間は常に小文字 + アンダースコア
トップレベル名前空間にはベンダー名が入る
サブ名前空間はいくつ使ってもよい
名前空間セパレータはディレクトリセパレータを表す
名前空間中のアンダースコアに特別な意味はない
ベンダー名は最短のもの(zend, cake, ...)
クラス名はアッパーキャメル
クラス名にはアンダースコアを含めてもよい
インターフェースにはInterfaceサフィックスをつける
抽象クラスにはAbstractサフィックスをつける
クラス名中のアンダースコアはディレクトリセパレータを表す
全てのパッケージはパッケージレベルのExceptionを定義する
全てのパッケージは可能な限りSPL例外を使う
パッケージレベルの例外はクラスでもインターフェースでもよい
パッケージからスローされる例外は可能な限りパッケージレベルの例外を継承もしくは実装する
パッケージからスローされる例外は可能な限り以下のルールに従う:
SPL例外がつかる場合はSPL例外
それ以外はパッケージレベルの例外を継承もしくは実装した例外
主要フレームワークの対応
Lithium
Zend Framework, PEAR2
symfony / Doctrine
命名規則は準拠
lithium\core\Object
lithium\data\Model
不明
準拠する?
zend\controller\FrontController
pear2\http\Request
PEAR2は pear2\HTTP\Request のようになるかも?
名前空間もアッパーキャメル
Symfony\Components\DependencyInjection\Container
Doctrine\ORM\Query
現状のPEARの命名規則における _ を \ に置き換えたものと同じ
Cakeは一切調べていません
SplClassLoader
Jonathanがつくったオートローダー
http://gist.github.com/221634
$classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
$classLoader->register();
$parser = new Doctrine\Common\Annotations\Parser();
# /path/to/doctrine/Doctrine/Common/Annotations/Parser.php
as
http://jp2.php.net/namespace
2009.12.15 モダンPHP勉強会