Reputation: 5608
I am experiencing an issue when trying to use a custom, namespaced class in Lumen, the micro-framework by Laravel. I am getting a Class not found
error when trying to instantiate the class.
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:
namespace App\Classes;
class GetImages
{
public $name = 'Class instantiated';
}
The get.php file, where error is occurring:
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:
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.
The autoload portion of 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. Any ideas what I'm missing?
Upvotes: 0
Views: 8819
Reputation: 4110
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:
"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.
Then I just need to run:
$ composer dump-autoload -o
And now, within the MyCodeLibrary
directory I add whatever classes I want. Let's say for example I add a class call Calculator.php
. I create it within 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.):
<?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. Primarily, because I'm trying to keep it light. Otherwise I'd be using Laravel.
Upvotes: 0
Reputation: 111899
If you run http://www.example.com/app/Http/Processors/get.php
and your whole get.php
file content looks like this:
use App\Classes\GetImages;
$n = new GetImages;
return $n->name;
it won't work because the file with class hasn't been loaded. In fact this file has nothing in common with Laravel/Lumen, it's just simple PHP file. 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.
You have 3 options:
require '/vendor/autoload.php';
(with valid path to autoload fileGetImages
class require '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.
Upvotes: 1
Reputation: 70933
You make an AJAX request to this URL: $.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.
Every static asset should belong into the public
folder in an appropriate sub directory of your choice (images may go into public/img
etc.).
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
. This requires correct configuration of the web server, i.e. an Apache web server usually will get a .htaccess file (if you cannot add the contents to the vhost) that does the URL rewriting.
The index.php
will bootstrap the autoloading of Composer, then initialize the framework and pass the current request to it for processing. 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).
This means that the URLs you should be using will never be identical to the path names of actual existing files. But this is what you did: app/Http/Processors/get.php
is directly accessed. This is a huge security hole, because all frameworks assume that the only folder that is publicly accessible is the public
folder. 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). 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.
Creating a controller is not enough, you also have to fix the configuration in general.
Upvotes: 1