PHP中不同的MySQL游标如何管理内存?我的意思是,当我创建一个MySQL查询来检索一个大的结果集,然后获取MySQL资源时,查询检索的数据有多少存储在本地内存中,以及如何检索更多结果?光标是否自动获取所有结果,并在我使用fetch_array或是缓冲系统迭代资源时将它们提供给我?
最后,mysql中不同驱动程序的游标是否实现不同?有几个MySQL的驱动PHP可用mysql,mysqli,pdo等他们是否都遵循同样的做法?
标题似乎有些愚蠢,但是我对此非常认真。今天在工作中,我遇到了无法解释的怪异的PHP行为。幸运的是,此行为已在PHP 7.4中修复,因此似乎也有人偶然发现了该行为。
我举了一个小例子来说明出了什么问题:
<?php
class A {
private $a = 'This is $a from A';
public $b = 'This is $b from A';
public function __sleep(): array
{
var_dump(array_keys(get_object_vars($this)));
return [];
}
}
class B extends A
{
public $a = 'This is $a from B';
}
$b = new B;
serialize($b);
Run Code Online (Sandbox Code Playgroud)
在此处运行此代码:https : //3v4l.org/DBt3o
这里是这里发生的事情的一点解释。我们必须同时共享一个属性的A类和B类$a。细心的读者注意到,该物业$a具有两种不同的可见性(公共,私人)。到目前为止还算不上什么。魔术发生在实例中__sleep被神奇调用的方法中serialize。我们希望拥有所有获得的对象变量,将其get_object_vars减少为仅包含键,array_keys并使用输出所有内容var_dump。
我期望这样(从PHP 7.4开始发生,这是我的期望输出):
array(2) {
[0]=>
string(1) "b"
[1]=>
string(1) …Run Code Online (Sandbox Code Playgroud) PHP 7.4 向后不兼容的更改列表包含以下注释:
序列化
o 序列化格式已被删除。由于它从未由 PHP 生成,因此这可能只会破坏手动制作的字符串的反序列化。
(请注意,这指的是 little- o,而不是O用于对象序列化的 big-格式。)
似乎这从未由 PHP 的serialize()函数生成,但是此注释存在的事实意味着它已被unserialize()函数识别。
我做了一个小测试小提琴 (3v4l.org),它表明这不仅仅是big-的同义词O,这将是一个明显的可能性。
小提琴通过输出的错误消息中的差异公开了 PHP 中的更改。在 PHP >= 7.4 中,我们在位置 0(o遇到 )出现错误,而在 7.4 之前,在位置 5(数据所在的位置)报告错误。这意味着o已识别但数据格式错误,这与我上面已经推断的内容有关。
那么,o序列化格式是什么,它反序列化为什么,如果 PHP 本身没有实际生成它,为什么还要支持这样的功能?
我正在为我的c ++库编写一个php扩展,其定义如下:
bool getPids(map<string,string> pidsMap, vector<string> ids);
Run Code Online (Sandbox Code Playgroud)
现在,我正在为这样的上述函数编写一个php包装器.
ZEND_METHOD(myFInfo, get_pids)
{
zval *idsArray;
if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "a",
&idsArray ) == FAILURE )
{
RETURN_NULL();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想调用getPids(),但我不知道将idsArray作为向量传递给c ++函数的正确方法.
在网上搜索之后,我找到了一个例子,其中zval数组被迭代以读取每个值,我想也许我可以用它来创建一个向量.
PHP_FUNCTION(hello_array_strings)
{
zval *arr, **data;
HashTable *arr_hash;
HashPosition pointer;
int array_count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
RETURN_NULL();
}
arr_hash = Z_ARRVAL_P(arr);
array_count = zend_hash_num_elements(arr_hash);
php_printf("The array passed contains %d elements", array_count);
for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;
zend_hash_move_forward_ex(arr_hash, &pointer)) {
if (Z_TYPE_PP(data) == IS_STRING) { …Run Code Online (Sandbox Code Playgroud) 由于现在默认情况下通过引用传递对象,是否有一些特殊情况才有&$obj意义?
PHP引擎会优化第二个示例来传递$arr引用吗?
function test1(array &$arr)
{
$arr[] = 123;
echo $arr[0];
}
function test2(array $arr)
{
echo $arr[0];
}
Run Code Online (Sandbox Code Playgroud) 我正在学习PHP扩展编写,以便使一些旧的扩展与PHP 7一起工作.
我试图从http://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension/修改示例扩展,但在破坏自定义对象时它会导致段错误.所有其他功能正常工作.(在我的代码中,汽车被BDict取代.)
这是我的代码:
#define Z_BDICT_OBJ_P(zv) php_bdict_object_fetch_object(Z_OBJ_P(zv))
zend_object_handlers bdict_object_handlers;
typedef struct _bdict_object {
BDict *bdict_data;
zend_object std;
} bdict_object;
zend_class_entry *bdict_ce;
static void bdict_free_storage(zend_object *object TSRMLS_DC)
{
bdict_object *intern = (bdict_object *)object;
// ***Both the following two lines will cause segfault***
delete intern->bdict_data;
zend_object_std_dtor(&intern->std TSRMLS_CC);
}
zend_object * bdict_object_new(zend_class_entry *ce TSRMLS_DC)
{
bdict_object *intern = (bdict_object *)ecalloc(1,
sizeof(bdict_object) +
zend_object_properties_size(ce));
zend_object_std_init(&intern->std, ce TSRMLS_CC);
object_properties_init(&intern->std, ce);
intern->std.handlers = &bdict_object_handlers;
return &intern->std;
}
static inline bdict_object * php_bdict_object_fetch_object(zend_object *obj)
{ …Run Code Online (Sandbox Code Playgroud) 我们有一段简单的代码:
1 <?php
2 $i = 2;
3 $j = &$i;
4 echo (++$i) + (++$i);
Run Code Online (Sandbox Code Playgroud)
在PHP5上,它输出8,因为:
$i为参考,当我们增加$i的++i,它会改变zval,而不是做一个副本,因此4号线会4 + 4 = 8.这是按参考分配.
如果我们评论第3行,它将输出7,每次我们通过增加它来改变它,PHP将复制,第4行将是3 + 4 = 7.这是Copy On Write.
但在PHP7中,它总是输出7.
我已经检查了PHP7中的更改:http://php.net/manual/en/migration70.incompatible.php ,但我没有得到任何线索.
任何帮助都会很棒,提前谢谢.
UPDATE1
以下是PHP5/PHP7上代码的结果:https://3v4l.org/USTHR
UPDATE2
操作码:
[huqiu@101 tmp]$ php -d vld.active=1 -d vld.execute=0 -f incr-ref-add.php
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename: …Run Code Online (Sandbox Code Playgroud) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flag) == FAILURE) {
return;
}
Run Code Online (Sandbox Code Playgroud)
特别是在ZEND_NUM_ARGS() TSRMLS_CC做什么?