首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >重复数组键(注意:成员变量"a“从__sleep()返回多次)

重复数组键(注意:成员变量"a“从__sleep()返回多次)
EN

Stack Overflow用户
提问于 2019-11-05 11:05:56
回答 3查看 408关注 0票数 8

这个标题看起来有点傻,但我完全是认真的。今天在工作中,我遇到了一个奇怪的PHP行为,我无法解释。幸运的是,这种行为在PHP7.4中得到了修正,因此似乎有人也无意中发现了这一点。

我举了一个小例子来说明出了什么问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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);

在这里运行以下代码:https://3v4l.org/DBt3o

以下是对这里所发生的事情的一点解释。我们必须使用A类和B类,它们都共享一个属性$a。仔细的读者注意到,属性$a有两个不同的可见性(公共的,私有的)。到目前为止还没什么好想的。魔术发生在__sleep方法中,当我们调用实例时,这个方法会被神奇地调用。我们希望拥有使用get_object_vars获得的所有对象变量,将其简化为只使用array_keys的键,并使用var_dump输出所有内容。

我预计会出现这样的情况(这种情况发生在PHP7.4之后,也是我的预期输出):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array(2) {
  [0]=>
  string(1) "b"
  [1]=>
  string(1) "a"
}

但我得到的是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "a"
}

PHP怎么会用两个完全相同的键传递一个数组呢?谁能够解释在内部发生的事情,因为在普通PHP中,我无法生成两个完全相同的键的数组?还是我错过了一些显而易见的东西?

我的同事一开始不想相信我,但他们中没有一个人在了解了这里发生的事情后对此有一个很好的解释。

我真的很想看到一个很好的解释。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-11-07 16:01:41

我在问题中找不到bug的报告,但有趣的是,此承诺似乎解决了同样的问题:

如果我们在可见的范围内,便不应看到隐藏的公共财产。

测试代码编写得很好,只要做一个简单的修改,我们就可以在这里得到它:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Test
{
    private $prop = "Test";

    function run()
    {
        return get_object_vars($this);
    }
}

class Test2 extends Test
{
    public $prop = "Test2";
}

$props = (new Test2)->run();

var_dump()上调用$props显示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array(2) {
  ["prop"]=>
  string(5) "Test2"
  ["prop"]=>
  string(4) "Test"
}

回到你的问题:

PHP怎么会用两个完全相同的键传递一个数组呢?谁能够解释在内部发生的事情,因为在普通PHP中,我无法生成两个完全相同的键的数组?

是的,您不能有一个具有两个相同键的数组:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var_dump(array_flip(array_flip($props)));

在以下方面的成果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array(1) {
  ["prop"]=>
  string(4) "Test"
}

但是,让我不同意您对two completely identical keys的看法,因为这两个具有相同密钥名的元素不会在哈希表内部使用相同的密钥存储。也就是说,除了潜在的冲突之外,这些被存储为唯一的整数,并且由于这是在内部发生的,对用户输入的限制被忽略了。

票数 6
EN

Stack Overflow用户

发布于 2019-11-05 11:44:02

在对此进行了一些处理之后,看起来这不依赖于__sleep()

显然,在PHP 7的早期版本中,情况总是如此(但在PHP 5中显然并非如此)。这个较小的例子显示了相同的行为。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A {
    private $a = 'This is $a from A';

    public function showProperties() { return get_object_vars($this); }
}

class B extends A
{
    public $a = 'This is $a from B';
}

$b = new B;
var_dump($b->showProperties());

PHP7.0- 7.3输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
array(2) {
  ["a"]=>
  string(17) "This is $a from B"
  ["a"]=>
  string(17) "This is $a from A"
}

我认为父类中的私有$a与子层中的公共$a是不同的属性。当您在B中更改可见性时,您没有在A中更改$a的可见性,而是使用相同的名称创建一个新属性。如果您var_dump对象本身,您可以看到这两个属性。

但是,它不应该有太大的效果,因为您将无法从子类中的父类访问私有属性,即使您可以看到它存在于早期的PHP 7版本中。

票数 3
EN

Stack Overflow用户

发布于 2019-11-08 00:49:53

我的两分钱。

我不知道同事,但我不相信,认为这是一个笑话。

为了解释这个问题,这个问题肯定是在"get_object_vars“变量下,因为它返回的是重复的关联数组。应该是相同键的两个不同的哈希表值(这是不可能的,但唯一的解释是)。我无法找到指向内部get_object_vars()实现的任何链接(尽管PHP基于开放源码,因此可以以某种方式获得代码和调试)。此外,我正在思考(到目前为止)在内存中看到数组表示形式(包括哈希表)的过程中(到目前为止没有成功)。另一方面,我能够使用PHP的“合法”函数,并对数组做一些技巧。

