简体   繁体   English

找不到Laravel / Lumen自定义类

[英]Laravel / Lumen custom class not found

I am experiencing an issue when trying to use a custom, namespaced class in Lumen, the micro-framework by Laravel. 当尝试在Lumen(Laravel的微框架)中使用自定义的,命名空间的类时遇到问题。 I am getting a Class not found error when trying to instantiate the class. 尝试实例化该类时,出现“ Class not found错误。

The relative directory: 相对目录:

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

The GetImages.php file, reduced for brevity: 为简洁起见,减少了GetImages.php文件:

namespace App\Classes;

class GetImages
{
    public $name = 'Class instantiated';
}

The get.php file, where error is occurring: get.php文件,发生错误:

use App\Classes\GetImages;

$n = new GetImages;
return $n->name;

If I make an ajax request within the home page like $.get('http://www.example.com/app/Http/Processors/get.php') I get the following error: 如果我在$.get('http://www.example.com/app/Http/Processors/get.php')之类的主页中发出ajax请求,则会出现以下错误:

Fatal error: Class 'App\Classes\GetImages' not found in http://www.example.com/app/Http/Processors/get.php on line 5.

However, as stated above, if I instantiate this class inside the routes.php file, it works properly. 但是,如上所述,如果我在routes.php文件中实例化此类,则它可以正常工作。

The autoload portion of composer.json : composer.json自动加载部分:

"autoload": {
    "psr-4": {
        "App\\": "app/"
    },
    "classmap": [
        "database/"
    ],
    "files": [
        "app/Http/helpers.php"
    ]
}

I feel this is an autoloading issue, but I have done composer dumpautoload -o , composer update , and followed PSR-4 standards, without any change. 我感觉这是一个自动加载的问题,但是我已经完成了composer dumpautoload -ocomposer update ,并遵循了PSR-4标准,没有任何更改。 Any ideas what I'm missing? 有什么想法我想念的吗?

If you run http://www.example.com/app/Http/Processors/get.php and your whole get.php file content looks like this: 如果您运行http://www.example.com/app/Http/Processors/get.php ,则整个get.php文件的内容如下所示:

use App\Classes\GetImages;

$n = new GetImages;
return $n->name;

it won't work because the file with class hasn't been loaded. 它不会工作,因为尚未加载具有class的文件。 In fact this file has nothing in common with Laravel/Lumen, it's just simple PHP file. 实际上,该文件与Laravel / Lumen没有任何共同点,只是简单的PHP文件。 When you use framework it uses Composer autoloader to load valid files, and when you use simple file you need to include autoloader or include necessary files manually. 使用框架时,它将使用Composer自动加载器加载有效文件,而当您使用简单文件时,则需要包含自动加载器或手动包含必要的文件。

