Class file not found by composer and psr-4 - php

I am having very hard times understanding how to use autoloading by psr-4.After loading vagrant and setting and testing all variables in Homestead.yaml I have prepared a file structure as the following:
\app
\folder
-- test.php
\vendor
\composer
-- autoload.php
-- index.php
-- composer.json
and the following are my codes:
index.php
<?PHP
namespace app;
require('vendor/autoload.php');
$object = new folder\test();
composer.json
"autoload":{
"psr-4":{
"app\\": "app"
}
}
test.php
<?php
namespace app\folder;
class test
{
function __construct ()
{
echo 'construction done right.';
}
}
But, after trying to visit the page, these are the error message displayed on the page:
(!) Fatal error: Uncaught Error: Class 'app\folder\test' not found in /home/vagrant/web/sites/app/index.php on line 6
( ! ) Error: Class 'app\folder\test' not found in /home/vagrant/web/sites/app/index.php on line 6
Would you help me understand and fix this error?

It doesn't work because you have told Composer that the classes from the app namespace are in the app subdirectory but there is no app subdirectory.
The entire application is stored in the app directory and it's name doesn't really matter for the application. The classes of the app namespace are stored in the current directory and the sub-namespaces are stored in subdirectories with the same name.
Accordingly, your composer.json file should read:
"autoload": {
"psr-4": {
"app\\": ""
}
}
Or, to be more clear, you can put . (the current directory) as the location of the app\ namespace:
"autoload": {
"psr-4": {
"app\\": "."
}
}
After you make the change run composer dump-autoloader in the main application directory and it will start working.

To fix it for your current setup, use the following:
"autoload":{
"psr-4":{
"app\\": ""
}
}
Your composer.json is in the app-directory, so there's no subdirectory named app to reference.
I would actually recommend to change your directory structure to the following:
\app
\src
\folder
-- test.php
-- index.php
\vendor
\composer
-- autoload.php
-- index.php
-- composer.json
And then in composer.json, set the following:
"autoload":{
"psr-4":{
"app\\": "src"
}
}
This makes sure that all files belonging to your 'app' namespace are contained within a single subdirectory.
Finally, I would recommend you to use a vendor namespace to prevent conflicts, and to use the naming guidelines from PSR-2.

I think you won't need PSR-4 just add classmap
classmap parameter for example :
"autoload": {
"classmap": [
"app"
]
}
After adding this run composer dump-autoload and you should see a number of classes being added.
Hope this helps.

in composer.json try to set
"autoload":{
"psr-4":{
"": "src/"
}
}
then do execute this command
composer dump-autoload -o

Related

PHP class_exists() cannot find a class that truly exists

I am trying to write a CakePHP Authentication plugin and am following and structuring it after this repository: https://github.com/ADmad/cakephp-jwt-auth
I am still at the early stages, trying to get my plugin to load during cakePHPs constructAuthenticate() method. I have narrowed down my issue to this method never finding my class when it calls class_exists()
I have Project structure as follows:
App/
plugins/
src/
Controller/
AppController.php
Model/
vendor/
Admad/
cakephp-jwt-auth/
src/
Auth/
JwtAuthenticate.php
composer.json
nates/
cakephp-total-auth/
src/
Auth/
TotalAuthenticate.php
composer.json
TotalAuthenticate is the class I'm trying to load, and it's namespace as defined in TotalAuthenticate.php is:
namespace nates\TotalAuth\auth;
After some debugging I have found that the Path being passed to classs_exists() is:
nates\TotalAuth\Auth\TotalAuthenticate
I have compared all of this info to the Admad/JwtAuth plugin and the relative paths all match up, and that plugin loads just fine so I'm really at a loss at whats going on here and why my plugin won't load.
My Autoload in App/composer.json Looks as such:
`"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests/",
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
}
},`
And my Plugins composer.json :
`"autoload": {
"psr-4": {
"nates\\TotalAuth\\": "src"
}
},
"autoload-dev": {
"psr-4": {
// "ADmad\\JwtAuth\\Test\\": "tests"
}`
PSR-4 autoloading standard requires that the namespace matches the file structure case-sensitive. You define your namespace in composer.json with capitals nates\TotalAuth, but in your class as nates\totalauth\....
Make sure all casings match and the casings match the file structure.

Class not found after auto loading in Laravel

I am struggling with PHP Namespaces and Auto loading in Laravel 5.4. I actually decided to put the models that I need to use in a definite and named folder as app/Models:
php artisan make:model Models/Customer
I have set Customer model's namespace to namespace Models;
Then, I created a route as follows:
Route::get('customer', function () {
$customer = \App\Models\Cutomer::find(1);
echo $customer;
});
To do auto loading work I opened the composer.json file located in the very root folder of the Laravel project and made the autoload to be as follows:
"autoload": {
"classmap": [
"database",
"app/Models"
],
"psr-4": {
"App\\": "app/",
"App\\Models\\": "App/Models"
}
},
After all of this I checked if my composer is an update version and ran dump-autoload:
composer self-update
composer dump-autoload -o
There is also worth of notice the contents of vendor/composer/autoload_classmap.php:
'App\\Models\\Customer' => $baseDir . '/app/Models/Customer.php',
'App\\Models\\Test\\Test' => $baseDir . '/app/Models/Test.php',
My problem is that whenever I execute the url: http://127.0.0.1:8000/customer I will encounter the following error output:
(1/1) FatalThrowableError
Class 'App\Models\Cutomer' not found
Would you please help me understand where of my work has been incorrect, and how to fix it? Thank you very much in advance.
The namespace in the model should be namespace App\Model; (hence why you call the class as \App\Models\Cutomer)
When you use php artisan make:model Models/Customer it should have set the namespace correctly then.
Also, you don't need to edit your composer.json to do this. Remove the additions you've made to your composer.json file for the autoloading and then run composer dumpautoload from the command line.
Hope this helps!
First, you have an error in your PSR-4 setup.
"App\\Models\\": "App/Models"
This does not map to a valid directory. Secondly, and more importantly, there is no need to autoload a nested namespace of one that is already declared. By autoloading App you will already autoload any nested namespaces as long as they conform to PSR-4 standards i.e namespace as directory name and filename as class name.
Composer setup only needs to be the following:
"psr-4": {
"App\\": "app/"
}

