dongtang5229
2018-04-07 07:58
浏览 243
已采纳

致命错误:未捕获错误:未找到类“应用程序\数据库”

I try to learn oop but in my first class it gives me this error.

Database class

<?php
namespace App;

class Database
{
   ...
}

in my functions.php

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

Class under the "app" folder and it's namespace is "App". Why I'm getting this error ?

图片转代码服务由CSDN问答提供 功能建议

我尝试学习oop但是在我的第一堂课中它给了我这个错误。

数据库类

 &lt;?php 
namespace App; 
 
class Database 
 {
 ... 
} 
  <  / pre> 
 
 

在我的functions.php

 &lt;?php 
require'helpers.php'; 
require'connection.php'; \  nuse App \ Database; 
 ... 
   
 
 

“app”文件夹下的类,它的名称空间为“App”。 为什么我收到此错误?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douchang8219 2018-04-07 08:05
    已采纳

    You either need to include the file, or use an AutoLoader. AutoLoaders tell PHP where a class can be found, as PHP needs to know the file.

    Autoloaders are fully explained in the PHP documentation: https://secure.php.net/manual/en/language.oop5.autoload.php

    Example from the mentioned documentation:

    <?php
    spl_autoload_register(function ($class_name) {
        include $class_name . '.php';
    });
    
    $obj  = new MyClass1();
    $obj2 = new MyClass2(); 
    ?>
    

    In this case spl_autoload_register is used to register the autoloader. The autoloader is a function which takes the class name, and includes the necessary class. For example you can use the autoloader function as used above, in which case the class name needs to be identical to the filename. This is a quite simple example, but a more advanced autoloader could check if files exist, check multiple locations, etc...

    Examples are mentioned in the comments on your original question.

    note: You will find other sources mentioning the __autoload($class) function. This function does exactly the same, but will be removed from PHP in future updates. Therefore, you are better off using spl_autoload_register

    已采纳该答案
    打赏 评论
  • dswu26846 2018-04-07 08:42

    Because I posted my Autoloader in the comments.

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

    You can find the code at the bottom of this post:

    The basic usage is as follows:

    require_once 'Autoloader.php';
    
    AutoLoader::getInstance()->regesterPath('\\', __DIR__);
    

    This assumes it's in the directory that is the root of you namespace. So if you have a class.

    namespace App;
    
    class Database{ ... }
    

    And this class is in

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

    Then it will look for __DIR__ + Namespace or __DIR__/APP/. You can register paths because if you have this setup.

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

    Where the class is located in includes/App and Autoloader is in / the root folder you can do it this way.

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

    Also if you have it setup like this.

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

    Where there is no actual App folder then you can do it like this.

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

    Or any combination of the above.

    It will account for the differences between \\App. App and \\App\\ for the most part. But you can also turn on debugging with this.

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

    And it will spit out a bunch of stuff telling you where it is looking. You may have to use <pre> to keep the whitespace format, if your working in HTML. Conveniently you can also turn off Debugging, because you may be autoloading a bunch of classes.

    $AutoLoader->setDebug(false);
    

    You can also assign multiple paths, and give them a priority and it will look in them in the order of the priority. But that is not really important in this case.

    So for example:

    I have a folder

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

    Which is also in the same Git Repo. It has the namespace of Lib\Email\IMAP of which only the IMAP exists.

    And to load It if I do this in index.php, which is inside the MISC file and at the same level as the AutoLoader.php file:

     //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);
    

    This is what it Outputs for debugging

    ================================= 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
    ==========================================================================================
    

    Right away we can see C:/Server/www/MISC/IMAP/IMAP/GmailClient.php That IMAP is in there 2x. This is because I included that in the path, So it starts looking in C:/Server/www/MISC/IMAP/ and then adds the namespace that wasn't given in the namespace arg IMAP from Lib/Email/IMAP. We gave it Lib/Email as the first argument. So essentially, because this was part of the path it's already in that folder when it looks for that.

    So If I just remove that IMAP from the path:

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

    It will output this:

    ================================= 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
    ==========================================================================================
    

    With the most important line being this

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

    Which obviously means that it found the class file and loaded it.

    Hope that makes sense.

    Following is the full code for the autoloader, that way the answer wont break if anything changes with the Repo I linked.

    <?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, '/') . '/';
        }
    }
    

    P.S. the GmailClient class I used in this example, I wrote to parse incoming Emails in a Gmail account. It's not 100% fleshed out as we needed it for a specific purpose. But it is in the same GitHub repository.

    打赏 评论

相关推荐 更多相似问题