You have 3 options: 您有3种选择:

  • create route for this action and do what you want in controller 为此操作创建路线并在控制器中执行所需操作
  • at the beginning of file add require '/vendor/autoload.php'; 在文件的开头添加require '/vendor/autoload.php'; (with valid path to autoload file (具有自动加载文件的有效路径
  • manually require GetImages class require 'app/Classes/GetImages.php'; 手动要求GetImagesrequire 'app/Classes/GetImages.php';

The best option will be probably the 1st one when you use framework and you don't use standalone PHP file to do the job. 当您使用框架并且不使用独立的PHP文件来完成这项工作时,最好的选择可能是第一个。

You make an AJAX request to this URL: $.get('http://www.example.com/app/Http/Processors/get.php') 您对此URL进行AJAX请求: $.get('http://www.example.com/app/Http/Processors/get.php')

If this really gets you an answer from PHP, then you are bypassing your whole framework and made a big mistake when setting it up. 如果确实从PHP得到了答案,那么您将绕过整个框架并在设置它时犯了一个大错误。

Every static asset should belong into the public folder in an appropriate sub directory of your choice (images may go into public/img etc.). 每个静态资产应该属于进入public文件夹在你选择一个合适的子目录(图像可能会进入public/img等)。

There should also be a file public/index.php , which is supposed to get every request that is not an existing file somewhere in public . 还应该有一个文件public/index.php ,它应该获取public某个地方不存在的每个请求。 This requires correct configuration of the web server, ie an Apache web server usually will get a .htaccess file (if you cannot add the contents to the vhost) that does the URL rewriting. 这需要正确配置Web服务器,即Apache Web服务器通常会获得一个.htaccess文件(如果无法将内容添加到虚拟主机),该文件将进行URL重写。

The index.php will bootstrap the autoloading of Composer, then initialize the framework and pass the current request to it for processing. index.php将引导Composer的自动加载,然后初始化框架并将当前请求传递给它进行处理。 The routing will find the associated controller, which will do some fancy data processing, and return a result (in the form of a rendered template, JSON data or anything else). 路由将找到关联的控制器,该控制器将进行一些精美的数据处理,并返回结果(呈示模板,JSON数据或其他任何形式)。

This means that the URLs you should be using will never be identical to the path names of actual existing files. 这意味着您应该使用的URL永远不会与实际现有文件的路径名相同。 But this is what you did: app/Http/Processors/get.php is directly accessed. 但这就是您所做的:直接访问app/Http/Processors/get.php This is a huge security hole, because all frameworks assume that the only folder that is publicly accessible is the public folder. 这是一个巨大的安全漏洞,因为所有的框架假设可公开访问的唯一文件夹是public文件夹。 You are exposing one directory level higher, and everyone can access any file (if he knows it's name, or if your web server creates a directory listing). 您将暴露一个更高级别的目录,每个人都可以访问任何文件(如果他知道文件名,或者您的Web服务器创建了目录列表)。 This might expose configuration files with sensitive passwords. 这可能会公开带有敏感密码的配置文件。

And also it breaks your script in the Ajax request, because now you have to do all the initialization work again. 而且它还会破坏Ajax请求中的脚本,因为现在您必须再次执行所有初始化工作。

Creating a controller is not enough, you also have to fix the configuration in general. 创建一个控制器是不够的,通常还必须修复配置。

I've got it working by adding a PS4 entry for the namespace of my custom classes and the directory where they are to be found within the composer.json file like so: 通过为自定义类的命名空间以及在composer.json文件中可以找到它们的目录添加一个PS4条目来使其工作,如下所示:

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "MyCompany\\MyCodeLibrary\\": "MyCodeLibrary/"
    },
    "classmap": [
        "database/"
    ]
},

Then within the project root (same directory containing the app directory) I create my MyCodeLibrary directory. 然后,在项目根目录(包含app目录的同一目录)中,创建MyCodeLibrary目录。

Then I just need to run: 然后我只需要运行:

$ composer dump-autoload -o

And now, within the MyCodeLibrary directory I add whatever classes I want. 现在,在MyCodeLibrary目录中,添加所需的任何类。 Let's say for example I add a class call Calculator.php . 举例来说,假设我添加了一个类Calculator.php I create it within MyCodeLibrary . 我在MyCodeLibrary创建它。

The file MyCodeLibrary/Calculator.php would look like this inside (note that I can use the Lumen app() and config() helper methods to load my custom config files (or do other things like making database queries.): 文件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
  ...
}

And if I need to use my class in Lumen Controllers, I can use it like this: 如果我需要在流明控制器中使用我的类,则可以这样使用它:

<?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();
  }

  ...

}

I know it's not the funnest thing to manually create your own instances but it works. 我知道手动创建自己的实例并不是最有趣的事情,但是它可以工作。 I really don't know if there's a clever Laravel-like way to create new instances of your custom classes automagically with service providers and/or facades in Lumen because I haven't tried to look for it. 我真的不知道是否存在一种巧妙的Laravel方式,可以通过Lumen中的服务提供商和/或Facades自动地创建自定义类的新实例,因为我没有尝试寻找它。 Primarily, because I'm trying to keep it light. 主要是因为我试图保持轻巧。 Otherwise I'd be using Laravel. 否则我会使用Laravel。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM