I have my file structure as
/
/app/
/app/logs/
/app/templates/
/app/index.php
/public_html/
/public_html/.htaccess
/public_html/index.php
/vendor
/vendor/(all vendor here)
My vhost is pointing to /public_html
in app/Index.php
namespace App;
class Index {}
Composer.json
"autoload":
{
"psr-0":
{
"App\\": "app/"
}
}
Yet it is still showing as ( ! ) Fatal error: Class 'App\Index' not found in C:\wamp\www\project\public_html\index.php on line 34
Line 34:
new \App\Index();
Using Slimframework as well if that matters, can't think what is wrong
Since you were using the PSR-0 standard, PHP was looking for the file app/App/Index.php, which does not exist. Note that in PSR-0, you define a base directory (app in your case) where the mapped namespace (App) can be found. However, the file structure within that base directory should exactly match the fully qualified class names. So class App\FooBar should be in the file app/App/FooBar.php. Note that app is the base directory, and App is the directory that contains all subdirectories and PHP files for that namespace.
Since this is not the case in your application (and also because PSR-0 has been deprecated), you should (as you already did) use PSR-4, the new autoloading standard, instead. In PSR-4, you can directly map a certain namespace to a certain directory. In your case, you have mapped the App namespace to the app directory, so that PHP will open the app/Index.php file if you need to use the App\Index class.
Related
I'm running into trouble with namespace in PHP. For an example I have a file like this
namespace App\Models\Abstracts;
abstract class Country{}
and then another file like this
namespace App\Models;
use App\Models\Abstracts\Country;
class City extends Country{}
I always get the
Fatal error: Uncaught Error: Class ... not found in ...
Can anyone help me?
thanks a lot.
To do that, I advise you to use the PSR (psr-4).
First, let's create a files structure as bellow :
Now let's init the composer to configure the psr-4.
jump to the root of the project (in this example the root directory of src), and run :
you will be asked to fill some project information, just skip it
composer init
A file named composer.json will be created in the root directory, let's configure the psr-4 inside.
{
"name": "root/project",
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Learn more about psr-4
to hover, we are just telling the PSR to point the name App to the directory src and then the name of subfolder should be the surname in your namespace.
Example:
App => src directory
App\Models => src/Models directory
And so on
Next, you should generate the autoload by
composer dump-autoload
The final project file structure seems to be something like :
I create a file called index.php in the root directory to test my code, but first, you should require the autoload which has been generated by the configuration we just did.
<?php
use App\Models\City;
require __DIR__.'/vendor/autoload.php';
$city = new City();
var_dump($city);
Result:
/var/www/myfm/index.php:9:
class App\Models\City#3 (0) {
}
I hope this helps you.
In my default symfony4 structure I want to add lib folder, where I have additional classes. So something like this:
-bin
-config
-lib
- Importer.php
...(other files with classes)
-public
-src
- Controller
- TestController.php
- Entity
- Form
...
...
But I cannot figure out how to later use my files (i.e.: Importer.php).
Let's say Importer.php has a single class Importer() inside. If I try to use it from TestController.php I get:
Attempted to load class "Importer" from namespace "lib". Did you
forget a "use" statement for another namespace?
TestController.php has
use Importer;
specified on top (autodetected by PhpStorm). I also tried adding namespace in my Importer.php file, for example:
namespace lib;
and then in TestController:
use lib\Importer;
But it produces the same result.
Lastly after reading about services, I tried adding the file to config/services.yaml
lib\:
resource: '../lib/Importer.php'
Which gives the same result...
What to do, how to live?
First of all read about php namespaces.
Next read about the psr-4 standart.
Select a prefix for your folder, let's say Lib. Make sure that all files in the lib folder has a properly namespace. E.g. Importer class must be stored in the lib\Importer.php and must have the namespace Lib;, Items\Item class must be stored in the lib\Items\Item.php and must have the namespace Lib\Items\Item; and so on.
Your files are ready. Just need to inform Symfony about them.
Symfony uses composer's autoloader, so check composer's autoload section. Than add new folder for autoloading in composer.json:
"autoload": {
"psr-4": {
"App\\": "src/",
"Lib\\": "lib/"
}
},
It says that all classes in lib folder have their own separate files and Lib prefix in their namespace and other part of namespace is similar to directories structure.
Next you need to clear autoloader's cache. Run in console:
composer dump-autoload
And finally you can use your class:
use Lib\Importer;
$importer = new Importer;
Also you can add your files to autowire.
I've been having a little play around with some Composer autoloading and i'm getting some issues so the directory structure is
index.php
app/
helpers/
router.php
vendor/
composer/
/*usual files*/
autoload.php
Inside my composer.json I have the following
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
Inside my index.php I have
<?php
// Autoload our namespaces
require __DIR__.'/vendor/autoload.php';
use App\Helpers\Router;
$route = new Router;
Getting the following error
Fatal error: Class 'App\Helpers\Router' not found in /var/www/public/index.php on line 6
I have tried a few different things to try and get it working but i'm unsure where i'm going wrong. This is my first time looking into autoloading using Composer outside of a framework so would appreciate any guidance.
PSR-4 is case sensitive. The structure has to be app/Helpers/Router.php or better App with capital A.
All class names MUST be referenced in a case-sensitive fashion.
The subdirectory name MUST match the case of the sub-namespace names.
The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
http://www.php-fig.org/psr/psr-4/
I have this error:
InvalidArgumentException in ControllerResolver.php line 147:
Class "MyProject\API\FrontController" does not exist.
Here is my structure of myproject:
composer.json
api
src
FrontController.php
BundlesFolders
app
web
vendor
clients
My composer.json
"psr-4": {
"MyProject\\API\\": "myproject/api/src",
"MyProject\\Client\\": "myproject/client/src"
}
My routing.php :
// myproject/api/app/config/routing.php
$routes->get('/', 'MyProject\API\FrontController::exec')
FrontController.php :
<?php
// myproject/api/src/FrontController
namespace MyProject\API;
class FrontController {
You've put an extra folder to your psr-4 map. The first myproject directory should not be in your path as this path is relative to the composer.json file and your src code is in api/src and clients/src (the second is just a guess, you didn't post the content of the clients directory).
Let me tell you that IMHO your directory layout is weird. I would have a single src directory and inside put an api and a client subdirectory.
PS: You've listed the client directory in singular but in composer you have it in plural, watch out for this details!
Also run composer dump-autolad after changing your psr-4 parameter.
I'm trying to use my custom namespace for my personal classes.
The directory structure is (as usual):
my_project/
- src/
|- myComponent.class.php
\- myWrapper.class.php
- vendor
|- OtherLibrary
\- Symfony
- composer.json
- index.php
in my composer.json I specify my own namespace with:
"autoload": {
"psr-0": {
"my_namespace\\": "src/"
}
}`
then in my PHP code I have something like:
myComponent.class.php
namespace my_namespace;
class myComponent
{
.... code
}
index.php
namespace my_namespace;
require_once __DIR__.'/vendor/autoload.php';
$component = new myComponent();
Running this I get a:
Fatal error: Class 'my_namespace\myComponent' not found in /path_to_root/my_project/index.php on line 5
while...
I would expect myComponent to be searched under my_project/src/, as specified in the composer.json and as defined into vendor/composer/autoload_namespaces.php ('my_namespace\\' => array($baseDir . '/src')).
I would expect to directly call my custom myComponent, when I define the namespace to my own namespace. Am I wrong?
What's wrong in my code and my assumptions?
How should I fix it?
You found the errors yourself, but here is a quick collection of what the useful autoload directives in Composer do:
PSR-0 converts the class name into a path name (underscores and backslashes from namespaces are converted into a directory separator), adds ".php" at the end, and tries to find this file in the path that you have given in the composer.json file. A class myNamespace\myClass and "psr-0":{"myNamespace\\": "src"} will try to load src/myNamespace/myClass.php.
PSR-4 only works with namespaces. It removed the namespace prefix given in composer.json from the full class name, and the remainder is converted into a path, ".php" added at the end, and searched in the path given. A class myNamespace\myClass and "psr-4":{"myNamespace\\": "src"} will try to load src/myClass.php.
Classmap autoloading will work by scanning all the files for classes, interfaces and traits (everything that can be autoloaded), and compiles an array map of it. It works with any file name schema and any directory layout, but try to avoid it because it will need an update to the map every time you add a new class. Also, it takes time to scan the files while installing, and it takes some CPU and memory to load and hold that map.