PHP Composer: Setting dynamic variable paths in the autoload function - php

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"
]
}
}
}

Related

How to handle autoloading with composer by keeping the WordPress naming conventions?

I'm a bit confused because I'm programming a plugin for WordPress by using composer as it's the real way to go.
So I've created a composer file inside my plugin and some other stuff. In the composer file I've added my namespace for autoloading:
"autoload": {
"psr-4": {
"Johnny\\Lolkick\\": [
"includes/classes/"
]
}
}
Inside my classes folder I've created now a class with the name class-main.php. I've decided to take this name because of the WordPress naming conventions:
https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#naming-conventions
The class by itself was named class Main {. Inside my base plugin file I've created now a new instance of my class which failed. After changing the file name to Main.php it worked.
So in result the WordPress naming convention broke the autoloading of composer. I want to know now how do you handle this problem? How should I keep the naming convention by using composer?
Since your code base is not compatible with PSR-4 autoloading, a psr-4 mapping inside your composer.json's autoload section won't work, as you noticed.
I'd say you have two choices here:
First one would be to use classmap instead:
{
"autoload": {
"classmap": ["includes/classes/"]
}
}
This would simply parse all the files recursively within that folder and map the classes to their names, no matter what naming scheme you're following.
Second one would be to build your own autoloader, and use files to have it loaded automatically:
{
"autoload": {
"files": ["includes/autoloader.php"]
}
}
That autoloader would have to define what should happen (which class should be loaded, or not) when referring to a given class name.
In both cases, don't forget to run composer dump-autoload afterward.

Composer: How to recursively autoload subfolders in /src

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...

Laravel custom directory structure

I am attempting to create a sort of custom directory structure, my proposed structure is as follows
App/ - Contains all Laravel core code
Repo/ - Contains packages, each package contains Controllers, Views, Modals, Seeds and Migrations specific to that package
Is it possible via Composer or would it take a lot of core modification?
Controller routing in routes.php
Route::resource('account', '\Repo\Accounts\Accounts');
The first occurrence of accounts is the folder and the second being the class. I know I could write each directory seperetly then dump composer autoload, however when you have 30 seperate packages per app, it is a little time consuming. Am I missing something super straight forward?
This is possible with composer. Add inside of your composer.json:
"autoload": {
"classmap": [
// ...
],
"psr-4": {
"Repo\\" : "Repo"
}
},
Then you can use classes inside of the /Repo directory, and classes in there will reside in the \Repo namespace.

Autoloading multiple PHP projects via composer

Assume I have folder layout as
projectA
projectA\src
projectA\vendor\autoload.php
projectB
projectB\src
projectB\vendor\autoload.php
projectC
projectC\src
projectC\vendor\autoload.php
These projects need to be in the same level and they need to coexist with each others, e.g. projectA might use codes from projectB and projectC and vice vera, so they cannot be placed into the vendor folder.
The thing is: the autoload.php in each project is able to autoload their own src and vendor folder, but how to autoload for the others as well?
Assume their neighbor's project will have the folder name as the PHP namespace, is it possible to setup a autoload.php (via composer) such that in the future when I add new project folder, the autoload will magically work?
You can write in each project a composer.json with custom autoload configuration..
examples:
ProjectA:
"autoload": {
"psr-0": {
"ProjectB\\": "path/ProjectB/src/",
"ProjectC\\": "path/ProjectC/src/"
}
},
ProjectB:
"autoload": {
"psr-0": {
"ProjectA\\": "path/ProjectA/src/",
"ProjectC\\": "path/ProjectC/src/"
}
},
Composer is conceived for manage dependencies of single project.. Load more autoload.php of different projects is not a good idea..
but with this method you can create a complete autoloader for each projects

Organizing Laravel and autoloading sub directories

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

Categories