Appearance
PHP
Table of contents:
Fundamental
Follow PSR
Always follow PSR.
PSR-12 is the most notable for maintaining a quality and consistent coding style.
Quality Coding
Use strict comparison ===
php
if ($type === 'multiple') {
return true;
}
The only exception is when you need type juggling with loose comparison ==
. Even then, you should prefer casting values into appropriate types then using strict comparison. Loose comparison can have unpredictable result.
Wrap control structures
Always wrap the body of a control structure (if
, else
, while
) with curly braces { }
even if it has only one statement.
php
if ($status === 'completed') {
$this->sendEmail();
}
Use Guard Clauses
Use Guard Clauses, which check for breaking conditions first then exit early. This allows for the rest of the code to flow like what normally happens and prevents nesting indentation.
Bad:
php
function divide(int $num, int $den)
{
if ($den !== 0 && $num !== 0) {
return $num / $den;
} else {
if ($den === 0) {
throw new DivisionByZeroError();
} else {
return 0;
}
}
}
Good:
php
function divide(int $num, int $den)
{
if ($den === 0) {
throw new DivisionByZeroError();
}
if ($num === 0) {
return 0;
}
// Normal flow here
return $num / $den;
}
A general rule of thumb is to eliminate all else
clauses.
Use multiline ternary operations
Each expression in your ternary operation should be on its own line, unless the operation is very short.
Avoid nesting ternary operations.
Bad:
php
return $this->hasUser() ? Person::HAS_USER_TYPE : Person::NO_USER_TYPE;
Good:
php
return $this->hasUser()
? Person::HAS_USER_TYPE
: Person::NO_USER_TYPE;
Don't use abbreviations
Don't use abbreviations when they're not readily understood by everyone. One acceptable abbreviation is id
.
Embrace complete names. They're expressive. It's better to write $order->user
than to write $ord->u
.
Use short operators
PHP has many great operators that can replace ugly if checks.
Bad:
php
if (! $type) {
$type = 'book';
}
if (is_null($user)) {
$user = User::find(1);
}
Good:
php
$type = $type ?: 'book';
$user = $user ?? User::find(1);
$user ??= User::find(1); // PHP 7.4+
Prefer nullable type to union type
php
public ?string $name; // Good
public string|null $name; // Bad
Specify void return type
If a function returns nothing, specify void
.
php
public function scopePublished(Builder $query): void
{
$query->
...
}
Type all properties instead of relying on docblock
Bad:
php
/** @var string */
public $name;
Good:
php
public string $name;
Recommended Styling
- No fully qualified class name usage. Use import.
- No leading slash in class usage.
- Trailing commas on arrays.
- Space after the Not Operator (
!
). - There should be no unused imports.
PHP_CodeSniffer
is a very good package to help automate these checks for you. Refer to their documentation for usage: https://github.com/squizlabs/PHP_CodeSniffer.
Programming Techniques
Store times in UTC
Store all times in UTC in the database. Compare, manipulate, and operate times in UTC.
You can display times in a different timezone based on your application's configuration or user's preference.
Use lookup tables
Instead of writing repetitive if elseif
or switch
statements, use an array to look up the wanted value based on the key you have.
Bad:
php
if ($order->product->option->type === 'mp3') {
$type = 'music';
} elseif ($order->product->option->type === 'pdf') {
$type = 'book';
} elseif ($order->product->option->type === 'epub') {
$type = 'book';
} else {
$type = 'other';
}
Good:
php
$type = [
'mp3' => 'music',
'pdf' => 'book',
'epub' => 'book',
][$order->product->option->type] ?? 'other';
Since PHP 8, you can use match
to achieve the same result conveniently:
php
$type = match($order->product->option->type) {
'mp3' => 'music',
'pdf', 'epub' => 'book',
default => 'other',
};
Design Patterns
Follow SOLID principles
SOLID is a matured methodology to develop applications. This article explains them very well in a PHP context.
Design fluent classes
A fluent class has methods that return to the object itself. Design it in a way so that upon usage you can chain its methods.
php
$paymentService = new PaymentService();
$paymentService->authenticate($token)
->setOrder($order)
->setAmount(100);
if ($subscription) {
$paymentService->subscribe();
}
$paymentService->connect()
->charge();