PHP 新手入门指南 – 使用命名空间

命名空间

什么是命名空间啊?

取名空间(英文:Namespace)表示标志符(identifier)的可以知道范围。三个标记符可在七个命名空间中定义,它在分化命名空间中的含义是互不相干的。那样,在贰个新的命名空间中可定义任何标记符,它们不会与其余已有个别标记符发生冲突,因为已某些定义都地处别的命名空间中。

简言之说来定名空间是为了缓慢解决差别库在同三个情状下行使时现身的命名冲突。比方小编要好有二个函数名称为A,不过系统已经有多少个A函数了,那就能冒出冲突。

前言

首先来打探一下命名空间:

PHP中的命名空间

PHP从5.3本子开头引进了命名空间,之后大多共处PHP类库以至框架都从头协理它。那么PHP的命名空间怎么用呢?

include 和 require 是PHP中引进文件的四个基本方式。在小框框开采中直接行使
include 和 require 没哟什么不妥,但在大型项目中会变成大气的 include 和
require
聚积。那样的代码既不佳看,实行功能也十分低,并且爱戴起来也一定困难。

(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    
//file a.php
namespace A;

const test = 'Atest'; 

function test() { 
    return __FUNCTION__; 
}

class Test{
    public function __construct(){
        return __METHOD__;
    }
}
?>

地点例子中就是二个超人的命名空间定义方法,独有constfunction,class受命名空间的封锁。

为了缓和那么些主题材料,部分框架会付给三个引进文件的配备项目清单,在对象起首化的时候把供给的文书引进。但那只是让代码变得更简练了一些,引进的功用照旧是相中。PHP5
之后,随着 PHP 面向对象扶植的兼顾,__autoload
函数才真的使得自动加载成为大概。

PHP 命名空间提供了大器晚成种将有关的类、函数和常量组合到一起的门道。

动用命名空间

使用命名空间的点子如下:

<?php 
namespace B;
use A;

const test = 'Btest';
function test() { 
    return __FUNCTION__; 
}

class Test{
    public function __construct(){
        return __METHOD__;
    }
}

include "a.php";//必须包含A命名空间的文件

// 完全限定
// `Btest`从绝对位置查找输出,如果是全局函数则`test`
echo Btest;   //输出Btest

// 限定名称  
// 这里已经通过`use A`申明了在这个文件可以通过`A...`使用A命名空间的函数
echo Atest;    //输出Atest

// 非限定名称
// 非限定名称的函数`test`会从当前命名控件查找,即B
echo test;      //输出Btest

// namespace关键字代表当前命名空间
echo namespace/test;
?>

首先要小心的是命名空间只起注明效率,也正是在动用了命名空间的时候依然得把那一个命名空间证明的不得了文件满含进来。在使用中能够通过__NAMESPACE__来查看当前定名空间。

越来越多内容能够查阅PHP官方文书档案

* include 和 require 功效是同后生可畏的,它们的比不上在于 include
出错开上下班时间只会发出警示,而 require 会抛出荒诞终止脚本。

更加多关于命名空间的详细内容,请参谋
法定文书档案

自行加载

种种文件既要申明命名控件又要手动include是格外不智能的事情,所以在融洽的PHP系统大概框架中得以采取机关加载才具,让系统协和去找

最简便易行的措施是利用函数__autoload函数,但是那些函数只可以在非命名控件下定义,也正是全局情状下:

function __autoload($class) {
  $dir = './';
  set_include_path(get_include_path().PATH_SEPARATOR.$ids_dir);
  $class = str_replace('\', '/', $class) . '.php'; 
  require_once($class); }

假若在早本来就有了命名空间的类中,能够动用函数spl_autoload_register来注册二个类中的方法来取代__autoload

* include_once 和 include 唯生机勃勃的界别在于 include_once
会检查文件是不是业已引进,借使是则不会重复引进。

小实践

接下去大家透过小实施将那几个体系手记中的项目中追加命名空间的施用。

首先,我们对 core目录下的类公事到场命名空间:

  • App.php, Request.php, Router.php

起来部分增加:

namespace AppCore;
  • database/Connection.php, database/QueryBuilder.php

起首部分加多:

namespace AppCoreDatabase;

扶持,对调控器目录下的类公事 PageController.php
UsersControler.php 增多命名空间:

namespace AppControllers;

use AppCoreApp;

因为调控器类中都有利用了 AppCoreApp 类,通过 use
关键字是引进命名空间下的类,以便大家无需每一趟都以如此书写代码:

$users = AppCoreApp::get('database')->selectAll('users');

如果 use 引进了命名空间下的类,只供给那样就能够:

$users = App::get('database')->selectAll('users');

同时,在 core/bootstrap.php 中,也急需引进命名空间。

在始发部分增多:

use AppCoreApp;
use AppCoreDatabase{QueryBuilder, Connection};

能够看看通过中括号和逗号的相间能添扩充取名空间下的类的引入。这里因为
QueryBuilderConnection
在相近命名空间下,很自然能够因此这么些方法引进它们。

品种的进口文件 index.php 中也可以有用到命名空间类,也亟需引入:

// index.php
<?php

require 'vendor/autoload.php';
require 'core/bootstrap.php';

use AppCore{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

运作程序,能够看见效用如初,命名空间就此选用到了花色中。

=================自动加载==================

自定义框架

在此个推行的根底之上,有以前的 controllersviews
目录,大家能够再建设构造叁个 models 目录,来寄存在项目会用到的模型类。

models 目录下新建 Project.php 文件:

<?php

namespace AppModels;

class Project
{
    // ...  
}

大家能够经过如此的方法来宏观模型类,稳步分类 MVC
档期的顺序的各样部分,让程序布局变得尤为显著。

我们仍是可以进一层的将品种的目录布局进行一些调动,效果如下:

图片 1

目录构造

这里新建了二个 app 目录,并将 controllers, modelsviews,
routes.php 放入了步入,变成了应用程序的布局档次。

再看看 core
目录中的内容,简单开掘,它平时被能够以为是贰个框架的主干基本功,它提供了加载器
bootstrap.php,应用容器 App.php,路由和要求 (Router.php
Request.phpState of Qatar,数据库操作类 (Connection
QueryBuilderState of Qatar,为应用程序提供底子用。

固然这里是经过简单的代码达成,但从全部上看来,大家毕竟创设了一个简短的自定义框架,即便不是相当完美,但也会有模有样。

若是想延续扩充,让它变得强盛,那就入手做吧。

兑现全自动加载最轻巧易行的不二秘诀正是应用 __autoload
魔术点子。当必要动用的类未有被引进时,那么些函数会在PHP报错前被触发,未定义的类名会被用作参数字传送入。至于函数具体的逻辑,那亟需客商自身去贯彻。

先是创造三个 autoload.php 来做二个简便的测验:

// 类未定义时,系统自动调用function __autoload{ /* 具体处理逻辑 */ echo $class;// 简单的输出未定义的类名}new HelloWorld();/** * 输出 HelloWorld 与报错信息 * Fatal error: Class 'HelloWorld' not found */

因此这几个大致的事例能够开掘,在类的实例化进度中,系统所做的干活大概是这么的:

/* 模拟系统实例化过程 */function instance{ // 如果类存在则返回其实例 if (class_exists { return new $class(); } // 查看 autoload 函数是否被用户定义 if (function_exists { __autoload; // 最后一次引入的机会 } // 再次检查类是否存在 if (class_exists { return new $class(); } else { // 系统:我实在没辙了 throw new Exception; }}

明白了 __autoload 函数的行事规律之后,那就让大家来用它去达成机关加载。

先是成立叁个类公事,代码如下:

class [ClassName] { // 对象实例化时输出当前类名 function __construct() { echo '' . __CLASS__ . ''; }}

(小编那边创办了一个 HelloWorld 类用作演示)接下去大家将在定义
__autoload 的具体逻辑,使它亦可落到实处全自动加载:

function __autoload{ // 根据类名确定文件名 $file = $class . '.php'; if  { include $file; // 引入PHP文件 }}new HelloWorld();/** * 输出 HelloWorld */

=================命名空间==================

骨子里命名空间并非怎样新闯事物,比超级多言语早都帮助那个特点了。只可是 PHP
起步比较晚,直到 PHP 5.3 之后才支撑。

命名空间一句话来讲就是大器晚成种标志,它的机要指标是解决命名冲突的标题。

就如在日常生活中,有大多姓名相符的人,怎样区分那几个人啊?那就要求加上部十一分加的标志。

把职能部门当成标志就像不错,那样就不要担忧 “撞名” 的难堪了。

此地我们来做二个小任务,去介绍百度的主任李彦宏(RobinState of Qatar:

namespace 百度;class 李彦宏{ function __construct() { echo '百度创始人'; }}

↑ 那就是李彦宏(Robin卡塔尔的基本资料了,namespace 是他的单位标记,class 是她的真名。

取名空间通过机要字 namespace
来声称。假使三个文书中满含命名空间,它必得在其余具备代码早先扬言命名空间。

new 百度李彦宏(); // 限定类名new 百度李彦宏(); // 完全限定类名

↑ 在相同情况下,无论是向别人介绍 “百度 李彦宏(Robin卡塔尔” 依然 “百度集团李彦宏(RobinState of Qatar”,他们都能够精晓。

在如今定名空间未有注脚的状态下,节制类名和完全约束类名是等价的。因为只要不点名空间,则默感觉全局。

namespace 谷歌;new 百度李彦宏new 百度李彦宏

↑ 借使你在Google商厦向她们的工作者介绍李彦宏,一定要指明是
“百度公司的李彦宏(Robin卡塔尔国”。不然他会以为百度是谷歌(Google卡塔尔(قطر‎的贰个机关,而李彦宏(Robin卡塔尔(قطر‎只是在那之中的一位职工而已。

其大器晚成例子显示了在命名空间下,使用限定类名和完全约束类名的分别。(完全限制类名
= 当前定名空间 + 约束类名)

/* 导入命名空间 */use 百度李彦宏;new 李彦宏/* 设置别名 */use 百度李彦宏 AS CEO;new CEO/* 任何情况 */new 百度李彦宏


第生龙活虎种情状是人家已经认知李彦宏(Robin卡塔尔国了,你只供给一向说名字,他就能够明白你指的是哪个人。第二种情景是李彦宏正是他俩的COO,你直接说CEO,他能够立时反应过来。

使用命名空间只是让类名有了前缀,不易于产生矛盾,系统依然不博览会开机动导入。

生机勃勃旦不引进文件,系统会在抛出 “Class Not Found” 错误早先触发 __autoload
函数,并将限定类名传入作为参数。

从而地方的例子皆以依附你早已将相关文件手动引进的动静下促成的,不然系统会抛出
” Class ‘百度李彦宏’ not found”。

=================spl_autoload==================

接下去让我们要在富含命名空间的情况下来完毕活动加载。这里大家利用
spl_autoload_register(State of Qatar 函数来促成,那须求你的 PHP 版本号大于 5.12。

spl_autoload_register 函数的效率正是把传播的函数注册到 SPL
__autoload 函数队列中,并移除系统默许的 __autoload() 函数。

假诺调用 spl_autoload_register(卡塔尔函数,当调用未定义类时,系统就能够按顺序调用注册到
spl_autoload_register(卡塔尔 函数的有所函数,并非机动调用 __autoload()
函数。

当今,大家来创制一个 Linux 类,它接纳 os 作为它的命名空间:

namespace os; // 命名空间class Linux // 类名{ function __construct() { echo '' . __CLASS__ . ''; }}

随后,在同八个目录下新建叁个 PHP 文件,使用 spl_autoload_register
以函数回调的艺术贯彻全自动加载:

spl_autoload_register { // class = osLinux /* 限定类名路径映射 */ $class_map = array( // 限定类名 => 文件路径 'os\Linux' => './Linux.php', ); /* 根据类名确定文件名 */ $file = $class_map[$class]; /* 引入相关文件 */ if  { include $file; }});new osLinux();

此处大家选取了多个数组去保存类名与公事路线的涉及,这样当类名传入时,自动加载器就精通该引进哪个文件去加载那些类了。

然而假如文件多起来的话,映射数组会变得十分长,那样的话维护起来会一定麻烦。假设命名能遵循统风度翩翩的约定,就足以让机关加载器自动解析判定类公事所在的路子。接下来要介绍的PSENCORE-4
正是朝气蓬勃种被布满使用的约定格局。

=================PSR-4规范==================

PSLX570-4
是有关由文件路线自动载入对应类的连带规范,标准规定了一个通通约束类名需求全体以下构造:

*

假使后续拿地方的事例打举例来讲,一流命名空间一定于公司,子命名空间一定于职位,类名也正是人名。那么李彦宏(RobinState of Qatar标准的称呼为
“百度集团 老总 李彦宏(Robin卡塔尔(قطر‎”。

PSPAJERO-4
标准中必定要有二个世界级命名空间,它的意义在于表示某八个出奇的目录。子命名空间代表的是类公事相对于文件基目录的那意气风发段路线,类名则与公事名保持黄金时代致。

举个例证:在全限制类名 appviewnewsIndex 中,如果 app 代表
C:Baidu,那么这些类的门径则是 C:BaiduviewnewsIndex.php

大家就以深入剖析 appviewnewsIndex 为例,编写二个归纳的 德姆o:

$class = 'appviewnewsIndex';/* 顶级命名空间路径映射 */$vendor_map = array( 'app' => 'C:Baidu',);/* 解析类名为文件路径 */$vendor = substr($class, 0, strpos; // 取出顶级命名空间[app]$vendor_dir = $vendor_map[$vendor]; // 文件基目录[C:Baidu]$rel_path = dirname(substr($class, strlen; // 相对路径[/view/news]$file_name = basename . '.php'; // 文件名[Index.php]/* 输出文件所在路径 */echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;

经过那么些 德姆o
能够看出限制类名调换为路线的进度。那么今后就让大家用标准的面向对象方式去落到实处自动加载器吧。

先是大家创造三个文本 Index.php,它地处 appmvcviewhome 目录中:

namespace appmvcviewhome;class Index{ function __construct() { echo ' Welcome To Home '; }}

随着大家在创立叁个加载类,它地处 目录中:

class Loader{ /* 路径映射 */ public static $vendorMap = array( 'app' => __DIR__ . DIRECTORY_SEPARATOR . 'app', ); /** * 自动加载器 */ public static function autoload { $file = self::findFile; if  { self::includeFile; } } /** * 解析文件路径 */ private static function findFile { $vendor = substr($class, 0, strpos; // 顶级命名空间 $vendorDir = self::$vendorMap[$vendor]; // 文件基目录 $filePath = substr($class, strlen . '.php'; // 文件相对路径 return strtr($vendorDir . $filePath, '\', DIRECTORY_SEPARATOR); // 文件标准路径 } /** * 引入文件 */ private static function includeFile { if  { include $file; } }}

最后,将 Loader 类中的 autoload 注册到 spl_autoload_register 函数中:

include 'Loader.php'; // 引入加载器spl_autoload_register; // 注册自动加载new appmvcviewhomeIndex(); // 实例化未引用的类/** * 输出:  Welcome To Home  */

演示中的代码其实正是 ThinkPHP 自动加载器源码的简洁明了版,它是 ThinkPHP 5
能促成惰性加载的机要。

迄今结束,自动加载的法规已经全副说完了,假使有意思味浓烈摸底的话,能够参见下边的ThinkPHP 源码。

class Loader{ protected static $instance = []; // 类名映射 protected static $map = []; // 命名空间别名 protected static $namespaceAlias = []; // PSR-4 private static $prefixLengthsPsr4 = []; private static $prefixDirsPsr4 = []; private static $fallbackDirsPsr4 = []; // PSR-0 private static $prefixesPsr0 = []; private static $fallbackDirsPsr0 = []; // 自动加载的文件 private static $autoloadFiles = []; // 自动加载 public static function autoload { // 检测命名空间别名 if (!empty(self::$namespaceAlias)) { $namespace = dirname; if (isset(self::$namespaceAlias[$namespace])) { $original = self::$namespaceAlias[$namespace] . '\' . basename; if (class_exists { return class_alias($original, $class, false); } } } if ($file = self::findFile { // Win环境严格区分大小写 if (IS_WIN && pathinfo($file, PATHINFO_FILENAME) != pathinfo, PATHINFO_FILENAME)) { return false; } __include_file; return true; } } /** * 查找文件 * @param $class * @return bool */ private static function findFile { if (!empty { // 类库映射 return self::$map[$class]; } // 查找 PSR-4 $logicalPathPsr4 = strtr . EXT; $first = $class[0]; if (isset(self::$prefixLengthsPsr4[$first])) { foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos { foreach (self::$prefixDirsPsr4[$prefix] as $dir) { if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) { return $file; } } } } } // 查找 PSR-4 fallback dirs foreach (self::$fallbackDirsPsr4 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr4)) { return $file; } } // 查找 PSR-0 if (false !== $pos = strrpos { // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS); } else { // PEAR-like class name $logicalPathPsr0 = strtr . EXT; } if (isset(self::$prefixesPsr0[$first])) { foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos { foreach  { if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } } } } // 查找 PSR-0 fallback dirs foreach (self::$fallbackDirsPsr0 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } return self::$map[$class] = false; } // 注册classmap public static function addClassMap { if  { self::$map = array_merge; } else { self::$map[$class] = $map; } } // 注册命名空间 public static function addNamespace($namespace, $path = '') { if  { foreach ($namespace as $prefix => $paths) { self::addPsr4($prefix . '\', rtrim; } } else { self::addPsr4($namespace . '\', rtrim; } } // 添加Ps0空间 private static function addPsr0($prefix, $paths, $prepend = false) { if  { if  { self::$fallbackDirsPsr0 = array_merge $paths, self::$fallbackDirsPsr0 ); } else { self::$fallbackDirsPsr0 = array_merge( self::$fallbackDirsPsr0, ; } return; } $first = $prefix[0]; if (!isset(self::$prefixesPsr0[$first][$prefix])) { self::$prefixesPsr0[$first][$prefix] =  $paths; return; } if  { self::$prefixesPsr0[$first][$prefix] = array_merge $paths, self::$prefixesPsr0[$first][$prefix] ); } else { self::$prefixesPsr0[$first][$prefix] = array_merge( self::$prefixesPsr0[$first][$prefix], ; } } // 添加Psr4空间 private static function addPsr4($prefix, $paths, $prepend = false) { if  { // Register directories for the root namespace. if  { self::$fallbackDirsPsr4 = array_merge $paths, self::$fallbackDirsPsr4 ); } else { self::$fallbackDirsPsr4 = array_merge( self::$fallbackDirsPsr4, ; } } elseif (!isset(self::$prefixDirsPsr4[$prefix])) { // Register directories for a new namespace. $length = strlen; if ('\' !== $prefix[$length - 1]) { throw new InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length; self::$prefixDirsPsr4[$prefix] =  $paths; } elseif  { // Prepend directories for an already registered namespace. self::$prefixDirsPsr4[$prefix] = array_merge $paths, self::$prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. self::$prefixDirsPsr4[$prefix] = array_merge( self::$prefixDirsPsr4[$prefix], ; } } // 注册命名空间别名 public static function addNamespaceAlias($namespace, $original = '') { if  { self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace); } else { self::$namespaceAlias[$namespace] = $original; } } // 注册自动加载机制 public static function register { // 注册系统自动加载 spl_autoload_register($autoload ?: 'think\Loader::autoload', true, true); // 注册命名空间定义 self::addNamespace([ 'think' => LIB_PATH . 'think' . DS, 'behavior' => LIB_PATH . 'behavior' . DS, 'traits' => LIB_PATH . 'traits' . DS, ]); // 加载类库映射文件 if (is_file(RUNTIME_PATH . 'classmap' . EXT)) { self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT)); } // Composer自动加载支持 if (is_dir(VENDOR_PATH . 'composer')) { self::registerComposerLoader(); } // 自动加载extend目录 self::$fallbackDirsPsr4[] = rtrim; } // 注册composer自动加载 private static function registerComposerLoader() { if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) { $map = require VENDOR_PATH . 'composer/autoload_namespaces.php'; foreach ($map as $namespace => $path) { self::addPsr0; } } if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) { $map = require VENDOR_PATH . 'composer/autoload_psr4.php'; foreach ($map as $namespace => $path) { self::addPsr4; } } if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) { $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php'; if  { self::addClassMap; } } if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) { $includeFiles = require VENDOR_PATH . 'composer/autoload_files.php'; foreach ($includeFiles as $fileIdentifier => $file) { if (empty(self::$autoloadFiles[$fileIdentifier])) { __require_file; self::$autoloadFiles[$fileIdentifier] = true; } } } } /** * 导入所需的类库 同java的Import 本函数有缓存功能 * @param string $class 类库命名空间字符串 * @param string $baseUrl 起始路径 * @param string $ext 导入的文件扩展名 * @return boolean */ public static function import($class, $baseUrl = '', $ext = EXT) { static $_file = []; $key = $class . $baseUrl; $class = str_replace(['.', '#'], [DS, '.'], $class); if  { return true; } if  { list = explode; if (isset(self::$prefixDirsPsr4[$name . '\'])) { // 注册的命名空间 $baseUrl = self::$prefixDirsPsr4[$name . '\']; } elseif  { //加载当前模块应用类库 $baseUrl = App::$modulePath; } elseif (is_dir { $baseUrl = EXTEND_PATH; } else { // 加载其它模块的类库 $baseUrl = APP_PATH . $name . DS; } } elseif  != DS) { $baseUrl .= DS; } // 如果类存在 则导入类库文件 if  { foreach  { $filename = $path . DS . $class . $ext; if  { break; } } } else { $filename = $baseUrl . $class . $ext; } if  && is_file { // 开启调试模式Win环境严格区分大小写 if (IS_WIN && pathinfo($filename, PATHINFO_FILENAME) != pathinfo, PATHINFO_FILENAME)) { return false; } __include_file; $_file[$key] = true; return true; } return false; } /** * 实例化模型 * @param string $name Model名称 * @param string $layer 业务层名称 * @param bool $appendSuffix 是否添加类名后缀 * @param string $common 公共模块名 * @return Object * @throws ClassNotFoundException */ public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common') { if (isset(self::$instance[$name . $layer])) { return self::$instance[$name . $layer]; } if  { list = explode; } else { $module = Request::instance; } $class = self::parseClass($module, $layer, $name, $appendSuffix); if  { $model = new $class(); } else { $class = str_replace('\' . $module . '\', '\' . $common . '\', $class); if  { $model = new $class(); } else { throw new ClassNotFoundException('class not exists:' . $class, $class); } } self::$instance[$name . $layer] = $model; return $model; } /** * 实例化控制器 格式:[模块名/]控制器名 * @param string $name 资源地址 * @param string $layer 控制层名称 * @param bool $appendSuffix 是否添加类名后缀 * @param string $empty 空控制器名称 * @return Object|false * @throws ClassNotFoundException */ public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '') { if  { list = explode; } else { $module = Request::instance; } $class = self::parseClass($module, $layer, $name, $appendSuffix); if  { return new $class; } elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) { return new $emptyClass; } } /** * 实例化验证类 格式:[模块名/]验证器名 * @param string $name 资源地址 * @param string $layer 验证层名称 * @param bool $appendSuffix 是否添加类名后缀 * @param string $common 公共模块名 * @return Object|false * @throws ClassNotFoundException */ public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common') { $name = $name ?: Config::get; if  { return new Validate; } if (isset(self::$instance[$name . $layer])) { return self::$instance[$name . $layer]; } if  { list = explode; } else { $module = Request::instance; } $class = self::parseClass($module, $layer, $name, $appendSuffix); if  { $validate = new $class; } else { $class = str_replace('\' . $module . '\', '\' . $common . '\', $class); if  { $validate = new $class; } else { throw new ClassNotFoundException('class not exists:' . $class, $class); } } self::$instance[$name . $layer] = $validate; return $validate; } /** * 数据库初始化 并取得数据库类实例 * @param mixed $config 数据库配置 * @param bool|string $name 连接标识 true 强制重新连接 * @return thinkdbConnection */ public static function db($config = [], $name = false) { return Db::connect; } /** * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作 * @param string $url 调用地址 * @param string|array $vars 调用参数 支持字符串和数组 * @param string $layer 要调用的控制层名称 * @param bool $appendSuffix 是否添加类名后缀 * @return mixed */ public static function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) { $info = pathinfo; $action = $info['basename']; $module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance; $class = self::controller($module, $layer, $appendSuffix); if  { if  { if  { parse_str; } else { $vars = [$vars]; } } return App::invokeMethod([$class, $action . Config::get], $vars); } } /** * 字符串命名风格转换 * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 * @param string $name 字符串 * @param integer $type 转换类型 * @return string */ public static function parseName { if  { return ucfirst(preg_replace_callback/', function  { return strtoupper); } else { return strtolower(trim(preg_replace("/[A-Z]/", "_\0", $name), "_")); } } /** * 解析应用类的类名 * @param string $module 模块名 * @param string $layer 层名 controller model ... * @param string $name 类名 * @param bool $appendSuffix * @return string */ public static function parseClass($module, $layer, $name, $appendSuffix = false) { $name = str_replace(['/', '.'], '\', $name); $array = explode; $class = self::parseName . (App::$suffix || $appendSuffix ? ucfirst; $path = $array ? implode . '\' : ''; return App::$namespace . '\' . ($module ? $module . '\' : '') . $layer . '\' . $path . $class; } /** * 初始化类的实例 * @return void */ public static function clearInstance() { self::$instance = []; }}/** * 作用范围隔离 * * @param $file * @return mixed */function __include_file{ return include $file;}function __require_file{ return require $file;}

总结

如上正是那篇小说的全部内容了,希望本文的源委对大家的求学大概工作有着一定的参阅学习价值,多谢大家对剧本之家的支撑。

发表评论

电子邮件地址不会被公开。 必填项已用*标注