重新启动 CLI 进程而不加载 Xdebug 扩展,除非xdebug.mode=off
。
最初是作为作曲家/作曲家的一部分编写的,现在提取并作为独立库提供。
删除了对旧 PHP 版本的支持并添加了类型声明。
对版本 2 (PHP 5.3.2 - 7.2.4) 的长期支持遵循 Composer 2.2 LTS 政策。
安装最新版本:
$ composer require composer/xdebug-handler
use Composer XdebugHandler XdebugHandler ;
$ xdebug = new XdebugHandler ( ' myapp ' );
$ xdebug -> check ();
unset( $ xdebug );
构造函数采用单个参数$envPrefix
,该参数为大写并添加到默认基值之前,以创建两个不同的环境变量。上面的示例允许使用:
MYAPP_ALLOW_XDEBUG=1
覆盖自动重启并允许 XdebugMYAPP_ORIGINAL_INIS
用于获取重新启动的进程中的 ini 文件位置从加载(和扫描)的 ini 文件创建临时 ini 文件,并注释掉对 Xdebug 扩展名的任何引用。当前的 ini 设置被合并,以便包含在命令行或应用程序中进行的大多数 ini 设置(请参阅限制)
MYAPP_ALLOW_XDEBUG
使用内部数据进行设置,以在重新启动时进行标记和使用。MYAPP_ALLOW_XDEBUG
未设置。请参阅示例以获取更多信息。
如果加载了 pcntl 扩展,则会自动启用异步信号处理。 SIGINT
在父进程中设置为SIG_IGN
,并在重新启动的进程中恢复为SIG_DFL
(如果未设置其他处理程序)。
从 Windows 上的 PHP 7.4 开始, CTRL+C
和CTRL+BREAK
处理会在重新启动的进程中自动启用,并在父进程中被忽略。
在重新启动的进程中运行时需要注意一些事项。
这些静态方法提供当前进程的信息,无论它是否已重新启动。
返回原始 ini 文件位置的数组。使用它而不是调用php_ini_loaded_file
和php_ini_scanned_files
,这将在重新启动的进程中报告错误的值。
use Composer XdebugHandler XdebugHandler ;
$ files = XdebugHandler:: getAllIniFiles ();
# $ files [ 0 ] always exists , it could be an empty string
$ loadedIni = array_shift ( $ files );
$ scannedInis = $ files ;
这些位置也可在MYAPP_ORIGINAL_INIS
环境变量中找到。这是一个路径分隔的字符串,包含从php_ini_loaded_file
返回的位置(可以为空),后跟通过调用php_ini_scanned_files
解析的位置。
返回可与 PHP 子进程一起使用的设置数组,如果进程未重新启动,则返回 null。
use Composer XdebugHandler XdebugHandler ;
$ settings = XdebugHandler:: getRestartSettings ();
/**
* $ settings : array ( if the current process was restarted ,
* or called with the settings from a previous restart ) , or null
*
* ' tmp Ini ' = > the temporary ini file used in the restart ( string )
* ' scanned Inis ' = > if there were any scanned inis ( bool )
* ' scan Dir ' = > the original PHP _ INI _ SCAN _ DIR value ( false |string )
* ' phprc ' = > the original PHPRC value ( false |string )
* ' inis ' = > the original inis from get AllIniFiles ( array )
* ' skipped ' = > the skipped version from get SkippedVersion ( string )
*/
返回重新启动时跳过的 Xdebug 版本字符串,如果没有重新启动,则返回空字符串(或者 Xdebug 仍然加载,可能是由于扩展类由于删除 Xdebug 之外的原因重新启动)。
use Composer XdebugHandler XdebugHandler ;
$ version = XdebugHandler:: getSkippedVersion ();
# $version : ' 3.1 . 1 ' ( for example ) , or an empty string
如果 Xdebug 已加载并在活动模式下运行(如果它支持模式),则返回 true。如果 Xdebug 未加载,或者以xdebug.mode=off
运行,则返回 false。
这些方法实现了一个流畅的接口,并且必须在主check()
方法之前调用。
允许将状态消息输出到外部 PSR3 记录器。所有消息均以DEBUG
或WARNING
日志级别报告。例如(显示级别和消息):
// No restart
DEBUG Checking MYAPP_ALLOW_XDEBUG
DEBUG The Xdebug extension is loaded (3.1.1) xdebug.mode=off
DEBUG No restart (APP_ALLOW_XDEBUG=0) Allowed by xdebug.mode
// Restart overridden
DEBUG Checking MYAPP_ALLOW_XDEBUG
DEBUG The Xdebug extension is loaded (3.1.1) xdebug.mode=coverage,debug,develop
DEBUG No restart (MYAPP_ALLOW_XDEBUG=1)
// Failed restart
DEBUG Checking MYAPP_ALLOW_XDEBUG
DEBUG The Xdebug extension is loaded (3.1.0)
WARNING No restart (Unable to create temp ini file at: ...)
状态消息也可以使用XDEBUG_HANDLER_DEBUG
输出。请参阅故障排除。
设置重新启动时运行的主脚本的位置。仅在更深奥的用例中,或者argv[0]
位置不可访问时才需要这样做。标准输入支持脚本--
。
使用持久设置配置重新启动,以便 Xdebug 不会在任何子进程中加载。
如果您的应用程序调用一个或多个 PHP 子进程并且不需要 Xdebug 扩展,请使用此方法。这避免了实施特定子流程策略的开销。
或者,此方法可用于设置默认的无 Xdebug环境,如果子进程需要 Xdebug,则可以更改该环境,然后恢复:
function SubProcessWithXdebug ()
{
$ phpConfig = new Composer XdebugHandler PhpConfig ();
# Set the environment to the original configuration
$ phpConfig -> useOriginal ();
# run the process with Xdebug loaded
. . .
# Restore Xdebug - free environment
$ phpConfig -> usePersistent ();
}
该库提供了两种策略来调用新的 PHP 进程而不加载 Xdebug,使用标准或持久设置。请注意,这仅在应用程序调用 PHP 子进程时才重要。
使用命令行选项仅从新进程中删除 Xdebug。
如果新进程调用 PHP 子进程,Xdebug 将在该子进程中加载(除非它实现了 xdebug-handler,在这种情况下将再次重新启动)。
这是重启时使用的默认策略。
使用环境变量从新进程中删除 Xdebug 并将这些设置保留到任何子进程。
PHP_INI_SCAN_DIR
设置为空字符串。这告诉 PHP 不要扫描额外的 inis。PHPRC
设置为临时 ini。如果新进程调用 PHP 子进程,则 Xdebug 将不会加载到该子进程中。
该策略可以通过调用setPersistent()在重启时使用。
PhpConfig
帮助程序类可以轻松调用 PHP 子进程(加载或不加载 Xdebug),无论是否重新启动。
它的每个方法都会返回一组 PHP 选项(添加到命令行)并为所需策略设置环境。 getRestartSettings() 方法在内部使用。
useOriginal()
- Xdebug 将在新进程中加载。useStandard()
- Xdebug不会在新进程中加载 - 请参阅标准设置。userPersistent()
- Xdebug不会在新进程中加载 - 请参阅持久设置如果没有重新启动,则会返回一个空选项数组,并且环境不会更改。
use Composer XdebugHandler PhpConfig ;
$ config = new PhpConfig ;
$ options = $ config -> useOriginal ();
# $options : empty array
# environment : PHPRC and PHP _ INI _ SCAN _ DIR set to original values
$ options = $ config -> useStandard ();
# $options : [ - n , - c , tmp Ini ]
# environment : PHPRC and PHP _ INI _ SCAN _ DIR set to original values
$ options = $ config -> usePersistent ();
# $options : empty array
# environment : PHPRC = tmpIni , PHP_INI_SCAN_DIR = ''
以下环境设置可用于解决意外行为:
XDEBUG_HANDLER_DEBUG=1
将状态消息输出到STDERR
(如果已定义),无论任何 PSR3 记录器如何。每条消息都有前缀xdebug-handler[pid]
,其中 pid 是进程标识符。
XDEBUG_HANDLER_DEBUG=2
如上所述,但另外保存临时 ini 文件并在状态消息中报告其位置。
API 由类及其可访问元素定义,这些元素未注释为 @internal。主类有两个受保护的方法,可以重写它们以提供附加功能:
默认情况下,如果 Xdebug 已加载并且未使用xdebug.mode=off
运行,则进程将重新启动。扩展此方法允许应用程序通过返回布尔(或等效)值来做出决定。仅当MYAPP_ALLOW_XDEBUG
为空时才会调用它,因此在重新启动的进程中(其中该变量包含内部数据)或重新启动已被覆盖时不会调用它。
请注意,如果需要,可以在此处使用 setMainScript() 和 setPersistent() 设置器。
应用程序可以扩展它来修改临时 ini 文件,其位置在tmpIni
属性中给出。新设置可以安全地附加到数据末尾,即PHP_EOL
终止。
$command
参数是将用于新进程的未转义命令行参数的数组。
请记住以parent::restart($command)
结束。
此示例演示了扩展基本功能的两种方法:
为了避免启动新进程的开销,如果请求简单的帮助命令,则会跳过重新启动。
应用程序需要对 phar 文件进行写访问,因此如果设置了phar.readonly
(无论是否加载 Xdebug)并在临时 ini 文件中更改此值,它将强制重新启动。
use Composer XdebugHandler XdebugHandler ;
use MyApp Command ;
class MyRestarter extends XdebugHandler
{
private $ required ;
protected function requiresRestart ( bool $ default ): bool
{
if (Command:: isHelp ()) {
# No need to disable Xdebug for this
return false ;
}
$ this -> required = ( bool ) ini_get ( ' phar.readonly ' );
return $ this -> required || $ default ;
}
protected function restart ( array $ command ): void
{
if ( $ this -> required ) {
# Add required ini setting to tmp Ini
$ content = file_get_contents ( $ this -> tmpIni );
$ content .= ' phar.readonly=0 ' . PHP_EOL ;
file_put_contents ( $ this -> tmpIni , $ content );
}
parent :: restart ( $ command );
}
}
testsApp
目录包含命令行脚本,可演示各种场景下的内部工作原理。请参阅功能测试脚本。
composer/xdebug-handler 根据 MIT 许可证获得许可,有关详细信息,请参阅许可证文件。