struggle-for-php / sfp-phpstan-psr-log
Extra strict and opinionated psr/log (psr-3) rules for PHPStan
Installs: 192 267
Dependents: 9
Suggesters: 0
Security: 0
Stars: 40
Watchers: 1
Forks: 3
Open Issues: 4
Type:phpstan-extension
pkg:composer/struggle-for-php/sfp-phpstan-psr-log
Requires
- php: ^7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0
- ext-json: *
- phpstan/phpstan: ^2.1.23
Requires (Dev)
- laminas/laminas-coding-standard: ^3
- maglnet/composer-require-checker: ^3 || ^4.15
- phpstan/phpstan-phpunit: ^2.0.7
- phpstan/phpstan-strict-rules: ^2.0.7
- phpunit/phpunit: ^9.6.29 || ^10 || ^11
- roave/security-advisories: dev-master
- squizlabs/php_codesniffer: ^3.13.4
- symfony/polyfill-php80: ^1.33
- vimeo/psalm: ^5.26 || ^6
Conflicts
- nikic/php-parser: <4.13.0
- 1.1.x-dev
- 1.0.x-dev
- 1.0.1
- 1.0.0
- 0.25.x-dev
- 0.24.x-dev
- 0.24.0
- 0.23.x-dev
- 0.23.0
- 0.22.x-dev
- 0.22.0
- 0.21.x-dev
- 0.21.0
- 0.20.x-dev
- 0.20.0
- 0.19.x-dev
- 0.19.1
- 0.19.0
- 0.18.x-dev
- 0.18.0
- 0.17.x-dev
- 0.17.0
- 0.16.x-dev
- 0.16.1
- 0.16.0
- 0.15.x-dev
- 0.15.0
- 0.14.x-dev
- 0.14.0
- 0.13.x-dev
- 0.13.0
- 0.12.x-dev
- 0.12.0
- 0.11.x-dev
- 0.11.1
- 0.11.0
- 0.10.x-dev
- 0.10.0
- 0.9.x-dev
- 0.9.0
- 0.8.x-dev
- 0.8.0
- 0.7.x-dev
- 0.7.0
- 0.6.x-dev
- 0.6.1
- 0.6.0
- 0.5.x-dev
- 0.5.1
- 0.5.0
- 0.4.x-dev
- 0.4.0
- 0.3.x-dev
- 0.3.0
- 0.2.0
- 0.1.3
- 0.1.1
- dev-1.0.x-merge-up-into-1.1.x_fDrK50fF
This package is auto-updated.
Last update: 2025-11-09 03:28:56 UTC
README
struggle-for-php/sfp-phpstan-psr-log is extra strict and opinionated psr/log (psr-3) rules for PHPStan.
Installation
To use this extension, require it in Composer:
composer require --dev struggle-for-php/sfp-phpstan-psr-log
Manual installation
include extension.neon & rules.neon in your project's PHPStan config:
includes: - vendor/struggle-for-php/sfp-phpstan-psr-log/rules.neon
Recommendation Settings
Write these parameters to your project's phpstan.neon.
parameters: sfpPsrLog: enableMessageStaticStringRule: false # default:true enableContextRequireExceptionKeyRule: true reportContextExceptionLogLevel: 'info' contextKeyOriginalPattern: '#\A[A-Za-z0-9-_]+\z#'
Rules
This package provides the following rules.
PlaceholderCharactersRule
Placeholder names SHOULD be composed only of the characters A-Z, a-z, 0-9, underscore _, and period .
| 📌 error identifier |
|---|
| sfpPsrLog.placeholderCharactersInvalidChar |
- reports when placeholder in
$messagecharacters are not,A-Z,a-z,0-9, underscore_, and period.
// bad $logger->info('message are {foo-hyphen}');
| 📌 error identifier |
|---|
| sfpPsrLog.placeholderCharactersDoubleBraces |
- reports when double braces pair
{{}}are used.
// bad $logger->info('message are {{foo}}');
PlaceholderCorrespondToKeysRule
Placeholder names MUST correspond to keys in the context array.
| 📌 error identifier |
|---|
| sfpPsrLog.placeholderCorrespondToKeysMissedContext |
- reports when placeholder exists in message, but
$contextparameter is missed.
// bad $logger->info('message has {nonContext} .');
| 📌 error identifier |
|---|
| sfpPsrLog.placeholderCorrespondToKeysMissedKey |
- reports when placeholder exists in message, but key in
$contextdoes not exist against them.
// bad $logger->info('user {user_id} gets an error {error} .', ['user_id' => $user_id]);
ContextKeyRule
Note
PSR-3 has no provisions for array keys, but this is useful in many cases.
| 📌 error identifier |
|---|
| sfpPsrLog.contextKeyNonEmptyString |
- reports when context key is not non-empty-string.
// bad [123 => 'foo']`, `['' => 'bar']`, `['baz']
| 📌 error identifier |
|---|
| sfpPsrLog.contextKeyOriginalPattern |
- reports when context key is not matched you defined pattern.
- if
contextKeyOriginalPatternparameter is not set, this check would be ignored.
- if
Configuration
- You can set specific key pattern by regex.(
preg_match())
parameters: sfpPsrLog: contextKeyOriginalPattern: '#\A[A-Za-z0-9-]+\z#'
ContextRequireExceptionKeyRule
Note
This is not a rule for along with PSR-3 specification, but provides best practices.
| 📌 error identifier |
|---|
| sfpPsrLog.contextRequireExceptionKey |
- It forces
exceptionkey into context parameter when current scope has\Throwableobject.
Example
<?php /** @var \Psr\Log\LoggerInterface $logger */ try { // } catch (LogicException $exception) { $logger->warning("foo"); }
$ ../vendor/bin/phpstan analyse Note: Using configuration file /tmp/your-project/phpstan.neon. 2/2 [â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“â–“] 100% ------ ------------------------------------------------------------- Line Demo.php ------ ------------------------------------------------------------- 6 Parameter $context of logger method Psr\Log\LoggerInterface::warning() requires \'exception\' key. Current scope has Throwable variable - $exception ------ ------------------------------------------------------------- [ERROR] Found 1 error
Configuration
- You can set the minimum required level to report. (default level is
debug)
parameters: sfpPsrLog: reportContextExceptionLogLevel: 'warning'
Then, debug| info | notice LogLevel is ignored for report.
} catch (\Exception $e) { $logger->info('more info'); // allow $logger->warning($e->getMessage(), ['exception' => $e]); }
- If you want to enable this rule, please add
enableContextRequireExceptionKeyRuleas true.
parameters: sfpPsrLog: enableContextRequireExceptionKeyRule: true
ContextTypeRule
Note
This rule validates that the $context parameter has the correct type according to PSR-3 specification.
| 📌 error identifier |
|---|
| sfpPsrLog.contextType |
- reports when
$contextparameter type does not match the expected type.- The default expected type is
array{exception?: Throwable}according to PSR-3.
- The default expected type is
// bad $logger->info('message', ['exception' => 'string value']); // exception must be Throwable
Configuration
- If you want to disable this rule, please add
enableContextTypeRuleas false.
parameters: sfpPsrLog: enableContextTypeRule: false
Advanced: Custom Context Type Provider
You can enforce stricter context types by implementing ContextTypeProviderInterface and injecting it via dependency injection.
- Example: Restricting to specific context keys
<?php // src/YourCustomContextTypeProvider.php use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantArrayTypeBuilder; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ObjectType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use Sfp\PHPStan\Psr\Log\TypeProvider\ContextTypeProviderInterface; final class YourCustomContextTypeProvider implements ContextTypeProviderInterface { public function getType(): Type { $builder = ConstantArrayTypeBuilder::createEmpty(); // Define allowed context keys with their types $builder->setOffsetValueType( new ConstantStringType('user_id'), new StringType(), true // optional ); $builder->setOffsetValueType( new ConstantStringType('exception'), new ObjectType(\Throwable::class), true // optional ); return $builder->getArray(); } }
Configure in phpstan.neon:
services: yourCustomContextTypeProvider: class: YourCustomContextTypeProvider contextTypeProviderResolver: class: Sfp\PHPStan\Psr\Log\TypeProviderResolver\AnyScopeContextTypeProviderResolver arguments: contextTypeProvider: @yourCustomContextTypeProvider - class: Sfp\PHPStan\Psr\Log\Rules\ContextTypeRule arguments: contextTypeProviderResolver: @contextTypeProviderResolver tags: - phpstan.rules.rule
This allows you to enforce project-specific context types, such as structured logging schemas (e.g., BigQuery) or custom application requirements.
MessageStaticStringRule
| 📌 error identifier |
|---|
| sfpPsrLog.messageNotStaticString |
- reports when $message is not static string value.
// bad $logger->info(sprintf('Message contains %s variable', $var));
Configuration
- If you want to disable this rule, please add
enableMessageStaticStringRuleas false.
parameters: sfpPsrLog: enableMessageStaticStringRule: false
LogMethodLevelRule
Implementors MUST implement the following interface, which describes the eight methods to write logs to the eight RFC 5424 levels (debug, info, notice, warning, error, critical, alert, emergency). — PSR-3 Logger Interface
| 📌 error identifier |
|---|
| sfpPsrLog.logMethodLevel |
- reports when the
$levelparameter oflog()method is not a valid PSR-3 log level.- Valid log levels:
emergency,alert,critical,error,warning,notice,info,debug
- Valid log levels:
// bad $logger->log('panic', 'message'); // 'panic' is not a valid PSR-3 log level $logger->log(100, 'message'); // level must be a string
Configuration
- If you want to disable this rule, please add
enableLogMethodLevelRuleas false.
parameters: sfpPsrLog: enableLogMethodLevelRule: false