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
Related
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.
I have this composer.json file
{
"require": {
"filp/whoops": "1.*"
}
}
However, I have a folder for my own project called vendor/imaqtpie/framework/src. This is not hosted anywhere, so if I do composer update to update autoload files, it gives an error.
The requested package "imaqtpie/framework" could not be found in any version, there may be a typo in package name.
I had to add this myself to autoload file to make it work.
'Framework' => array($vendorDir . '/imaqtpie/framework/src')
Is there any way to solve this?
I want to tell Composer that this local vendor folder has to be autoloaded each time regardless of checking server/version, or looking for a more elegant solution since I'm new to composer.
You have to create your own local git repository with your package code to achieve that.
After that, put something like this into your composer.json file.
"repositories": [
{
"type":"vcs",
"url":"/path/to/your/source"
}
],
"require":{
"filp/whoops":"dev-master"
}
Autoloading shouldn't be an issue if you implement it this way...
There are a few ways you can do this.
1.
I'd say the most correct way, is to host it and use Satis to produce a private 'packagist'. Then composer will behave "normally" and get the latest version, do version checking etc. but you say you don't care for this.
If you want more details I can expand on this, I have set up many satis packages and it works really well. (Note there's also the new commercial Toran Proxy which I haven't trialled yet.)
2.
If your 'imaqtpie' library is a fake vendor library (it sounds like you just have some files you've stored there, like you would an old-fashioned include library?), then you could simply use a classmap to point the autoloader to that folder from your top level application. This only makes sense if you are including that folder in your top-level app.
So your app's composer json could look like:
{
"require": {
"filp/whoops": "1.*"
},
"autoload": {
"classmap":[
"vendor/imaqtpie/framework/src"
]
}
}
So this tells composer there's a bunch of classes in that folder. When you run composer dump-autoload it will scan the folder and generate vendor/composer/autoload_classmap.php with all your files listed.
This isn't how you're supposed to use composer, but you're not asking to use composer for package management you're asking how to use composer's autoloader, which I guess is fine! as long as you understand the risks.
3.
If your package is either PSR0 or 4 (it sounds likely from the "src" folder) then you'd similarly do this in your top-level app:
{
"require": {
"filp/whoops": "1.*"
},
"autoload": {
"psr-4": {
"Imaqtpie\\Framework\\":"vendor/imaqtpie/framework/src"
}
}
}
Which again is a bit odd, but should work!
Normally, you'd specify this path in your package's composer.json and then when you do an update it gets merged into your composer.lock and then the vendor/composer/installed.json (which is the source used for the dump-autoload). But in theory you can load whatever you want from the top level app, and therefore you can 'hard code' a package into the vendor library and classpath to it.
I'd probably recommend not doing this though! The vendor folder is a tenuous location which most people and programs would assume can be destroyed and rebuilt at a whim. So it's a dangerous place to store anything which isn't in a package. It's also confusing for any other developers who will assume the same.
So I'd recommend moving your library to another location away from the vendor folder, e.g. 'lib', and then using the classpath approach above to include it in the autoloader.
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
I've got some libraries loaded through composer, and I'm wondering if it's possible to add my own library in the /vendor map, and then to have the composer autoloader load it? The structure would be something like /vendor/mylibrary/ and then a namespace mylibrary.
Would this be possible? Also would it be possible to add a different map to the composer autoloader? Like for example /app/src/ and then to have it load all the classes in that folder? Or do I have to make my own loader for that?
Thanks
Reading the composer documentation:
You can even add your own code to the autoloader by adding an autoload field to composer.json.
{
"autoload": {
"psr-0": {"Acme": "src/"}
}
}
Composer will register a PSR-0 autoloader for the Acme namespace.
You define a mapping from namespaces to directories. The src directory would be in your project root, on the same level as vendor directory is. An example filename would be src/Acme/Foo.php containing an Acme\Foo class.
After adding the autoload field, you have to re-run install to
re-generate the vendor/autoload.php file.
So basically, you just need to follow PSR-0, and tell composer where to find your library, by adding that line to your composer.json
Yes.You can achieve it. Configure your composer.json file as following:
{
"autoload": {
"classmap": [ "classes" ]
}
Here classes is the name of the directory where you have all your application related classes.Vendor related class should be auto detected as well. Just add the following line to achieve both at the same time:
require 'vendor/autoload.php';
And you can use the namesapce to reference your class like the following:
use classes\Model\Article;
Yes, of course it is possible to add own libraries and you should feel highly encouraged to do so. If your library is available publicly, you can simply register it at packagist.org. If not, it's a bit more complicated, but not impossible.
If your project does not follow the PSR-0 standard, composer will create a classmap for you. A custom autoloader is not supported.
I'd recommend you to read the (really excellent) documentation about all this and come back, if you're running into problems.
http://getcomposer.org/doc/
I've started a new project, where I use Composer to handle some dependencies, as well as their auto-loading.
I only keep the composer.json file in the VCS, instead of the entire vendor directory, so I don't want to start adding my code in there.
How should I handle my own project specific code, so that it auto loads as well?
This is actually very simple. Excluding vendors directory from your repository is the right approach. Your code should be stored in a separate place (like src).
Use the autoload property to make that composer recognizes your namespace(s):
{
"autoload": {
"psr-4": {
"Acme\\": "src/"
}
}
}
Assuming you have class names following the psr-4 standard, it should work. Below some example of class names and their locations on the file system:
Acme\Command\HelloCommand -> src/Command/HelloCommand.php
Acme\Form\Type\EmployeeType -> src/Form/Type/EmployeeType.php
Remember to define a namespace for each class. Here's an example of Acme\Command\HelloCommand:
<?php
namespace Acme\Command;
class HelloCommand
{
}
Don't forget to include the autoloader in your PHP controllers:
<?php
require 'vendor/autoload.php';
Read more on PSR-4 standard on PHP Framework Interoperability Group.
Note that if you edit composer.json, you need to either run install, update or dump-autoload to refresh the autoloader class paths.