Extension for PHPStan to allow analysis of Drupal code.
PHPStan is able to discover symbols by using autoloading provided by Composer. However, Drupal does not provide autoloading information for modules and themes. This project registers those namespaces so that PHPStan can properly discover symbols in your Drupal code base automatically.
Would you like to sponsor?
When you are using phpstan/extension-installer, phpstan.neon will be automatically included.
If you don't want to use phpstan/extension-installer, include extension.neon in your project's PHPStan config:
includes:
- vendor/mglaman/phpstan-drupal/extension.neon
To include Drupal specific analysis rules, include this file:
includes:
- vendor/mglaman/phpstan-drupal/rules.neon
Ask for assistance in the discussions or #phpstan channel on Drupal Slack.
To exclude tests from analysis, add the following parameter
parameters:
excludePaths:
- *Test.php
- *TestBase.php
This project depends on phpstan/phpstan-deprecation-rules which adds deprecation rules. We provide Drupal-specific
deprecated scope resolvers.
To only handle deprecation testing, use a phpstan.neon like this:
parameters:
customRulesetUsed: true
reportUnmatchedIgnoredErrors: false
# Ignore phpstan-drupal extension's rules.
ignoreErrors:
- '#Drupal calls should be avoided in classes, use dependency injection instead#'
- '#Plugin definitions cannot be altered.#'
- '#Missing cache backend declaration for performance.#'
- '#Plugin manager has cache backend specified but does not declare cache tags.#'
includes:
- vendor/mglaman/phpstan-drupal/extension.neon
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
To disable deprecation rules while using phpstan/extension-installer, you can do the following:
{
"extra": {
"phpstan/extension-installer": {
"ignore": [
"phpstan/phpstan-deprecation-rules"
]
}
}
}See the extension-installer documentation for more information: https://github.com/phpstan/extension-installer#ignoring-a-particular-extension
@internal classesYou can disable the ClassExtendsInternalClassRule rule by adding the following to your phpstan.neon:
parameters:
drupal:
rules:
classExtendsInternalClassRule: falseThe EntityTypeManagerGetStorageDynamicReturnTypeExtension service helps map dynamic return types. This inspects the
passed entity type ID and tries to return a known storage class, besides the default EntityStorageInterface. The
default mapping can be found in extension.neon. For example:
parameters:
drupal:
entityMapping:
block:
class: DrupalblockEntityBlock
storage: DrupalCoreConfigEntityConfigEntityStorage
node:
class: DrupalnodeEntityNode
storage: DrupalnodeNodeStorage
taxonomy_term:
class: DrupaltaxonomyEntityTerm
storage: DrupaltaxonomyTermStorage
user:
class: DrupaluserEntityUser
storage: DrupaluserUserStorage
To add support for custom entities, you may add the same definition in your project's phpstan.neon. See the following
example for adding a mapping for Search API:
parameters:
drupal:
entityMapping:
search_api_index:
class: Drupalsearch_apiEntityIndex
storage: Drupalsearch_apiEntitySearchApiConfigEntityStorage
search_api_server:
class: Drupalsearch_apiEntityServer
storage: Drupalsearch_apiEntitySearchApiConfigEntityStorage
Similarly, the EntityStorageDynamicReturnTypeExtension service helps to determine the type of the entity which is
loaded, created etc.. when using an entity storage.
For instance when using
$node = Drupal::entityTypeManager()->getStorage('node')->create(['type' => 'page', 'title' => 'foo']);It helps with knowing the type of the $node variable is DrupalnodeEntityNode.
The default mapping can be found in extension.neon:
parameters:
drupal:
entityMapping:
block:
class: DrupalblockEntityBlock
storage: DrupalCoreConfigEntityConfigEntityStorage
node:
class: DrupalnodeEntityNode
storage: DrupalnodeNodeStorage
taxonomy_term:
class: DrupaltaxonomyEntityTerm
storage: DrupaltaxonomyTermStorage
user:
class: DrupaluserEntityUser
storage: DrupaluserUserStorageTo add support for custom entities, you may add the same definition in your project's phpstan.neon likewise.
Contributed modules can provide their own mapping that can be automatically registered with a user's code base when
they use the phpstan/extension-installer. The extension installer scans installed package's composer.json for a
value in extra.phpstan. This will automatically bundle the defined include that contains an entity mapping
configuration.
For example, the Paragraphs module could have the following entity_mapping.neon file:
parameters:
drupal:
entityMapping:
paragraph:
class: DrupalparagraphsEntityParagraph
paragraphs_type:
class: DrupalparagraphsEntityParagraphsTypeThen in the composer.json for Paragraphs, the entity_mapping.neon would be provided as a PHPStan include
{
"name": "drupal/paragraphs",
"description": "Enables the creation of Paragraphs entities.",
"type": "drupal-module",
"license": "GPL-2.0-or-later",
"require": {
"drupal/entity_reference_revisions": "~1.3"
},
"extra": {
"phpstan": {
"includes": [
"entity_mapping.neon"
]
}
}
}