Laravel / Lumen 自定义 class 未找到
Laravel / Lumen custom class not found
我在 Lumen 中尝试使用自定义的命名空间 class 时遇到问题,Laravel 的微框架。尝试实例化 class.
时出现 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 App\Classes;
class GetImages
{
public $name = 'Class instantiated';
}
get.php文件,发生错误的地方:
use App\Classes\GetImages;
$n = new GetImages;
return $n->name;
如果我在主页中发出 ajax
请求,例如 $.get('http://www.example.com/app/Http/Processors/get.php')
,我会收到以下错误:
Fatal error: Class 'App\Classes\GetImages' not found in http://www.example.com/app/Http/Processors/get.php on line 5.
但是,如上所述,如果我在 routes.php
文件中实例化此 class,它可以正常工作。
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 App\Classes\GetImages;
$n = new GetImages;
return $n->name;
它不会工作,因为 class 的文件还没有被加载。事实上这个文件与Laravel/Lumen没有任何共同之处,它只是简单的PHP文件。当您使用框架时,它使用 Composer 自动加载器加载有效文件,当您使用简单文件时,您需要包含自动加载器或手动包含必要的文件。
您有 3 个选项:
- 为此操作创建路由并在控制器中执行您想要的操作
- 在文件开头添加
require '/vendor/autoload.php';
(具有自动加载文件的有效路径
- 手动要求
GetImages
class 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
中某处不存在的每个请求。这需要正确配置网络服务器,即 Apache 网络服务器通常会获得一个 .htaccess 文件(如果您无法将内容添加到虚拟主机),该文件会执行 URL 重写。
index.php
会bootstrap自动加载Composer,然后初始化框架,将当前请求传递给它处理。路由会找到关联的控制器,它会做一些花哨的数据处理,然后 return 一个结果(以渲染模板、JSON 数据或其他任何形式)。
这意味着您应该使用的 URLs 永远不会与实际存在的文件的路径名相同。但这就是您所做的: app/Http/Processors/get.php
是直接访问的。这是一个巨大的安全漏洞,因为所有框架都假定唯一可公开访问的文件夹是 public
文件夹。你公开了一个更高的目录级别,每个人都可以访问任何文件(如果他知道它的名字,或者如果你的网络服务器创建了一个目录列表)。这可能会暴露带有敏感密码的配置文件。
而且它还会破坏您在 Ajax 请求中的脚本,因为现在您必须再次进行所有初始化工作。
只创建一个controller还不行,还得把配置搞定。
我通过为自定义 classes 的命名空间添加一个 PS4 条目以及在 composer.json 文件中找到它们的目录来实现它的工作,例如所以:
"autoload": {
"psr-4": {
"App\": "app/",
"MyCompany\MyCodeLibrary\": "MyCodeLibrary/"
},
"classmap": [
"database/"
]
},
然后在项目根目录(包含 app
目录的相同目录)中创建我的 MyCodeLibrary
目录。
那我只需要运行:
$ composer dump-autoload -o
现在,在 MyCodeLibrary
目录中,我可以添加我想要的任何 classes。比方说,我添加了一个 class 调用 Calculator.php
。我在 MyCodeLibrary
内创建它。
文件 MyCodeLibrary/Calculator.php
内部看起来像这样(请注意,我可以使用 Lumen app()
和 config()
辅助方法来加载我的自定义配置文件(或执行其他操作,例如进行数据库查询。):
<?php
namespace MyCompany\MyCodeLibrary;
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
...
}
如果我需要在 Lumen 控制器中使用我的 class,我可以这样使用它:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use MyCompany\MyCodeLibrary\Calculator;
class TestController extends Controller
{
public $calculator;
public function __construct() {
$this->calculator = new Calculator();
}
public function doSomething() {
$this->calculator->something();
}
...
}
我知道手动创建自己的实例并不是最有趣的事情,但它确实有效。我真的不知道是否有一种聪明的 Laravel-like 方法可以在 Lumen 中使用服务提供商 and/or facades 自动创建自定义 classes 的新实例,因为我还没有尝试过寻找它。主要是因为我想保持轻松。否则我会使用 Laravel.
我在 Lumen 中尝试使用自定义的命名空间 class 时遇到问题,Laravel 的微框架。尝试实例化 class.
时出现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 App\Classes;
class GetImages
{
public $name = 'Class instantiated';
}
get.php文件,发生错误的地方:
use App\Classes\GetImages;
$n = new GetImages;
return $n->name;
如果我在主页中发出 ajax
请求,例如 $.get('http://www.example.com/app/Http/Processors/get.php')
,我会收到以下错误:
Fatal error: Class 'App\Classes\GetImages' not found in http://www.example.com/app/Http/Processors/get.php on line 5.
但是,如上所述,如果我在 routes.php
文件中实例化此 class,它可以正常工作。
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 App\Classes\GetImages;
$n = new GetImages;
return $n->name;
它不会工作,因为 class 的文件还没有被加载。事实上这个文件与Laravel/Lumen没有任何共同之处,它只是简单的PHP文件。当您使用框架时,它使用 Composer 自动加载器加载有效文件,当您使用简单文件时,您需要包含自动加载器或手动包含必要的文件。
您有 3 个选项:
- 为此操作创建路由并在控制器中执行您想要的操作
- 在文件开头添加
require '/vendor/autoload.php';
(具有自动加载文件的有效路径 - 手动要求
GetImages
classrequire '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
中某处不存在的每个请求。这需要正确配置网络服务器,即 Apache 网络服务器通常会获得一个 .htaccess 文件(如果您无法将内容添加到虚拟主机),该文件会执行 URL 重写。
index.php
会bootstrap自动加载Composer,然后初始化框架,将当前请求传递给它处理。路由会找到关联的控制器,它会做一些花哨的数据处理,然后 return 一个结果(以渲染模板、JSON 数据或其他任何形式)。
这意味着您应该使用的 URLs 永远不会与实际存在的文件的路径名相同。但这就是您所做的: app/Http/Processors/get.php
是直接访问的。这是一个巨大的安全漏洞,因为所有框架都假定唯一可公开访问的文件夹是 public
文件夹。你公开了一个更高的目录级别,每个人都可以访问任何文件(如果他知道它的名字,或者如果你的网络服务器创建了一个目录列表)。这可能会暴露带有敏感密码的配置文件。
而且它还会破坏您在 Ajax 请求中的脚本,因为现在您必须再次进行所有初始化工作。
只创建一个controller还不行,还得把配置搞定。
我通过为自定义 classes 的命名空间添加一个 PS4 条目以及在 composer.json 文件中找到它们的目录来实现它的工作,例如所以:
"autoload": {
"psr-4": {
"App\": "app/",
"MyCompany\MyCodeLibrary\": "MyCodeLibrary/"
},
"classmap": [
"database/"
]
},
然后在项目根目录(包含 app
目录的相同目录)中创建我的 MyCodeLibrary
目录。
那我只需要运行:
$ composer dump-autoload -o
现在,在 MyCodeLibrary
目录中,我可以添加我想要的任何 classes。比方说,我添加了一个 class 调用 Calculator.php
。我在 MyCodeLibrary
内创建它。
文件 MyCodeLibrary/Calculator.php
内部看起来像这样(请注意,我可以使用 Lumen app()
和 config()
辅助方法来加载我的自定义配置文件(或执行其他操作,例如进行数据库查询。):
<?php
namespace MyCompany\MyCodeLibrary;
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
...
}
如果我需要在 Lumen 控制器中使用我的 class,我可以这样使用它:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use MyCompany\MyCodeLibrary\Calculator;
class TestController extends Controller
{
public $calculator;
public function __construct() {
$this->calculator = new Calculator();
}
public function doSomething() {
$this->calculator->something();
}
...
}
我知道手动创建自己的实例并不是最有趣的事情,但它确实有效。我真的不知道是否有一种聪明的 Laravel-like 方法可以在 Lumen 中使用服务提供商 and/or facades 自动创建自定义 classes 的新实例,因为我还没有尝试过寻找它。主要是因为我想保持轻松。否则我会使用 Laravel.