标签: php-internals

PHP'foreach'如何实际工作?

让我通过说我知道它是什么foreach,做什么以及如何使用它来加上前缀.这个问题涉及它如何在发动机罩下工作,我不希望任何答案都是"这就是你如何循环阵列foreach".


很长一段时间,我认为这foreach与数组本身一起工作.然后我发现许多引用它的数据副本的事实,我已经假设这是故事的结尾.但是我最近讨论了这个问题,经过一些实验后发现这实际上并非100%正确.

让我说明我的意思.对于以下测试用例,我们将使用以下数组:

$array = array(1, 2, 3, 4, 5);
Run Code Online (Sandbox Code Playgroud)

测试案例1:

foreach ($array as $item) {
  echo "$item\n";
  $array[] = $item;
}
print_r($array);

/* Output in loop:    1 2 3 4 5
   $array after loop: 1 2 3 4 5 1 2 3 4 5 */
Run Code Online (Sandbox Code Playgroud)

这清楚地表明我们不直接使用源数组 - 否则循环将永远持续,因为我们在循环期间不断地将项目推送到数组.但只是为了确保这种情况:

测试案例2:

foreach ($array as $key => $item) {
  $array[$key + 1] = $item + 2;
  echo "$item\n";
}

print_r($array);

/* Output …
Run Code Online (Sandbox Code Playgroud)

php iteration foreach loops php-internals

1926
推荐指数
7
解决办法
39万
查看次数

"zend_mm_heap corrupted"是什么意思

突然之间,我的应用程序出现了问题,这是我以前从未遇到的问题.我决定检查Apache的错误日志,我发现一条错误消息"zend_mm_heap corrupted".这是什么意思.

操作系统:Fedora Core 8 Apache:2.2.9 PHP:5.2.6

php heap fedora php-internals

123
推荐指数
8
解决办法
16万
查看次数

括号改变函数调用结果的语义

另一个问题中指出,在括号中包装PHP函数调用的结果可以某种方式将结果转换为完全成熟的表达式,以便以下工作:

<?php
error_reporting(E_ALL | E_STRICT);

function get_array() {
   return array();
}

function foo() {
   // return reset(get_array());
   //              ^ error: "Only variables should be passed by reference"

   return reset((get_array()));
   //           ^ OK
}

foo();
Run Code Online (Sandbox Code Playgroud)

我试图在文档中找到任何内容,以明确无误地解释这里发生的事情.与C++不同,我不太了解PHP语法及其语句/表达式的处理方法,以便自己派生它.

有关此行为的文档中是否隐藏了任何内容?如果没有,其他人可以解释它而不诉诸假设吗?


更新

我首先发现这个EBNF声称代表PHP语法,并试图自己解码我的脚本,但最终放弃了.

然后,使用phc生成.dot两个foo()变体的文件,我使用以下命令为两个脚本生成 AST图像:

$ yum install phc graphviz
$ phc --dump-ast-dot test1.php > test1.dot
$ dot -Tpng test1.dot > test1.png
$ phc --dump-ast-dot test2.php > test2.dot
$ dot -Tpng …
Run Code Online (Sandbox Code Playgroud)

php php-internals

52
推荐指数
1
解决办法
2364
查看次数

PHP中while(true)和for(;;)之间有什么区别?

有没有之间的PHP任何差异while(true)for(;;)除了语法和可读性?

编辑:我不认为这是重复 - 我想知道PHP特有的答案.就发动机而言,有什么真正的区别吗?他们编译成同样的东西吗?他们有同等的表现吗?

编辑2:我也不会认为相对表现和相关的OpCodes是基于意见.可读性存在意见空间,但这显然不是问题.

php for-loop infinite-loop while-loop php-internals

42
推荐指数
1
解决办法
2820
查看次数

为什么PHP属性不允许函数?

我是PHP的新手,但我已经用类似语言编程多年了.我对以下内容感到困惑:

class Foo {
    public $path = array(
        realpath(".")
    );
}
Run Code Online (Sandbox Code Playgroud)

它产生了语法错误:Parse error: syntax error, unexpected '(', expecting ')' in test.php on line 5这是realpath调用.

但这很好用:

$path = array(
    realpath(".")
);
Run Code Online (Sandbox Code Playgroud)

在我的头撞了一会儿之后,我被告知你不能在属性默认情况下调用函数; 你必须这样做__construct.我的问题是:为什么?!这是"功能"还是草率实施?理由是什么?

php language-design php-internals

41
推荐指数
4
解决办法
5431
查看次数

php.ini中Extension和zend_extension之间的区别是什么?

当我安装Xdebug时pecl,它将以下行添加到我的php.ini文件中.

extension="xdebug.so"
Run Code Online (Sandbox Code Playgroud)

以及我用过的所有东西.直到今天.

今天我在设置Xdebug以进行交互式调试时遇到了麻烦.直到我改变了上面的内容,我才能得到任何工作

zend_extension="/usr/local/lib/php/extensions/xdebug.so"
Run Code Online (Sandbox Code Playgroud)

(警告:我认为这是让我工作的原因,但我不是百分百肯定)

这引起了我的疑问.通过extension=vs. 加载扩展有什么区别zend_extension

php xdebug pecl php-internals

37
推荐指数
2
解决办法
2万
查看次数

预编译PHP文件

作为一个学习练习,我试图保存php文件的编译状态,以便以后执行它而不必zend_compile_file再次执行.

我做的第一件事是写一个钩子的扩展zend_compile_file.如果请求是在未编译的文件(即:file.php)上进行的,则会将zend_op_array数据转储到另一个文件(即:compiled-file.php).如果请求是在这样的编译文件上进行的,它会将数据加载到新的zend_op_array中然后返回它.

为简单起见,我忽略了与类和函数相关的所有内容,因此我不希望我的扩展适用于包含这些内容的脚本.但我认为其他更简单的脚本应该可行吗?

好吧,它适用于非常简单的脚本,但通常它只是挂起并达到最大执行时间限制.我发现它总是在错误的条件分支上失败.例如,这个脚本可以工作:

<?php
$a = 10;
$b = 5;
if ($b < $a)
    echo $a;
Run Code Online (Sandbox Code Playgroud)

虽然这个会挂起:

<?php
$a = 10;
$b = 5;
if ($b > $a)
    echo $a;
Run Code Online (Sandbox Code Playgroud)

我的问题:我是否正确假设对于没有函数或类的简单脚本,制作zend_op_array的深层副本并返回它应该足以复制php编译?如果没有,我应采取的其他步骤是什么?

以下是我的扩展的相关文件: opdumper.c oploader.c

编辑:我设法通过更改此代码"修复"我的问题:

void dump_znode_op(FILE* fp, znode_op node, zend_uchar type)
{
    fwrite(&type, sizeof(type), 1, fp);
    switch(type) {
        case IS_UNDEF:
        case IS_UNUSED:
            break;
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

到这一个:

void dump_znode_op(FILE* fp, znode_op node, zend_uchar type)
{
    fwrite(&type, sizeof(type), 1, fp);
    switch(type) {
        case IS_UNDEF:
        case …
Run Code Online (Sandbox Code Playgroud)

php c php-extension php-internals

29
推荐指数
0
解决办法
936
查看次数

为什么你不能继承一个尚未定义的类继承自一个尚未定义的类?

我研究类编译,它的序列和逻辑.

如果我在简单父级之前声明一个类:

 class First extends Second{}
 class Second{}
Run Code Online (Sandbox Code Playgroud)

这将工作正常.查看PHP版本的实例.

但是,如果父类还有一些尚未声明的父类(扩展或实现),如下例所示:

class First extends Second{}
class Second extends Third{}
class Third{}
Run Code Online (Sandbox Code Playgroud)

我会有一个错误:

致命错误:找不到"第二级"......

查看PHP版本的实例.

那么,为什么在第二个例子中它找不到Second类?也许php无法编译这个类因为它还需要编译Third类,还是什么?

我试图找出为什么在第一个例子中,PHP编译类第二,但如果它将有一些父类,它不会.我研究了很多,但没有确切的.

  • 我不是试图以这种方式编写代码,但在这个例子中,我试图理解编译及其序列是如何工作的.

php inheritance php-internals

28
推荐指数
1
解决办法
905
查看次数

哪里是php-src/PHP-Internals主入口点

什么函数或位代码作为PHP本身源代码中执行/解释PHP程序的主要入口点?基于我在Google书目中搜索或阅读的内容,我知道PHP旨在与某种服务器一起工作(即使CLI命令通过启动"命令行SAPI"工作,它充当了设计的迷你服务器处理单个请求),服务器将要求PHP执行程序.

我知道minitrinit生命周期函数,它们作为PHP扩展的入口点.

我不知道的是PHP源代码与自己进行这种对话的位置

嘿看,这个文件/字符串中有一个PHP程序.我应该跑它

我不想在这里完成任何具体任务.我试图理解PHP的内部如何完成它的工作,并找到一个主要的入口点,我可以开始执行它.

php php-internals

28
推荐指数
1
解决办法
2488
查看次数

我在哪里可以了解PHP内部?

有什么好的资源可以开始学习PHP和Zend Engine的内部结构?

php php-internals

27
推荐指数
2
解决办法
5875
查看次数