I have problem with autoloading module controller class from my app. I try to configure composer.json but still not working. Probably am doing somthing wrong with this directory structure. I try examples from composer doc but again dont work...
Directory structure:
|- admin
|----- modules
|--------- Menu
|------------Controller
|--------------MenuController.php
Lets see composer.json
{
"autoload": {
"psr-0": { "Admin\\Modules\\": "" }
}
}
I try to set path but nothing again // "Admin\Modules\": "admin/modules"
Menu controller:
namespace Admin\Modules\Menu\Controller;
class MenuController extends AbstractAdminBaseController
FrontController
require 'vendor/autoload.php';
new \Admin\Modules\Menu\Controller\MenuController();
All time Class not found. I try 100 examples from google and nothing. Any example how to slowe this problem? Thanks
Update structure:
├───admin
│ └───modules
│ └───Menu
│ └───controller
│ └───MenuController.php
├───vednor
│ └───autoload.php
│ └───composer
│ └───autoload_classmap.php
│ └───autoload_namespaces.php
│ └───autoload_psr4.php
│ └───autoload_real.php
│ └───ClassLoader.php
├───public
├───assets
├───index.php
├───composer.json
├───composer.lock
Your PSR-0 will never work, because this standard dictates that the path to the file has to be EXACTLY like the classname. Note that your first part of the namespace is "Admin", but the first directory part is only "admin" - cases must match exactly, or it won't work (or will only work with case insensitive filesystems).
You will succeed with using PSR-4, though. Why? Because with PSR-4, the given namespace prefix is removed from the full classname, and the rest is being converted into a path that is searched in the directory given for the namespace prefix.
Example for your case:
"autoload": {
"psr-0": { "Admin\\Modules\\": "" }
}
Will not work because the files are in path admin/modules, but must be in Admin/Modules.
"autoload": {
"psr-4": { "Admin\\Modules\\": "admin/modules/" }
}
Will work because the prefix Admin\Modules\ is removed and the remaining class name is being converted to a path and added to admin/modules.
Ah, one gotcha! It will NOT work, because you chose to name the class ...\Controller\..., but the path once again .../controller/....
Honestly, I'd highly recommend to convert your file names and location to PSR-4 compatibility, even for the prefixed directories that you'd be able to work around with Composer. This will eliminate the surprising lowercase directory structures I see.
I mean: Why is that controller directory even lower case in the first place if every class located there is Controller? I really can't understand this.
Related
I have this kind of project structure.
├───app
│ ├───config
│ ├───controllers
│ ├───libraries
| | Controller.php
│ │ Core.php
│ │ DB.php
│ ├───models
│ └───views
└───vendor
└───composer
autoload.php
I want to load classes from libraries folder.
I have a file named bootstrap.php which is including autoload.php file and use of namespace
bootstrap.php
require_once __DIR__ . '/../vendor/autoload.php';
use Libs\DB;
use Libs\Core;
use Libs\Controller;
in the index.php file, i'm not getting any output from any class. Class names are the same as the file name and have the constructor
example DB.php
namespace Libs;
class DB {
public function __construct() {
die("Hello");
}
}
$db = new DB();
This is how composer.json looks like
{
"autoload": {
"psr-4": {
"Libs\\" : "app/libraries/"
}
}
}
and lastly my index.php file
require_once '../app/bootstrap.php';
I cannot figure out why it is not working, can you please help me, what I've been doing wrong?
This happens because you're not creating any objects of the classes you defined, so the mechanism that includes class definition file is not triggered. I guess you expected the use statements trigger this mechanism to include those files, but this is not how it works. If you try to create an object of those classes, you'll see the constructor being called. So in your index.php add this:
$db = new \Libs\DB;
$core = new \Libs\Core;
$controller = new \Libs\Controller;
to see the objects are being created correctly.
I'm using Composer's PSR-4 to autoload classes, but it won't load my classes.
Every time I try to use one of my classes the app dies without any error, even though it should display error.
Here is my file structure:
/
│ composer.lock
│ composer.json
│ index.php
├───src
│ Array.php
│ File.php
├───vendor
...
composer.json - autoload part
"autoload": {
"psr-4": {
"FileManager\\": "src"
}
}
Start of index.php
<?php
require(__DIR__ . '/vendor/autoload.php');
var_dump(class_exists('Array'), class_exists('Array', false));
var_dump(class_exists('File'), class_exists('File', false));
And it dumps this:
bool(false)
bool(false)
bool(false)
bool(false)
If I add
use FileManager\Array;
it will die instantly. If I add
use FileManager\File;
it won't die, but it won't recognize File class either.
I have ran
$ composer dumpautoload
Can somebody help me with this?
The problem is that you are passing strings to class_exists().
If you use string values to reference class names, you will need to use the fully-qualified class name.
<?php
require_once __DIR__ . '/vendor/autoload.php';
var_dump(
class_exists('FileManager\ArrayUtil'),
class_exists('FileManager\File')
);
Alternatively, you can use the class keyword (requires at least PHP 5.5):
<?php
use FileManager\ArrayUtil;
use FileManager\File;
require_once __DIR__ . '/vendor/autoload.php';
var_dump(
class_exists(ArrayUtil::class),
class_exists(File::class)
);
For reference, see:
http://php.net/manual/en/language.namespaces.dynamic.php
http://php.net/manual/de/migration55.new-features.php#migration55.new-features.class-name
http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.class
I have the following project structure
src/
├─ MyPackage/
├─ MySDK.php
└─ SDKHelper.php
test/
├─ MySDKTest.php
└─ TestUtils.php
composer.json
composer.lock
My composer.json file looks like this:
"autoload": {
"psr-4": {
"MyPackage\\": "src/MyPackage"
}
}
Everything worked great, and MySDKTest.php unit tests were passing, until I tried adding some utility methods to a third file, TestUtils.php. When I try to call TestUtils::utilityMethod() from MySDKTest.php, phpunit complains that the class TestUtils is not found.
I've been reading about adding an autoload-dev key, variations whereof I have tried, but so far, it appears that nothing is working. I should clarify that I am able to use MySDK and SDKHelper methods inside MySDKTest. MySDKTest.php looks like this when it works:
use MyPackage\MySDK;
class MySDKTest extends PHPUnit_Framework_TestCase {
public function testPackage() {
$sdk = new MySDK();
$sdk->exampleMethod();
}
}
It should be pretty simple. Composer's PSR-4 autoloader just defines a mapping from a namespace to a folder.
Are your tests namespaced correctly? It looks like they're not since you have a use at the top of your test class. If MySDK is in the namepace MyPackage (fully qualified MyPackage\MySDK), I would expect MySDKTest to also be in the MyPackage namespace at MyPackage\MySDKTest. It doesn't have to be that way - you could put the tests in a different namespace if you prefer.
Regardless, the reason it's not working is you didn't register the test folder with the autoloader. The way it looks like your stuff is currently set up, your autoloader config should look like this:
{
"autoload": {
"psr-4": { "MyPackage\\": ["src/MyPackage/", "test/"] }
}
}
Also you'd need to change use MyPackage\MySDK; to namespace MyPackage; in your test class.
Note
Your folder structure is a little weird. I would expect test to match src. So it would be like this:
test/
├─ MyPackage/
├─ MySDK.php
└─ SDKHelper.php
Adjust the namespace accordingly:
{
"autoload": {
"psr-4": { "MyPackage\\": ["src/MyPackage", "test/MyPackage"] }
}
}
This question is independent but I did ask a similar question before:-
Composer Gives Error, "Class Not Found"
The problem was solved but I failed to explain the nesting issue. I thought it will be more appropriate to make a new question.
I searched a lot but I can't make the nesting namespaces to work with psr-4 autoloading.
Directory Structure:-
│ composer.json
│ run.php
│
├───src
│ ├───one
│ │ parentclass.php
│ │
│ └───two
│ childclass.php
│
└───vendor
│ autoload.php
│
└───composer
autoload_classmap.php
autoload_namespaces.php
autoload_psr4.php
autoload_real.php
ClassLoader.php
installed.json
LICENSE
parentclass.php:-
<?php
namespace myns\one;
abstract class parentclass
{
abstract public function abc();
}
childclass.php:-
namespace myns\two;
namespace myns\one;
use myns\one\parentclass as parentclass;
class childclass extends parentclass
{
public function abc()
{
echo 'hello world';
}
}
composer.json:-
{
"name": "myvendor/mypackage",
"description": "nothing",
"authors": [
{
"name": "Omar Tariq",
"email": "XXXXX#gmail.com"
}
],
"require": {},
"autoload": {
"psr-4": {
"myns\\": "src/",
"myns\\one\\": "src/one/",
"myns\\two\\": "src/two/"
}
}
}
run.php:-
<?php
require_once __DIR__ . '/vendor/autoload.php';
use myns\two\childclass as childclass;
$childclass = new childclass();
$childclass->abc();
When I run php run.php. It gives error:-
Fatal error: Class 'myns\two\childclass' not found in C:\wamp\...\run.php on line 7
A class can only declare one namespace in the file. By including two namespaces in childclass.php, you are likely overriding the first.
A full example can be seen here of using multiple namespaces, but the file only includes 1 namespace declaration. That said, I suspect for your case you simply made a mistake and only need one namespace.
Because the file is located in myns\two; you should use namespace myns\two; and remove the other.
You should only add
"autoload": {
"psr-4": {
"myns\\": "src/"
}
}
The other two you added may be conflicting the namespace, because you are overriding it and tell to point to the same root /src
I am trying to use namespaces in fatfree framework, but somehow its not able to find the class following is my setup
routes.ini
[routes]
GET /=Src\Controllers\Index->index
index.php
namespace Src\Controllers;
class Index {
function index($f3) {
$f3->set('name','world');
echo View::instance()->render('template.htm');
}
}
Global index.php
// Retrieve instance of the framework
$f3=require('lib/base.php');
// Initialize CMS
$f3->config('config/config.ini');
// Define routes
$f3->config('config/routes.ini');
// Execute application
$f3->run();
UPDATE:
Error:
Not Found
HTTP 404 (GET /)
• index.php:13 Base->run()
UPDATE 2:
config.ini
[globals]
; Where the framework autoloader will look for app files
AUTOLOAD=src/controllers/
; Remove next line (if you ever plan to put this app in production)
DEBUG=3
; Where errors are logged
LOGS=tmp/
; Our custom error handler, so we also get a pretty page for our users
;ONERROR=""
; Where the framework will look for templates and related HTML-support files
UI=views/
; Where uploads will be saved
UPLOADS=assets/
I'm not sure what's going wrong.
Thanks In advance.
The autoloader of the Fat-Free Framework is very basic. It expects you to define one or more autoloading folders, each of them will map to the root namespace.
So let's say you define $f3->set('AUTOLOAD','app/;inc/') and your file structure is:
- app
- inc
- lib
|- base.php
- index.php
Then a class named MyClass belonging to the Foo\Bar namespace (full path: Foo\Bar\MyClass) should be stored in either app/foo/bar/myclass.php or inc/foo/bar/myclass.php (remember: we specified two autoloading folders).
NB: don't forget to specify namespace Foo\Bar at the beginning of myclass.php (the autoloader won't do it for you).
--
So to answer your specific problem, having the following file structure:
- lib
|- base.php
- src
|- controllers
|- index.php
- index.php
three configurations are possible:
Config 1
$f3->set('AUTOLOAD','src/controllers/')
Then all the files under src/controllers/ will be autoloaded, but remember : src/controllers/ maps to the root namespace, so that means the Index class should belong to the root namespace (full path: \Index).
Config 2
$f3->set('AUTOLOAD','src/')
Then all the files under src/ will be autoloaded, which means the Index class should belong to the Controllers namespace (full path: \Controllers\Index).
Config 3
$f3->set('AUTOLOAD','./')
Then all the files under ./ will be autoloaded, which means the Index class should belong to the Src\Controllers namespace (full path: \Src\Controllers\Index).
Fat-Free is always the root namespace "\". (the following might be wrong) Since F3 loads your classes through the autoloader, you always have to add the root namespace to your own namespaces. In this case you have to change it to
namespace \Src\Controllers;
And of course you have to change it in your routes.ini too.
GET /=\Src\Controllers\Index->index
To help you finding those issues in the future you can higher the DEBUG value with
$f3->set('DEBUG', 2); // 0-3; 0=off, 3=way too much information
Try this config - Your class:
namespace Creo\Controllers;
Framework routes
GET|POST / = \Creo\Controllers\IndexController->indexAction
folder location
_your_app_dir/app/Creo/Controllers
Your bootstrap file (in this case in _your_app_dir/app/)
spl_autoload_register(function ($className) {
$filename = __DIR__ . '/' . str_replace('\\', '/', $className) . ".php";
if (file_exists($filename)) {
include($filename);
if (class_exists($className)) {
return true;
}
}
return false;
});
Hope this will help.