I run a portail with composer's autoloading class system:
"autoload": {
"psr-4": {
"Portal\\": "src/"
}
}
It works when I run composer.phar dump -o, for instance my class Boostrap is well referenced into vendor/composer/autoload_classmap.php file:
'Portal\\Core\\Bootstrap' => $baseDir . '/src/core/Bootstrap.php',
But when I don't run the optimized option on autoload dumping, the autoloading system doesn't works anymore:
Fatal error: Class 'Portal\Core\Bootstrap' not found in /var/www/portail/prod/web/index.php on line 7
How can I make autoloading works without -o option?
There are two ways to fix it.
change composer.json to
"Portal\\Core\\": "src/core/"
Or rename the core directory to Core
https://getcomposer.org/doc/04-schema.md#psr-4
The subdirectory name MUST match the case of the sub-namespace names.
http://www.php-fig.org/psr/psr-4/
Related
I'm developing a brand new Wordpress plugin and I would like to use Composer to autoload classes.
Here is the plugin directory heriarchy:
my composer.json content:
{
"autoload": {
"psr-4": {
"G4S_ECommerce\\": "src"
}
}
}
In the directory where composer.json is, on cmd, I execute:
composer install -> this generates the vendor/composer folder and the vendore/autoload.php.
composer composer dumpautoload -o -> outputs "Generated optimized autoload files containing 0 classes"
In the main file G4S_Ecommerce.php I put the following line:
require __DIR__.'/vendor/autoload.php';
In the same file I put
use G4S_Ecommerce\Includes\Ecommerce;
$starter = new Ecommerce();
but it leads me to a Fatal error: Uncaught Error: Class 'G4S_Ecommerce\Includes\Ecommerce' not found
Why the composer dumpautoload -o returns 0 classes? What am I doing wrong?
Thanks
First (it is not obvious from your files structure) you need to set a namespace for your Ecommerce class (i.e., G4S_Ecommerce/Includes)
Second, based on what you've declared in the autoload directive, composer is expecting to find the G4S_Ecommerce folder under the src folder, and in that folder you need to place your php class file with a name identical to the class name (i.e., Ecommerce).
I'm currently working on a Laravel project that needs to access classes from its parent directory.
composer.json > PSR-4:
"psr-4": {
...
"ModuleA\\": "../ModuleA/baseObjects",
"ModuleB\\": "../ModuleB/baseObjects"
}
Example file structure:
/var/www
+- /xxx (project)
+- /ModuleA
+- /baseObjects
- configClass.inc
+- /ModuleB
+- /baseObjects
- configClass.inc
+- /laravel
- composer.json
I run composer dump-autoload but the project still can't find ModuleA\configClass neither ModuleB\configClass.
Furthermore, inside my autoload_psr4.php, the above gets referenced as following:
'MobuleA\\' => array($baseDir . '/../MobuleA/baseObjects')
'MobuleB\\' => array($baseDir . '/../MobuleB/baseObjects')
PSR-4 requires the loaded files to have a namespaced class, and the namespace structure has to match the directory structure, relative to the "base directory" defined in the configuration (http://www.php-fig.org/psr/psr-4/).
So, in file /var/xxx/ModuleA/baseObjects/configClass.inc should be the class
namespace ModuleA\baseObjects;
class configClass {
...
}
Then in var/www/laravel/composer.json you could have
"psr-4": {
"App\\": "app/",
"ModuleA\\": "../ModuleA"
}
Which means: "directory ../ModuleA should be the root for ModuleA namespace, then follow subnamespaces by matching subdirectories from there".
Use classmap autoload will solve this problem.
{
...
"autoload": {
"classmap": ["ModuleA/", "ModuleB/"]
}
}
It could be used with PSR-4
{
...
"autoload": {
"psr-4": {
"Acme\\": "src/Acme/"
},
"classmap": ["ModuleA/", "ModuleB/"]
}
}
Ref: https://getcomposer.org/doc/04-schema.md#classmap
The problem you're experiencing is not related to parent directories. In fact, your Composer.json autoload configuration is correct for your directory structure.
The problem is the .inc file extension, which is incompatible with the PSR-4 specification. More info here: How To Make Composer (PSR-4) To Work With ".class.php" Extension?
If you cannot update your source code to match the PSR-4 spec, you can use Class Mapping:
The classmap references are all combined, during install/update, into a single key => value array which may be found in the generated file vendor/composer/autoload_classmap.php. This map is built by scanning for classes in all .php and .inc files in the given directories/files.
You can use the classmap generation support to define autoloading for all libraries that do not follow PSR-0/4. To configure this you specify all directories or files to search for classes.
So your config might look like:
"autoload": {
"classmap": [
"../ModuleA/baseObjects",
"../ModuleB/baseObjects"
]
}
Remember, if you use class mapping, you'll need to run composer dump-autoload any time you change composer.json, add a class, modify a class' name/filename/path, etc.
Extra: as pointed out by #alepeino, using autoloader optimization will generate a class map from any PSR-0 and PSR-4 autoload definitions, using the same underlying code that classmap autoload uses. This will "allow" you to use PSR-4 autoloader and the .inc extension. This will still require you to run composer dump-autoload --optimize every time you make a file change, though, just like classmap.
Best recommendation: change your source code to follow PSR-4 specifications, and use the .php extension.
Next best if you can't do that: use classmap for autoloading.
try it:
"psr-4": {
...
"ModuleA\\": "ModuleA/baseObjects",
"ModuleB\\": "ModuleB/baseObjects"
}
According to this answer you can add it in the index.php file:
$loader = require 'vendor/autoload.php';
$loader->add('Namespace\\Somewhere\\Else\\', __DIR__);
$loader->add('Namespace\\Somewhere\\Else2\\', '/var/www/html/xxx');
I did my best to find a question/answer that applied, but I don't think I understand enough about the autoloader to recognize a suitable answer.
I have a package with the following composer.json:
{
"name": "Pva_agent",
"type":"library",
"description" : "query the pva agent",
"version":"0.1b",
"authors" : [
{
"name":"Ed Greenberg",
"email":"ed#precisionpros.com"
}
],
"minimum-stability":"dev",
"require": {},
"autoload": {
"psr-0": {
"Pva_agent": "."
}
}
}
My directory structure after composer installation of the package:
.
./vendor
./vendor/autoload.php
./vendor/Pva_agent
./vendor/Pva_agent/Agent.php
./vendor/Pva_agent/composer.json
./vendor/Pva_agent/.gitignore
./vendor/composer
./vendor/composer/autoload_psr4.php
./vendor/composer/autoload_real.php
./vendor/composer/autoload_classmap.php
./vendor/composer/autoload_namespaces.php
./vendor/composer/installed.json
./vendor/composer/autoload_static.php
./vendor/composer/ClassLoader.php
./vendor/composer/LICENSE
./composer.lock
./composer.json
./test_pva_agent.php
My test program:
<?php
require_once('vendor/autoload.php');
use Pva_agent\Agent;
$agent = new Agent();
My result:
edg#arthur pva_project $ php test_pva_agent.php
PHP Fatal error: Class 'Pva_agent\Agent' not found in /home/edg/PhpstormProjects/pva_project/test_pva_agent.php on line 6
PHP Stack trace:
PHP 1. {main}() /home/edg/PhpstormProjects/pva_project/test_pva_agent.php:0
edg#arthur pva_project $
I didn't think I needed the 'use' statement, since the autoloader should find the class, right?
Can somebody tell me where the problem lies?
Thanks,
Ed Greenberg
Your Pva_agent library should not sit in the vendor/ directory. This directory should contain only auto-generated data from Composer. This directory is usually not stored in VCS.
You should consider refactoring your directory structure to something similar to this one:
.
|____composer.json
|____composer.lock
|____src
| |____Pva_agent
|____vendor
Your library functionality should be added to src/Pva_agent directory.
Consider to use PSR-4 instead of PSR-0 for autoload functionality, as there is no need to regenerate the autoloader when you add classes. dump-autoloader has to be run in case of PSR-0 after adding classed.
For the directory structure above and the PSR-4 autoloader your composer.json autoload section should look similar to this one:
"autoload": {
"psr-4": { "Pva_agent\\": "src/Pva_agent" }
}
Your library should be auto loaded after this. Your auto-loaded library will be registered under the Pva_agent namespace.
I have a question with regards to refactoring a legacy PHP application to be compatible with PHP's PSR-4 standards. I have some classes located at app/classes/ folder which are not yet namespaced properly and I want them to be autoloaded directly when I call composer's vendor/autoload.php. I added a name space according to \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName> and I have tried creating a vendor/myapp/classes/src/ directory under the vendor folder of composer, and executed a dump-autoload command but to no avail. The class doesn't get loaded up and composer can't figure out where to find it. Any pointers on how to do this?
Thanks,
Jan
Thing/s to Note:
-> I don't want to upload the source code to any repository that can be publicly searchable like Packagist as the code is for internal use only.
EDIT:
Here is my composer.json:
...
"autoload":{
"psr-4": {
"Myapp\\" : "Myapp"
}
},
...
But now the structure looks like:
->Myapp
-->Classes
--->Module1
---->submodule.php
--->Module2
---->submodule2.php
--->Module3
---->submodule3.php
--->Config
---->config.db.php
->vendor
-->autoload.php
Here are my issues/questions:
When I try to load submodule.php, which in turn would load submodule2.php and submodule3.php, it would tell me that submodule3.php is not found. The namespace of submodule3.php is Myapp\Classes\Module3 but it says its not found.
I want to include forcibly, config.db.php, on every call of autoload.php
I now figured it out. But the source files will not reside in the /vendor folder, which is okay for my case. If you want to make your files be autoloaded automatically no matter which folder, just add it to the psr-4 block in the composer.json, or create it if it's not yet there. In my composer.json, I have this block on the top level object, which adds the folder I want to get autoloaded and includes also the specific file I want to include, like a config file of some sorts:
...
"autoload":{
"files": [
"somefolder/somefile.php"
],
"psr-4": {
"MyApp\\" : "MyApp"
}
},
...
Which simply means that composer should autoload files residing in the MyApp directory which will also have a namespace of MyApp.
So my folder structure looks like this now:
->MyApp
-->Classes
--->MyClass1.php --> namespace MyApp\Classes classname: MyClass1
-->Components
--->MyClass2.php --> namespace MyApp\Classes classname: MyClass2
->somefolder
-->somefile.php
->vendor
-->autoload.php
->index.php
So if I want to include the file MyClass1.php in index.php, I will just add it like:
include_once( __DIR__ . "/vendor/autoload.php");
use \MyApp\Classes\MyClass1;
$foo = new MyClass1();
$foo->bar();
Hope it helps.
You could approach this by creating your own composer package, adding it to your private git repository, and adding the package to your project's composer.json file:
"require": {
"{your-vendor}/{package-name}": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:{your-vendor}/{package-name}.git"
}
],
Once this is done, run composer update.
using composer in a Php project, with Twig and my own framework.
I would like to "override" the Twig_Node_Expression_GetAttr class from Twig with my own class.
Everything it's working fine, but I have to manually add in composer autoload_classmap.php file :
'Twig_Node_Expression_GetAttr' => 'ebuildy/ebuildy/src/eBuildy/Templating/Twig_Node_Expression_GetAttr.php',
How can I declare this in my composer.json description file ?
Thanks,
You can just define the classmap entry in your project's composer.json, or using PSR-0 mapping as well. See the composer docs on autoloading for details. If you define the PSR-0 namespace with a more restrictive namespace than what Twig has, then you're sure yours will take over, .e.g:
{
"autoload": {
"psr-0": {
"Twig_Node_": "path/to/src/"
}
}
}
This however only works if in this src/ dir you have a file called: src/Twig/Node/Expression/GetAttr.php.