成功包含时未找到类

时间:2017-11-25 18:07:42

标签: php

我找不到这个致命的错误:

  

致命错误:未捕获错误:Class' HomeController'找不到

但文件已包含在内。

require_once self::CONTROLLERS_PATH . $this->controller . '.php';
var_dump(file_exists(self::CONTROLLERS_PATH . $this->controller . '.php'));
new $this->controller;

我通过var_dumping file_exists调试它,返回true。我检查了命名空间,一切看起来都不错。如果我转储$this->controller,则其值与预期值相同 - string(14) "HomeController"。如果我像new HomeController();那样对其进行硬编码,则会初始化该类。但是为什么它不能从变量中运行呢?你可以在下面看到我的代码。这是我的文件结构:

enter image description here

App.php

<?php


namespace App\Core;

class App
{
    protected $controller = 'HomeController';
    protected $method = 'index';
    protected $params = [];

    const CONTROLLERS_PATH = '../App/Controllers/';

    public function __construct ()
    {
        $url = $this->parseUrl();

        if(file_exists(self::CONTROLLERS_PATH . ucfirst($url[0]) . '.php'))
        {
            $this->controller = ucfirst($url[0]); //Update $this->controller value
            unset($url[0]);
            echo 'file exists';
        }
        require_once self::CONTROLLERS_PATH . $this->controller . '.php';
        var_dump(file_exists(self::CONTROLLERS_PATH . $this->controller . '.php'));
        var_dump($this->controller);
        new $this->controller;

        if(isset($url[1]))
        {
            if(method_exists($this->controller, $url[1]))
            {
                $this->method = $url[1];
                unset($url[1]);
                echo 'method exists';
            }
        }

        $this->params = $url ? array_values($url): [];
        call_user_func_array([$this->controller, $this->method], $this->params);
        var_dump($url);
    }

    public function parseUrl()
    {
        if(isset($_GET['url']))
        {
            return $url = explode('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));
        }
    }
}

HomeController.php

<?php

namespace App\Controllers;

    class HomeController
    {
        public function index()
        {
            echo 'asd';
        }
    }

2 个答案:

答案 0 :(得分:2)

通过变量名实例化类时,您始终必须包含整个命名空间。并且必须首先将其存储为字符串 一个例子:

import matplotlib.pyplot as plt
import numpy as np
import time
import matplotlib as mpl
mpl.rcParams['lines.linewidth'] = 2
plt.ion()
%matplotlib notebook

x = np.arange(-10, 10, 0.01)

fig = plt.figure(figsize = (12, 7))
ax = fig.add_subplot(111)
ax.grid()
plt.show()
for j in range(1,5):
    ax.set_title(r"%6.2f    $y = \frac{\sin{(\pi x j)}}{(\pi x j)}$" % j)
    y = np.sin( np.pi*x*j )/( np.pi*x*j )
    line, = ax.plot(x, y, 'b')
    fig.canvas.draw()
    time.sleep(1)
    if j != 4:
        line.remove()

在你的情况下:

namespace Api;

Class test {

    public function __construct() {
        echo "test";
    }
}

$className = 'test';
$classNameNamespaced = "\\Api\\".$className;

$a = new $classNameNamespaced;  // echoes "test"

答案 1 :(得分:0)

由于代码位于命名空间中,new $this->controllernew HomeController不同,即使$this->controller的值为HomeController

表达式new HomeController在编译时进行评估,由于名称空间,它被扩展为new \App\Controllers\HomeControllerName resolution rules上的规则#6)。解释器需要完全限定的类名才能找到它。

在运行时期间评估表达式new $this->controller,它导致new HomeControllernew \HomeController相同。在根命名空间中没有定义任何类HomeController,因此会出现错误。

您可以通过将完整的类名构建为字符串来轻松实现:

$class = 'App\\Controllers\\'.$this->controller;
new $class;

在文档页面"Namespaces and dynamic language features"中查找更多示例。

但加载类的最佳方法是使用autoloader generated by Composer