skip to content

In PHP, what are magic constants such as __DIR__, __CLASS__ and __METHOD__, and how do they differ from ordinary constants?

level: juniorimportance: should knowfreq 48%

answer

  1. filled in by the compiler from position
  2. case-insensitive, invisible to defined()
  3. empty string outside their context
  4. __CLASS__ in a trait gives the using class
  5. __FUNCTION__ closure names changed in 8.4

basics

~20 s

Magic constants are compiler keywords replaced with facts about where they are written: file, directory, line, function, class, trait, method, namespace or property. They vary by location, are case-insensitive and are invisible to defined() and constant().

solid answer

~40 s

Magic constants such as `__FILE__`, `__DIR__`, `__LINE__`, `__FUNCTION__`, `__CLASS__`, `__TRAIT__`, `__METHOD__`, `__NAMESPACE__` and, since PHP 8.4, `__PROPERTY__` are **keywords the compiler replaces** with information about their own position in the source. So their value differs from line to line and file to file, which is why the manual says they are not real constants. They are case-insensitive, `defined()` and `constant()` do not recognise them, and outside their context (for example `__CLASS__` outside a class) they become an empty string. The details interviewers probe: `__DIR__` equals `dirname(__FILE__)` with no trailing slash; `__METHOD__` gives `Class::method` while `__FUNCTION__` gives just the method name; inside a trait `__CLASS__` is the class using the trait; and since 8.4 a closure's `__FUNCTION__` names its file and line instead of `{closure}`.

code

php · 21 lines
php
<?php
namespace App\Payroll;

trait LogsCalls
{
    public function trace(): void
    {
        echo __CLASS__, ' | ', __TRAIT__, ' | ', __METHOD__, ' | ', __FUNCTION__, PHP_EOL;
    }
}

final class PayslipService
{
    use LogsCalls;
}

(new PayslipService())->trace();
// App\Payroll\PayslipService | App\Payroll\LogsCalls | App\Payroll\LogsCalls::trace | trace

echo __NAMESPACE__, PHP_EOL;  // App\Payroll
var_dump(\defined('__LINE__')); // bool(false)

go deeper

for a junior

Recall the common magic constants and their values: FILE, DIR, LINE, FUNCTION, CLASS, METHOD and NAMESPACE.

for a middle

Explain that the compiler substitutes each value from the definition site, and walk through the trait case and the FUNCTION versus METHOD difference.

for a senior

Point out where definition-site values mislead in production, such as CLASS versus static::class in inherited code, and log formats relying on the pre-8.4 {closure} name.

for a principal

Weigh magic-constant-based diagnostics against structured context from backtraces or logging processors when designing how a codebase records where events originate.

