Checklists for PHP developers
This page is for PHP developers who want to check their work in one pass. Each list links to the page that explains it. Copy a list into your pull request description or your review notes.
Contents
- Before you write
- Every PHP file
- A new class
- A module view
- A command or cronjob part
- A datatype or workflow event type
- Security
- Velocity and long runs
- Tests
- Commit and pull request
- Deploy
Before you write
- To do: Is there a setting, a shipped extension or an extension point that does it already? (Extension points from PHP)
- To do: Kernel change or extension? (Contributing PHP changes)
- To do: The prefix of the new names is chosen (Class naming and the exp prefix)
Every PHP file
- To do: Starts with
<?php, Unix line endings, spaces, no trailing spaces - To do:
php -lpasses on the newest PHP, and on PHP 8.0 (make lint80) - To do: No syntax or function newer than PHP 8.0 unguarded (Writing code that runs on PHP 8.0)
- To do:
array( ... ), spaces inside parentheses, function braces on their own line (The coding standard) - To do: No scalar, return or property type declarations; docblocks with
@paramand@return - To do:
make phpcsadds no violations;make phpstanadds no findings
A new class
- To do: One class per file, lower case file name of the class
- To do: Properties declared (no dynamic properties)
- To do:
php bin/php/ezpgenerateautoloads.php -erun (Autoloads and class maps) - To do: No class static assigned outside the class body
- To do: A setting that names the class goes live after the class is deployed
A module view
- To do:
module.phpnames the view'sfunctions(policy) (Write your first module view) - To do: Written as a class extending
Exponential\Runnable\ModuleView, the view file one line - To do:
$Paramscast and validated - To do: Data changes only on POST, through module actions
- To do: HTML in a template, every value through
|wash - To do: POST, redirect, GET after a successful save; redirect targets from the request checked
A command or cronjob part
- To do: A class extending
Exponential\Runnable\CommandorCronjobPart(Write a console command, Write a cronjob part) - To do:
@descriptiontag in the entry file - To do: Exit code
0on success, another on failure; quiet with-q - To do:
--dry-runfor anything that changes data - To do: Bounded work per run, short transactions, in-memory caches cleared between batches
- To do: The work in a service class the view, the command and the cronjob part share
A datatype or workflow event type
- To do: Method signatures exactly as in
eZDataType/eZWorkflowEventType(Write a datatype) - To do: Registered with
eZDataType::register()oreZWorkflowEventType::registerEventType()and in the INI file - To do:
toString()/fromString()round trip tested - To do:
execute()fast, returns a status, never throws (Write a workflow event type)
Security
- To do: Input read through
eZHTTPTool,$Paramsor module actions; numbers cast, choices in allow lists (Validating input and casting) - To do: SQL: strings through
escapeString(), numbers cast, or persistent object conditions (SQL with eZDB, safely) - To do: Output escaped for its context;
htmlspecialchars()with explicit flags (Escaping output from PHP) - To do: Permissions checked in views, fetch functions, server functions, REST actions and commands (Security in PHP code)
- To do: POSTs carry the form token (CSRF protection and ezformtoken)
- To do: No secrets in code, URLs or logs
- To do: No inline scripts or
style=""in generated markup
Velocity and long runs
- To do: No function statics, no register-once
trueflags (Static state traps) - To do: Caches keyed by siteaccess, language and user where they depend on them
- To do:
eZExecution::cleanExit()not insidecatch ( Exception ) - To do: Paths from
EXP_ROOT_DIRoreZSys, not from a kernel file's__DIR__ - To do: Tested twice in a row on the same worker, as two users
Tests
- To do: A DB-less test for the logic (PHPUnit without a database)
- To do: Database tests marked
@group database(Database and live tests) - To do: INI values set in a test are restored in
tearDown() - To do: Works with PHPUnit 10.5 to 13
- To do:
tests/test-map.jsonentry when the test does not name the source file literally
Commit and pull request
- To do: Subject starts with
Added:,Updated:,Fixed:,Removed:orRenamed:; the body says why - To do: The product is written Exponential in the message
- To do:
share/filelist.md5refreshed (make manifest-fix) and committed - To do:
make checkpasses - To do: CLA on file; pull request small and focused; squashed and rebased onto
main(Contributing PHP changes)
Deploy
- To do: Autoloads regenerated, INI cache cleared (
--clear-tag=ini) - To do: PHP-FPM reloaded, Velocity workers restarted (
exp:velocity deploy) - To do: Rendered-output caches cleared after the reload
- To do: Caches warmed (OPcache and cache preloading)
- To do: Front page and the changed pages checked; logs read
Related pages
- The upgrade checklist
- The release checklist
- PHP developer FAQ
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.