Fork me on GitHub

php命名空间和自动载入理解


每个人的心里都有一片属于自己的森林,迷失的人迷失了,相遇的人会再相遇

今天写一个demo,遇到一个问题,平时框架用多了,下意识的就以为use就能引入类,导致一直跑不成功,后来才意识到use与引用类并不是一回事。use只是指定了要使用哪个命名空间下的类,但是并不会引入类,类的引用还是需要使用include或require。

不使用命名空间

我们的所有的php文件都没有申明使用命名空间, 所有相关文件的引入使用include或require, 并需要指明文件的具体路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
include_once 'AnimalInterface.php';
include_once 'Cat.php';
include_once 'Dog.php';
class Demo
{
public function action(AnimalInterface $animal)
{
return $animal->run();
}
}
$demo = new Demo();
echo $demo->action(new Cat());
echo $demo->action(new Dog());

注意:使用 include_once 可以防止文件重复引入定义

如果不使用命名空间, 那么我们的同一个文件夹就不能重复定义相同的类名, 如果需要解决这个重名的冲突, 就需要放在不同的文件夹下面, 或者申明不同的命名空间;

使用命名空间

申明使用命名空间

1
2
3
4
5
6
7
8
<?php
namespace App;
interface AnimalInterface
{
public function run();
}

申明以后所有需要引入这个文件都必须使用use

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
use App\AnimalInterface;
include_once 'AnimalInterface.php';
class Dog implements AnimalInterface
{
public function run()
{
return 'dog run';
}
}

如果引用的文件是在同一个命名空间下, 则无需使用use

1
2
3
4
5
6
7
8
<?php
namespace App;
interface AnimalInterface
{
public function run();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
namespace App;
include_once 'AnimalInterface.php';
include_once 'Cat.php';
include_once 'Dog.php';
class Demo
{
public function action(AnimalInterface $animal)
{
return $animal->run();
}
}

如果被引入的文件没有申明命名空间,则默认全局命名空间\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
namespace App\Index;
use App\AnimalInterface;
include_once 'AnimalInterface.php';
include_once 'Cat.php';
include_once 'Dog.php';
class Demo
{
public function action(AnimalInterface $animal)
{
return $animal->run();
}
}
$demo = new Demo();
echo $demo->action(new \Cat());
echo $demo->action(new \Dog());
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
use App\AnimalInterface;
include_once 'AnimalInterface.php';
class Dog implements AnimalInterface
{
public function run()
{
return 'dog run';
}
}

自动载入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
namespace App\Index;
use App\AnimalInterface;
spl_autoload_register(function ($filename) {
if ($filename) {
if (file_exists($filename.'.php')) {
include_once $filename.'.php';
}
}
});
//include_once 'AnimalInterface.php';
//include_once 'Cat.php';
//include_once 'Dog.php';
class Demo
{
public function action(AnimalInterface $animal)
{
return $animal->run();
}
}
$demo = new Demo();
echo $demo->action(new \Cat());
echo $demo->action(new \Dog());

所有文件的自动载入需要在spl_autoload_register这个函数中通过include_once实现;

PSR

命名空间跟文件加载并无直接关系,只是有些语言,将命名空间结构和文件结构对应起来了。 以php为例,一般的命名空间结构,跟php文件结构是存在映射关系的,通过命名空间名称,就能算出该类的实际存储位置, 然后实例化的时候,会触发用设置的spl自动加载函数将文件引入。