PHP 魔术常量
Eight interpreter-filled constants and how to use them in debugging and logging.
The eight constants
| Constant | Value |
|---|---|
| __LINE__ | 当前行号 |
| __FILE__ | 文件的完整路径与文件名 |
| __DIR__ | 文件所在目录 |
| __FUNCTION__ | 当前函数名 |
| __CLASS__ | 当前类名(含命名空间) |
| __METHOD__ | 当前方法名(含类名) |
| __NAMESPACE__ | 当前命名空间 |
| __TRAIT__ | 当前 trait 名 |
Line and file
<?php
echo "第一行代码在第 " . __LINE__ . " 行\n";
echo "这一行在第 " . __LINE__ . " 行\n";
echo basename(__FILE__) . "\n";
echo basename(__DIR__) . "\n";第一行代码在第 2 行
这一行在第 3 行
magic.php
demoThe file is /var/www/demo/magic.php. __FILE__ yields the absolute path; basename() trims it. Logging absolute paths leaks server layout in production.
Function and class
<?php
namespace App\Demo;
function show(): void {
echo __FUNCTION__ . "\n";
echo __NAMESPACE__ . "\n";
}
class Report
{
public function run(): void {
echo __CLASS__ . "\n";
echo __METHOD__ . "\n";
}
}
show();
(new Report())->run();App\Demo\show
App\Demo
App\Demo\Report
App\Demo\Report::run__FUNCTION__ includes the namespace, __METHOD__ includes the class. For the short name use basename(str_replace('\\', '/', __CLASS__)).Practical use in logging
To log the caller's line you cannot use __LINE__ inside the function — it always points at the function body. Pass __LINE__ from the call site.
<?php
function debug(string $msg, int $line = 0): void {
printf("[%s:%d] %s\n", basename(__FILE__), $line, $msg);
}
debug("开始处理", __LINE__); // 第 6 行
$total = 0;
for ($i = 1; $i <= 3; $i++) {
$total += $i;
}
debug("合计 $total", __LINE__); // 第 12 行[magic.php:6] 开始处理
[magic.php:12] 合计 6The debug($msg, __LINE__) idiom is common in Laravel and Symfony logging wrappers. Add a __FILE__ parameter if needed — but avoid absolute paths in production logs.
__DIR__ and includes
__DIR__ locates files independently of the working directory. include "config.php" depends on include_path and CWD; include __DIR__ . "/config.php" does not.
<?php
// 反例:受工作目录影响
// include "config.php";
// 正例:始终相对本文件
$path = __DIR__ . "/config.php";
echo $path === realpath(__DIR__) . DIRECTORY_SEPARATOR . "config.php" ? "路径正确" : "路径错误", "\n";
echo basename(dirname(__DIR__)), "\n";路径正确
wwwWith the file at /var/www/demo/magic.php, dirname(__DIR__) is /var/www. PSR-4 autoloaders locate vendor/autoload.php the same way.
全部八个
| 常量 | 值 |
|---|---|
| __LINE__ | 当前行号 |
| __FILE__ | 文件的完整路径与文件名 |
| __DIR__ | 文件所在目录 |
| __FUNCTION__ | 当前函数名 |
| __CLASS__ | 当前类名(含命名空间) |
| __METHOD__ | 当前方法名(含类名) |
| __NAMESPACE__ | 当前命名空间 |
| __TRAIT__ | 当前 trait 名 |
行号与文件
<?php
echo "第一行代码在第 " . __LINE__ . " 行\n";
echo "这一行在第 " . __LINE__ . " 行\n";
echo basename(__FILE__) . "\n";
echo basename(__DIR__) . "\n";第一行代码在第 2 行
这一行在第 3 行
magic.php
demo上面这段代码保存为 /var/www/demo/magic.php。__FILE__ 给绝对路径,basename() 取文件名——日志里打绝对路径会泄露服务器目录结构,线上要小心。
函数与类
<?php
namespace App\Demo;
function show(): void {
echo __FUNCTION__ . "\n";
echo __NAMESPACE__ . "\n";
}
class Report
{
public function run(): void {
echo __CLASS__ . "\n";
echo __METHOD__ . "\n";
}
}
show();
(new Report())->run();App\Demo\show
App\Demo
App\Demo\Report
App\Demo\Report::run__FUNCTION__ 在函数内包含命名空间,__METHOD__ 包含类名。要拿不带命名空间的短名,用 basename(str_replace('\\', '/', __CLASS__))。调试与日志里的实际用法
想在日志里打「这一行」的行号,不能靠函数内部的 __LINE__(那永远是函数体那一行),得在调用处把 __LINE__ 当参数传进去。
<?php
function debug(string $msg, int $line = 0): void {
printf("[%s:%d] %s\n", basename(__FILE__), $line, $msg);
}
debug("开始处理", __LINE__); // 第 6 行
$total = 0;
for ($i = 1; $i <= 3; $i++) {
$total += $i;
}
debug("合计 $total", __LINE__); // 第 12 行[magic.php:6] 开始处理
[magic.php:12] 合计 6这个 debug($msg, __LINE__) 的写法在 Laravel、Symfony 的日志封装里很常见。要连文件名一起传,就再补一个 __FILE__ 参数;但线上日志别打绝对路径。
__DIR__ 与文件包含
__DIR__ 最大的价值是不依赖当前工作目录地定位文件。include "config.php" 受 include_path 和 CWD 影响,include __DIR__ . "/config.php" 则永远指向同目录。
<?php
// 反例:受工作目录影响
// include "config.php";
// 正例:始终相对本文件
$path = __DIR__ . "/config.php";
echo $path === realpath(__DIR__) . DIRECTORY_SEPARATOR . "config.php" ? "路径正确" : "路径错误", "\n";
echo basename(dirname(__DIR__)), "\n";路径正确
www上面假设文件在 /var/www/demo/magic.php,所以 dirname(__DIR__) 是 /var/www,取 basename 得 www。这也是 PSR-4 自动加载器定位 vendor/autoload.php 的常见写法。