Menu

Config Reference

NEON format #

PHPStan uses configuration format called NEON. It’s very similar to YAML so if you’re familiar with it, you can also write NEON.

This is how a possible example of a config file can look like:

parameters:
	level: 6
	paths:
		- src
		- tests

Config file #

A config file can be passed to the phpstan executable using the -c|--configuration option:

vendor/bin/phpstan analyse -c phpstan.neon

When using a config file, you have to pass the --level|-l option to analyse command (default value 0 does not apply here), or provide it as a level parameter in the config file itself. Learn more about other command line options »

If you do not provide a config file explicitly, PHPStan will look for files named phpstan.neon, phpstan.neon.dist, or phpstan.dist.neon in the current directory.

The resolution priority is as such:

  1. If config file is provided as a command line option, it will be used.
  2. Otherwise, if phpstan.neon exists in the current working directory, it will be used.
  3. Otherwise, if phpstan.neon.dist exists in the current working directory, it will be used.
  4. Otherwise, if phpstan.dist.neon exists in the current working directory, it will be used.
  5. If none of the above is true, no config will be used.

The usual practice is to have phpstan.neon.dist or phpstan.dist.neon under version control, and allow the user to override certain settings in their environment (on their own computer or on a continuous integration server) by creating phpstan.neon that’s present in .gitignore file. See Multiple files for more details:

Multiple files #

The NEON format supports an includes section to compose the final configuration from multiple files. Let’s say the phpstan.neon.dist project config file looks like this:

parameters:
	level: 6
	paths:
		- src
		- tests

If the user doesn’t have certain PHP extensions, wants to ignore some reported errors from the analysis, and to disable parallel CPU processing, they can create phpstan.neon file with this content:

includes:
	- phpstan.neon.dist

parameters:
	ignoreErrors:
		- '#Function pcntl_open not found\.#'
	parallel:
		maximumNumberOfProcesses: 1

Relative paths in the includes section are resolved based on the directory of the config file is in. So in this example, phpstan.neon.dist and phpstan.neon are next to each other in the same directory.

includes can also reference PHP files that can be used to define dynamic configurations, see ignore-by-php-version.neon.php and phpstan.neon as examples.

Ignoring errors #

Learn more about ignoring errors in the user guide.

Related config keys: ignoreErrors, reportUnmatchedIgnoredErrors.

Discovering symbols #

Learn more about discovering symbols in the user guide.

Related config keys: scanFiles, scanDirectories.

Bootstrap #

If you need to initialize something in PHP runtime before PHPStan runs (like your own autoloader), you can provide your own bootstrap files:

parameters:
	bootstrapFiles:
		- phpstan-bootstrap.php

Relative paths in the bootstrapFiles key are resolved based on the directory of the config file is in.

Caching #

By default, PHPStan stores its cache files in sys_get_temp_dir() . '/phpstan' (usually /tmp/phpstan). You can override this by setting the tmpDir parameter:

parameters:
	tmpDir: tmp

Relative path in the tmpDir key is resolved based on the directory of the config file is in. In this example PHPStan cache will be stored in tmp directory that’s next to the configuration file.

Analysed files #

PHPStan accepts a list of files and directories on the command line:

vendor/bin/phpstan analyse -c src tests

You can save some keystrokes each time you run PHPStan by moving the analysed paths to the config file:

parameters:
	paths:
		- src
		- tests

Relative paths in the paths key are resolved based on the directory of the config file is in.

If you provide analysed paths to PHPStan on the command line and in the config file at the same time, they are not merged. Only the paths on the command line will be used.

If your codebase contains some files that are broken on purpose (e. g. to test behaviour of your application on files with invalid PHP code), you can exclude them using the excludePaths key. Each entry is used as a pattern for the fnmatch() function.

