opencoreemr / openemr-phpstan-rules
PHPStan rules for OpenEMR core and module development
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 4
Type:phpstan-extension
pkg:composer/opencoreemr/openemr-phpstan-rules
Requires
- php: ^8.2
- phpstan/phpstan: ^2.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.42
- squizlabs/php_codesniffer: ^4.0
This package is auto-updated.
Last update: 2025-12-11 22:24:18 UTC
README
Composer-installable PHPStan rules for OpenEMR core and module development. Enforces modern coding patterns and best practices.
Installation
composer require --dev opencoreemr/openemr-phpstan-rules
Usage
For OpenEMR Core Development
Include the core ruleset in your phpstan.neon:
includes: - vendor/opencoreemr/openemr-phpstan-rules/core.neon
For OpenEMR Module Development
Include the module ruleset in your phpstan.neon:
includes: - vendor/opencoreemr/openemr-phpstan-rules/module.neon
Rules
Core Rules (for OpenEMR Core and Modules)
Database Rules
ForbiddenFunctionsRule
- Forbids: Legacy
sql.inc.phpfunctions (sqlQuery,sqlStatement,sqlInsert, etc.) - Requires:
QueryUtilsmethods instead - Example:
// ❌ Forbidden $result = sqlStatement($sql, $binds); // ✅ Required $records = QueryUtils::fetchRecords($sql, $binds);
ForbiddenClassesRule
- Forbids: Laminas-DB classes (
Laminas\Db\Adapter,Laminas\Db\Sql, etc.) - Requires:
QueryUtilsorDatabaseQueryTrait
Globals Rules
ForbiddenGlobalsAccessRule
- Forbids: Direct
$GLOBALSarray access - Requires:
OEGlobalsBag::getInstance() - Example:
// ❌ Forbidden $value = $GLOBALS['some_setting']; // ✅ Required $globals = OEGlobalsBag::getInstance(); $value = $globals->get('some_setting');
Testing Rules
NoCoversAnnotationRule
- Forbids:
@coversannotations on test methods - Rationale: Excludes transitively used code from coverage reports
NoCoversAnnotationOnClassRule
- Forbids:
@coversannotations on test classes - Rationale: Same as above - incomplete coverage tracking
Module-Specific Rules (for OpenEMR Modules Only)
These additional rules enforce Symfony-inspired MVC patterns in OpenEMR modules.
CatchThrowableNotExceptionRule
- Forbids:
catch (\Exception $e) - Requires:
catch (\Throwable $e) - Rationale: Catches both exceptions and errors (
TypeError,ParseError, etc.) - Example:
// ❌ Forbidden try { $service->doSomething(); } catch (\Exception $e) { // Misses TypeError, ParseError, etc. } // ✅ Required try { $service->doSomething(); } catch (\Throwable $e) { // Catches everything }
NoSuperGlobalsInControllersRule
- Forbids:
$_GET,$_POST,$_FILES,$_SERVERin Controller classes - Requires: Symfony
Requestobject methods - Example:
// ❌ Forbidden in controllers $name = $_POST['name']; $filter = $_GET['filter']; // ✅ Required $request = Request::createFromGlobals(); $name = $request->request->get('name'); $filter = $request->query->get('filter');
NoLegacyResponseMethodsRule
- Forbids:
header(),http_response_code(),die(),exit, directechoin controllers - Requires: Symfony
Responseobjects - Example:
// ❌ Forbidden in controllers header('Location: /some/path'); http_response_code(404); echo json_encode($data); die('Error'); // ✅ Required return new RedirectResponse('/some/path'); return new Response($content, 404); return new JsonResponse($data); throw new ModuleException('Error');
ControllersMustReturnResponseRule
- Forbids: Controller methods returning
voidor no return type - Requires: Return type declaration of
Responseor subclass - Example:
// ❌ Forbidden public function handleRequest(): void { // ... } // ✅ Required public function handleRequest(): Response { return new Response($content); }
Rule Configuration
You can selectively enable rules by creating your own configuration:
# Custom phpstan.neon services: # Just database rules - class: OpenCoreEMR\PHPStan\Rules\Database\ForbiddenFunctionsRule tags: - phpstan.rules.rule # Just module controller rules - class: OpenCoreEMR\PHPStan\Rules\Module\NoSuperGlobalsInControllersRule tags: - phpstan.rules.rule
Baselines
If you're adding these rules to an existing codebase, generate a baseline to exclude existing violations:
vendor/bin/phpstan analyze --generate-baseline
New code will still be checked against all rules.
Migration Guides
See MIGRATION_GUIDE.md for detailed migration patterns for each rule.
Development
Running Tests
# Install dependencies composer install # Run PHPStan on the rules themselves vendor/bin/phpstan analyze
Contributing
Contributions are welcome! Please:
- Follow existing code style and patterns
- Add tests for new rules
- Update documentation
License
GNU General Public License v3.0 or later. See LICENSE
Authors
- Michael A. Smith michael@opencoreemr.com