| name | php |
| description | Language-specific super-code guidelines for php. |
| risk | safe |
| source | community |
| date_added | 2026-06-16 |
PHP: Idiomatic Efficiency Reference
Table of Contents
- Arrays & Collections
- Type Safety
- Error Handling
- String Handling
- OOP & Modern PHP
- Functions & Closures
- Anti-patterns specific to PHP
1. Arrays & Collections {#arrays}
$result = [];
foreach ($items as $item) {
if ($item->isActive()) {
$result[] = strtoupper($item->getName());
}
}
$result = array_map(
fn($i) => strtoupper($i->getName()),
array_filter($items, fn($i) => $i->isActive())
);
$grouped = [];
foreach ($items as $item) {
$grouped[$item->getCategory()][] = $item;
}
if (isset($data['key'])) {
$value = $data['key'];
} else {
$value = 'default';
}
$value = $data['key'] ?? 'default';
array_push($items, $newItem);
$items[] = $newItem;
Use array_map/array_filter for transforms. The foreach loop is fine when array functions would be less readable.
2. Type Safety {#types}
function process($items) {
return $items;
}
function process(array $items): array {
return $items;
}
function find(string $key): string|null { ... }
function find(string $key): ?string { ... }
if ($value == '0') { ... }
if ($value === '0') { ... }
if (gettype($x) === 'integer') { ... }
if (is_int($x)) { ... }
Enable declare(strict_types=1) at the top of every file.
3. Error Handling {#errors}
$data = @file_get_contents($path);
$data = file_get_contents($path);
if ($data === false) {
throw new RuntimeException("Failed to read: $path");
}
try { process(); }
catch (\Exception $e) { }
try {
process();
} catch (SpecificException $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
throw new AppException('Processing failed', previous: $e);
}
function divide(int $a, int $b): int|false {
if ($b === 0) return false;
return intdiv($a, $b);
}
function divide(int $a, int $b): int {
if ($b === 0) throw new \DivisionByZeroError();
return intdiv($a, $b);
}
4. String Handling {#strings}
$msg = 'Hello, ' . $name . '! You have ' . $count . ' messages.';
$msg = "Hello, {$name}! You have {$count} messages.";
if (strpos($haystack, $needle) !== false) { ... }
if (str_contains($haystack, $needle)) { ... }
if (substr($str, 0, 4) === 'http') { ... }
if (substr($str, -4) === '.php') { ... }
if (str_starts_with($str, 'http')) { ... }
if (str_ends_with($str, '.php')) { ... }
5. OOP & Modern PHP {#oop}
class User {
private string $name;
private int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
class User {
public function __construct(
private readonly string $name,
private readonly int $age,
) {}
}
class Status {
const ACTIVE = 'active';
const INACTIVE = 'inactive';
}
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
}
if ($shape instanceof Circle) { ... }
elseif ($shape instanceof Rectangle) { ... }
$area = match(true) {
$shape instanceof Circle => $shape->radius ** 2 * M_PI,
$shape instanceof Rectangle => $shape->width * $shape->height,
default => throw new \InvalidArgumentException("Unknown shape"),
};
class Money {
public static function fromCents(int $cents): self {
$m = new self();
$m->cents = $cents;
return $m;
}
}
class Money {
public function __construct(
public readonly int $cents,
) {}
}
$m = new Money(cents: 500);
6. Functions & Closures {#functions}
$doubled = array_map(function ($x) { return $x * 2; }, $numbers);
$doubled = array_map(fn($x) => $x * 2, $numbers);
global $db;
function getUser(int $id) {
global $db;
return $db->find($id);
}
function getUser(int $id, PDO $db): ?User {
return $db->find($id);
}
str_pad(string: $s, length: 10, pad_string: ' ', pad_type: STR_PAD_LEFT);
str_pad($s, 10, ' ', STR_PAD_LEFT);
7. Anti-patterns specific to PHP {#antipatterns}
| Anti-pattern | Preferred |
|---|
== for comparison | === (strict equality) |
@ error suppression | explicit error handling |
global keyword | dependency injection |
extract() on user input | access keys explicitly |
die() / exit() in library code | throw exception |
strpos !== false for contains | str_contains() (PHP 8.0) |
| Manual constructor assignment | constructor promotion (PHP 8.0) |
| Class constants for enums | enum (PHP 8.1) |
mixed return types | specific typed returns |
array for everything | typed classes / DTOs |
var_dump / print_r debugging | proper logging (PSR-3) |
Not using declare(strict_types=1) | always enable |
Limitations
- These are language-specific guidelines and do not cover overall architectural decisions.
- Over-compression might reduce readability; apply judgement.