簡體   English   中英

致命錯誤:未捕獲的錯誤:未找到類“ App \\ Database”

[英]Fatal error: Uncaught Error: Class 'App\Database' not found

我嘗試學習oop,但是在我的第一堂課上,它給了我這個錯誤。

數據庫類

<?php
namespace App;

class Database
{
   ...
}

在我的functions.php中

<?php
require 'helpers.php';
require 'connection.php';
use App\Database;
...

“ app”文件夾下的類,其命名空間為“ App”。 為什么我會收到此錯誤?

您要么需要包含文件,要么使用AutoLoader。 自動加載程序告訴PHP在哪里可以找到類,因為PHP需要知道該文件。

PHP文檔中對自動加載器進行了詳細說明: https : //secure.php.net/manual/en/language.oop5.autoload.php

來自上述文檔的示例:

<?php
spl_autoload_register(function ($class_name) {
    include $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2(); 
?>

在這種情況下,spl_autoload_register用於注冊自動加載器。 自動加載器是采用類名稱的功能,並包括必要的類。 例如,您可以使用上面使用的自動加載器功能,在這種情況下,類名必須與文件名相同。 這是一個非常簡單的示例,但是更高級的自動加載器可以檢查文件是否存在,檢查多個位置等。

有關原始問題的評論中提到了示例。

注意:您會發現其他來源提到__autoload($ class)函數。 該函數的功能完全相同,但是在以后的更新中將從PHP中刪除它 因此,最好使用spl_autoload_register

因為我在評論中張貼了我的自動裝帶器。

https://github.com/ArtisticPhoenix/MISC/blob/master/Autoloader.php

您可以在這篇文章的底部找到代碼:

基本用法如下:

require_once 'Autoloader.php';

AutoLoader::getInstance()->regesterPath('\\', __DIR__);

假定它位於名稱空間根目錄中。 因此,如果您有一堂課。

namespace App;

class Database{ ... }

這個班在

 www
  |- Autoloader.php
  |- App
  | --Database.php

然后它將查找__DIR__ +命名空間或__DIR__/APP/ 您可以注冊路徑,因為如果您有此設置。

 www
  |- Autoloader.php
  |- includes
  |-- App
  | ---Database.php

該類位於includes/App和Autoloader位於/根文件夾中的位置,您可以通過這種方式進行。

require_once 'Autoloader.php';

AutoLoader::getInstance()->regesterPath('\\', __DIR__.'/includes/');

另外,如果您有這樣的設置。

 www
  |- Autoloader.php
  |- includes
  | --Database.php

如果沒有實際的App文件夾,則可以這樣進行。

require_once 'Autoloader.php';

AutoLoader::getInstance()->regesterPath('\\App\\', __DIR__.'/includes/');

或以上的任何組合。

它將說明\\\\App之間的差異。 App\\\\App\\\\大部分情況下。 但是您也可以使用此功能打開調試。

require_once 'Autoloader.php';

$AutoLoader = AutoLoader::getInstance();
$AutoLoader->setDebug(true);
$AutoLoader>regesterPath('\\App\\', __DIR__.'/includes/');

它會吐出一堆東西,告訴您它在找什么。 如果使用HTML,則可能必須使用<pre>保留空白格式。 方便地,您還可以關閉“調試”,因為您可能正在自動加載許多類。

$AutoLoader->setDebug(false);

您還可以分配多個路徑,並為其賦予優先級,它將按優先級順序查找它們。 但這在這種情況下並不重要。

因此,例如:

我有一個文件夾

      www
       |-MISC
       |--index.php
       |--Autoloader.php
       |---IMAP
       |----GmailClient.php

也是在同一個Git Repo中。 它具有Lib\\Email\\IMAP的名稱空間,其中只有IMAP存在。

並加載它,如果我在MISC文件中與AutoLoader.php文件處於同一級別的index.php中這樣做:

 //include the Autoloader
 require_once __DIR__.'/Autoloader.php';

 //get an instance of it (Singleton pattern)
 $Autoloader = Autoloader::getInstance();

 //regester a namespace, path pair
 $Autoloader->regesterPath('Lib\Email', __DIR__.'/IMAP/');

 //preserve whitespace
 echo "<pre>";

 //turn on debugging before a problem class
 $Autoloader->setDebug(true);

 //Attempt to load the class as normal
 $G = new GmailClient($hostname, $username, $password);

 //turn off debugging after trying to load a problem class.
 $AutoLoader->setDebug(false);

這是調試輸出

================================= Autoloader::debugMode ==================================
Autoloader::splAutoload Lib\Email\IMAP\GmailClient
Checking class: GmailClient
Checking namespace: Lib/Email/IMAP
checking pathname:C:/Server/www/MISC/IMAP/IMAP/GmailClient.php
==========================================================================================

馬上我們可以看到C:/Server/www/MISC/IMAP/IMAP/GmailClient.php IMAP在其中2 C:/Server/www/MISC/IMAP/IMAP/GmailClient.php 這是因為我將其包含在路徑中,因此它開始在C:/Server/www/MISC/IMAP/查找,然后添加Lib/Email/IMAP的名稱空間arg IMAP未提供的名稱空間。 我們將Lib/Email作為第一個參數。 實質上,因為這是路徑的一部分,所以在查找時已經在該文件夾中。

因此,如果我只是從路徑中刪除該IMAP

$Autoloader->regesterPath('Lib\Email', __DIR__);

它將輸出以下內容:

================================= Autoloader::debugMode ==================================
Autoloader::splAutoload Lib\Email\IMAP\GmailClient
Checking class: GmailClient
Checking namespace: Lib/Email/IMAP
checking pathname:C:/Server/www/MISC/IMAP/GmailClient.php
Found: C:/Server/www/MISC/IMAP/GmailClient.php
==========================================================================================

最重要的是

Found: C:/Server/www/MISC/IMAP/GmailClient.php

這顯然意味着它找到了類文件並加載了它。

希望有道理。

以下是自動裝帶器的完整代碼,這樣,如果Repo I鏈接發生任何更改,答案就不會中斷。

<?php
/**
 *
 * (c) 2016 ArtisticPhoenix
 *
 * For license information please view the LICENSE file included with this source code. GPL-3
 *
 * PSR4 compatible Autoloader
 * 
 * @author ArtisticPhoenix
 * @see http://www.php-fig.org/psr/psr-4/
 * 
 * @example
 * $Autoloader = Autoloader::getInstance();
 * //looks in includes for folder named /includes/Lib/Auth/User/
 * $Autoloader->regesterPath('Lib\\Auth\\User', __DIR__.'/includes/');
 *
 */
final class Autoloader
{
    /**
     *
     * @var int
     */
    const DEFAULT_PRIORITY = 10;

    /**
     * namespace / class path storage
     * @var array
     */
    private $paths = array();

    /**
     * cashe the loaded files
     * @var array
     */
    private $files = array();

    /**
     * namespace / class path storage
     * @var array
     */
    private $debugMode = false;

    /**
     *
     * @var Self
     */
    private static $instance;


    /**
     * No public construction allowed - Singleton
     */
    private function __construct($throw, $prepend)
    {
        spl_autoload_register(array( $this,'splAutoload'), $throw, $prepend);
    }

    /**
     * No cloning of allowed
     */
    private function __clone()
    {
    }

    /**
     *
     * Get an instance of the Autoloader Singleton
     * @param boolean $throw
     * @param boolean $prepend
     * @return self
     */
    public static function getInstance($throw = false, $prepend = false)
    {
        if (!self::$instance) {
            self::$instance = new self($throw, $prepend);
        }
        return self::$instance;
    }

    /**
     * set debug output
     * @param boolean $debug
     * @return self
     */
    public function setDebug($debug = false)
    {
        $this->debugMode = $debug;
        return $this;
    }

    /**
     * Autoload
     * @param string $class
     */
    public function splAutoload($class)
    {
        $this->debugMode('_START_');
        $this->debugMode(__METHOD__.' '.$class);
        //keep the orignal class name
        $_class = str_replace('\\', '/', $class);
        $namespace = '';
        if (false !== ($pos = strrpos($_class, '/'))) {
            $namespace = substr($_class, 0, ($pos));
            $_class = substr($_class, ($pos + 1));
        }
        //replace _ in class name only
        if (false !== ($pos = strrpos($_class, '/'))) {
            if (strlen($namespace)) {
                $namespace .= '/'.substr($_class, 0, ($pos));
            } else {
                $namespace = substr($_class, 0, ($pos));
            }
            $_class = substr($_class, ($pos + 1));
        }

        $this->debugMode("Checking class: $_class");
        $this->debugMode("Checking namespace: $namespace");
        do {
            if (isset($this->paths[ $namespace ])) {
                foreach ($this->paths[ $namespace ] as $registered) {
                    $filepath = $registered['path'] . $_class . '.php';

                    $this->debugMode("checking pathname:{$filepath}");
                    if (file_exists($filepath)) {
                        $this->debugMode("Found: $filepath");
                        $this->debugMode('_END_');
                        require_once $filepath;
                        $this->files[$class] = $filepath;
                    }
                }
            }

            if (strlen($namespace) == 0) {
                //if the namespace is empty and we couldn't find the class we are done.
                break;
            }

            if (false !== ($pos = strrpos($namespace, '/'))) {
                $_class = substr($namespace, ($pos + 1)) . '/' . $_class;
                $namespace = substr($namespace, 0, ($pos));
            } else {
                $_class = (strlen($namespace) ? $namespace : '') . '/' . $_class;
                $namespace = '';
            }
        } while (true);
        $this->debugMode('_END_');
    }

    /**
     * get the paths regestered for a namespace, leave null go get all paths
     * @param string $namespace
     * @return array or false on falure
     */
    public function getRegisteredPaths($namespace = null)
    {
        if (is_null($namespace)) {
            return $this->paths;
        } else {
            return (isset($this->paths[$namespace])) ? array($namespace => $this->paths[$namespace])  : false;
        }
    }

    /**
     *
     * @param string $namespace
     * @param string $path
     * @param int $priority
     * @return self
     */
    public function regesterPath($namespace, $path, $priority = self::DEFAULT_PRIORITY)
    {
        $namespace = str_replace('\\', '/', $namespace); //convert to directory seperator
        $path = ($this->normalizePath($path));

        $this->paths[$namespace][sha1($path)] = array(
            'path'        => $path,
            'priority'    => $priority
        );
        $this->sortByPriority($namespace);
        return $this;
    }

    /**
     * un-regester a path
     * @param string $namespace
     * @param string $path
     */
    public function unloadPath($namespace, $path = null)
    {
        if ($path) {
            $path = $this->normalizePath($path);
            unset($this->paths[$namespace][sha1($path)]);
        } else {
            unset($this->paths[$namespace]);
        }
    }

    /**
     * check if a namespace is regestered
     * @param string $namespace
     * @param string $path
     * @return bool
     */
    public function isRegistered($namespace, $path = null)
    {
        if ($path) {
            $path = $this->normalizePath($path);
            return isset($this->paths[$namespace][sha1($path)]) ? true : false;
        } else {
            return isset($this->paths[$namespace]) ? true : false;
        }
    }

    /**
     * get the file pathname of a loaded class
     * @param string $class
     * @return mixed
     */
    public function getLoadedFile($class = null)
    {
        if (!$class) {
            return $this->files;
        }

        if (isset($this->files[$class])) {
            return $this->files[$class];
        }
    }
    /**
     * output debug message
     * @param string $message
     */
    protected function debugMode($message)
    {
        if (!$this->debugMode) {
            return;
        }

        switch ($message) {
            case '_START_':
                echo str_pad("= ".__METHOD__." =", 90, "=", STR_PAD_BOTH) . PHP_EOL;
            break;
            case '_END_':
                echo str_pad("", 90, "=", STR_PAD_BOTH) . PHP_EOL . PHP_EOL;
            break;
            default:
                echo $message . PHP_EOL;
        }
    }

    /**
     * sort namespaces by priority
     * @param string $namespace
     */
    protected function sortByPriority($namespace)
    {
        uasort($this->paths[$namespace], function ($a, $b) {
            return ($a['priority'] > $b['priority']) ? true : false;
        });
    }

    /**
     * convert a path to unix seperators and make sure it has a trailing slash
     * @param string $path
     * @return string
     */
    protected function normalizePath($path)
    {
        if (false !== strpos($path, '\\')) {
            $path = str_replace("\\", "/", $path);
        }

        return rtrim($path, '/') . '/';
    }
}

PS我在本示例中使用的GmailClient類是我編寫的,用於解析Gmail帳戶中的傳入電子郵件。 它不是100%充實的,因為我們有特定目的需要它。 但是它在同一個GitHub存儲庫中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM