我在Laravel的微框架Lumen中尝试使用自定义的名称空间类时遇到了一个问题。我在尝试实例化类时遇到Class not found
错误。
相对目录:
|--- app
| |---Classes
| | |--- GetImages.php < My custom, namespaced class
|--- Http
|--- |--- routes.php < Using the class here works
| |--- Processors
| | |--- get.php < Using the class here does not work, generates the error (listed below)
GetImages.php文件,为简洁起见简化为:
namespace AppClasses;
class GetImages
{
public $name = 'Class instantiated';
}
get.php文件,其中发生错误:
use AppClassesGetImages;
$n = new GetImages;
return $n->name;
如果我在主页中像$.get('http://www.example.com/app/Http/Processors/get.php')
一样发出ajax
请求,我会得到以下错误:
Fatal error: Class 'AppClassesGetImages' not found in http://www.example.com/app/Http/Processors/get.php on line 5.
但是,如上所述,如果我在routes.php
文件中实例化这个类,它就可以正常工作。
composer.json
:的自动加载部分
"autoload": {
"psr-4": {
"App\": "app/"
},
"classmap": [
"database/"
],
"files": [
"app/Http/helpers.php"
]
}
我觉得这是一个自动加载问题,但我已经完成了composer dumpautoload -o
、composer update
,并遵循了PSR-4
标准,没有任何更改。你知道我错过了什么吗?
如果运行http://www.example.com/app/Http/Processors/get.php
,则整个get.php
文件内容如下所示:
use AppClassesGetImages;
$n = new GetImages;
return $n->name;
它无法工作,因为类为的文件尚未加载。事实上,这个文件与Laravel/Lumen没有任何共同之处,它只是一个简单的PHP文件。当您使用框架时,它使用Composer自动加载器来加载有效的文件,当您使用简单文件时,您需要包括自动加载器或手动包括必要的文件。
您有3个选项:
- 为该操作创建路由并在控制器中执行您想要的操作
- 在文件的开头添加
require '/vendor/autoload.php';
(具有自动加载文件的有效路径 - 手动要求
GetImages
类require 'app/Classes/GetImages.php';
当您使用框架并且不使用独立的PHP文件来完成这项工作时,最好的选择可能是第一个。
您向以下URL发出AJAX请求:$.get('http://www.example.com/app/Http/Processors/get.php')
如果这真的让你从PHP得到了答案,那么你绕过了整个框架,在设置它时犯了一个大错误。
每个静态资产都应该属于您选择的适当子目录中的public
文件夹(图像可能会进入public/img
等)
还应该有一个文件public/index.php
,它应该获取public
中某个地方的所有不是现有文件的请求。这需要正确配置web服务器,即Apache web服务器通常会获得一个.htaccess文件(如果您无法将内容添加到vhost)来进行URL重写。
index.php
将引导Composer的自动加载,然后初始化框架并将当前请求传递给它进行处理。路由将找到相关的控制器,该控制器将进行一些奇特的数据处理,并返回结果(以呈现的模板、JSON数据或其他任何形式)。
这意味着您应该使用的URL永远不会与实际现有文件的路径名相同。但这就是您所做的:app/Http/Processors/get.php
是直接访问的。这是一个巨大的安全漏洞,因为所有框架都认为唯一可以公开访问的文件夹是public
文件夹。您公开了一个更高级别的目录,每个人都可以访问任何文件(如果他知道文件的名称,或者如果您的web服务器创建了一个目录列表)。这可能会暴露具有敏感密码的配置文件。
它还破坏了Ajax请求中的脚本,因为现在您必须再次完成所有初始化工作。
仅仅创建一个控制器是不够的,通常还必须修复配置。
我为我的自定义类的名称空间和在composer.json文件中找到它们的目录添加了一个PS4条目,如下所示:
"autoload": {
"psr-4": {
"App\": "app/",
"MyCompany\MyCodeLibrary\": "MyCodeLibrary/"
},
"classmap": [
"database/"
]
},
然后在项目根目录(包含app
目录的同一目录)中创建我的MyCodeLibrary
目录。
然后我只需要运行:
$ composer dump-autoload -o
现在,在MyCodeLibrary
目录中,我添加了我想要的任何类。举个例子,我添加了一个名为Calculator.php
的类。我在MyCodeLibrary
中创建它。
文件MyCodeLibrary/Calculator.php
内部看起来是这样的(注意,我可以使用Lumen app()
和config()
辅助方法来加载我的自定义配置文件(或者做其他事情,比如进行数据库查询):
<?php
namespace MyCompanyMyCodeLibrary;
class Calculator {
public $app_settings;
public __construct() {
// load custom config files
app()->configure('my-app-settings');
$this->app_settings = config('my-app-settings');
}
...
// other custom class methods
...
}
如果我需要在流明控制器中使用我的类,我可以这样使用:
<?php
namespace AppHttpControllers;
use IlluminateHttpRequest;
use MyCompanyMyCodeLibraryCalculator;
class TestController extends Controller
{
public $calculator;
public function __construct() {
$this->calculator = new Calculator();
}
public function doSomething() {
$this->calculator->something();
}
...
}
我知道手动创建自己的实例不是最有趣的事情,但它是有效的。我真的不知道是否有一种类似Laravel的聪明方法可以在Lumen中与服务提供商和/或门面自动创建自定义类的新实例,因为我没有尝试过寻找它。主要是因为我试图保持轻松。否则我会用拉拉威尔。