Outil d'analyse statique et d'optimisation de code PHP, écrit en Python. Détecte les problèmes de performance, fuites mémoire, vulnérabilités de sécurité, code mort et annotations de type manquantes, puis génère un rapport console, JSON ou HTML.
Langues : Français (ce fichier) · English
- 9 analyseurs spécialisés orchestrés par
SimpleAnalyzer - ~70 règles classées en 7 catégories avec des poids de sévérité de 0 (très faible) à 4 (critique)
- Suggestions adaptées à la version PHP cible pour les annotations de type (PHP 7.0 → 8.2+)
- Filtrage intelligent par règle, par catégorie ou par poids minimum
- Trois formats de rapport : console couleur, HTML interactif, JSON pour CI
- Aucune exécution PHP : moteur d'analyse heuristique en regex pur
# Cloner le dépôt
git clone <url-du-depot> phpoptimizer
cd phpoptimizer
# Créer l'environnement virtuel (Windows)
python -m venv venv
.\venv\Scripts\Activate.ps1
# Installer les dépendances et le paquet en mode éditable
pip install -r requirements.txt
pip install -e .Python ≥ 3.8 requis. La commande installée est
phpoptimizer.
# Analyser un fichier en mode verbeux
phpoptimizer analyze examples/example.php --verbose
# Analyser un dossier récursivement, sortie HTML
phpoptimizer analyze chemin/vers/projet-php/ --recursive --output-format html --output rapport.html
# Audit de sécurité uniquement (catégorie critique)
phpoptimizer analyze chemin/vers/projet-php/ --include-categories=security --recursive
# Ne montrer que les problèmes de poids ≥ 2
phpoptimizer analyze chemin/vers/projet-php/ --min-weight=2 --recursive
# Cibler une version PHP précise pour les annotations de type
phpoptimizer analyze chemin/vers/projet-php/ --php-version=7.4 --recursiveExécution en module Python :
python -m phpoptimizer analyze examples/ --recursiveGénérer un fichier de configuration JSON par défaut :
python -m phpoptimizer init-config example_config.json| Option | Description |
|---|---|
--recursive, -r |
Parcourir les sous-dossiers |
--output-format |
console (par défaut), json, html |
--output, -o |
Fichier de sortie (obligatoire pour json/html) |
--rules |
Fichier de configuration JSON (voir plus bas) |
--severity |
Sévérité minimum : info, warning, error |
--include-rules |
Liste blanche de règles (séparées par des virgules) |
--exclude-rules |
Liste noire de règles |
--include-categories |
Catégories incluses uniquement |
--exclude-categories |
Catégories exclues |
--min-weight |
Poids minimum : 0-4 |
--php-version |
Version PHP cible (7.0 … 8.2) |
--verbose, -v |
Sortie détaillée (descriptions, suggestions, exemples) |
| Catégorie | Poids | Exemples |
|---|---|---|
security |
4 / Critique | Injection SQL, XSS, hachage faible |
error |
3 / Élevé | Foreach sur scalaire, code mort, syntaxe |
performance.critical |
3 / Élevé | Tri/recherche en boucle, requête en boucle, imbrication profonde |
performance.general |
2 / Moyen | Calculs répétés, appels dynamiques, regex |
memory |
2 / Moyen | unset() manquant, gros tableaux, fuites |
code_quality |
1 / Faible | Annotations de type, complexité, documentation |
psr |
0 / Très faible | Longueur de ligne, nommage, indentation |
{
"severity_level": "info",
"excluded_paths": ["vendor/", "node_modules/"],
"rules": {
"performance.repetitive_array_access": {
"enabled": true,
"severity": "info",
"params": { "min_occurrences": 2 }
},
"best_practices.line_length": {
"enabled": true,
"severity": "info",
"params": { "max_line_length": 120 }
},
"best_practices.missing_documentation": { "enabled": false }
}
}Paramètres ajustables :
performance.repetitive_array_access.min_occurrences(défaut3)performance.large_arrays.max_array_size(défaut1000)performance.inefficient_loops.max_nested_loops(défaut3)best_practices.function_complexity.max_complexity(défaut10)best_practices.too_many_parameters.max_parameters(défaut5)best_practices.line_length.max_line_length(défaut120)
security.sql_injection,security.xss_vulnerabilitysecurity.weak_password_hashing,security.file_inclusionsecurity.command_injection,security.insecure_deserializationsecurity.path_traversal,security.ssrfsecurity.csrf_missing_protectionsecurity.dangerous_function,security.authenticationsecurity.configuration,security.sensitive_data_exposure
error.foreach_non_iterable— foreach sur une valeur scalaireerror.null_method_call,error.uninitialized_variableerror.assignment_in_condition,error.string_math_operationerror.unclosed_quotes,error.syntax_*dead_code.unreachable_after_return/_after_breakdead_code.always_false_condition
performance.inefficient_loops—count()dans une condition de boucleperformance.deeply_nested_loops,performance.nested_loop_same_arrayperformance.linear_search_in_loop,performance.sort_in_loopperformance.heavy_function_in_loop,performance.query_in_loopperformance.object_creation_in_loopperformance.superglobal_access_in_loopperformance.loop_fusion_opportunity
performance.constant_propagation,performance.repeated_calculationsperformance.repetitive_array_accessperformance.dynamic_method_call,performance.dynamic_function_callperformance.string_concatenation,performance.regex_performanceperformance.unprepared_queryperformance.inefficient_file_reading,performance.repeated_file_checks
performance.memory_management— gros tableau jamais libéré parunset()performance.large_arrays,performance.excessive_memoryperformance.resource_leak,performance.circular_referenceperformance.unused_variables,performance.unused_global_variableperformance.global_could_be_local
performance.missing_parameter_type,performance.missing_return_typeperformance.mixed_type_opportunitybest_practices.function_complexity,best_practices.too_many_parametersbest_practices.complex_condition,best_practices.function_namingbest_practices.line_length,best_practices.namingbest_practices.brace_style,best_practices.mixed_indentation
phpoptimizer/ # Racine du dépôt
├── src/
│ └── phpoptimizer/ # Paquet Python importable
│ ├── __init__.py # API publique : SimpleAnalyzer, ReportGenerator, Config
│ ├── __main__.py # Point d'entrée `python -m phpoptimizer`
│ ├── cli.py # CLI Click (analyze, version, init-config)
│ ├── config.py # Config, RuleConfig, catégories, poids
│ ├── simple_analyzer.py # Orchestrateur des analyseurs spécialisés
│ ├── reporter.py # Rapports console, JSON et HTML
│ ├── suggestions.py # Suggestions détaillées avant/après
│ └── analyzers/ # 9 analyseurs spécialisés
│ ├── base_analyzer.py
│ ├── loop_analyzer.py
│ ├── security_analyzer.py
│ ├── error_analyzer.py
│ ├── performance_analyzer.py
│ ├── memory_analyzer.py
│ ├── code_quality_analyzer.py
│ ├── dead_code_analyzer.py
│ ├── dynamic_calls_analyzer.py
│ └── type_hint_analyzer.py
├── tests/ # Tests unitaires (lancés via pytest)
├── examples/ # Fichiers PHP pour vérifications manuelles
├── CATEGORIES_GUIDE.md # Guide de filtrage
├── DYNAMIC_CALLS_OPTIMIZATION.md # Détails sur les appels dynamiques
├── CONTRIBUTING.md # Guide de contribution
├── agents.md # Carte rapide pour les agents IA travaillant sur le dépôt
├── requirements.txt # Dépendances Python
└── setup.py # Métadonnées du paquet
Le paquet utilise la structure Python standard
src/: les métadonnées, tests et exemples restent à la racine, tandis que le code importable vit danssrc/phpoptimizer/.
SimpleAnalyzer lit un fichier PHP comme un simple texte, puis demande à
chaque analyseur spécialisé (LoopAnalyzer, SecurityAnalyzer, …) de
retourner ses issues (de simples dictionnaires construits via
BaseAnalyzer._create_issue). Les issues sont ensuite filtrées par
Config.should_apply_rule() (la règle doit être activée et passer les
filtres de catégorie / poids actifs), dédupliquées et triées par numéro
de ligne. ReportGenerator produit la sortie.
Pour ajouter une règle :
- Implémenter la détection dans le bon analyseur de
src/phpoptimizer/analyzers/en utilisant_create_issue(rule_name, …) - Déclarer le
rule_namedansConfig._init_default_rules()avec une catégorie, une sévérité et un poids — sinon la règle sera filtrée - Ajouter éventuellement une suggestion détaillée dans
src/phpoptimizer/suggestions.py - Ajouter au moins un test positif et un test négatif dans
tests/
Voir agents.md et CONTRIBUTING.md.
python -m pytest tests/
python -m pytest tests/test_analyzer.py -vLa suite est écrite en style unittest et lancée via pytest.
============================================================
RAPPORT D'ANALYSE PHP OPTIMIZER
============================================================
Statistiques générales:
Fichiers analysés : 1/1
Problèmes détectés : 5
Répartition par sévérité:
Erreurs : 1
Avertissements : 2
Informations : 2
📄 examples/simple_test.php
📍 Ligne 12 : Injection SQL : requête SELECT avec concaténation de variable
💡 Solution : Utiliser une requête préparée avec paramètres liés
📍 Ligne 34 : Gros tableau $large_data (50000 éléments) non libéré avec unset()
💡 Solution : Appeler unset($large_data) une fois la donnée inutile
Voir CONTRIBUTING.md. Les rapports de bugs, nouvelles règles et nouveaux analyseurs sont les bienvenus.
MIT — voir LICENSE.