首页 > 解决方案 > phpredis 会话锁定 -- 未能获得锁定会引发 php 通知 -- 会出现致命错误

问题描述

当使用php redis作为具有会话锁定的会话处理程序时,如果出现无法发生锁定的错误,则会引发 php 通知并且脚本继续。有没有办法为致命错误配置它并且脚本根本不处理?

标签: phpphpredis

解决方案


确保您遵循此文档声明:

锁定功能目前仅支持具有 单个主实例的 Redis 设置

如果您仍然有一些问题,那么可以使用set_error_handler设置您自己的错误处理程序来快速修复整个应用程序,以解决该特定问题。下面的示例处理程序仅对使用未声明的变量作出反应。更改正则表达式模式,使其与您的 Redis 错误消息匹配。

<?php

error_reporting(E_ALL);

$redisNoticeFunction = function($errno, $errstr, $errfile, $errline, array $errcontext) {

    // is the error E_NOTICE?
    if ($errno === \E_NOTICE) {
            
        // if error was suppressed with the @-operator
        if (0 === \error_reporting()) {
            // do nothing, continue execution of script
            return;
        }
        
        // check if notice is about Redis
        $pattern = '/.*Undefined variable.*/'; // <== change pattern so it matches notice about Redis
        $subject = $errstr;
        $status = \preg_match($pattern, $subject);
        
        // if there was a problem with regex
        if (false === $status) {
            $msg = 'Could not perform preg_math with pattern: ' . $pattern . ' and subject: ' . $subject . \PHP_EOL;
            // exit by throwing an exception
            throw new \InvalidArgumentException($msg);
        }

        // if notice was about about Redis
        if ($status) {
            $error_msg = 'Redis locking problem with notice msg: ' . $errstr;
            $error_msg .= ' at ' . $errfile . ':' . $errline . \PHP_EOL;
            
            // signal fatal error
            $error_type = \E_USER_ERROR;
            \trigger_error ($error_msg, $error_type);
            
            // or throw exception (comment above line with \trigger_error())
            throw new \RuntimeException($error_msg);
        }

        // the notice was not related to the Redis
        // echo its message and continue script
        echo $errstr . \PHP_EOL;
        return;
    }

    // the error was not the E_NOTICE
    // do other error handling if needed

    // or just end the script
    die;

};

set_error_handler($redisNoticeFunction);    

echo @ $notDeclared; // does not end script

echo $notDeclared; // end script or throws an exception

最后一行

echo $notDeclared; // end script or throws an exception

以信息结束脚本:

致命错误:带有通知消息的 Redis 锁定问题:未定义变量:未在 /tmp/index.php:59 声明

set_error_handler应该在你的 php 脚本的开头使用(完全在一个公共文件中,就像 bootstrap.php 一样)

使用自己的错误处理程序的缺点是,如果您使用框架或其他包装代码,它可能已经设置了自己的错误处理程序,该错误处理程序提供了一些有用的功能,例如调试,或者甚至可能该错误处理程序对于该框架错误处理、日志记录至关重要等等

如果您希望恢复到原始错误处理程序(PHP 的默认值或您自己之前设置的错误处理程序),请使用restore_error_handler


推荐阅读