成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Laravel中出現(xiàn)第三方包報classnotfound如何解決-創(chuàng)新互聯(lián)

今天就跟大家聊聊有關Laravel中出現(xiàn)第三方包報class not found如何解決,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據(jù)這篇文章可以有所收獲。

創(chuàng)新互聯(lián)公司是一家專業(yè)提供鹽邊企業(yè)網(wǎng)站建設,專注與網(wǎng)站制作、成都做網(wǎng)站、H5建站、小程序制作等業(yè)務。10年已為鹽邊眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進行中。

出現(xiàn)的問題

公司開發(fā)使用PHP,技術框架使用Laravel。最近線上出現(xiàn)一個問題,就是上線之后,每次都會出錯。查看出錯原因,是composer安裝的第三方出現(xiàn)class not found。因為這個問題,在線下使用Lumen框架的時候,遇到過,查找問題原因是因為依賴的composer包中composer.json中的”autoload”:{“psr-4”:{}}書寫格式問題。解決方法使用命令:composer dump-autoload -o;

雖然知道問題的所在,但是有一個現(xiàn)象比較費解:這個第三方包已經(jīng)使用很久了,為什么最近才開始報錯呢?下面就開始查找出錯原因

解決方案

如果確認第三方包已安裝,并且正確使用use引用了,嘗試執(zhí)行composer dump-autoload -o

最終結果

因為可能篇幅會比較長,所以這里先說明一下最終問題處理結果:原因還未準確定位到,現(xiàn)推測發(fā)布服務器環(huán)境問題,但因為發(fā)布服務器監(jiān)控服務較多,不允許進行測試,所以具體環(huán)境哪個配置導致的問題,還沒有定位到。

下面主要介紹問題解決過程:

 1. 查看laravel autoload
 2. 查看composer源碼;
 3. 重新編譯composer打印日志;
 4. 分析composer install過程;
 5. 查看php artisan optimize源碼

對分析查找問題的過程感興趣的同學可以繼續(xù)往下看。

問題分析及解決過程

1. 查找class not found原因

分析

既然class not found,確認composer包已經(jīng)安裝。那問題就確定在autoload過程

查看源碼

首先自動加載入口 public/index.php 中

require __DIR__.'/../bootstrap/autoload.php';

然后繼續(xù)進入 bootstrap/autoload.php 文件

require __DIR__.'/../vendor/autoload.php';

然后繼續(xù)進入 vendor/autoload.php

// require 自動加載類
require_once __DIR__ . '/composer/autoload_real.php';

// 真正返回文件列表的操作
return ComposerAutoloaderInit3f39d071b2e74e04102a9c9b6f221123::getLoader();

進入getLoader()方法中

public static function getLoader()
{
 if (null !== self::$loader) {
 return self::$loader;
 }

 // 注冊自動加載方法,用來后面初始化ClassLoader類
 spl_autoload_register(array('ComposerAutoloaderInit3f39d071b2e74e04102a9c9b6f221123', 'loadClassLoader'), true, true);
 // 初始化ClassLoarder
 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
 spl_autoload_unregister(array('ComposerAutoloaderInit3f39d071b2e74e04102a9c9b6f221123', 'loadClassLoader'));

 // 這里zend_loader_file_encoded查了一下,解釋為:
 // Returns TRUE if the current file was encoded with Zend Guard or FALSE otherwise. If FALSE, consider disabling the Guard Loader
 // 又查了一下Zend Guard,貌似是php代碼加密并提高執(zhí)行效率的,提高有限,比較雞肋
 // 打印了一下,發(fā)現(xiàn)不存在這個方法,即!function_exists('zend_loader_file_encoded')為true
 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
 if ($useStaticLoader) {
 // 程序在這里執(zhí)行
 // 引用ComposerStaticInit類
 require_once __DIR__ . '/autoload_static.php';

 // 調用ComposerStaticInit類中的getInitializer方法
 // 主要作用是使用ComposerStaticInit類中的值初始化上面創(chuàng)建的ComposerAutoloader對象中的prefixLengthsPsr4、prefixDirsPsr4、prefixesPsr0、classMap等值
 call_user_func(\Composer\Autoload\ComposerStaticInit3f39d071b2e74e04102a9c9b6f221123::getInitializer($loader));
 } else {
 $map = require __DIR__ . '/autoload_namespaces.php';
 foreach ($map as $namespace => $path) {
  $loader->set($namespace, $path);
 }

 $map = require __DIR__ . '/autoload_psr4.php';
 foreach ($map as $namespace => $path) {
  $loader->setPsr4($namespace, $path);
 }

 $classMap = require __DIR__ . '/autoload_classmap.php';
 if ($classMap) {
  $loader->addClassMap($classMap);
 }
 }

 // 重點在這個方法
 $loader->register(true);

 if ($useStaticLoader) {
 $includeFiles = Composer\Autoload\ComposerStaticInit3f39d071b2e74e04102a9c9b6f221123::$files;
 } else {
 $includeFiles = require __DIR__ . '/autoload_files.php';
 }
 foreach ($includeFiles as $fileIdentifier => $file) {
 composerRequire3f39d071b2e74e04102a9c9b6f221123($fileIdentifier, $file);
 }

 return $loader;
}

ClassLoader的register方法

public function register($prepend = false)
{
 // 調用ClassLoader類的loadClass方法
 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}

ClassLoader類的loadClass方法

public function loadClass($class)
{
 // 查找文件,如果查找到文件,則加載文件
 if ($file = $this->findFile($class)) {
 includeFile($file);

 return true;
 }
}

ClassLoader類的findFile方法

