Menu
Coddy logo textTech

__call & __callStatic

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 47 of 91.

Just as __get() and __set() intercept property access, the __call() and __callStatic() methods intercept method calls. They're triggered when you call a method that doesn't exist or is inaccessible on an object or class.

The __call() method handles instance method calls. It receives the method name and an array of arguments:

<?php
class Messenger {
    public function __call(string $name, array $arguments): string {
        return "Called '$name' with: " . implode(", ", $arguments);
    }
}

$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");

Output:

Called 'sendEmail' with: Hello, World

For static method calls, use __callStatic(). Notice it must be declared as static:

<?php
class QueryBuilder {
    public static function __callStatic(string $name, array $arguments): string {
        if (str_starts_with($name, "findBy")) {
            $field = substr($name, 6);
            return "Finding by $field: " . $arguments[0];
        }
        return "Unknown method: $name";
    }
}

echo QueryBuilder::findByEmail("test@example.com");

Output:

Finding by Email: test@example.com

These magic methods are powerful for creating fluent APIs, implementing method forwarding, or building dynamic query builders where method names translate into database operations. They let your objects respond intelligently to any method call, even ones you haven't explicitly defined.

challenge icon

Challenge

Easy

Let's build a dynamic API client that uses magic methods to handle method calls flexibly. You'll create a class that intercepts both instance and static method calls, translating them into meaningful API-like responses without defining each method explicitly.

You'll organize your code across two files:

  • ApiClient.php — Create an ApiClient class that simulates API interactions using magic methods. Your class should have a private $baseUrl property set through the constructor. Implement two magic methods:
    • __call() — Handles instance method calls. When a method starting with get is called (like getUsers or getPosts), extract the resource name (the part after "get") and return "GET [baseUrl]/[resource]: [arguments joined by comma]". The resource name should be converted to lowercase. If the method doesn't start with "get", return "Unknown action: [methodName]".
    • __callStatic() — Handles static method calls. When a method starting with create is called (like createUser), extract the resource name and return "POST /[resource]: [arguments joined by comma]". The resource name should be lowercase. For methods starting with delete, return "DELETE /[resource]: [first argument]". For any other method, return "Static action not supported: [methodName]".
  • main.php — Include the ApiClient file. You'll receive three inputs: a base URL, a resource identifier, and a value. Create an ApiClient instance with the base URL. Then print four lines:
    • Call a dynamic get method using the resource identifier as the method name suffix (e.g., if resource is "Users", call getUsers) with the value as an argument
    • Call getProducts with two arguments: "electronics" and "active"
    • Call the static method createOrder with the value as an argument
    • Call the static method deleteItem with the resource identifier as an argument

The magic methods let your API client respond to any method call dynamically. Instead of defining getUsers(), getPosts(), getProducts(), and dozens more, a single __call() method handles them all by examining the method name and extracting the relevant information.

Cheat sheet

The __call() method intercepts instance method calls that don't exist or are inaccessible. It receives the method name and an array of arguments:

<?php
class Messenger {
    public function __call(string $name, array $arguments): string {
        return "Called '$name' with: " . implode(", ", $arguments);
    }
}

$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");
// Output: Called 'sendEmail' with: Hello, World

The __callStatic() method intercepts static method calls. It must be declared as static:

<?php
class QueryBuilder {
    public static function __callStatic(string $name, array $arguments): string {
        if (str_starts_with($name, "findBy")) {
            $field = substr($name, 6);
            return "Finding by $field: " . $arguments[0];
        }
        return "Unknown method: $name";
    }
}

echo QueryBuilder::findByEmail("test@example.com");
// Output: Finding by Email: test@example.com

These magic methods are useful for creating fluent APIs, implementing method forwarding, or building dynamic query builders where method names translate into operations.

Try it yourself

<?php

require_once 'ApiClient.php';

// Read inputs
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Create an ApiClient instance with the base URL

// TODO: Call a dynamic get method using the resource as method name suffix
// Hint: Use variable method calls like $api->{"get" . $resource}($value)

// TODO: Call getProducts with two arguments: "electronics" and "active"

// TODO: Call static method createOrder with the value as argument
// Hint: Use ApiClient::createOrder($value)

// TODO: Call static method deleteItem with the resource as argument

?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming