{
    "slug": "magic_methods",
    "term": "Magic Methods (__get, __set, __call…)",
    "category": "php",
    "difficulty": "intermediate",
    "short": "Special PHP methods invoked automatically in response to language events — property access, method calls, serialisation, and more.",
    "long": "PHP magic methods include __construct/__destruct (lifecycle), __get/__set/__isset/__unset (property overloading), __call/__callStatic (method overloading), __toString (string casting), __invoke (callable objects), __clone (copy construction), and __wakeup/__sleep/__serialize/__unserialize (serialisation). Magic methods can dramatically simplify APIs but also hide bugs, complicate static analysis, and create security risks — __toString XSS, __wakeup object injection. Use them intentionally and document their behaviour clearly.",
    "aliases": [
        "PHP magic methods",
        "__construct __destruct",
        "__get __set __call"
    ],
    "tags": [
        "php",
        "oop",
        "metaprogramming"
    ],
    "misconception": "Magic methods like __get and __set are a good way to add flexible property access. Overusing magic methods makes classes opaque to static analysis tools, IDEs, and other developers — explicit properties with proper types are preferable except in specific cases like proxies and ORMs.",
    "why_it_matters": "PHP magic methods are implicitly called by the runtime for specific operations — misusing them creates hidden behaviour that violates the principle of least astonishment and is hard to debug.",
    "common_mistakes": [
        "__get() and __set() that silently create properties instead of throwing on undefined access — masks typos.",
        "__toString() that throws an exception — PHP does not allow exceptions from __toString() prior to PHP 8.",
        "__clone() not deep-copying nested objects — the cloned object shares references with the original.",
        "Heavy logic in __construct() — makes the class hard to instantiate in tests and violates single responsibility."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "serialize_function",
        "insecure_deserialization"
    ],
    "prerequisites": [
        "type_declarations",
        "interfaces",
        "reflection_api"
    ],
    "refs": [
        "https://www.php.net/manual/en/language.oop5.magic.php"
    ],
    "bad_code": "// __get silently swallows undefined property access:\nclass Config {\n    public function __get(string $key): mixed {\n        return $this->data[$key] ?? null; // Returns null for any typo — no error\n    }\n}\n$config->databse_host; // Typo — silently returns null instead of error",
    "good_code": "class Collection {\n    private array $items = [];\n\n    public function __construct(array $items = []) {\n        $this->items = $items;\n    }\n\n    // Called when accessing inaccessible/undefined property\n    public function __get(string $name): mixed {\n        return $this->items[$name] ?? null;\n    }\n\n    // Called when setting inaccessible/undefined property\n    public function __set(string $name, mixed $value): void {\n        $this->items[$name] = $value;\n    }\n\n    // Called by echo / string cast\n    public function __toString(): string {\n        return implode(', ', $this->items);\n    }\n\n    // Called by var_dump — PHP 8.2+\n    public function __debugInfo(): array {\n        return ['count' => count($this->items)];\n    }\n\n    // Called when object used as function\n    public function __invoke(mixed $item): static {\n        return new static([...$this->items, $item]);\n    }\n}",
    "quick_fix": "Add return types and parameter types to magic methods (__get, __set, __call); avoid __get/__set — they hide properties from static analysis tools",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/magic_methods",
        "html_url": "https://codeclaritylab.com/glossary/magic_methods",
        "json_url": "https://codeclaritylab.com/glossary/magic_methods.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Magic Methods (__get, __set, __call…)](https://codeclaritylab.com/glossary/magic_methods) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/magic_methods"
            }
        }
    }
}