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

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

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

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

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

代码语言:javascript
运行
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
运行
AI代码解释
复制
array(2) {
  [0]=>
  string(1) "b"
  [1]=>
  string(1) "a"
}

但我得到的是:

代码语言:javascript
运行
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
运行
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
运行
AI代码解释
复制
array(2) {
  ["prop"]=>
  string(5) "Test2"
  ["prop"]=>
  string(4) "Test"
}

回到你的问题:

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

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

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

在以下方面的成果:

代码语言:javascript
运行
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
运行
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
运行
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
运行
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
运行
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

复制
相关文章
MFC中属性表单和向导对话框的使用
每次在使用MFC创建一个框架时,需要一步步选择自己的程序的外观,基本功能等选项,最后MFC会生成一个基本的程序框架,这个就是向导对话框;而属性表单则是另外一种对话框,表单上有多个属性页,每点击某一页,会显示该页的内容,最好的例子是Visual C++6.0中的Option对话框; 属性表单的创建: 属性表单上由许多属性页组成,每个属性页都可以在可视化的编辑环境中编辑,需要添加的资源名称是对话框下面的IDD_PROPPAGE_LARGE、IDD_PROPPAGE_MEDIUM, IDD_PROPPAGE_SMALL,
Masimaro
2018/08/31
1.7K0
是时候在项目中使用这个CSS属性了
八月份做移动端项目的时候,同事让我帮忙看个底部安全距离的问题,我立即摩拳擦掌,原因无他,仅仅是因为当天上午我在medium闲逛时,正好看到了这篇文章:You have to start using this CSS property in your websites(https://bootcamp.uxdesign.cc/you-have-to-start-using-this-css-property-in-your-websites-7353f46def79) 我是被标题骗进去的。
刘小夕
2021/10/18
6390
是时候在项目中使用这个CSS属性了
css opacity属性_CSS中的opacity属性[通俗易懂]
With the growing need of making websites, the need for styling them has also increased. Therefore, CSS has become an indispensable part of creating websites. Thus one must be aware of which properties to use while creating a website.
全栈程序员站长
2022/09/01
3.2K0
css opacity属性_CSS中的opacity属性[通俗易懂]
「css基础」Transforms 属性在实际项目中如何应用?
关于Transform变形属性大家都不陌生吧,可以通过此属性实现元素的位移translate(x,y),缩放scale(x,y),2d旋转rotate(angle),3d旋转rotate3d(angle),倾斜变换skew(x-angle,y-angle)等,你也许已经很熟悉了这些属性,或许你也会有这样的困惑,这些属性在实际项目中如何应用呢?
前端达人
2019/07/21
2.6K0
「css基础」Transforms 属性在实际项目中如何应用?
React项目中 使用 CSS Module
由于新的 react-app-rewired@2.x 版本的关系,还需要安装 customize-cra。但是我们这里不需要安装 react-app-rewired@2.x。只需要安装 react-app-rewired@2.0.2-next.0这个版本就可以了。
Vam的金豆之路
2021/11/30
3990
React项目中 使用 CSS Module
由于新的 react-app-rewired@2.x 版本的关系,还需要安装 customize-cra。但是我们这里不需要安装 react-app-rewired@2.x。只需要安装 react-app-rewired@2.0.2-next.0这个版本就可以了。
马克社区
2022/06/20
3990
「css基础」Transforms 属性在实际项目中如何应用?
关于Transform变形属性大家都不陌生吧,可以通过此属性实现元素的位移translate(x,y),缩放scale(x,y),2d旋转rotate(angle),3d旋转rotate3d(angle),倾斜变换skew(x-angle,y-angle)等,你也许已经很熟悉了这些属性,或许你也会有这样的困惑,这些属性在实际项目中如何应用呢?
前端达人
2019/07/24
3.3K0
「css基础」Transforms 属性在实际项目中如何应用?
那些经常使用的 CSS3属性
实用的css3属性 1、display:flex||inline-flex display flex inline-flex 解释 将对象作为弹性伸缩盒显示 将对象作为内联块级弹性伸缩盒显示 项目中的应用 我当时写过一个因为子元素浮动让div自适应高度的解决办法,使用的是css方法解决的。div高度自适应 下面就是换用display:flex解决 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <titl
潇洒哥和黑大帅
2018/10/23
7310
那些经常使用的 CSS3属性
css 的 opacity 属性
opacity 用于指定元素透明度, 支持 0~1 之间的小数. 默认值 1-完全不透明, 0-完全透明
全栈程序员站长
2022/09/01
6440
css 的 opacity 属性
CSS的display 属性
1.7、compact:CSS 中有值 compact,不过由于缺乏广泛支持,已经从 CSS2.1 中删除。
爱知汇
2020/10/10
1.1K0
解决python3项目中无法使用supervisor的问题
在我的Dockerfile中这样安装 # 安装项目所需的第三方 RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt \ && python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple \ gunicorn \ && python3 -m pip install git+https
简单、
2018/07/17
1.2K0
实用的CSS3属性和使用技巧
CSS可以改进网站的设计并且开拓网站设计更多的可能性,可以令你的网页更具吸引力。对于前端开发者、网站设计师来说,掌握并熟练应用CSS是一项必不可少的技能。
全栈程序员站长
2022/07/15
4210
CSS3之opacity属性的简单使用
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/141344.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/24
3460
CSS3之opacity属性的简单使用
【规范】统一项目中包管理器的使用
Dear,大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~ 【规范】统一项目中包管理器的使用 背景介绍: 我们这里暂不说各种包管理器的优缺点,在实际开发中遇到的一个问题就是,你本地经常使用cnpm来安装,但Jenkins自动构建用的npm,偶尔就会出现本地开发很正常但是Jenkins构建失败报警了,为了避免类似问题的出现,也应该要将能统一的都统一规范。 实现原理: 通过preinstall来在执行install前执行指定脚本; 在preinstall脚
前端小鑫同学
2022/12/26
1.4K0
【规范】统一项目中包管理器的使用
CSS中Fixed的属性
下面这个小demo演示一下fixed与父级子级同级的效果展示 这三个div都是【fixed】属性,但你会发现父级的zindex这时压根没盖过子级的z-index 同级的情况下是会被遮罩住的。
2021/11/08
1.5K0
CSS_文本的属性
color:文本颜色 font-family:字体 font-size:字体大小 font-weight:bold;文字加粗 font-style:italic;斜体 text-indent:60px;首行缩进 text-align:center;水平对齐方式 line-height:100px;行高 text-decoration:underline/none; 如果想要段落的一行高一点,但是文字又垂直居中显示,可以尝试下面的代码: { height:100px; line-height:100px; }
bye
2020/11/24
8810
gridview的属性_grid css
protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e) { e.Row.Attributes.Add(“onmouseover”, “this.style.backgroundColor=’#E6F5FA'”); e.Row.Attributes.Add(“onmouseout”, “this.style.backgroundColor=’#ccccff'”); for (int i = 0; i < e.Row.Cells.Count; i++) { e.Row.Cells[i].Attributes.Add(“class”, “linebottom”); } }
全栈程序员站长
2022/09/28
6650
gridview的属性_grid css
常用的CSS属性大全
1. 动画属性 属性 描述 CSS @keyframes 定义一个动画,@keyframes定义的动画名称用来被animation-name所使用。 3 animation 复合属性。检索或设置对象所应用的动画特效。 3 animation-name 检索或设置对象所应用的动画名称 ,必须与规则@keyframes配合使用,因为动画名称由@keyframes定义 3 animation-duration 检索或设置对象动画的持续时间 3 animation-timing-func
十玖八柒
2022/07/28
3.2K0
回顾css的animation属性
异名新接一个需求,实现一个文字的切换,结果发现太久没写css动画,对animation属性已经很陌生,尤其是对steps()函数的理解已经丢掉了。
异名
2020/12/18
9790
回顾css的animation属性
点击加载更多

相似问题

Egit检测制表符是否已更改

10

nginx regex:检测是否存在分隔符

32

phpDocumentor制表符分隔符

13

路径分隔符的grep

38

分隔符之间的Grep?

22
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

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

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文