PHP: Idiomatic Efficiency Reference

← Back to skills

1. [Arrays & Collections](#arrays) 2. [Type Safety](#types) 3. [Error Handling](#errors) 4. [String Handling](#strings) 5. [OOP & Modern PHP](#oop) 6. [Functions & Closures](#functions) 7. [Anti-patterns specific to PHP](#antipatterns)

Category: General & Miscellaneous
Repo: antigravity-awesome-skills
Path: skills/super-code/php/SKILL.md
Updated: 6/18/2026, 7:42:54 AM

AI Summary

1. [Arrays & Collections](#arrays) 2. [Type Safety](#types) 3. [Error Handling](#errors) 4. [String Handling](#strings) 5. [OOP & Modern PHP](#oop) 6. [Functions & Closures](#functions) 7. [Anti-patterns specific to PHP](#antipatterns). It is useful for general automation, multi-purpose workflows, cross-disciplinary tasks, and utility skills. Source: antigravity-awesome-skills (skills/super-code/php/SKILL.md).

PHP: Idiomatic Efficiency Reference

Table of Contents

  1. Arrays & Collections
  2. Type Safety
  3. Error Handling
  4. String Handling
  5. OOP & Modern PHP
  6. Functions & Closures
  7. Anti-patterns specific to PHP

1. Arrays & Collections {#arrays}

// ❌ Manual accumulation
$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())
);
// ❌ Manual key-value grouping
$grouped = [];
foreach ($items as $item) {
    $grouped[$item->getCategory()][] = $item;
}

// ✅ (PHP 8.1+) — or use the loop above; PHP lacks a built-in groupBy
// The foreach is actually idiomatic PHP for grouping. No need to force array_* here.
// ❌ Checking isset then accessing
if (isset($data['key'])) {
    $value = $data['key'];
} else {
    $value = 'default';
}

// ✅
$value = $data['key'] ?? 'default';
// ❌ array_push for single element
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}

// ❌ No type declarations
function process($items) {
    return $items;
}

// ✅ (PHP 8.0+)
function process(array $items): array {
    return $items;
}
// ❌ Union type for nullable
function find(string $key): string|null { ... }

// ✅
function find(string $key): ?string { ... }
// ❌ Loose comparison
if ($value == '0') { ... } // true for 0, '', false, null

// ✅
if ($value === '0') { ... }
// ❌ Type checking with gettype()
if (gettype($x) === 'integer') { ... }

// ✅
if (is_int($x)) { ... }
// or with union types, avoid checks entirely

Enable declare(strict_types=1) at the top of every file.


3. Error Handling {#errors}

// ❌ Suppressing errors with @
$data = @file_get_contents($path);

// ✅
$data = file_get_contents($path);
if ($data === false) {
    throw new RuntimeException("Failed to read: $path");
}
// ❌ Catching \Exception and swallowing
try { process(); }
catch (\Exception $e) { /* silence */ }

// ✅
try {
    process();
} catch (SpecificException $e) {
    $this->logger->error($e->getMessage(), ['exception' => $e]);
    throw new AppException('Processing failed', previous: $e);
}
// ❌ Returning mixed types for error indication
function divide(int $a, int $b): int|false {
    if ($b === 0) return false;
    return intdiv($a, $b);
}

// ✅ — throw exception for exceptional cases
function divide(int $a, int $b): int {
    if ($b === 0) throw new \DivisionByZeroError();
    return intdiv($a, $b);
}

4. String Handling {#strings}

// ❌ Concatenation for variable interpolation
$msg = 'Hello, ' . $name . '! You have ' . $count . ' messages.';

// ✅
$msg = "Hello, {$name}! You have {$count} messages.";
// ❌ Manual string contains check
if (strpos($haystack, $needle) !== false) { ... }

// ✅ (PHP 8.0+)
if (str_contains($haystack, $needle)) { ... }
// ❌ substr for prefix/suffix check
if (substr($str, 0, 4) === 'http') { ... }
if (substr($str, -4) === '.php') { ... }

// ✅ (PHP 8.0+)
if (str_starts_with($str, 'http')) { ... }
if (str_ends_with($str, '.php')) { ... }

5. OOP & Modern PHP {#oop}

// ❌ Manual constructor property assignment
class User {
    private string $name;
    private int $age;
    public function __construct(string $name, int $age) {
        $this->name = $name;
        $this->age = $age;
    }
}

// ✅ (PHP 8.0+)
class User {
    public function __construct(
        private readonly string $name,
        private readonly int $age,
    ) {}
}
// ❌ Constants as class properties
class Status {
    const ACTIVE = 'active';
    const INACTIVE = 'inactive';
}

// ✅ (PHP 8.1+)
enum Status: string {
    case Active = 'active';
    case Inactive = 'inactive';
}
// ❌ instanceof chains
if ($shape instanceof Circle) { ... }
elseif ($shape instanceof Rectangle) { ... }

// ✅ (PHP 8.0+)
$area = match(true) {
    $shape instanceof Circle => $shape->radius ** 2 * M_PI,
    $shape instanceof Rectangle => $shape->width * $shape->height,
    default => throw new \InvalidArgumentException("Unknown shape"),
};
// ❌ Named constructor via static method returning new self()
class Money {
    public static function fromCents(int $cents): self {
        $m = new self();
        $m->cents = $cents;
        return $m;
    }
}

// ✅ (PHP 8.0+) — constructor promotion + named arguments
class Money {
    public function __construct(
        public readonly int $cents,
    ) {}
}
$m = new Money(cents: 500);

6. Functions & Closures {#functions}

// ❌ Verbose closure for simple operation
$doubled = array_map(function ($x) { return $x * 2; }, $numbers);

// ✅ (PHP 7.4+)
$doubled = array_map(fn($x) => $x * 2, $numbers);
// ❌ Passing globals or using `global` keyword
global $db;
function getUser(int $id) {
    global $db;
    return $db->find($id);
}

// ✅ — dependency injection
function getUser(int $id, PDO $db): ?User {
    return $db->find($id);
}
// ❌ Named arguments abused for every call
str_pad(string: $s, length: 10, pad_string: ' ', pad_type: STR_PAD_LEFT);

// ✅ — named args are useful for readability on ambiguous params; don't force
str_pad($s, 10, ' ', STR_PAD_LEFT);
// but named args shine for: new User(name: 'Alice', age: 30)

7. Anti-patterns specific to PHP {#antipatterns}

Anti-patternPreferred
== for comparison=== (strict equality)
@ error suppressionexplicit error handling
global keyworddependency injection
extract() on user inputaccess keys explicitly
die() / exit() in library codethrow exception
strpos !== false for containsstr_contains() (PHP 8.0)
Manual constructor assignmentconstructor promotion (PHP 8.0)
Class constants for enumsenum (PHP 8.1)
mixed return typesspecific typed returns
array for everythingtyped classes / DTOs
var_dump / print_r debuggingproper 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.

Related skills