PHPのライブラリなどで
useやnamespaceといった記述を見かけます。
一体何なんだこれ?
理解しておく必要がありそうです。
理解を深めるためにもまとめておきたいと思います。
namespaceの利用が役立つとき
別なファイルのインスタンスに同じ名前のインスタンスが
ある場合の衝突を避けることができます。
use の利用が役立つとき
namespaceが長い場合
記述画面どうなのでエイリアスを作成し参照できるようになります。
実例をと思いましたが。
簡潔にわかりやすく記載してくれているページがありました。
引用
namespaceを使わない場合に起こりえる問題点を示します。2つのPHPファイル、lib1.phpとlib2.phpがあるとします。この2つのファイルにはそれぞれFooというクラスと、get_fooというメソッドが定義されていたとします。
・lib1.php
<?php class Foo { public function get_foo() { return 'lib1.foo'; } }
・lib2.php
<?php class Foo { public function get_foo() { return 'lib2.foo'; } }
ここで、これらの2つのPHPファイルを読み込んで、Fooクラスのインスタンスを生成してget_fooメソッドを実行してみます。
<?php require_once 'lib1.php'; require_once 'lib2.php'; $foo = new Foo(); echo $foo->get_foo() . "\n";
すると、以下のようにFatal errorが発生します。
Fatal error: Cannot declare class Foo, because the name is already in use in .../lib2.php on line 3
要は、lib1.phpでFooクラスを定義していて、lib2.phpでもFooクラスを定義しているから、クラス名が重複していて怒られているんですね!
解決方法: namespaceを利用
それでは、先ほどのクラス名が衝突した問題点を、namespaceを使って解決してみます。そのために、lib1.phpとlib2.phpに、
namespace xxx;
という行を追加します。・lib1.php
<?php namespace Lib1; // これを追加 class Foo { public function get_foo() { return 'lib1.foo'; } }
・lib2.php
<?php namespace Lib2; // これを追加 class Foo { public function get_foo() { return 'lib2.foo'; } }
そして、これら2つのファイルを読み込んで、先ほどと同様にget_fooメソッドを実行してみます。
先ほどの例だと、Fooクラスのインスタンスを生成するときに、
$foo = new Foo();
としました。今回は、lib1.phpとlib2.phpにnamespaceを追加したので、lib1.phpのFooクラスのインスタンスを生成は$foo = new Lib1\Foo()
と書くことができます。また、lib2.phpのFooクラスのインスタンスは$foo = new Lib2\Foo()
で生成できます。<?php require_once 'lib1.php'; require_once 'lib2.php'; // $foo = new Foo(); $foo = new Lib1\Foo(); echo $foo->get_foo() . "\n"; // 「lib1.foo」と出力します。 $foo = new Lib2\Foo(); echo $foo->get_foo() . "\n"; // 「lib2.foo」と出力します。
つまり、lib1.phpとlib2.phpにnamespaceを指定したので、同じFooクラスでも、Lib1というnamespace(名前空間)に属するFooクラスと、Lib2というnamespaceに属するFooクラスで、区別できるようになったということです。これで、クラス名の衝突による問題は解決できました!
useでエイリアスを作成
最後にuseを使用してみます。その前に、lib1.phpを修正します。具体的には、namespaceを長くして、Foo2クラスとFoo3クラスを追加してみます。(※これ以降、lib2.phpはでてきません。)
・lib1.php
<?php namespace Foo\Bar\Baz\Lib1; // 長い。。。 class Foo { public function get_foo() { return 'lib1.foo'; } } class Foo2 { public function get_foo() { return 'lib1.foo2'; } } class Foo3 { public function get_foo() { return 'lib1.foo3'; } }
先ほどのnamespaceの例のように、lib1.phpを読み込むと、FooクラスはFoo\Bar\Baz\Lib1\Foo、Foo2クラスはFoo\Bar\Baz\Lib1\Foo2、Foo3クラスはFoo\Bar\Baz\Lib1\Foo3でアクセスすることができます。
<?php require_once 'lib1.php'; $foo = new Foo\Bar\Baz\Lib1\Foo(); $foo2 = new Foo\Bar\Baz\Lib1\Foo2(); $foo3 = new Foo\Bar\Baz\Lib1\Foo3(); echo $foo->get_foo() . "\n"; // 「lib1.foo」と出力します。 echo $foo2->get_foo() . "\n"; // 「lib1.foo2」と出力します。 echo $foo3->get_foo() . "\n"; // 「lib1.foo3」と出力します。
なんだか、Foo\Bar\Baz\Lib1\がいっぱい出現して、面倒な感じですよね。。。
ここで登場するのがuseです。useを使うと、Foo\Bar\Baz\Lib1というnamespace(名前空間)のエイリアスを作成し、Lib1で参照できるようになります!先ほどのコードはuseを使って、以下のように修正できます。
<?php require_once 'lib1.php'; /* $foo = new Foo\Bar\Baz\Lib1\Foo(); $foo2 = new Foo\Bar\Baz\Lib1\Foo2(); $foo3 = new Foo\Bar\Baz\Lib1\Foo3(); */ use Foo\Bar\Baz\Lib1 as Lib1; // Foo\Bar\Baz\Lib1を、Lib1で参照できるようにエイリアスを作成します。 $foo = new Lib1\Foo(); $foo2 = new Lib1\Foo2(); $foo3 = new Lib1\Foo3(); echo $foo->get_foo() . "\n"; // 「lib1.foo」と出力します。 echo $foo2->get_foo() . "\n"; // 「lib1.foo2」と出力します。 echo $foo3->get_foo() . "\n"; // 「lib1.foo3」と出力します。
useを使ってエイリアスを作成したら、コードがすっきりしました!
ちなみに、この例だとuseのas以降を省略することもできます。(※asを使うと、作成するエイリアスの名前をLib1以外にすることができます。)
// use Foo\Bar\Baz\Lib1 as Lib1; use Foo\Bar\Baz\Lib1;
また、エイリアスでnamespaceだけではなくて、クラスなどのエイリアスも作成することができます。
use Foo\Bar\Baz\Lib1\Foo; use Foo\Bar\Baz\Lib1\Foo2; use Foo\Bar\Baz\Lib1\Foo3; // PHP7以降は以下の記述も使えます。※asの省略も可能です。 // use Foo\Bar\Baz\Lib1\{Foo as Foo, Foo2 as Foo2, Foo3 as Foo3}; $foo = new Foo(); $foo2 = new Foo2(); $foo3 = new Foo3();
引用:https://remotestance.com/blog/3064/