## What makes a constant "magic" An ordinary PHP constant, such as `PHP_EOL` or a `const API_VERSION = 'v2';` you declare, has one value for the whole request. A **magic constant** is a keyword that the compiler replaces with a fact about **where it is written**: the file, the line, or the function, class, trait, namespace or property hook that encloses it. The PHP manual itself notes that they "aren't actually constants", because the same spelling has a different value in every place it appears. Because the value is determined by position, almost always while the file is compiled (the exception is `__CLASS__` inside a trait, which the engine looks up when the method runs), a magic constant always describes the *definition site*, never the caller. ## The full set | Magic constant | Value | |---|---| | `__LINE__` | the line number where it is written | | `__FILE__` | full path of the file, symlinks resolved | | `__DIR__` | directory of the file, same as `dirname(__FILE__)`, no trailing slash unless it is the root | | `__FUNCTION__` | function name including namespace; inside a method, just the method name | | `__CLASS__` | class name including namespace; inside a trait, the class that uses the trait | | `__TRAIT__` | trait name including namespace | | `__METHOD__` | `Class::method`; inside a trait, the trait name replaces the class name | | `__NAMESPACE__` | the current namespace, empty in the global namespace | | `__PROPERTY__` | the property name, inside a property hook (PHP 8.4+) | `ClassName::class` looks similar and is also resolved by the compiler, but it is a class-name resolution feature rather than one of the magic constants in this table. ## How they differ from ordinary constants 1. **Value depends on location.** `__LINE__` on line 10 and line 20 of the same file are different values. 2. **Case-insensitive.** `__dir__` works, whereas user constants are case-sensitive. 3. **Invisible to the constant functions.** `defined('__LINE__')` returns `false`, and a `define('__FOO__', ...)` you write does not change any magic constant. The manual warns against defining double-underscore names at all, since PHP may add magic ones later. 4. **Empty outside their context.** `__CLASS__`, `__FUNCTION__`, `__METHOD__` and `__TRAIT__` at the top level of a file become `""`, not an error. ## Traits, methods and closures The combinations interviewers like to ask about: - In a trait method used by class `App\Payroll\PayslipService`, `__CLASS__` gives `App\Payroll\PayslipService`, while `__TRAIT__` gives the trait's name and `__METHOD__` gives `Trait::method`. Magic constants are resolved against the trait's code, with `__CLASS__` as the one special case. - `__CLASS__` is where the code is **written**; to get the class a method was **called on** in an inheritance chain, use `static::class`. - Inside an anonymous function, `__FUNCTION__` used to be the literal `{closure}`. Since **PHP 8.4** the engine names closures after their definition site, for example `{closure:/app/src/payroll.php:12}` at file level, or `{closure:App\Payroll\Calculator::net():12}` inside a method. Log parsers matching the old `{closure}` string need updating. ## Everyday uses - **Logging and diagnostics**: `__METHOD__` and `__LINE__` in a log context tell you where a message came from without hard-coding names that go stale on refactor. - **Paths relative to the current file**: `__DIR__` gives a stable base directory regardless of the working directory the script was started from. How include paths are resolved is its own topic; the point here is that `__DIR__` is fixed per file. - **Namespace-aware dynamic names**: `__NAMESPACE__ . '\\TAX_RATE'` builds a fully qualified constant name to pass to `constant()` or `defined()`. ## Where the "definition site" is not obvious A few places make people unsure which location a magic constant describes: - **Inherited methods**: a method declared in `AbstractPayrollJob` and called on `MonthlyPayrollJob` still reports `AbstractPayrollJob` through `__CLASS__` and `__METHOD__`, because that is the code the constant sits in. - **`eval()`'d code**: `__DIR__` inside a string passed to `eval()` gives the directory of the file that called `eval()`, since the evaluated code has no file of its own. - **Included files**: each file has its own `__FILE__`, `__DIR__` and `__LINE__`; including a file does not make it inherit the includer's values. ## Common confusions - Magic constants are **not** resolved at the call site: a helper function that logs `__FILE__` always logs the helper's file, not the caller's. For the caller, look at a backtrace instead. - `__FUNCTION__` inside a method is only the method name; people expecting `Class::method` want `__METHOD__`.

  • Inside a trait method, what do __CLASS__ and __METHOD__ return?
    `__CLASS__` returns the name of the class that uses the trait, which is the one special case. `__METHOD__` is resolved against the trait's own code, so it returns `TraitName::method`, and `__TRAIT__` returns the trait name. So a log line built from `__METHOD__` inside a trait names the trait, not the class.
  • How did the value of __FUNCTION__ inside a closure change in PHP 8.4?
    Before 8.4 every anonymous function reported the literal `{closure}`. Since 8.4 the engine generates a name from the definition site, such as `{closure:/app/src/payroll.php:12}`, or `{closure:App\Payroll\Calculator::net():12}` when the closure is written inside a method. Stack traces and log lines become easier to trace, but code that compared against `{closure}` breaks.
  • Why does defined('__DIR__') return false?
    Magic constants are not registered in the constant table at all; the compiler substitutes their value where they are written. `defined()` and `constant()` only look in that table, so they do not see `__DIR__`, `__LINE__` or the others.

A magic constant is like a postmark: it is stamped with the place the letter was posted, and it keeps saying that place no matter who later reads it or where it is carried.

saying these in an interview costs you the question

  • Says __CLASS__ inside a parent method returns the child class it was called on.
  • Believes __FILE__ in a helper function reports the file of the caller.
  • Thinks magic constants are case-sensitive like user-defined constants.
  • Claims __FUNCTION__ inside a method returns Class::method.
  • Says defined('__LINE__') returns true because __LINE__ is always available.