parameters:
	excludePaths:
		- tests/*/data/*

This is a shortcut for:

parameters:
	excludePaths:
	    analyseAndScan:
		    - tests/*/data/*

If your project’s directory structure mixes your own code (the one you want to analyse and fix bugs in) and third party code (which you’re using for discovering symbols, but don’t want to analyse), the file structure might look like this:

├── phpstan.neon
└── src
    ├── foo.php
    ├── ...
    └── thirdparty
        └── bar.php

In this case, you want to analyse the whole src directory, but want to exclude src/thirdparty from analysing. This is how to configure PHPStan:

parameters:
    excludePaths:
        analyse:
            - src/thirdparty

Additionally, there might be a src/broken directory which contains files that you don’t want to analyse nor use for discovering symbols. You can modify the configuration to achieve that effect:

parameters:
    excludePaths:
        analyse:
            - src/thirdparty
        analyseAndScan:
            - src/broken

By default, PHPStan analyses only files with the .php extension. To include other extensions, use the fileExtensions key:

parameters:
	fileExtensions:
		- php
		- module
		- inc

Rule level #

Learn more about rule levels in the user guide.

Instead of using the CLI option --level, you can save some keystrokes each time you run PHPStan by moving the desired level to the config file:

parameters:
	level: 6

Custom ruleset #

PHPStan requires you to specify a level to run which means it will choose the enforced rules for you. If you don’t want to follow the predefined rule levels and want to create your own ruleset, tell PHPStan to not require a level by setting customRulesetUsed to true:

parameters:
	customRulesetUsed: true

You can then choose your own ruleset by copying parts of the level configuration files from PHPStan sources, or include your own custom rules.

Bleeding edge #

Bleeding edge offers a preview of the next major version. When you enable Bleeding edge in your configuration file, you will get new rules, behaviour, and bug fixes that will be enabled for everyone later when the next PHPStan’s major version is released.

includes:
	- phar://phpstan.phar/conf/bleedingEdge.neon

Learn more about bleeding edge.

Solving undefined variables #

Learn more about solving undefined variables in Writing PHP Code.

Related config keys: earlyTerminatingMethodCalls, earlyTerminatingFunctionCalls.

Universal object crates #

Classes without predefined structure are common in PHP applications. They are used as universal holders of data - any property can be set and read on them. Notable examples include stdClass, SimpleXMLElement (these are enabled by default), objects with results of database queries etc. Use universalObjectCratesClasses key to let PHPStan know which classes with these characteristics are used in your codebase:

parameters:
	universalObjectCratesClasses:
		- Dibi\Row
		- Ratchet\ConnectionInterface

See also object shape PHPDoc type for a better alternative that lets you describe types of properties of such objects.

Constants #

Learn more about letting PHPStan know about your global constants in the user guide.

Sometimes your constants can have different values in different environments, like DATABASE_ENGINE that can have different values like mysql or pgsql. To let PHPStan know that the value of the constant can be different, and prevent errors like Strict comparison using === between 'pgsql' and 'mysql' will always evaluate to false., add the constant name to dynamicConstantNames key:

parameters:
	dynamicConstantNames:
		- DATABASE_ENGINE
		- Foo::BAR_CONSTANT # class constants are also supported

Stub files #

Learn more about stub files in the user guide.

Related config key: stubFiles.

Stricter analysis #

Existing outside of rule levels there are additional parameters affecting analysis result you can tune.

polluteScopeWithLoopInitialAssignments #

default: true (strict-rules sets it to false)

example: with true, with false

When set to false it prevents reading variables set in for loop initial statement and while loop condition after the loop.

polluteScopeWithAlwaysIterableForeach #

default: true (strict-rules sets it to false)

example: with true, with false

When set to false it prevents reading key and value variables set in foreach when iterating over a non-empty array.

checkAlwaysTrueCheckTypeFunctionCall #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports occurrences of type-checking functions always evaluated to true.

checkAlwaysTrueInstanceof #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports instanceof occurrences always evaluated to true.

checkAlwaysTrueStrictComparison #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports === and !== occurrences always evaluated to true.

checkExplicitMixedMissingReturn #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports code paths with missing return statement in functions and methods with @return mixed PHPDoc.

checkFunctionNameCase #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports function and method calls with incorrect name case.

checkInternalClassCaseSensitivity #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports references to built-in classes with incorrect name case.

reportMaybesInMethodSignatures #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports violations of parameter type contravariance and return type covariance. By default, PHPStan only reports completely incompatible types in signatures, see this example.

reportMaybesInPropertyPhpDocTypes #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports violations of property type invariance. By default, PHPStan only reports completely incompatible PHPDoc typescheckInternalClassCaseSensitivity, see this example.

reportStaticMethodSignatures #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports violations of parameter type contravariance and return type covariance in static methods.

checkTooWideReturnTypesInProtectedAndPublicMethods #

default: false

When set to true, it reports return typehints that could be narrowed down because some of the listed types are never returned from a public or protected method. For private methods PHPStan does this by default.

public function doFoo(): ?string
{
	// Method Foo::doFoo() never returns null so it can be removed from the return typehint.
	return 'str';
}

checkUninitializedProperties #

default: false

When set to true, it reports properties with native types that weren’t initialized in the class constructor.

// "Class has an uninitialized property $foo. Give it default value or assign it in the constructor."
private int $foo;

public function setFoo(int $foo): void
{
	$this->foo = $foo;
}

checkDynamicProperties #

default: false (strict-rules sets it to true)

example: with false, with true

When set to true, it reports use of dynamic properties as undefined.

rememberPossiblyImpureFunctionValues #

Available in PHPStan 1.8.0

default: true

By default, PHPStan considers all functions that return a value to be pure. That means that second call to the same function in the same scope will return the same narrowed type:

public function getName(): string
{
    return $this->name;
}

if ($this->getName() === 'Foo') {
    echo $this->getName(); // still 'Foo'
}

This is a sane default in case of getters but sometimes we have a function that can return different values based on a global state like a random number generator, database, or time.

public function getRandomNumber(): int
{
    return rand();
}

if ($this->getRandomNumber() === 4) {
    echo $this->getRandomNumber(); // it's not going to be 4 but PHPStan will think it is
}

You can mark getRandomNumber() with /** @phpstan-impure */ but if you have many functions like this in your codebase and don’t want to assume functions return the same value when called multiple times, you can set rememberPossiblyImpureFunctionValues to false:

parameters:
	rememberPossiblyImpureFunctionValues: false

checkImplicitMixed #

default: false

When set to true, PHPStan is strict about values with an unspecified (implicit mixed) type. It enables the same checks for values with no type specified that rule level 9 enables for explicitly specified mixed type values.

checkBenevolentUnionTypes #

Available in PHPStan 1.9.0

default: false

PHPStan defines benevolent union types, such as array-key. Benevolent unions aren’t checked strictly even at the highest level:

public function requireInt(int $value): void {}
public function requireString(string $value): void {}

/**
 * @param array-key  $value1 // array-key is a benevolent union (int|string)
 * @param int|string $value2
 */
public function test($value1, int|string $value2): int
{
    $this->requireInt($value1);    // No error
    $this->requireString($value1); // No error
    $this->requireInt($value2);    // Error
    $this->requireString($value2); // Error
}

Enable stricter analysis of benevolent union types with the checkBenevolentUnionTypes option (needs level 7 or higher):

parameters:
    checkBenevolentUnionTypes: true

reportAlwaysTrueInLastCondition #

Available in PHPStan 1.10.0 + Bleeding Edge

default: false

By default PHPStan does not report always true last condition in a series of elseif branches and match expression arms:

// $o is A|B
if ($o instanceof A) {
    // ...
} elseif ($o instanceof B) { // "Instanceof between B and B will always evaluate to true." IS NOT reported
    // ...
}

By setting reportAlwaysTrueInLastCondition to true the error in elseif will be reported.

reportWrongPhpDocTypeInVarTag #

Available in PHPStan 1.10.0 + Bleeding Edge

default: false (strict-rules sets it to true)

example: with true, with false

By default PHPStan reports wrong type in @var tag only for native types on the right side of =. With reportWrongPhpDocTypeInVarTag set to true it will consider PHPDoc types too.

This effectively means that inline @var cast can only be used to narrow down original types. PHPStan offers many utilities to use instead:

reportAnyTypeWideningInVarTag #

Available in PHPStan 1.10.60 + Bleeding Edge

default: false

This option strictens checks used in reportWrongPhpDocTypeInVarTag. It strictly disallows any type widening. Compared to default behaviour, it disallows array key widening in inline PHPDoc @var tags, so those would get reported:

  • list<int> => array<int>
  • array<int, int> => array<int>

checkMissingOverrideMethodAttribute #

Available in PHPStan 1.10.42

default: false

When set to true, PHPStan reports missing #[\Override] attribute above methods that override a method coming from their parent classes, implemented interfaces, or abstract method from a used trait.