Why won't my Composer package autoload?

I've been testing getting my packages up to Packagist with a simple class I made. Whenever I require it in a different project, it says the class cannot be found. Is something wrong with my composer.json autoload block?
Here's my project repo file structure:
- src
- prodikl
- View.php
- .gitignore
- composer.json
And here's my composer.json:
{
"name":"prodikl/simple-view",
"description":"A simple to use, basic View object.",
"require" : {
"php" : ">=5.3.0"
},
"autoload": {
"psr-4": {"prodikl": "src/"}
}
}
And finally, in my View.php:
<?php
namespace prodikl;
class View
{
...
}
But whenever I require it into a project and do require "vendor/autoload.php" and use use prodikl\View; it it keeps saying not found
You just need to point your autoloader down one more directory:
"autoload": {
"psr-4": {"prodikl": "src/prodikl/"}
}
This means "classes that belong to the \prodikl namespace can be found in the src/prodikl/ directory."
You might need trailing backslashes on the namespace name too, not sure how picky Composer is about it:
"psr-4": {"prodikl\\": "src/prodikl/"}

Psr-4 composer autoload own class - no found

I have structure directory
autoload composer:
"autoload": {
"psr-4": {
"model\\": "src/"
}
},
my class
namespace model;
class ClientAgent
{
private $pdo;
public function __construct(\PDO $pdo)
{
$this->pdo = $pdo;
}
public function sentAgent()
{
}
}
in index.php i tried add
use model\ClientAgent; but it throw error, not found class? why?
Edit after answer
"autoload": {
"psr-4": {
"model\\": "src/model/"
}
},
my index.php
use model\ClientAgent;
$loader=require_once __DIR__ . '/../vendor/autoload.php';
$clientAgent =new ClientAgent($pdo);
error
Uncaught Error: Class 'model\ClientAgent' not found in C:\xampp\htdocs\Wieloagenty\index.php:15
My suggestion is to introduce a vendor prefix. That might be your developer name, the name of your company or the name of the application.
composer.json
"autoload": {
"psr-4": {
"YourApplication\\": "src/"
}
},
Now, every class inside the src folder and below needs this vendor prefix on it's namespace.
Let's take src\model\ClientAgent.php as example:
namespace YourApplication\Model;
class ClientAgent
{
Now, the FQCN (full qualified class name) is YourApplication\Model\ClientAgent and you might use it as part of a use statment.
// first require the Composer autoloader
require_once __DIR__ . '/../vendor/autoload.php';
// declare which other classes you are using
use YourApplication\Model\ClientAgent;
$clientAgent = new ClientAgent($pdo);
Important!
After the modifications (to classes and the composer.json file) please regenerate the Composer autoloader with php composer.phar dumpautoload -o.
Composer will scan the complete src folder including subfolders for classes (so you'll have all classes from src\models\ and src\views autoloading ready).
"model\\": "src/" will give you the folder src/ as the base for the model-namespace. So this would give you model\model\Classname.
Change it to:
"psr-4": {
"model\\": "src/model/"
}
When defining psr-4 autoloader in composer, you associate a folder with a specific namespace.
Any sub folders will be a sub-namespace. So if you create a folder in your "model"-folder, the namespace would be: model\new-foldername\Classname and so on.
Note: When ever you update your composer.json file, you always need to run the command: composer dump-autoload to make composer regenerate all it's cached files.

How to autoload classes without namespaces with Composer without reinstalling?

I just need to autoload some classes, and I don't like the psr-0 namespace insanity (no offense).
This used to work just fine in my project:
"psr-0": {
"": [
"app/controller/",
"app/model/"
]
}
For some reason it doesn't work anymore, even though I'm using the same Composer version. I need it for a new project that is also using Silex. Could this be a conflict with Silex?
I know about the "classmap" option, but it's kind of useless because it requires that I run "composer install" every time I add a new class.
Any ideas?
Try to use "primitive" JSON properties; not an array (like in your example).
This works for me with psr-4 like you say, with "": "app/":
{
"autoload": {
"psr-4": {
"Robbie\\": "core/",
"": "app/"
}
},
"require": {
"monolog/monolog": "1.2.*"
}
}
This gives me the Robbie namespace under the directory core, as an example of sources not controlled by composer, the 3rd party (vendor) Monolog namespace and my default or non-namespace for sources underneath the app directory.
After a composer update, all of them are available when including the generated autoload.php:
<?php
require_once 'vendor/autoload.php';
// ...
?>
Use classmap in instead of psr-4:
"autoload": {
"classmap": ["models/"]
}
If you just want to regenerate the autoload file use composer dump-autoload.

Categories