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
Related
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.
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'm kind of confused on how to load my own code (classes or just regular functions) into a Laravel app. I've seen this done in several ways:
Creating a folder inside the app directory (for example: app/libs) and add app_path().'/libs' to start/global.php
Add it into composer.json's "require"
Add "psr-0" into composer.json's "autoload" and add there the files
Add a My\Custom\Service\Provider into app/config/app.php's 'providers' and the alias for the facade
What's the difference between them? Why and when should I use any of those ways? Should I load a class, several .php files or simply the folder? Maybe reference those 3 things at the same time?
EDIT:
These are my guesses:
Option 2 is just for packages
Option 3 if you want to load every class inside a custom namespace declared within the new created folder (don't get why the "psr-0" instead of just adding it to "classmap")
Option 1 is the same as option 3, just handled by Laravel instead of Composer
You can reference a folder and it will load every class found inside, or you can reference a certain file and it will load the class found inside
About option 4:
If you want to use the facade anywhere on your code, and that will need the namespace added into composer.json
EDIT 2:
If you add them to "classmap":
"classmap": [
"app/libs"
]
every class from any namespace within files inside the app/libs folder, will be loaded
If you add them to "psr-0":
"psr-0": {
"Libs": "app/"
}
it will load every class within the Libs namespace inside the app/libs folder
Still not sure why/when to use service providers and aliases.
EDIT 3:
"psr-0" if I want to load a namespace that follows a folder structure (it won't load a class within a subnamespace if it doesn't match the folder structure)
"classmap" for "random" classes, functions... sort of "the rest"
you can load your own code 2 (maybe 3) ways in laravel.
use composer
use ClassLoader
Manual include or require anywhere
Option 2 is just for packages
yes, you're right.
Option 1 is the same as option 3, just handled by Laravel instead of
Composer
yes, you're right.
Option 3 if you want to load every class inside a custom namespace
declared within the new created folder (don't get why the "psr-0"
instead of just adding it to "classmap")
some packages or classes adhere psr-0 standard, the rest is not. psr-0 option is mapping namespace to directory. the classmap is mapping
the namespace to certain directory or file and used for the class that is not adhere psr-0 standard.
You can use the classmap generation support to define autoloading for all libraries that do not follow PSR-0/4.
If you want to use the facade anywhere on your code, and that will
need the namespace added into composer.json
nope, instead, you have to add class alias for the facade in app/config/app.php
if your code is just file, not a class, then use composer autoload files
if your code is class but not adhere psr-0/4 standard, use composer autoload classmap or just add the containing directory to app/start/global.php.
otherwise, use composer autoload psr-0 or psr-4.
in Laravel 4,I add all of my class in "mylibrary" folder.
Then at app/start/global.php , I add app_path().'/mylibrary',
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/mylibrary',
));
Within mylibrary there is MyClass.php , within MyClass.php there is test_myfunction()
and at app/view/home.blade.php I add these code :
<?php
$FMyClass11 = new MyClass;
$just_test=($FMyClass1->test_myfunction());
?>
Hope it works for you. :)
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.