PHP and Object-Oriented Programming

PHP Beyond the Basics

The language features that make Laravel possible

12 min read · Lesson 7 of 18

PHP Is Better Than You Think

PHP has a bad reputation from its early days of spaghetti code and inconsistent function naming. Modern PHP (8.x) is a genuinely powerful language. Laravel leverages these features extensively, and understanding them makes the framework's "magic" comprehensible.


Type Declarations

PHP 7+ introduced scalar type declarations. PHP 8 added union types and named arguments. Use them:

function calculateDiscount(float $price, int $percentage = 10): float
{
    return $price * ($percentage / 100);
}

// Union types (PHP 8.0)
function findUser(int|string $identifier): ?User
{
    return is_int($identifier)
        ? User::find($identifier)
        : User::where('email', $identifier)->first();
}

// Intersection types (PHP 8.1)
function processCollection(Countable&Iterator $items): void
{
    // $items must implement BOTH interfaces
}

Type declarations catch bugs at runtime and serve as documentation. Laravel's codebase uses them extensively.


Closures and Arrow Functions

A closure is an anonymous function that can capture variables from its surrounding scope:

$multiplier = 3;
$multiply = function ($n) use ($multiplier) {
    return $n * $multiplier;
};
echo $multiply(5); // 15

Arrow functions (PHP 7.4+) are shorter and automatically capture variables:

$multiply = fn ($n) => $n * $multiplier; // No 'use' needed

You use closures constantly in Laravel — collection methods, route definitions, middleware, event listeners, and query scopes all accept closures.


Array Functions That Replace Loops

Stop writing foreach loops for everything. PHP's array functions (and Laravel Collections) are more expressive:

// Filter: keep only active users
$active = array_filter($users, fn ($u) => $u->is_active);

// Map: transform each element
$names = array_map(fn ($u) => $u->name, $users);

// Reduce: accumulate a single value
$total = array_reduce($orders, fn ($sum, $o) => $sum + $o->total, 0);

// Laravel Collection equivalents (more readable):
$active = $users->filter(fn ($u) => $u->is_active);
$names = $users->pluck('name');
$total = $orders->sum('total');

Null Coalescing and Safe Navigation

// Null coalescing operator (??) — use instead of isset() checks
$name = $user->name ?? 'Anonymous';

// Null coalescing assignment (??=)
$config['timeout'] ??= 30; // Only sets if null

// Nullsafe operator (?->) — PHP 8.0
$city = $user?->address?->city; // Returns null if any step is null

PHP 8.x Features Worth Using

  • Named argumentsarray_slice(array: $arr, length: 3). Especially useful with functions that have many optional parameters.
  • Match expressions — A stricter, expression-based switch that uses strict comparison and returns a value.
  • Enums (8.1) — Type-safe enumerations. Use them for status fields, types, and categories.
  • Readonly properties (8.1) — public readonly string $name. Set once in the constructor, immutable afterward.
  • Fibers (8.1) — Cooperative concurrency. Laravel uses these internally for some async operations.

Key Takeaways

  • Use type declarations everywhere — they catch bugs and document your code.
  • Closures and arrow functions are the backbone of Laravel's fluent API. Know the difference between function () use ($var) and fn () => $var.
  • Prefer array functions and Collections over raw foreach loops.
  • The nullsafe operator (?->) and null coalescing (??) eliminate entire categories of null-check boilerplate.
Ask about this lesson