gpt4 book ai didi

php - 在 PHP7 中原生分析多个脚本

转载 作者:可可西里 更新时间:2023-11-01 13:27:26 26 4
gpt4 key购买 nike

自 PHP 7 发布以来,现在不可能使用 declare(ticks=1) 分析整个脚本选择。在你的基本文件中,然后使用 register_tick_function()监视每个滴答声,因为它不再遵循包含路径。根据在 https://bugs.php.net/bug.php?id=71448 提交的 PHP 错误这将永远不会在 PHP 7 中再次可用。

Due to an implementation bug, the declare(ticks=1) directive leaked into different compilation units prior to PHP 7.0. This is not how declare() directives, which are per-file or per-scope, are supposed to work.

对于这种使用 native PHP(不是 C 或 pear 扩展等)的方法,是否有任何替代方法可供我在 PHP 7 中使用,这将允许我分析页面加载中调用的每个函数或文件,获取详细信息至少实际文件路径。

导致发现错误的我最初的问题可以在 How to avoid redeclaring ticks on every file in PHP 7 找到, 这个问题现在是关于替代方法的。

最佳答案

在没有 declare(ticks=1) 的情况下执行此操作的一种常见方法是使用分析器。探查器会注意到调用的任何方法/函数、加载的文件等,甚至会获取时间信息,因此您不仅可以说出调用了哪个函数、何时调用了哪些代码以及打开了哪些文件程序的哪个部分用了多长时间。

一个著名的 PHP 分析器带有著名的 Xdebug 扩展。它还附带一个调试器:

一个好处是您不需要更改代码来进行分析,它只是您需要采用的 PHP 配置,因此您可以根据需要打开和关闭它(例如调试/分析 session ) .

PHP Userland(勾选函数)

作为在每个文件的开头(#71448 之后)没有 declare(ticks=1); 的解决方法,可以通过注入(inject)它的文件协议(protocol)(对于本地文件系统中的文件,这是常见的)上的流包装器。

这在技术上是可行的,方法是创建一个在文件协议(protocol)上注册的流包装器来代理标准文件 i/o 操作。在这个PoC (Gist on Github)显示了最低限度的实现以证明它适用于包含。当 test.php 被执行时,尽管 other.php 没有 declare(ticks=1); 在磁盘上,注册的 tick作为回溯显示的打印,函数在包含上被调用:

...
tick_handler() called
#0 tick_handler(1) called at [/home/hakre/stream-wrapper-default-files/test.php:18]
#1 tick_handler() called at [/home/hakre/stream-wrapper-default-files/other.php:2]
#2 include(/home/hakre/stream-wrapper-default-files/other.php) called at [/home/hakre/stream-wrapper-default-files/test.php:24]
...

输出是从注册的 tick 函数生成的(此处:test.php):

<?php
/**
* Inject declare ticks on include
*/
declare(ticks=1);

require __DIR__ . '/streamwrapper.php';

FileStreamWrapper::init();

// using a function as the callback
register_tick_function('tick_handler', true);


// Function which is called on each tick-event
function tick_handler()
{
echo "tick_handler() called\n";
debug_print_backtrace();
}

register_tick_function('tick_handler');

include "other.php";
include "another.php"; # file does not exists

stream wrapper in the gist example只实现了两个 include 语句所需的工作量,因为 PHP 脚本通常会执行更多文件 i/o,因此需要根据需要进行扩展。当涉及查找等时,需要考虑动态插入等,但每个文件操作(句柄)都有状态,因为每个操作都有一个实例,因此应该很好地封装。全局状态用于为每个操作注册/注销流包装器以代理到真正的文件系统函数中,否则它会创建无限递归(包装器使用包装器使用包装器......)。到目前为止,PoC 展示了它在原则上是如何工作的。

这也可以(误)用于其他事情,但这个 PoC 是针对您的特定声明标记和包含用例的。

关于php - 在 PHP7 中原生分析多个脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44473694/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com