问题标签 [php-internals]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1539 浏览

php - PHP 操作码与实际执行的二进制代码有何关系?

test.php 作为纯文本:

test.php 作为操作码:

test.php 作为二进制表示:

(跳过 test.php 的回声输出)

现在我想了解更多关于操作码如何转换为二进制表示的信息。

编辑和澄清的问题:

操作码如何翻译成二进制版本?你能看到 'a' 到 !0 的分配吗?ECHO 语句是否在某处以及它的输出?

我在二进制版本中发现很少有模式暗示操作码的逐行表示。

(“2f726f6f742f746573742e706870”是“/root/test.php”的十六进制表示)

编辑

当行长度设置为 4 字节并在不同程序之间进行比较时,十六进制表示揭示了模式。

但是我对虚拟机如何在这种级别上工作的知识太薄弱,无法真正正确地分析并将其链接到 C 代码。

编辑

PHP 有像 Java 这样的虚拟机吗?

Zend 引擎可以嵌入到 PHP 之外吗?

0 投票
1 回答
126 浏览

php - 什么时候在 PHP 中创建“符号”/“变量名”?

这是我的设置:
display_startup_errors = on
display_errors = On
error_reporting = E_ALL | E_STRICT

上面的代码行将创建一个 zval 容器并将其与符号 a' 相关联。并会给出以下 o/p。

现在考虑以下代码:

将生成 o/p;

来自 PHP 手册的Reference Counting Basics :当使用常量值创建新变量时会创建 zval 容器

这是否意味着,

1] 遇到类似于code2 的第 1 行的代码时不创建符号ie $a;。由于 xdebug_debug_zval 没有找到符号/变量名称“a”。根据     Reference Counting Basics中的声明,没有创建 zval 容器。2] 只有在遇到类似于code2 ie的第 3 行的
代码时才会创建符号。即,仅当变量与常量值相关联时才会创建符号,并且根据引用计数基础中的语句创建 zval 容器并与符号“a”相关联。而code2 的第 1 行即是一段无用的代码$a = "abcd";$a;

有关 xdebug_debug_zval 的信息,请访问此处

0 投票
3 回答
1812 浏览

php - array_keys 如何进行值搜索?

PHP array_keys 如何进行值搜索?

例子:

因为它们是键值对。我猜 PHP 会基于哈希进行搜索,而不是遍历数组中的每个密钥对。

对此有任何“明确的想法”吗?

受此问题启发的问题:如果类似大小的数组中的相应元素是数字(没有迭代),如何获取数组中空元素的键?

0 投票
2 回答
460 浏览

php - 用“新”实例化时到底发生了什么?

让我们考虑以下代码:

输出:

实例化成 $obj1 后:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }

将“Hello”分配给 $obj->var1 后:
Hello

obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='你好' }

逐个:

实例化成 $obj1 后:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }

为什么$obj1->var1只有refcount=2一个a类对象时有?

是因为new操作员如何赋值吗?PHP 使用引用进行赋值。当用 实例化时new,没有符号/变量名称与该实例相关联。但是,类属性确实有名称。是recount=2因为这个吗?

如果是这种情况,则使用浅拷贝 WRT 类实例会发生 COW(写入时复制)。虽然属性仍然指向在实例化期间使用new.

现在,

将“Hello”分配给 $obj->var1 后:
Hello

obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='你好' }

因此,当我为该属性分配一个值时,该属性$obj1->var1的新 zval 容器,因此refcount=1?

这是否意味着在使用实例化期间创建的 zval 容器new仍然存在但由于没有与之关联的符号/变量名称而无法访问?

请注意(来自xdebug:Variable Display Features):
debug_zval_dump()不同于xdebug_debug_zval().

void xdebug_debug_zval( [字符串变量名 [, ...]] )

显示有关变量的信息

此函数显示有关一个或多个变量的结构化信息,包括其类型、值和引用计数信息。使用值递归地探索数组。该函数的实现方式与 PHP 的debug_zval_dump()函数不同,以便解决该函数所存在的问题,因为变量本身实际上是传递给函数的。Xdebug 的版本更好,因为它使用变量名在内部符号表中查找变量并直接访问所有属性,而无需处理实际将变量传递给函数。结果是这个函数返回的信息比 PHP 自己的显示 zval 信息的函数要准确得多。

UPDATEDec 31th 2011:

我正在尝试查看使用new时如何进行内存分配。但是我现在要做的事情太多了。我希望我能尽快发布有用的更新。在那之前,这里是我正在查看的代码的链接:

0 投票
1 回答
101 浏览

php - 为什么在“写入属性”/“将属性注入类的对象”时不会发生 COW?

输出:

echo1: 实例化后:
t1: (refcount=1, is_ref=0)=class a { public $test = (refcount=2, is_ref=0)='msg1' }

echo2: 将 $t1 分配给 $t2 后:
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=2, is_ref=0)='msg1' }

echo3: 分配后 $t1->test = "msg2" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }

echo4: 分配后 $t2->test="msg3" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }

echo5: 将 $test2 注入 $t2 后:
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='c ap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3'; public $test2 = (refcount=1, is_ref=0)='c
ap!' }

忽略echo1&echo2因为这个:用“新”实例化时到底发生了什么?& 预期的行为。

考虑echo3

echo3: 分配后 $t1->test = "msg2" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg2' }

这是可以理解的,因为我只是更改$t1->test变量而不直接更改&t2->test.

考虑到echo4,在哪里进行直接更改$t2->test

echo4: 分配后 $t2->test="msg3" :
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }
t2: ( refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg3' }

没有奶牛发生!$t1即使is_ref未设置,更改也会反映到。

考虑echo5到变量$test2被注入的位置$t2

echo5: 将 $test2 注入 $t2 后:
t1: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='c ap!' }
t2: (refcount=2, is_ref=0)=class a { public $test = (refcount=1, is_ref=0)='msg4'; public $test2 = (refcount=1, is_ref=0)='c
ap!' }

再一次,没有奶牛发生!$t1即使is_ref未设置,更改也会反映到。

Why is this behaviour!?

0 投票
2 回答
3899 浏览

php - 什么是 #在对象的 var_dump 中的对象(someClass)旁边?我有一个推断。我对吗?

这是我用来得出以下推论的代码及其输出:

输出:

对象的line in#<some-number>旁边实际上是. 在哪里,object(someClass)var_dump#<count>

count 是对象的对象/ zval 的数量,无论它属于哪个类,到目前为止已创建。当 zval 的引用计数达到零(即垃圾收集)时,它会为每个创建的对象不断增加并减 1。

我对吗?

0 投票
1 回答
624 浏览

php - 如何从 PHP 扩展中重载函数?

我一直在阅读一些 PHP 扩展教程,但我找不到任何有关如何重载现有函数的信息。

例如,我想将 fopen() 更改为类似

我怎么能那样做?谢谢

PS。我的意思是扩展名(用 C 编写,编译为 .so 并包含在 httpd.conf 中,而不是 .php 程序)


编辑:找到解决方案,感谢 Gordon 链接。

我已经下载了功能的 PECL 包rename_function。它的源代码使我得出了必要的结论:

  • 有一个全局哈希表function_table,它根据函数的名称保存函数的所有指针。

  • zend_hash_find//将允许我在这个表中做任何我想做的改变zend_hash_addzend_hash_del

0 投票
1 回答
584 浏览

php - php 扩展:无法使用 zend_hash_update 更新类字段

我想将这个类实现为 php 扩展:

我已经实现了 __constructor、$attrs 字段和 __get 方法。现在我想不通__set。

有我的c代码:

其中 attrs - 在 init 函数中声明受保护的属性(我已将属性声明为 null,但是当我在构造函数中向 $attrs 添加数据时 - 属性更新为数组)

所以我的问题是:我需要如何在 c 中更新我的 attr 字段?我的扩展成功编译,我可以定义属性,读取它们,但我无法设置它们 - 因为设置的值变为空,例如:

我是 c 开发的新手,我真的需要帮助。

UPD 1.我尝试将 __set 正文更改为:

现在我可以设置字符串值了。如果我需要打开每种类型的 zval??

0 投票
3 回答
2099 浏览

php - 为什么 file_get_contents 比 memcache_get 快?

我正在使用 file_get_contents 从磁盘加载 XML 文件,作为测试,我发现我可以file_get_contents()在 3.99 秒内使用 1,000 次加载 156K 文件。我已经对执行加载的部分进行了子类化,并将其替换为 memcache 层,在我的开发机器上发现我可以在 4.54 秒内完成 1000 次相同文档的加载。

我很欣赏 file_get_contents() 会做一些缓存,但看起来它实际上比众所周知的缓存技术更快。在单个服务器上,性能是否file_get_contents()达到了可以达到的水平?

我通过 Macports、OS X 10.6.8 使用 PHP 5.2.17。

编辑:我在这种大小的 XML 文档中发现,使用该MEMCACHE_COMPRESSED标志有一点好处。通过 memcache 加载 1,500 次在 6.44 秒(压缩)而不是 6.74 秒(不压缩)内完成。但是,两者都比 慢file_get_contents,后者在 5.71 秒内完成相同数量的加载。

0 投票
3 回答
1619 浏览

php - 从扩展返回“本机”PHP 对象

我正在为个人项目创建一个 PHP 扩展。除了上面文章中的链接之外,我对 zend_engine 没有任何了解,而且我的 C 技能已经过时了 10 年,而且只是学术性的。所有这些都是在说“如果看起来我在问一个愚蠢的问题,我可能是”。

是否可以在我自己的扩展中调用其他 PHP 扩展中的函数,或者每个 PHP 扩展都被视为一个孤岛,对系统的其他部分没有洞察力?如果这是可能的,这是常见的做法,还是一个坏主意™?

也就是说,我知道我可以返回一个类似这样的字符串。

我希望能够返回一个 SimpleXML 元素或一个 DomDocument 元素。谷歌搜索已被证明是困难的,因为没有大量关于扩展开发的内容,而且有大量关于标准 PHP 使用的内容。