class Foo
{
	public function doFoo(): void
	{

	}
}

class Bar extends Foo
{
	public function doFoo(): void
	{
		// missing #[\Override] above this method
	}
}

Please note that aside from setting this config parameter to true, you also need to set phpVersion to 80300 or higher. If you’re not changing phpVersion in your config, make sure you’re running PHPStan with PHP 8.3 or newer.

Exceptions #

Advanced exceptions-related rules are available. Read this article for more details ».

Related config keys: exceptions.implicitThrows, exceptions.uncheckedExceptionRegexes, exceptions.uncheckedExceptionClasses, exceptions.checkedExceptionRegexes, exceptions.checkedExceptionClasses, exceptions.reportUncheckedExceptionDeadCatch, exceptions.check.missingCheckedExceptionInThrows, exceptions.check.tooWideThrowType

Vague typehints #

Level 6 checks for missing typehints. Not only it reports when there’s no typehint at all, but also when it’s not specific enough. PHPStan needs to know about array item types. So array isn’t specific enough but int[] is.

If you want to use level 6 to report missing typehints, but are fine with array instead of int[], you can disable this behaviour by setting checkMissingIterableValueType key to false:

parameters:
	checkMissingIterableValueType: false

If you’re using generics, another thing that level 6 does is that it requires type variables always be specified in typehints. So ReflectionClass isn’t sufficient but ReflectionClass<Foo> is.

You can disable this strict approach to generics by setting checkGenericClassInNonGenericObjectType key to false:

parameters:
	checkGenericClassInNonGenericObjectType: false

If you use callables, you might find that callable or \Closure is too vague for your liking. For example, PHPStan won’t complain if you pass callable(int) : void to callable, but it will complain if you pass callable(int) : void to callable(string) : void. So, being specific with callable signatures helps PHPStan find more bugs.

However, by default PHPStan won’t complain if you don’t specify a signature for a callable or closure.

You can make PHPStan require that callable signatures are specified with PHPStan’s callable PHPDoc syntax by setting the checkMissingCallableSignature key to true (disabled by default):

parameters:
	checkMissingCallableSignature: true

Type aliases #

Learn more about type aliases in Writing PHP Code.

Related config key: typeAliases.

PHPStan Pro #

You can override the DNS servers PHPStan Pro uses to download the application:

parameters:
	pro:
		dnsServers:
			- '8.8.8.8'
Available in PHPStan 1.10.39

By default, PHPStan Pro stores its files in sys_get_temp_dir() . '/phpstan-fixer'. If that does not work for you for example because of multi-user environment, you can change this setting. You can also take advantage of environment variables:

parameters:
	pro:
		tmpDir: tmp

Relative path in the pro.tmpDir key is resolved based on the directory of the config file is in. In this example PHPStan cache will be stored in tmp directory that’s next to the configuration file.

Parallel processing #

PHPStan runs in multiple threads by default, taking advantage of multiple cores in your CPU. It uses a formula to figure out how many child processes to spawn. The child processes are given “jobs” - each job represents a batch of a certain number of files to process. The inputs to the formula are:

  • Auto-detected number of logical CPU cores on your system. If you have 8 physical cores and hyper-threading-enabled CPU, you have 16 logical CPU cores.
  • Maximum number of desired spawned processes, to prevent CPU hogging of the whole system if it’s resource-constrained. (maximumNumberOfProcesses)
  • Minimum number of jobs per process. Process is spawned only if it will process at least 2 jobs by default. (minimumNumberOfJobsPerProcess)
  • Job size - how many files are analysed in a single batch (jobSize)
  • Number of analysed files - it’s different each time because of how your codebase changes, and also thanks to the result cache.

These variables can be changed in the configuration. Here are the defaults:

parameters:
	parallel:
		jobSize: 20
		maximumNumberOfProcesses: 32
		minimumNumberOfJobsPerProcess: 2

You might encounter this error message when running PHPStan:

Child process timed out after 60 seconds. Try making it longer with parallel.processTimeout setting.

This can happen when a single job takes longer than the set timeout. It prevents PHPStan from running indefinitely when something unexpected occurs. In case of large files, it might be normal that the analysis of some of them takes longer. You can make the timeout longer in the configuration:

parameters:
	parallel:
		processTimeout: 300.0

To disable parallel processing altogether, set maximumNumberOfProcesses to 1:

parameters:
	parallel:
		maximumNumberOfProcesses: 1

Parallel processing is also disabled when running with --debug. [1]

Clickable editor URL #

You can configure PHPStan to show clickable editor URL leading to the file and line with error in the default table error formatter. Learn more

Related config key: editorUrl

Miscellaneous parameters #

phpVersion #

default: null (current PHP version is used)

If you want to analyse a codebase as if it was written for a different PHP version than you’re currently running, change the phpVersion parameter:

parameters:
    phpVersion: 70400 # PHP 7.4

PHPStan will automatically infer the config.platform.php version from the last composer.json file it can find, if not configured in the PHPStan configuration file.

inferPrivatePropertyTypeFromConstructor #

default: false

When set to true, it doesn’t require typehints for properties if the types can be inferred from constructor injection:

private $foo; // PHPStan infers $foo to be Foo

public function __construct(Foo $foo)
{
	$this->foo = $foo;
}

treatPhpDocTypesAsCertain #

default: true

example: with true, with false

PHPStan by default doesn’t differentiate between PHPDoc and native types. It considers them both as certain.

This might not be what you want in case you’re writing a library whose users might pass a wrong argument type to a function. Setting treatPhpDocTypesAsCertain to false relaxes some of the rules around type-checking.

tipsOfTheDay #

default: true

From time to time, PHPStan shows “💡 Tips of the Day” at the end of a successful analysis. You can turn this off by setting tipsOfTheDay key to false.

errorFormat #

default: null

If you want to change the default error formatter, you can specify that using:

parameters:
    errorFormat: json

additionalConstructors #

default: []

If you want to avoid errors caused by writing to readonly properties outside of constructors, configure additionalConstructors to specify methods to treat as constructors:

parameters:
	additionalConstructors:
		- PHPUnit\Framework\TestCase::setUp

This is useful when injecting dependencies with setter methods, or when writing “wither” methods on immutable objects.

Environment variables #

Available in PHPStan 1.10.33

Parameters can reference environment variables:

parameters:
    tmpDir: %env.PHPSTAN_TMP_DIR%

This example assumes you’ve set an environment variable called PHPSTAN_TMP_DIR before running PHPStan:

export PHPSTAN_TMP_DIR=/home/ondrej/phpstan-temp

Expanding paths #

There are two predefined parameters usable to expand in config parameters that represent paths:

  • %rootDir% - root directory where PHPStan resides (i.e. vendor/phpstan/phpstan in Composer installation)
  • %currentWorkingDirectory% - current working directory where PHPStan was executed

These are no longer very useful as all relative paths in config parameters are resolved based on the directory of the config file is in, resulting in a short and concise notation.

Consider this directory structure:

app/
  model/
  ui/
	Foo.php
build/
  phpstan.neon
src/
tests/
vendor/

To reference the Foo.php file from phpstan.neon, you can simply use ../app/ui/Foo.php.

To reference the Foo.php involving %rootDir%, you’d have to use %rootDir%/../../../app/ui/Foo.php which isn’t really nice.

Custom parameters #

When developing custom PHPStan extensions, you might need a custom config parameter to provide customization to the user.

PHPStan does not allow unknown parameters to be present in the config in order to prevent typos. Any new parameter also needs to be added to the top-level parametersSchema section of the config file.

The schema is defined using nette/schema library. Definition of some of the built-in PHPStan parameters looks like this:

parametersSchema:
	earlyTerminatingMethodCalls: arrayOf(listOf(string()))
	earlyTerminatingFunctionCalls: listOf(string())
	memoryLimitFile: string()
	staticReflectionClassNamePatterns: listOf(string())
	dynamicConstantNames: listOf(string())
	customRulesetUsed: bool()

If your parameters are nested arrays, you need to use the structure keyword:

parametersSchema:
	symfony: structure([
		container_xml_path: schema(string(), nullable())
		constant_hassers: bool()
		console_application_loader: schema(string(), nullable())
	])

  1. Although you don’t want to always run PHPStan with this option. ↩︎

Edit this page on GitHub

© 2016–2024 Ondřej Mirtes