{
    "slug": "nullsafe_operator",
    "term": "Nullsafe Operator (?->)",
    "category": "php",
    "difficulty": "beginner",
    "short": "Chains method calls and property accesses on potentially-null objects without nested null checks; returns null on the first null encounter.",
    "long": "Introduced in PHP 8.0, the nullsafe operator ?-> short-circuits a method/property chain when it encounters null, returning null rather than throwing an Error. This eliminates deeply nested isset() / !== null guards for fluent interfaces. For example, $user?->getProfile()?->getAvatar()?->getUrl() returns null if any step is null. It is not a substitute for proper null handling in all cases — side-effect-producing methods in a chain may not execute if a preceding step returns null.",
    "aliases": [
        "nullsafe operator",
        "?-> operator",
        "PHP 8 nullsafe chain"
    ],
    "tags": [
        "php8",
        "php",
        "null-safety",
        "syntax"
    ],
    "misconception": "The nullsafe operator ?-> is the same as checking with isset() first. isset() checks for null and undefined; ?-> short-circuits the chain and returns null on the first null encountered. They are not equivalent for complex chains and ?-> is significantly more readable.",
    "why_it_matters": "?-> returns null instead of throwing an error when called on null — it makes optional relationship traversal safe without wrapping every step in an if-null check.",
    "common_mistakes": [
        "Using ?-> on objects that should never be null — hides bugs that should throw.",
        "Expecting ?-> to short-circuit side effects in method arguments — arguments are evaluated before the null check.",
        "Not using it consistently — mixing isset() checks and ?-> in the same codebase for the same pattern.",
        "Using it with property access but forgetting it works for method calls too — both are supported."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "null_coalescing",
        "match_expression"
    ],
    "prerequisites": [
        "null_coalescing",
        "nullable_types",
        "defensive_programming"
    ],
    "refs": [
        "https://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.nullsafe"
    ],
    "bad_code": "// Without nullsafe — verbose:\n$country = null;\nif ($user !== null) {\n    $profile = $user->getProfile();\n    if ($profile !== null) $country = $profile->getCountry();\n}\n\n// With nullsafe operator:\n$country = $user?->getProfile()?->getCountry();",
    "good_code": "// Before PHP 8.0 — tedious null guards\n$city = null;\nif ($user !== null) {\n    $address = $user->getAddress();\n    if ($address !== null) {\n        $city = $address->getCity();\n    }\n}\n\n// PHP 8.0+ nullsafe operator — short-circuits on null\n$city = $user?->getAddress()?->getCity();\n\n// Works with method chains and property access\n$countryCode = $order?->getCustomer()?->getAddress()?->getCountry()?->getIsoCode();",
    "quick_fix": "Use $user?->getAddress()?->getCity() instead of $user !== null ? $user->getAddress() : null — the nullsafe operator short-circuits the entire chain on the first null",
    "severity": "low",
    "effort": "low",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/nullsafe_operator",
        "html_url": "https://codeclaritylab.com/glossary/nullsafe_operator",
        "json_url": "https://codeclaritylab.com/glossary/nullsafe_operator.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": "[Nullsafe Operator (?->)](https://codeclaritylab.com/glossary/nullsafe_operator) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/nullsafe_operator"
            }
        }
    }
}