这是我尝试用关联数组测试一些功能的尝试。下面是输出。不需要解释-你可以看到所有的东西,自己尝试相同的代码,所以只有一些评论。

  1. 我的环境是php 7.2.12 x86 (32位)-嗯.是啊,真丢脸
  2. 我摆脱了“魔法”和串行化,只留下了东西带来的问题。
  3. 完成了对类A和B的重构以及函数调用。
  4. A类下的$key必须是私有的,否则就没有奇迹了。
  5. 部分测试vars没有什么有趣的,除了主要的问题。
  6. 部件测试copy_vars -数组复制与复制!成功地添加了新密钥。
  7. 部分测试迭代和new_vars迭代没有出现问题,但是新数组不接受重复,最后一个键被接受。
  8. 测试更换-在第二个键上完成更换,重复停留。
  9. 测试k排序-数组没有改变,复制没有被识别。
  10. 测试asort --在更改值和运行asort之后,我能够更改订单并交换重复的键。现在,第一个键变成第二个键,当我们按键调用数组或分配一个键时,新的键就是那个键。因此,我可以改变两个钥匙!!在我认为重复的键是某种不可见的键之前,现在很清楚的是,当我们引用或分配密钥时,最后一个键可以工作。
  11. 转换为stdClass对象-不可能!只接受最后一个钥匙!
  12. 测试未设定-好的工作!最后一个键被删除,但是第一个键负责,只剩下一个键,没有重复。
  13. 内部表示测试-这是一个主题,添加了一些其他功能,并看到了重复的来源。我现在正在考虑这个问题。

结果输出低于代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

class A {
    private $key = 'This is $a from A';

    protected function funcA() {
        $vars = get_object_vars($this);

        return $vars;
    }
}

class B extends A
{
    public $key = 'This is $a from B';

    public function funcB() {
        return $this->funcA();
    }
}

$b = new B();

$vars = $b->funcB();

echo "testing vars:\n\n\n";

var_dump($vars);
var_dump($vars['key']);
var_dump(array_keys($vars));

echo "\n\n\ntesting copy_vars:\n\n\n";

$copy_vars = $vars;
$copy_vars['new_key'] = 'this is a new key';

var_dump($vars);
var_dump($copy_vars);

echo "\n\n\ntesting iteration and new_vars:\n\n\n";

$new_vars = [];
foreach($vars as $key => $val) {
    echo "adding '$key', '$val'\n";
    $new_vars[$key] = $val;
}

var_dump($new_vars);

echo "\n\n\ntesting replace key (for copy):\n\n\n";

var_dump($copy_vars);
$copy_vars['key'] = 'new key';
var_dump($copy_vars);

echo "\n\n\ntesting key sort (for copy):\n\n\n";

var_dump($copy_vars);
ksort($copy_vars);
var_dump($copy_vars);

echo "\n\n\ntesting asort (for copy):\n\n\n";

$copy_vars['key'] = "A - first";
var_dump($copy_vars);
asort($copy_vars);
var_dump($copy_vars);
$copy_vars['key'] = "Z - last";
var_dump($copy_vars);

echo "\n\n\ntesting object conversion (for copy):\n\n\n";

var_dump($copy_vars);
$object = json_decode(json_encode($copy_vars), FALSE);
var_dump($object);


echo "\n\n\ntesting unset (for copy):\n\n\n";

var_dump($copy_vars);
unset($copy_vars['key']);
var_dump($copy_vars);


echo "\n\n\ntesting inernal representation:\n\n\n";

debug_zval_dump($vars);

现在的产出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
testing vars:


array(2) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(17) "This is $a from A"
}
string(17) "This is $a from A"
array(2) {
  [0]=>
  string(3) "key"
  [1]=>
  string(3) "key"
}



testing copy_vars:


array(2) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(17) "This is $a from A"
}
array(3) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(17) "This is $a from A"
  ["new_key"]=>
  string(17) "this is a new key"
}



testing iteration and new_vars:


adding 'key', 'This is $a from B'
adding 'key', 'This is $a from A'
array(1) {
  ["key"]=>
  string(17) "This is $a from A"
}



testing replace key (for copy):


array(3) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(17) "This is $a from A"
  ["new_key"]=>
  string(17) "this is a new key"
}
array(3) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(7) "new key"
  ["new_key"]=>
  string(17) "this is a new key"
}



testing key sort (for copy):


array(3) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(7) "new key"
  ["new_key"]=>
  string(17) "this is a new key"
}
array(3) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(7) "new key"
  ["new_key"]=>
  string(17) "this is a new key"
}



testing asort (for copy):


array(3) {
  ["key"]=>
  string(17) "This is $a from B"
  ["key"]=>
  string(9) "A - first"
  ["new_key"]=>
  string(17) "this is a new key"
}
array(3) {
  ["key"]=>
  string(9) "A - first"
  ["key"]=>
  string(17) "This is $a from B"
  ["new_key"]=>
  string(17) "this is a new key"
}
array(3) {
  ["key"]=>
  string(9) "A - first"
  ["key"]=>
  string(8) "Z - last"
  ["new_key"]=>
  string(17) "this is a new key"
}



testing object conversion (for copy):


array(3) {
  ["key"]=>
  string(9) "A - first"
  ["key"]=>
  string(8) "Z - last"
  ["new_key"]=>
  string(17) "this is a new key"
}
object(stdClass)#2 (2) {
  ["key"]=>
  string(8) "Z - last"
  ["new_key"]=>
  string(17) "this is a new key"
}



testing unset (for copy):


array(3) {
  ["key"]=>
  string(9) "A - first"
  ["key"]=>
  string(8) "Z - last"
  ["new_key"]=>
  string(17) "this is a new key"
}
array(2) {
  ["key"]=>
  string(9) "A - first"
  ["new_key"]=>
  string(17) "this is a new key"
}



testing inernal representation:


array(2) refcount(2){
  ["key"]=>
  string(17) "This is $a from B" refcount(2)
  ["key"]=>
  string(17) "This is $a from A" refcount(4)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58717899

复制
相关文章
Python类变量和成员变量的使用注意点
之前在用python写一个项目,发现一个很恶心的bug,就是同由一个类生成的两个实例之间的数据竟然会相互影响,这让我非常不解。后来联想到java的类有类变量也有实例变量,因此翻阅了相关资料,发现python也有类似的类变量和实例变量,比如下面的代码中:
mythsman
2022/11/14
1.5K0
【C++】静态成员变量 ( 静态成员变量概念 | 静态成员变量声明 | 静态成员变量初始化 | 静态成员变量访问 | 静态成员变量生命周期 )
静态成员归属 : 静态成员变量 是特殊的成员变量 , 是 类所有的 成员 , 而不是对象所有的成员 ;
韩曙亮
2023/10/15
1.7K0
【C++】静态成员变量 ( 静态成员变量概念 | 静态成员变量声明 | 静态成员变量初始化 | 静态成员变量访问 | 静态成员变量生命周期 )
python类成员变量和实例成员变量
print 'need %f hour(s)'% (distance/self.speed)
用户7886150
2020/12/20
1.4K0
python里使用vars()返回当前局部作用域的所有成员函数和成员变量
print("the %(book)s book contains more than %(scripts)s scripts" % vars())
用户7886150
2021/01/24
1.2K0
[LEETCODE]从排序数组中删除重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
用户2353021
2020/05/11
6.3K0
静态变量和成员变量的区别 && 成员变量和局部变量的区别
=============================================================================
黑泽君
2018/10/11
1.6K0
[Objective-C Runtime] 成员变量与属性
在上篇文章[Objective-C Runtime] 类与对象详细讲解了Runtime机制对于类和对象相关处理,今天继续讲解一下Runtime在成员变量和属性上的处理方法和策略。 成员变量(Ivar)的数据结构 在Objective-C中,成员变量即Ivar类型,是指向结构体struct objc_ivar的指针,在Objc/runtime.h 中查到,如下所示: typedef struct objc_ivar *Ivar; 结构体struct objc_ivar的数据结构如下所示: struct o
Jacklin
2018/05/15
1.9K0
java成员变量和局部变量
最新通知 ●回复"每日一练"获取以前的题目! ●【新】Android视频更新了!(回复【安卓视频】获取下载链接) ●【新】Ajax知识点视频更新了!(回复【学习视频】获取下载链接) ●【新】HTML5知识点视频更新了!(回复【前端资料】获取下载链接) ●答案公布时间:为每期发布题目的第二天 ★【新】回复“测试题”获取昨天发布的软件工程师初级阶段测试题答案 ★【新】回复“学习资料”获取java学习电子文档 ★【新】需要求职简历模板的可以加小编微信xxf960513 聊天系统 ●我希望大家积极参与答题!有什么不
Java学习
2018/04/16
1.3K0
java成员变量和局部变量
Java - 局部变量和成员变量
概念 成员变量 成员变量就是属于类的变量,在类中,方法体外定义的变量 成员变量又分为两种: **类变量(静态变量):**是被static所修饰的成员变量,是属于类的部分,属于类的范畴。 **实例变量(非静态变量):**是没有被static修饰的成员变量,是属于类的部分,但是属于对象的范畴。 局部变量: 局部变量就是定义在方法体,代码块内的变量,是局部的变量,属于方法的范畴。 **比如:**方法的形参,方法内定义的变量等等。 区别 1、定义的位置不一样 局部变量:在方法的内部 成员变量:在方法的外部,直接写在
kenvie
2022/01/20
1.3K0
Android之有效防止按钮多次重复点击
我的想法是,判断用户点击按钮间隔时间,如果间隔时间太短,则认为是无效操作,否则进行相关业务处理
贺biubiu
2019/06/10
1.6K0
成员变量和局部变量的区别是什么_实例变量和成员变量的区别
大家好,又见面了,我是你们的朋友全栈君。 成员变量和局部变量的区别? A:在类中的位置不同 成员变量:在类中方法外 局部变量:在方法定义中或者方法声明上 B:在内存中的位置不同 成员变量:在
全栈程序员站长
2022/11/17
8750
JAVA反射--获取成员变量
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; public class Text { public static void main(String[] a){ try { Class class1 = Class.forN
用户2965768
2019/03/15
2.3K0
JAVA反射--获取成员变量
VFP表单返回对像、数组、值,这个细节要注意,防止崩溃
我们会选择模式表单进行返回值操作,为了保证表单的临时表是独立环境,各个表单的数据不会影响,我们选择私有工作期。
加菲猫的VFP
2022/04/07
6260
VFP表单返回对像、数组、值,这个细节要注意,防止崩溃
类的静态成员变量
类的静态成员要在类内声明,类外定义。这样做的原因参照 here类外定义时又要注意哪些内容呢?不在头文件中定义静态成员变量这是“尽量不在头文件中定义变量”(参考)的延伸。错误的代码示例class.h#ifndef __CLASS_H#define __CLASS_Hclass A{ static int var;};int A::var = 1;#endifmain.cppint main() { return 0;}test1.cpp#include "class.h"test2
村子里的设计师
2023/05/20
1K0
RN监听返回键
BackAndroid已经被废弃。改用BackHandler 关键代码 componentWillMount() { if (Platform.OS === 'android') { this.listener = BackHandler.addEventListener('hardwareBackPress', this.onBackAndroid); } } componentWillUnmount() { i
提莫队长
2018/05/18
2.4K0
flutter 返回键监听
在客户端,MethodChannel(API)允许发送与方法调用相对应的消息。 在平台方 面,Android(API)上的MethodChannel和 iOS(API)上的 FlutterMethodChannel启用接收方法调用并发回结果。
徐建国
2021/08/02
4.1K1
Fragment 点击返回键 做返回操作
在Fragment中点击返回键,做一些更新页面的操作,我就遇到了这个问题(NC客户)总点返回键,然后跟我说怎么我按返回键没反应呢,按连续按2次就要退出了?哼?你是怎么做的啊?
全栈程序员站长
2021/04/07
1.8K0
Swift 从排序数组中删除重复项 - LeetCode
给定一个有序数组,你需要原地删除其中的重复内容,使每个元素只出现一次,并返回新的长度。
韦弦zhy
2018/09/11
5.3K0
被联想键盘sleep键坑了,睡眠+电源键怎么取消
F12右边的键位,大多键盘都是PrtSc SysRq全屏截图键,但联想km4800键盘此处是睡眠sleep键,昨天误按了让电脑睡眠了已被坑了一把,结果到晚上时将我坑下了悬崖,我也不清楚为什么朋睡眠中唤醒后,原本设置的电源管理高性能模式会变成平衡模式,结果就是不动电脑几十分钟后就转成睡眠模式,让我原本给电脑布置的全夜加班任务,让这货提前打卡下班了,今天早上起来看着电脑处理到一半的任务,吐血连连,三升的盆子都没接住。
用户5570797
2023/06/26
3320
Python中类变量、成员变量、局部变量的区别
class A:v1 = 100 # 类变量def __init__(self):self.v2 = 200 # 成员变量v3 = 300 # 局部变量类变量可以由类名统一修改:A.v1 = 300# 则每一个A实例里v1都变成300成员变量只能由实例自己改变:A.v2 # 这个是错的。a = A()a.v2 # 这个是可以访问的。局部变量只在函数内部生效
狼啸风云
2020/10/16
4.4K0

相似问题

从__sleep()返回的作为成员变量返回的symfony序列化(),但不存在

21

如何多次返回变量并创建数组

26

如何从返回的数组对象访问日期成员变量

12

从成员变量指针返回bool

12

从数组中获取重复键

25
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文