设为首页 收藏本站
查看: 815|回复: 0

[经验分享] PHP 命名空间与自动加载机制介绍

[复制链接]

尚未签到

发表于 2017-12-29 15:40:48 | 显示全部楼层 |阅读模式
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($class)
  {
  // 检测命名空间别名
  if (!empty(self::$namespaceAlias)) {
  $namespace = ($class);
  if (isset(self::$namespaceAlias[$namespace])) {
  $original = self::$namespaceAlias[$namespace] . '\\' . ($class);
  if (($original)) {

  return>  }
  }
  }
  

  if ($file = self::findFile($class)) {
  

  // Win环境严格区分大小写
  if (IS_WIN && ($file, PATHINFO_FILENAME) != (($file), PATHINFO_FILENAME)) {
  return false;
  }
  

  __include_file($file);
  return true;
  }
  }
  

  /**
  * 查找文件
  * @param $class
  * @return bool
  */
  private static function findFile($class)
  {
  if (!empty(self::$map[$class])) {
  // 类库映射
  return self::$map[$class];
  }
  

  // 查找 PSR-4
  $logicalPathPsr4 = ($class, '\\', DS) . EXT;
  

  $first = $class[0];
  if (isset(self::$prefixLengthsPsr4[$first])) {
  foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
  if (0 === ($class, $prefix)) {
  foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
  if (($file = $dir . DS . ($logicalPathPsr4, $length))) {
  return $file;
  }
  }
  }
  }
  }
  

  // 查找 PSR-4 fallback dirs
  foreach (self::$fallbackDirsPsr4 as $dir) {
  if (($file = $dir . DS . $logicalPathPsr4)) {
  return $file;
  }
  }
  

  // 查找 PSR-0
  if (false !== $pos = ($class, '\\')) {

  // namespaced>  $logicalPathPsr0 = ($logicalPathPsr4, 0, $pos + 1)
  . (($logicalPathPsr4, $pos + 1), '_', DS);
  } else {

  // PEAR-like>  $logicalPathPsr0 = ($class, '_', DS) . EXT;
  }
  

  if (isset(self::$prefixesPsr0[$first])) {
  foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) {
  if (0 === ($class, $prefix)) {
  foreach ($dirs as $dir) {
  if (($file = $dir . DS . $logicalPathPsr0)) {
  return $file;
  }
  }
  }
  }
  }
  

  // 查找 PSR-0 fallback dirs
  foreach (self::$fallbackDirsPsr0 as $dir) {
  if (($file = $dir . DS . $logicalPathPsr0)) {
  return $file;
  }
  }
  

  return self::$map[$class] = false;
  }
  

  // 注册classmap
  public static function addClassMap($class, $map = '')
  {
  if (($class)) {
  self::$map = (self::$map, $class);
  } else {
  self::$map[$class] = $map;
  }
  }
  

  // 注册命名空间
  public static function addNamespace($namespace, $path = '')
  {
  if (($namespace)) {
  foreach ($namespace as $prefix => $paths) {
  self::addPsr4($prefix . '\\', ($paths, DS), true);
  }
  } else {
  self::addPsr4($namespace . '\\', ($path, DS), true);
  }
  }
  

  // 添加Ps0空间
  private static function addPsr0($prefix, $paths, $prepend = false)
  {
  if (!$prefix) {
  if ($prepend) {
  self::$fallbackDirsPsr0 = (
  (array) $paths,
  self::$fallbackDirsPsr0
  );
  } else {
  self::$fallbackDirsPsr0 = (
  self::$fallbackDirsPsr0,
  (array) $paths
  );
  }
  

  return;
  }
  

  $first = $prefix[0];
  if (!isset(self::$prefixesPsr0[$first][$prefix])) {
  self::$prefixesPsr0[$first][$prefix] = (array) $paths;
  

  return;
  }
  if ($prepend) {
  self::$prefixesPsr0[$first][$prefix] = (
  (array) $paths,
  self::$prefixesPsr0[$first][$prefix]
  );
  } else {
  self::$prefixesPsr0[$first][$prefix] = (
  self::$prefixesPsr0[$first][$prefix],
  (array) $paths
  );
  }
  }
  

  // 添加Psr4空间
  private static function addPsr4($prefix, $paths, $prepend = false)
  {
  if (!$prefix) {
  // Register directories for the root namespace.
  if ($prepend) {
  self::$fallbackDirsPsr4 = (
  (array) $paths,
  self::$fallbackDirsPsr4
  );
  } else {
  self::$fallbackDirsPsr4 = (
  self::$fallbackDirsPsr4,
  (array) $paths
  );
  }
  } elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
  // Register directories for a new namespace.
  $length = ($prefix);
  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]                = (array) $paths;
  } elseif ($prepend) {
  // Prepend directories for an already registered namespace.
  self::$prefixDirsPsr4[$prefix] = (
  (array) $paths,
  self::$prefixDirsPsr4[$prefix]
  );
  } else {
  // Append directories for an already registered namespace.
  self::$prefixDirsPsr4[$prefix] = (
  self::$prefixDirsPsr4[$prefix],
  (array) $paths
  );
  }
  }
  

  // 注册命名空间别名
  public static function addNamespaceAlias($namespace, $original = '')
  {
  if (($namespace)) {
  self::$namespaceAlias = (self::$namespaceAlias, $namespace);
  } else {
  self::$namespaceAlias[$namespace] = $original;
  }
  }
  

  // 注册自动加载机制
  public static function register($autoload = '')
  {
  // 注册系统自动加载
  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 ((RUNTIME_PATH . 'classmap' . EXT)) {
  self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
  }
  

  // Composer自动加载支持
  if ((VENDOR_PATH . 'composer')) {
  self::registerComposerLoader();
  }
  

  // 自动加载extend目录
  self::$fallbackDirsPsr4[] = (EXTEND_PATH, DS);
  }
  

  // 注册composer自动加载
  private static function registerComposerLoader()
  {
  if ((VENDOR_PATH . 'composer/autoload_namespaces.php')) {
  $map = require VENDOR_PATH . 'composer/autoload_namespaces.php';
  foreach ($map as $namespace => $path) {
  self::addPsr0($namespace, $path);
  }
  }
  

  if ((VENDOR_PATH . 'composer/autoload_psr4.php')) {
  $map = require VENDOR_PATH . 'composer/autoload_psr4.php';
  foreach ($map as $namespace => $path) {
  self::addPsr4($namespace, $path);
  }
  }
  

  if ((VENDOR_PATH . 'composer/autoload_classmap.php')) {
  $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php';
  if ($classMap) {
  self::addClassMap($classMap);
  }
  }
  

  if ((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($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        = (['.', '#'], [DS, '.'], $class);
  if (isset($_file[$key])) {
  return true;
  }
  

  if (empty($baseUrl)) {
  list($name, $class) = (DS, $class, 2);
  

  if (isset(self::$prefixDirsPsr4[$name . '\\'])) {
  // 注册的命名空间
  $baseUrl = self::$prefixDirsPsr4[$name . '\\'];
  } elseif ('@' == $name) {
  //加载当前模块应用类库
  $baseUrl = App::$modulePath;
  } elseif ((EXTEND_PATH . $name)) {
  $baseUrl = EXTEND_PATH;
  } else {
  // 加载其它模块的类库
  $baseUrl = APP_PATH . $name . DS;
  }
  } elseif (($baseUrl, -1) != DS) {
  $baseUrl .= DS;
  }
  // 如果类存在 则导入类库文件
  if (($baseUrl)) {
  foreach ($baseUrl as $path) {
  $filename = $path . DS . $class . $ext;
  if (($filename)) {
  break;
  }
  }
  } else {
  $filename = $baseUrl . $class . $ext;
  }
  

  if (!empty($filename) && ($filename)) {
  // 开启调试模式Win环境严格区分大小写
  if (IS_WIN && ($filename, PATHINFO_FILENAME) != (($filename), PATHINFO_FILENAME)) {
  return false;
  }
  __include_file($filename);
  $_file[$key] = true;
  return true;
  }
  return false;
  }
  

  /**
  * 实例化(分层)模型
  * @param string $name         Model名称
  * @param string $layer        业务层名称
  * @param bool   $appendSuffix 是否添加类名后缀
  * @param string $common       公共模块名
  * @return Object

  * @throws>  */
  public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
  {
  if (isset(self::$instance[$name . $layer])) {
  return self::$instance[$name . $layer];
  }
  if (($name, '/')) {
  list($module, $name) = ('/', $name, 2);
  } else {
  $module = Request::instance()->module();
  }
  $class = self::parseClass($module, $layer, $name, $appendSuffix);
  if (($class)) {
  $model = new $class();
  } else {
  $class = ('\\' . $module . '\\', '\\' . $common . '\\', $class);
  if (($class)) {
  $model = new $class();
  } else {

  throw new>  }
  }
  self::$instance[$name . $layer] = $model;
  return $model;
  }
  

  /**
  * 实例化(分层)控制器 格式:[模块名/]控制器名
  * @param string $name         资源地址
  * @param string $layer        控制层名称
  * @param bool   $appendSuffix 是否添加类名后缀
  * @param string $empty        空控制器名称
  * @return Object|false

  * @throws>  */
  public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
  {
  if (($name, '/')) {
  list($module, $name) = ('/', $name);
  } else {
  $module = Request::instance()->module();
  }
  $class = self::parseClass($module, $layer, $name, $appendSuffix);
  if (($class)) {
  return new $class(Request::instance());
  } elseif ($empty && ($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) {
  return new $emptyClass(Request::instance());
  }
  }
  

  /**
  * 实例化验证类 格式:[模块名/]验证器名
  * @param string $name         资源地址
  * @param string $layer        验证层名称
  * @param bool   $appendSuffix 是否添加类名后缀
  * @param string $common       公共模块名
  * @return Object|false

  * @throws>  */
  public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
  {
  $name = $name ?: Config::get('default_validate');
  if (empty($name)) {
  return new Validate;
  }
  

  if (isset(self::$instance[$name . $layer])) {
  return self::$instance[$name . $layer];
  }
  if (($name, '/')) {
  list($module, $name) = ('/', $name);
  } else {
  $module = Request::instance()->module();
  }
  $class = self::parseClass($module, $layer, $name, $appendSuffix);
  if (($class)) {
  $validate = new $class;
  } else {
  $class = ('\\' . $module . '\\', '\\' . $common . '\\', $class);
  if (($class)) {
  $validate = new $class;
  } else {

  throw new>  }
  }
  self::$instance[$name . $layer] = $validate;
  return $validate;
  }
  

  /**
  * 数据库初始化 并取得数据库类实例
  * @param mixed         $config 数据库配置
  * @param bool|string   $name 连接标识 true 强制重新连接
  * @return \think\db\Connection
  */
  public static function db($config = [], $name = false)
  {
  return Db::connect($config, $name);
  }
  

  /**
  * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
  * @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   = ($url);
  $action = $info['basename'];
  $module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller();
  $class  = self::controller($module, $layer, $appendSuffix);
  if ($class) {
  if (($vars)) {
  if (($vars, '=')) {
  ($vars, $vars);
  } else {
  $vars = [$vars];
  }
  }
  return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars);
  }
  }
  

  /**
  * 字符串命名风格转换
  * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
  * @param string  $name 字符串
  * @param integer $type 转换类型
  * @return string
  */
  public static function parseName($name, $type = 0)
  {
  if ($type) {
  return (('/_([a-zA-Z])/', function ($match) {
  return ($match[1]);
  }, $name));
  } else {
  return ((("/[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  = (['/', '.'], '\\', $name);
  $array = ('\\', $name);
  $class = self::parseName(($array), 1) . (App::$suffix || $appendSuffix ? ($layer) : '');
  $path  = $array ? ('\\', $array) . '\\' : '';
  return App::$namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class;
  }
  

  /**
  * 初始化类的实例
  * @return void
  */
  public static function clearInstance()
  {
  self::$instance = [];
  }
  
}
  

  
/**
  * 作用范围隔离
  *
  * @param $file
  * @return mixed
  */
  
function __include_file($file)
  
{
  return include $file;
  
}
  

  
function __require_file($file)
  
{
  return require $file;
  
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-429387-1-1.html 上篇帖子: php截取字符串几个实用的函数 下篇帖子: PHP中设置时区方法小结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表