public function findFile($class)
{
 // class map lookup
 // class map加載方式,我的理解:是通過將類與對應路徑生成一個對應表
 // 該方式優(yōu)點:加載速度快,相當于查詢字典;
 // 缺點:無法實現(xiàn)自動加載,添加新類后,需要對應維護class map
 if (isset($this->classMap[$class])) {
 return $this->classMap[$class];
 }

 // $classMapAuthoritative默認值為false,流程到目前,沒有設置過該值
 // $missingClasses通過查看該方法最后幾行,發(fā)現(xiàn)作用是記錄自動加載過程中不存在的文件
 // 所以這里第一次加載會返回false
 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
 return false;
 }

 // APCu 是老牌 PHP 字節(jié)碼和對象緩存,緩存器 APC 的分支(PS:我也是查的,不懂呀~大家感興趣可以自己深研究)
 // 經(jīng)測試,$this->apcuPrefix=null
 if (null !== $this->apcuPrefix) {
 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
 if ($hit) {
  return $file;
 }
 }

 // 最后一層方法(保證是最后一個方法)
 $file = $this->findFileWithExtension($class, '.php');

 // Search for Hack files if we are running on HHVM
 if (false === $file && defined('HHVM_VERSION')) {
 $file = $this->findFileWithExtension($class, '.hh');
 }

 if (null !== $this->apcuPrefix) {
 apcu_add($this->apcuPrefix.$class, $file);
 }

 // 記錄無法找到的類,方便再次加載直接返回
 if (false === $file) {
 // Remember that this class does not exist.
 $this->missingClasses[$class] = true;
 }

 return $file;
}

ClassLoader類中findFileWithExtension方法

private function findFileWithExtension($class, $ext)
{
 // 終于看到加載psr-4了
 // PSR-4 lookup
 // 對路徑中的\轉換為文件系統(tǒng)中對應路徑分隔符并+后綴,
 // 比如wan\test類,最后處理為wan/test.php(linux下)
 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

 // 獲得類名中第一個字母,主要用于在ClassLoader中prefixLengthsPsr4快速檢索包,并找到對應包前綴長度,后面截取時使用
 // 對比autoload_static.php中的$prefixLengthsPsr4即可明白作用
 $first = $class[0];
 if (isset($this->prefixLengthsPsr4[$first])) {
 $subPath = $class;
 while (false !== $lastPos = strrpos($subPath, '\\')) {
  // 從右往左一層層循環(huán)類名中的路徑
  $subPath = substr($subPath, 0, $lastPos);
  $search = $subPath.'\\';
  // 找到對應composer包前綴后,取出對應路徑,將包前綴截取后,替換成對應的目錄路徑,即為class所對應文件
  if (isset($this->prefixDirsPsr4[$search])) {
  foreach ($this->prefixDirsPsr4[$search] as $dir) {
   $length = $this->prefixLengthsPsr4[$first][$search];
   if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
   return $file;
   }
  }
  }
 }
 }

 // 到這里psr-4文件就加載完了,后面是psr-0等其他文件加載,這里就不分析了。
 // 這里分析一下為什么是第三方包psr-4格式錯誤
 // 比如包名為wan/lib,即composer安裝命令對應composer require wan/lib
 // 第三方包中autoload psr-4配置為 "psr-4" : { "wan\\" : "src" } 
 // (**警告:上面是錯誤配置,為了舉例說明;正確應該是"psr-4" : { "wan\\lib\\" : "src" })
 // 最終生成的$prefixLengthsPsr4為{'w' =>array ('wan\\' => 5,),}
 // 生成$prefixDirsPsr4為'wan\\' => array (0 => __DIR__ . '/..' . '/wan/lib/src',),
 // 對應上面代碼,在最后$file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length)
 // $file拼接出來的路徑是vendor/wan/lib/src/lib/$className.php,導致最后無法拼接出正確路徑

 // PSR-4 fallback dirs
 foreach ($this->fallbackDirsPsr4 as $dir) {
 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
  return $file;
 }
 }

 // PSR-0 lookup
 if (false !== $pos = strrpos($class, '\\')) {
 // namespaced class name
 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
  . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
 } else {
 // PEAR-like class name
 $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
 }

 if (isset($this->prefixesPsr0[$first])) {
 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
  if (0 === strpos($class, $prefix)) {
  foreach ($dirs as $dir) {
   if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
   return $file;
   }
  }
  }
 }
 }

 // PSR-0 fallback dirs
 foreach ($this->fallbackDirsPsr0 as $dir) {
 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
  return $file;
 }
 }

 // PSR-0 include paths.
 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
 return $file;
 }

 return false;
}

看完上述內容,你們對Laravel中出現(xiàn)第三方包報class not found如何解決有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

名稱欄目:Laravel中出現(xiàn)第三方包報classnotfound如何解決-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://jinyejixie.com/article42/ccehec.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供外貿建站、建站公司、網(wǎng)站維護、面包屑導航、網(wǎng)站內鏈、電子商務

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

h5響應式網(wǎng)站建設
中超| 息烽县| 广水市| 平果县| 南充市| 莎车县| 绥中县| 微山县| 汕头市| 徐闻县| 内江市| 大渡口区| 延川县| 沁水县| 丹东市| 离岛区| 晋宁县| 微山县| 左权县| 荣昌县| 泽州县| 彭山县| 泰宁县| 大关县| 大同市| 广州市| 陆良县| 威宁| 梁平县| 台北县| 杨浦区| 平昌县| 扎鲁特旗| 彭山县| 巴中市| 思茅市| 大姚县| 昂仁县| 汾西县| 乌兰浩特市| 青海省|