I'm writing some tests for a composer package, but i cannot load classes in subfolders of /src.
My folder structure
root
- src
- file1.php
- folder1
- folder2
- file2.php
- tests
The tests' folder structure reflects the one of src.
In my composer.json i've:
{
"autoload": {
"psr-4": {
"Namespace1\\\Package_Namespace\\\": "src"
}
}
}
Now, when i launch the tests, only the ones in src can well include their own classes, while the ones that use the classes in subfolders can't (for example, file2.php is never loaded).
I've tried also to explicitly specify the subfolders in composer.json file, but it seems not working.
I hope someone can help me. If you need more info, please let me know and i'll provide them.
Thank you and i wish you a merry Christmas!
I think you may need to escape the namespace in the config:
"autoload": { "psr-4": { "Namespace1\\Package_Namespace\\": "src" } }
and make sure your classes / filenames follow PSR-4. Also, be sure PHPUnit / whatever test suite you're running loads the composer autoload file.
ETA:
You can also manually add your tests to the namespace in the bootstrap.php file (if you're using one for your tests):
$loader = require __DIR__ . "/../vendor/autoload.php";
$loader->addPsr4('Namespace1\\Package_Namespace\\', __DIR__.'/testdir');
Obviously you'll need to adjust the above accordingly to your paths.
I think there is something wrong with the way Composer loads psr-4 maps.
Infact i've changed namespace reflecting the folder structure and now all work well.
I think namespace can be different from folder structure, but this doesn't work.
I cannot better explain my solution, but only that reflecting the folder structure works. Is it a casuality? Mah!
Anyway, it now works...
Related
This is a general question I have out of curiosity and might lead to something useful in projects of mine.
Every time I add a new file (for example a new controller or model) I have to run composer dump-autoload -o for it to include the file, not sure if i'm just doing something wrong or if that is how it works.
Is it possible for me to get composer to see the file automatically after I created the file with its contents?
My first thought was to just create a script to run the command in either a special "refresh" file but that seems to be a waste.
I am using PSR-4 to load my files.
composer.json autoload:
"autoload":{
"psr-4":{
"Website\\":"app"
}
},
You need to configure your composer.json file so that the autoloader knows where to look for specific namespaces:
"autoload": {
"psr-4": {
"App\\": "src/"
},
"files": [
"src/simpleFunctions.php"
]
}
After running composer update, the autoloader will know where to look when a script encounters a namespace that falls under these definitions automatically, without any further command to write.
You have to respect the file hierarchy and psr-4 while naming and creating your classes. In the example above, adding a App\Controller\MyController class is straightforward, you add it in the Controller folder and it will be autoloaded on your next run.
/src
/Controller
MyController.php
/Model
/Mappers
MyMapper.php
simpleFunctions.php
namespace App\Controller;
class MyController {}
Casing is important!
When seeing a namespace like Website\Controllers, the autoloader will look for there files, under the root for the namespace specified, with the same casing. That means, that if you are under a case sensitive system (like Linux distributions) you actually need to respect the case. In your case the class Website\Controllers\Front must be in app/Website/Controllers/Front.php.
Basically, Composer doesn't aware of files that you are creating, you have to run the dump-autoload command which won't download anything new. It just regenerates the list of all classes that need to be included in the project (autoload_classmap.php). Ideal for when you have a new class inside your project.
Ideally, we execute composer dump-autoload -o , for a faster load of your webpages. The only reason it is not default, is because it takes a bit longer to generate (but is only slightly noticeable)
I have recently started using composer to autoload my classes. But I find I have to upload each directory individually as I store an src/ directory and a tests/ directory foreach class. For example:
"Core\\Router\\": "system/Core/Router/src/",
"Core\\Router\\Tests\\": "system/Core/Router/tests/",
"Core\\DatabaseManager\\": "system/Core/DatabaseManager/src/",
"Core\\DatabaseManager\\Tests\\": "system/Core/DatabaseManager/tests/"
Is there a way to make it so that composer reads a variable path? e.g.
"Core\\{VARIABLE_PATH}\\": "system/Core/{VARIABLE_PATH}/src/",
"Core\\{VARIABLE_PATH}\\Tests\\": "system/Core/{VARIABLE_PATH}/tests/"
No, "dynamic paths" are not supported.
A "component" folder layout, where "src" and "tests" are inside a subfolder is definitely nice, but at the moment there is no "automatical" autoloading support for this structure.
When you use one namespace "application\namespace" for your system/core/ folder, all classes are scanned (including src and tests) and become part of the autoloading map. In other words autoloading will work, but when thinking of production usage, then your map will be quite big, because it includes the test classes also. And that might result in a speed decrease. If you do not care about this, then everything is fine: autoloading will work fine, when using a single App\Namespace\Core mapped to the top folder \system\Core.
If you care, then you could try to divide src and tests manually by using autoload and autoload-dev sections and listing the individual component folders under the top namespace. That's tedious, but will result in a smaller classmap for production (no-dev).
You can define multiple dirs to search in, like so:
composer.json
{
"autoload": {
"psr-4": {
"App\\Namespace\\":
[
"ComponentOne/src",
"ComponentTwo/src"
]
}
},
"autoload-dev": {
"psr-4": {
"App\\Namespace\\Tests":
[
"ComponentOne/tests",
"ComponentTwo/tests"
]
}
}
}
Vagrant and mounted folders do not play nice with composer using relative paths to folders added in via the
"autoload" option.
It in-correctly detects what the baseDir is and therefore will fail to register the namespaces.
Has anyone come across this before?
For isntance
"autoload": {
"psr-4": { "Inventory\\" : "./core/src/inventory/" }
}
The autoloading is supposed to be given relative to the path where the composer.json file is located. I've never seen that path starting with a dot, so first of all I'd try to get rid of that and see how that works.
Second thing that might simply be is that you got the autoloading wrong in some detail and mistake it for being something related to Vagrant. The way you currently set it up, a class named \Inventory\Foo must be located in the path core/src/inventory/Foo.php. Can you verify that this is the case? Otherwise please give an example of an existing class name and it's file name.
I am wanting to structure my laravel app in a way that all of my code is under the src directory. My project structure would look something like the below. How would I do this where I can still call Route::get('accounting/item/{id}','AccountingItemController#getId')
I am wanting to avoid adding every module under src to the ClassLoader. Is there a way to tell the class loader to load all sub-directories under the parent directory src?
app
app/src
app/src/accounting
app/src/accounting/controllers
app/src/accounting/models
app/src/accounting/repos
app/src/accounting/interfaces
app/src/job
app/src/job/controllers
app/src/job/models
app/src/job/repos
app/src/job/interfaces
Yes, it's called PSR-0.
You should namespace all of your code. Typically you'll have a vendor name that you'll use a the top level namespace. Your application structure should then look something like this.
app/src/Vendor/Accounting/Controllers
app/src/Vendor/Job/Controllers
Your controllers will then be namespaced accordingly.
namespace Vendor\Accounting\Controllers;
And when using them in routes.
Route::get('accounting/item/{id}','Vendor\Accounting\Controllers\ItemController#getId');
Lastly, you can register your namespace with Composer in your composer.json.
"autoload": {
"psr-0": {
"Vendor": "app/src"
}
}
Of course, if you don't want that top level Vendor namespace you can remove it, but you'll need to register each component as PSR-0.
"autoload": {
"psr-0": {
"Accounting": "app/src",
"Job": "app/src",
}
}
Once done, run composer dump-autoload once and you should be able to add new controllers, models, libraries, etc. Just make sure the directory structure aligns with the namespacing of each file.
Do you have composer installed? You should use this:
composer dump-autoload
But you can could add directories to the Laravel's classloader. Check the reference here: http://laravel.com/api/class-Illuminate.Support.ClassLoader.html
This is a more cosmetical question...
I'm using composer.phar in an existing project to autoload my classes.
This is an example snippet of composer.json for my project named Acme:
{
"autoload": {
"psr-0": {
"Acme\\Mail": "modules/mail/src/",
}
}
}
and a par of my file structure is like:
app.php
composer.phar
vendor/
modules/
mail/
src/
Acme/
Mail.php (contains Acme\Mail\Mail.php)
I have to stick to the folder "modules/mail" in my case and can't rename them.
Basically this works, but I have to create an additional folder Acme below src which is a little bit ugly.
How must the autoloading be defined, if I want to leave out the highest namespace part Acme in my mail folder so it looks like this:
app.php
composer.phar
vendor/
modules/
mail/
src/
Mail.php (contains Acme\Mail\Mail.php)
and I still can use it like that in a php file:
use Acme\Mail;
$mail = new Mail();
Or isn't that possible?
PSR4 is going to allow that to be possible. See: https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md and http://www.sitepoint.com/battle-autoloaders-psr-0-vs-psr-4/
You can use the classmap generation if you do not want to follow PSR-0 standard (which, you really should re-consider doing). See the reference at http://getcomposer.org/doc/04-schema.md#autoload