首先来了解一下命名空间:
(PHP 5 >= 5.3.0, PHP 7)
什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。
在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:
- 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
- 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
PHP 命名空间提供了一种将相关的类、函数和常量组合到一起的途径。
更多关于命名空间的详细内容,请参考 官方文档
小实践
接下来我们通过小实践将这个系列手记中的项目中增加命名空间的运用。
首先,我们对 core
目录下的类文件加入命名空间:
-
App.php
,Request.php
,Router.php
开头部分添加:
namespace App\Core;
-
database/Connection.php
,database/QueryBuilder.php
开头部分添加:
namespace App\Core\Database;
其次,对控制器目录下的类文件 PageController.php
和 UsersControler.php
添加命名空间:
namespace App\Controllers;
use App\Core\App;
因为控制器类中都有用到了 App\Core\App
类,通过 use
关键字是引入命名空间下的类,以便我们不需要每次都是这样书写代码:
$users = App\Core\App::get('database')->selectAll('users');
如果 use
引入了命名空间下的类,只需要这样即可:
$users = App::get('database')->selectAll('users');
同时,在 core/bootstrap.php
中,也需要引入命名空间。
在开头部分添加:
use App\Core\App;
use App\Core\Database\{QueryBuilder, Connection};
可以看到通过中括号和逗号的分隔能添加多命名空间下的类的引入。这里因为 QueryBuilder
和 Connection
在同一命名空间下,很自然可以通过这个方式引入它们。
项目的入口文件 index.php
中也有用到命名空间类,也需要引入:
// index.php
<?php
require 'vendor/autoload.php';
require 'core/bootstrap.php';
use App\Core\{Router, Request};
Router::load('app/routes.php')
->direct(Request::uri(), Request::method());
当我们使用了命名空间,我们的路由解析需要调整,否则会找不到类而无法实例化出错,所以在 core/Router.php
中,对 callAction
修改后如下:
public function callAction($controllerName, $action)
{
$controller = "App\\Controllers\\{$controllerName}";
$controller = new $controller;
if (! method_exists($controller, $action)) {
throw new Exception("{$controllerName} does not respond to the {$action}.");
}
return $controller->$action();
}
这里拼接字符串 App\\Controllers\\{$controllerName}
定义了控制所在命名空间。
至此,所有的修改都完成,接下来我们需要重新生成自动加载类:
composer dump-autoload
运行程序,可以看到效果如初,命名空间就此运用到了项目中。
自定义框架
在这个实践的基础之上,有之前的 controllers
和 views
目录,我们可以再建立一个 models
目录,来存放项目会用到的模型类。
在 models
目录下新建 Project.php
文件:
<?php
namespace App\Models;
class Project
{
// ...
}
我们可以通过这样的方式来完善模型类,逐步分类 MVC 层次的各个部分,让程序结构变得更加清晰。
我们还可以进一步的将项目的目录结构进行一些调整,效果如下:
目录结构这里新建了一个 app
目录,并将 controllers
, models
,views
, routes.php
纳入了进去,形成了应用程序的结构层次。
再看看 core
目录中的内容,不难发现,它通常被可以认为是一个框架的核心基础,它提供了加载器 bootstrap.php
,应用容器 App.php
,路由和请求 (Router.php
和 Request.php
),数据库操作类 (Connection
和QueryBuilder
),为应用程序提供核心功能。
虽然这里是通过简单的代码实现,但从整体上看来,我们算是构建了一个简单的自定义框架,即使不是非常完美,但也有模有样。
如果想继续扩展,让它变得强大,那就动手做吧。
网友评论