PHP Namespace directory structure - php

It is my understanding that namespaces are declared as follows : vendor\module\classname.
And directory structure would be:
/Acme
/Module1
/src
/Module1
/Class.php
And a valid way to instantiate the class is : new Acme\Module1\Class();
Are my assumptions correct? If so, what's the benefit of using the src folder?

Convention usually.
If you're using composer and you want to autoload your classes, it looks like you're trying to do PSR-0 autoloading.
So if you have "Acme": "src/"
Then in the same directory as your composer.json file would be a src folder, and in the src folder would be a Acme folder. All files in that folder would be namespace Acme; and all files in subdirectories of that folder would be namespace Acme\Subdirectory;.
In the console you need to type composer dump-autoload every time you make changes to the autoloading part of your composer.json file. (or for classmap autoloading, every time you add new files to directories being autoloaded.) This causes the files generated by composer to be updated. (you can find these files in the vendor/composer directory).
So if there was a src/Acme/Subdirectory/ClassName.php with a class in it named ClassName then to instantiate that class you could type new \Acme\Subdirectory\ClassName();
edit: so if this is your composer.json file
{
"autoload": {
"psr-0": {
"Acme": "src/"
}
}
}
then your directory structure would be something like this
/ProjectRoot
composer.json
/src
/Acme
/Module1
Class.php
And you would create a new instance of your class by typing
new \Acme\Module1\Class();

Related

symfony4.3 adding custom folder with classes

In my default symfony4 structure I want to add lib folder, where I have additional classes. So something like this:
-bin
-config
-lib
- Importer.php
...(other files with classes)
-public
-src
- Controller
- TestController.php
- Entity
- Form
...
...
But I cannot figure out how to later use my files (i.e.: Importer.php).
Let's say Importer.php has a single class Importer() inside. If I try to use it from TestController.php I get:
Attempted to load class "Importer" from namespace "lib". Did you
forget a "use" statement for another namespace?
TestController.php has
use Importer;
specified on top (autodetected by PhpStorm). I also tried adding namespace in my Importer.php file, for example:
namespace lib;
and then in TestController:
use lib\Importer;
But it produces the same result.
Lastly after reading about services, I tried adding the file to config/services.yaml
lib\:
resource: '../lib/Importer.php'
Which gives the same result...
What to do, how to live?
First of all read about php namespaces.
Next read about the psr-4 standart.
Select a prefix for your folder, let's say Lib. Make sure that all files in the lib folder has a properly namespace. E.g. Importer class must be stored in the lib\Importer.php and must have the namespace Lib;, Items\Item class must be stored in the lib\Items\Item.php and must have the namespace Lib\Items\Item; and so on.
Your files are ready. Just need to inform Symfony about them.
Symfony uses composer's autoloader, so check composer's autoload section. Than add new folder for autoloading in composer.json:
"autoload": {
"psr-4": {
"App\\": "src/",
"Lib\\": "lib/"
}
},
It says that all classes in lib folder have their own separate files and Lib prefix in their namespace and other part of namespace is similar to directories structure.
Next you need to clear autoloader's cache. Run in console:
composer dump-autoload
And finally you can use your class:
use Lib\Importer;
$importer = new Importer;
Also you can add your files to autowire.

Silex autoload psr-4 class does not exist

I have this error:
InvalidArgumentException in ControllerResolver.php line 147:
Class "MyProject\API\FrontController" does not exist.
Here is my structure of myproject:
composer.json
api
src
FrontController.php
BundlesFolders
app
web
vendor
clients
My composer.json
"psr-4": {
"MyProject\\API\\": "myproject/api/src",
"MyProject\\Client\\": "myproject/client/src"
}
My routing.php :
// myproject/api/app/config/routing.php
$routes->get('/', 'MyProject\API\FrontController::exec')
FrontController.php :
<?php
// myproject/api/src/FrontController
namespace MyProject\API;
class FrontController {
You've put an extra folder to your psr-4 map. The first myproject directory should not be in your path as this path is relative to the composer.json file and your src code is in api/src and clients/src (the second is just a guess, you didn't post the content of the clients directory).
Let me tell you that IMHO your directory layout is weird. I would have a single src directory and inside put an api and a client subdirectory.
PS: You've listed the client directory in singular but in composer you have it in plural, watch out for this details!
Also run composer dump-autolad after changing your psr-4 parameter.

How to distinct vendor classes and native classes in PHP autoload?

How to distinct vector classes and native project classes in PHP autoload?
see a part of the file and namespace structure:
app/
app/Models/
app/Models/User.php
app/Contoller/
app/Contoller/Login.php
vendor/
vendor/company/package/Helper.php
Now PSR-4 says if there a class is needed to be included, autoload must include it from vendor, so how can I include my native project classes like including a model in a controller?
For Example following code:
$user = new App\Models\User();
autoload looks for "App" company (folder) in vendor folder, one approach could be use some conditions in autoload and if the namespace starts with "App" look for class in native project, is it the standard approach?
Second one, what about this, there is a package in vendor which its company name is "App" in vendor name, what is complete way?
The best solution is setting PSR-4 autoloads in your composer.json file as the following example illustrates:
// Part of composer.json
"autoload" : {
"psr-4" : {
"App\\" : "app/"
}
}
Now you don't need to extra autoload, the Composer autoload will do it for you.
When the requested class is under App namespace, Composer looking for it in the app folder as it set in the composer.json file above.

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

Problems with the namespace autoloading in composer

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

Categories