PHP 高级技巧:7 个实用但鲜为人知的功能

在人类语言中,并非所有词汇都同样常用,但它们都有其存在的意义和独特力量。编程语言也是如此。我们编写的大部分代码都只是变量、函数、类和循环。这些是完成应用程序所需的基础知识。今天,我不打算讨论这些基础内容,而是想分享一些我虽然不常用但非常有用的 PHP 技巧。

匿名函数和类

有时在代码中,你需要提供一个回调函数(例如在 usort 中)。与其定义一个全局函数,不如动态创建一个匿名函数,使用一两次后就丢弃(如果需要的话)。这样还能省去命名的麻烦(毕竟命名是件重要的事)。

下面的例子展示了一个匿名函数作为回调,帮助按年龄对人进行排序:

php
$list = [
    ['name' => 'John', 'age' => 31],
    ['name' => 'Mike', 'age' => 25],
    ['name' => 'Ben', 'age' => 27]
];

usort($list, function($a, $b) {
    if ($a['age'] == $b['age']) {
        return 0;
    }
    return ($a['age'] < $b['age']) ? -1 : 1;
});

你还可以将函数动态创建并保存到变量中,然后调用它,最后销毁它:

php
$sqrt = function($a) {
    return $a * $a;
};
echo $sqrt(2);
unset($sqrt);

PHP 7 还增加了对匿名类的支持,这为开发带来了更多可能性。

自动加载类

在使用 PHP 进行面向对象编程时,最佳实践是为每个类创建一个单独的文件。这样做的好处是类更易于开发和维护,而且应用程序可以只加载完成请求所需的类。这可以通过注册一个自动加载函数来实现,该函数会在需要时包含类文件。

与其这样写:

php
include "some/dir/Class1.php"
include "some/dir/Class2.php"
include "some/dir/Class3.php"

不如这样写:

php
spl_autoload_register(function ($class) {
    include "some/dir/" . $class . ".php";
});

然后下面的代码就能正常工作了:

php
$object1 = new Class1();
$object2 = new Class2();
// Class3 不会被加载,因为不需要

将错误转换为异常

在 PHP 7 之前,错误报告机制有些混乱。PHP 7 在这方面做了一些改进。将错误转换为异常这个技巧多年来一直很实用,我想分享给你。只需要几行代码,就能改善错误处理方式:

php
set_error_handler(function($errorNumber, $errorMessage, $errorFile, $errorLine) {
    throw new \ErrorException($errorMessage, 0, $errorNumber, $errorFile, $errorLine);
});

现在你只需要关注异常捕获,这比抑制错误、注册自定义处理程序和处理不同的错误处理配置要简单得多。例如:

php
try {
    echo 5 / 0;
} catch (Exception $e) {
    print_r($e);
}

魔术方法

面向对象编程现在非常流行,而 PHP 提供了一些强大的工具来提升面向对象的能力。魔术方法允许你调整对类方法或属性的调用,并在特定操作发生时更新对象状态。

假设你需要创建以下类:

php
class Person
{
    public $age = null;
    public $eyesColor = null;
    public $hairColor = null;
}

你可以提供 __construct 魔术方法来设置对象的默认值:

php
class Person
{
    public $age = null;
    public $eyesColor = null;
    public $hairColor = null;
    
    function __construct(){
        $this->age = 20;
        $this->eyesColor = 'blue';
        $this->hairColor = 'brown';
    }
}

你还可以使用 __set 验证属性,使用 __get 获取属性:

php
class Person
{
    private $data = [];
    public $eyesColor = null;
    public $hairColor = null;
    
    function __set($name, $value)
    {
        if ($name === 'age') {
            if (is_int($value) && $value >= 18) {
                $this->data[$name] = $value;
            } else {
                throw new InvalidArgumentException('年龄无效。必须年满18岁。');
            }
        }
    }
    
    function __get($name)
    {
        return $this->data[$name] ?? null;
    }
    
    function __isset($name)
    {
        return isset($this->data[$name]);
    }
    
    function __unset($name)
    {
        unset($this->data[$name]);
    }
}

你可以在 php.net 查看完整的魔术方法列表。

Xdebug 调试工具

在处理大型应用程序时,调试和分析是必不可少的。多年来,Xdebug 工具一直以出色的表现完成这些任务。使用 Xdebug,你可以轻松找到代码中的性能瓶颈并进行优化。访问 xdebug.org 获取更多信息。

register_shutdown_function() 函数

顾名思义,这个函数注册一个在请求执行即将结束时调用的函数。我经常用它来检查致命错误并输出友好的错误信息。

php
register_shutdown_function(function() {
    $errorData = error_get_last();
    if (is_array($errorData)) {
        ob_end_clean();
        echo '发生错误! - ' . $errorData['message'];
    }
});

另一个很好的用途是记录日志:

php
register_shutdown_function(function() {
    // 记录请求结束时间、内存使用情况等
    $log = sprintf(
        "[%s] 内存使用: %s MB\n",
        date('Y-m-d H:i:s'),
        memory_get_peak_usage() / 1024 / 1024
    );
    file_put_contents('shutdown_log.txt', $log, FILE_APPEND);
});

命令行脚本

PHP 主要以其作为流行的服务器端语言而闻名,用于驱动网页。但它不仅仅适用于网页。你可以编写有用的脚本和程序,从命令行调用它们。例如:

bash
php hello-world.php -name John

这是程序的代码。变量 $argv 包含所有传递的参数。索引 0 是文件名。

php
if (isset($argv[1]) && $argv[1] === '-help') {
    echo '请输入 -name <你的名字> 让我能正确问候你。';
    exit();
}

if (isset($argv[1], $argv[2]) && $argv[1] === '-name') {
    echo '你好,' . $argv[2];
    exit();
}

echo '命令无效。输入 -help 获取帮助。';
exit();

结语

希望这些技巧对你有所帮助!PHP 作为一门成熟的语言,提供了许多强大的功能,合理利用这些功能可以显著提高开发效率和代码质量。

CatchAdmin
后端开发工程师,前端入门选手,略知相关服务器知识,偏爱❤️ Laravel & Vue
本作品采用《CC 协议》,转载必须注明作者和本文链接