繁体   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