PSR-4 namespaces and autoloading in Drupal 8
Summary
Drupal 8 implements the PSR-4 standard for package-based PHP namespace autoloading by the PHP Framework Interoperability Group. Upgrading Drupal 7 modules to Drupal 8 will require using PSR-4 standards. See more background info on Drupal 8 development here, for PSR-4 in context.
Example vegetable.module directory structure:
- modules/vegetable/
- css/
- js/
- src/
- Controller/
- VegetableController.php → class Drupal\vegetable\Controller\VegetableController
- Form/
- VegetableForm.php → class Drupal\vegetable\Form\VegetableForm
- Plugin/
- Block/
- VegetableBlock.php → class Drupal\vegetable\Plugin\Block\VegetableBlock
- Block/
- Entity/
- Tomato.php → class Drupal\vegetable\Entity\Tomato
- Cucumber.php → class Drupal\vegetable\Entity\Cucumber
- tests/
- TomatoTest.php → class Drupal\Tests\vegetable\Entity\TomatoTest
- CucumberTest.php → class Drupal\Tests\vegetable\Entity\CucumberTest
- VegetableManagerTest.php → class Drupal\Tests\vegetable\VegetableManagerTest
- templates/
- fixtures/
- weather-data.json
- Controller/
- vegetable.info.yml
- vegetable.routing.yml
- vegetable.module
Explanation:
-
Each module has a namespace that corresponds to its module name.
Here:
Drupal\vegetable\ -
The module's namespace is mapped to the
./src/folder in the module directory.Here:
Drupal\vegetable\→modules/vegetable/src/ -
Anything after the module namespace directly maps to the directory and file structure in the
./src/folder.Here:
Drupal\vegetable\Entity\Tomato→modules/vegetable/src/Entity/Tomato.php
The identical logic applies to PHPUnit tests contained in ./tests/src/.
Namespace resolution
The namespace of all Drupal core components, as well as contributed modules, begins with Drupal\
The first parts of a namespaced class name indicate the base namespace that maps to a registered base directory, in which PHP files will be looked up:
| Base namespace | Base directory | Contains | |
|---|---|---|---|
| Drupal core | Drupal\Component\ |
core/lib/Drupal/Component/ |
Components that are reusable outside of Drupal. |
Drupal\Core\ |
core/lib/Drupal/Core/ |
Components that are specific to Drupal. | |
Drupal\Tests\ |
core/tests/Drupal/Tests/ |
PHPUnit tests of core components. | |
| Modules | Drupal\$modulename\ |
modules/$modulename/src/ |
Main integration files. |
Drupal\$modulename\Tests\ |
modules/$modulename/src/Tests/ |
Simpletest tests of the module. | |
Drupal\Tests\$modulename\ |
modules/$modulename/tests/src/ |
PHPUnit tests of the module. |
For modules, $modulename is the unique machine name of the module, which consists of lowercase characters and underscores.
The remaining part of a namespaced class name indicates the relative path within the base directory: each PHP namespace separator (\) is replaced with a directory separator (/) and the .php extension is appended:
| Base namespace | Relative class name | → | Base directory | Relative file path |
|---|---|---|---|---|
| Drupal\Component\ | Diff\DiffEngine | → | core/lib/Drupal/Component/ | Diff/DiffEngine.php |
| Drupal\node\ | Entity\Node | → | core/modules/node/src/ | Entity/Node.php |
| Drupal\Tests\views_ui\ | Form\Ajax\RearrangeFilterTest | → | core/modules/views_ui/tests/src/ | Form/Ajax/RearrangeFilterTest.php |
| Drupal\devel\ | Plugin\Block\DevelSwitchUser | → | modules/contrib/devel/src/ | Plugin/Block/DevelSwitchUser.php |
Each PHP class, interface, or trait lives in a separate PHP file.
For example, the class Drupal\Component\Diff\DiffEngine is defined in core/lib/Drupal/Component/Diff/DiffEngine.php.