PSR4 Composer Autoloading namespaces - php

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/

Related

PHP: Autoloading via PSR-4 is saying class not found

I am trying to use a class in my src folder, DependencyContainer, but it is saying class not found?
Index:
<?php
$dc = new \Mango\DependencyContainer();
File structure:
src/
DependencyContainer.php
index.php
composer.json
composer.json:
{
"name": "mqwerty/ioc-container",
"type": "library",
"require": {},
"autoload": {
"psr-4": {
"Mango\\": "src/"
}
}
}
DependencyContainer class:
<?php
declare(strict_types = 1);
namespace Mango;
class DependencyContainer
{
}
First you need to add the autoload file in your index like this
require __DIR__ . '/vendor/autoload.php';
And your index.php is going to sth like this
<?php
require __DIR__ . '/vendor/autoload.php';
$dc = new \Mango\DependencyContainer();
It will solve your problem
Autoloading doesn't just happen automagically; composer is set up to manage the creation and updating of your PSR autoloading based off the PSR settings of your composer.json.
Do a composer install in your CLI; that will generate the autoload files in the vendor folder based off of your composer.json and create a composer.lock file, even if you don't have any dependencies.
From there, you will need to bootstrap the autoload file before executing your code.
Hey this has already been solved many times but ill still explain just incase you didnt understand others questions.
So I had this problem once too and you can find it on my profile.
psr works based on your path. when you set your src path thats where it starts from,
for example, your layout is something like the following:
vendor
your-vendor-name
your-package
src
App.php
Class.php
composer.json
then your psr location should have this after the : "/src"
and before it should be something like the following:
"your-vendor-name\your-package\"
when using a class, make sure you composer class names start with an uppercase letter and the class inside matches the file name, make sure the class namespaces are something like this \your-vendor-name\your-package
and to use
$app = new \your-vendor-name\your-package\(then the class name you want to use, so lets say, Class.php, then you would put Class() here)
hopefully this should solve your problem

PHP namespace & use Fatal error class not found even when i already specified class with use

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.

Custom composer namespace doesn't find class

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.

Composer ClassLoader Namespaces Trouble

I'm trying to use the Composer ClassLoader.
I'm trying to load up some CodeIgniter Libraries with PSR namespaces.
In my index.php I have:
$loader = include_once ROOTPATH . 'vendor/autoload.php';
$loader->add('CLI', ROOTPATH . 'application/libraries/CLI/');
$loader->register();
A simplified example of my folder structure is:
libaries/
CLI/
Tree/
Parser.php - namespace CLI\Tree;
Settings.php - namespace CLI;
Am I correct in assuming that Parser.php and Settings.php would be autoloaded? As I understood the documentation example it looks into sub-folders.
I want to avoid having to do the following:
$loader->addClassMap([
'CLI\\Settings' => ROOTPATH . 'application/libraries/CLI/Settings.php',
'CLI\\Tree\\Parser' => ROOTPATH . 'application/libraries/CLI/Tree/Parser.php',
]);
$loader->register();
Why don't you simply add the autoloading of your own code to the composer.json file you already have? That way Composer will create the autoloading file also for your own classes, you would be able to include your current project in another project without having to worry about autoloading (may be unlikely, but:), and you learn how to declare autoloading if you want to create your own modules.
From your code I guess this would work:
"autoload": {
"psr-0": {
"CLI": "application/libraries"
}
}
Explanation: CLI is the prefix of the classes that could possibly found in the path. Make this as long as possible if you are using a lot of CLI classes, and only some are found in that path. Otherwise Composer will search a class in more than one directory, which is sort of bad for performance.
application/libraries is the prefix path where the PSR-0 style classes are located. PSR-0 dictates that a class named X_Y_Z or X\Y\Z is located in the path X/Y/Z.php, so the class prefix you were giving is NOT included in the prefix path you tell Composer to search for.
The prefix path is relative to the location of composer.json.
You could also use PSR-4. That would allow to remove empty directory structures, but will work only with namespaces:
"autoload": {
"psr-4": {
"CLI\\": "application/libraries/CLI"
}
}
Two important differences: The class prefix must end with a backslash (and because this is JSON, the backslash has to be escaped, so double backslash).
Second: The class prefix will get removed from the path that is getting created from the classname. So a class W\X\Y\Z with the class prefix W\X\ will only create Y\Z.php as the path to the class and add the path prefix to it.
I added "CLI" to your path to show that PSR-4 would work, but that directory is not really needed in terms of PSR-4 - if it is empty, you could move files one level up.

Class not found with composer autoload

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.

Categories