V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
543400
V2EX  ›  PHP

我又来了,关于函数数组里面怎么创建新的键值问题

  •  
  •   543400 · 2017-05-08 19:41:49 +08:00 via Android · 2165 次点击
    这是一个创建于 2733 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <?php

    function demoArray(){

    return array(
    "a"="我是 a",
    "b"="我是 b",

    );

    };

    $aa=demoArray();
    echo $aa["a"];
    echo '---------------------';

    /*我查了 PHP 的官方文档,没有找到对这种间接调用数组的方式做出详细创建数组的方法,求大神解答

    */














    ?>
    28 条回复    2017-05-12 23:47:02 +08:00
    543400
        1
    543400  
    OP
       2017-05-08 19:45:06 +08:00 via Android
    顺便问一下 为啥代码没高亮 @ω@
    noark9
        2
    noark9  
       2017-05-08 21:25:13 +08:00
    return array(
    "a"=>"我是 a",
    "b"=>"我是 b",

    );

    不是应该这样?难道 run 的时候没提示语法错误?
    543400
        3
    543400  
    OP
       2017-05-08 21:31:38 +08:00 via Android
    @noark9 能讲解你这种方法怎么输出数组吗?
    543400
        4
    543400  
    OP
       2017-05-08 21:47:19 +08:00
    补充一下 刚试了一下 unset()函数居然也失效了,不知道是不是我方法不对

    unset( demoArray()["a"] );

    这一段失效,不能删除
    543400
        5
    543400  
    OP
       2017-05-08 22:04:47 +08:00
    <?php

    function demoArray(){

    return array(
    "a"=>"我是 a",
    "b"=>"我是 b",

    );

    };

    unset( demoArray()["a"] );

    $aa=demoArray();
    echo $aa["a"];
    echo '---------------------';

    /*我查了 PHP 的官方文档,没有找到对这种间接调用数组的方式做出详细创建数组的方法,求大神解答

    */


    ?>
    noark9
        6
    noark9  
       2017-05-09 14:32:28 +08:00
    每次调用 demoArray 方法都会返回一个独立的数组对象,那你这里 unset( demoArray()["a"] ); 做 unset 跟下面 $aa=demoArray(); 所获取到的数组对象半毛钱关系都没有啊
    以及你的问题很不清晰,“间接调用数组的方式做出详细创建数组的方法” 是什么意思
    543400
        7
    543400  
    OP
       2017-05-09 17:18:39 +08:00 via Android
    @noark9 我的问题已经很清晰 我这个 demoArray() 用的是间接调用数组方法 但是不清楚这类方法怎么创建键值。 另外你不方便回复我上一个问你的问题?



    return array(
    "a"=>"我是 a",
    "b"=>"我是 b",

    );

    不是应该这样?难道 run 的时候没提示语法错误?


    这是你的回答,我的追问是"能讲解你这种方法怎么输出数组吗?"



    "每次调用 demoArray 方法都会返回一个独立的数组对象,那你这里 unset( demoArray()["a"] ); 做 unset 跟下面 $aa=demoArray(); 所获取到的数组对象半毛钱关系都没有啊 " 可以讲清楚你这句话的意思吗??

    我这段代码的意思是删除了"a"键值,但是无效,所以把它贴出来,是为了寻找我的 unset()函数失效的原因

    $aa=demoArray(); 这种就是间接调用数组的方式,很抱歉,请重新翻看 php 文档。
    543400
        8
    543400  
    OP
       2017-05-09 17:22:09 +08:00 via Android
    @noark9 很抱歉,要是我的问题让你脾气很暴躁或者没耐心,请拒绝回答,谢谢
    543400
        9
    543400  
    OP
       2017-05-10 22:45:04 +08:00
    找到问题所在了,现在把解决方法贴出来,避免更多的人踩坑.

    function demoArray() 是内部函数,外部要调用,创建,删除数组的话,首先要把内部函数改成全局变量才行,直接用 global 就可以解决这个问题了

    global 之前先要实例化,

    $bbb=demoArray() ;
    global $bbb;
    noark9
        10
    noark9  
       2017-05-11 12:01:49 +08:00
    你代码里面,每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西
    你把 unset 放在 $aa = demoArray() 后面,就有效了
    上一个问题也没有拒绝回答,你说不输出,那么你原来代码用的是 = 不是语法有错么,原文问题没有提到 unset 的问题嘛,后面才加的
    以及,问题,什么是间接调用数组,没明白这个话,从你代码上看,就是一个函数返回了一个数组
    543400
        11
    543400  
    OP
       2017-05-11 13:29:59 +08:00
    @noark9 https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20001.png
    https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20002.png

    我讲的是不方便回答,没说你拒绝,我最后说拒绝的意思是给你台阶,你不懂就不要乱回答.这只会浪费双方的时间.

    https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20003.png
    https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20004.png

    这是你所说的" 你代码里面,每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西
    你把 unset 放在 $aa = demoArray() 后面,就有效了 "

    打脸的事情一次就够,请不要多次.不懂就不要装懂,不懂就不要乱回答,谢谢
    noark9
        12
    noark9  
       2017-05-11 21:19:36 +08:00
    我说的是把 unset($aa['a']) 放到 $aa = demoArray() 下面
    另外 demoArray() 函数每次返回确实都是一个独立的数组对象,所以你使用 unset(demoArray()['a']) 是没用的

    unset(demoArray()['a']); 这行代码,本质上你可以认为解释器做了下面的操作

    $tmp = demoArray();
    unset($tmp);

    ---------------分割线,也就是说你的程序本质上变成下面的样子
    function demoArray(){

    return array(
    "a"=>"我是 a",
    "b"=>"我是 b",

    );

    };


    $tmp = demoArray(); // 这里原来是这样的 unset( demoArray()["a"] );
    unset($tmp);

    $aa=demoArray();
    echo $aa["a"];
    ---------------分割线

    所以我说你 unset(demoArray()['a']) 和下面 $aa = demoArray(); 所操作的是两个独立的数组

    你所说的间接引用数组,看了你发的文档才知道-,-原来以前的 php 这么二,函数返回值必须要用临时变量保存,不能直接使用,你那中文文档我没见过,这么翻译也很诡异

    其次,不用说打脸不打脸,台阶不台阶,大家讨论问题,淡定点
    noark9
        13
    noark9  
       2017-05-11 22:26:20 +08:00
    @543400
    最近刚好在研究 PHP 内存管理方面的问题,但是如果是 C 就好了,可以很容易把内存地址打印出来,PHP 没有这么个东西来做,但是 PHP 提供了查看变量内存引用计数的函数 debug_zval_dump,配合你的代码做下分析

    // 上半部分代码不变
    function demoArray(){

    return array(
    "a"=>"我是 a",
    "b"=>"我是 b",

    );

    };
    // 把你代码下面改一下改成这样
    echo "\nS.1 -----------------------\n";
    debug_zval_dump(demoArray());
    unset( demoArray()["a"] );
    debug_zval_dump(demoArray());

    echo "\nS.2 -----------------------\n";
    $aa=demoArray();
    debug_zval_dump(demoArray());
    debug_zval_dump($aa);

    echo "\nS.3 -----------------------\n";
    unset($aa['a']);
    debug_zval_dump(demoArray());
    debug_zval_dump($aa);

    对应下面的输出,下面来细说具体,下面的 refcount 就是引用数量,代表有多少个变量引用着这个变量,但是要注意的是 debug_zval_dump 函数自身会对变量产生一个引用,也就是真实的引用数量实际上是下面的数字 -1,如果 refcount - 1 = 0 了说明上下文代码中没有引用到这个变量,在 debug_zval_dump 调用结束后,他的内存就会被回收

    S.1 -----------------------
    代码是这样

    echo "\nS.1 -----------------------\n";
    debug_zval_dump(demoArray());
    unset( demoArray()["a"] );
    debug_zval_dump(demoArray());

    输出是这样
    array(2) refcount(1){
    ["a"]=>
    string(8) "我是 a" refcount(2)
    ["b"]=>
    string(8) "我是 b" refcount(2)
    }
    array(2) refcount(1){
    ["a"]=>
    string(8) "我是 a" refcount(2)
    ["b"]=>
    string(8) "我是 b" refcount(2)
    }
    这里,是用来比较 unset 对 demoArray() 的影响
    可以看到 unset(demoArray()['a']) 对 demoArray() 函数的返回值没有任何的影响
    也说明了每次 demoArray() 返回的结果是相互独立的
    其中对于数组的 refcount = 1 是 debug_zval_dump 函数产生的,对于数组中两个元素的 refcount = 2 是数组本身对数组中变量的引用和 debug_zval_dump 函数对数组两个元素的引用

    S.2 -----------------------
    代码是这样

    echo "\nS.2 -----------------------\n";
    $aa=demoArray();
    debug_zval_dump(demoArray());
    debug_zval_dump($aa);

    输出是这样

    array(2) refcount(1){
    ["a"]=>
    string(8) "我是 a" refcount(3)
    ["b"]=>
    string(8) "我是 b" refcount(3)
    }
    array(2) refcount(2){
    ["a"]=>
    string(8) "我是 a" refcount(2)
    ["b"]=>
    string(8) "我是 b" refcount(2)
    }
    这里是看使用 $aa = demoArray() 对引用计数的影响
    第一组结果:数组的引用数量还是 1 证明只有 debug_zval_dump 函数对其引用了,但是里面的数组元素的引用数变成了 3 这是因为除了第一步中说到的 debug_zval_dump() 函数,和 demoArray() 返回的数组本身对这两个元素进行了引用,还有赋值以后 $aa 这个数组,对这两个元素进行了引用( PHP 是写时复制,也就是说,在不改变变量的情况下,PHP 并不会真实的复制变量,而是对原来变量的引用计数 +1,等到真实的发生读写的时候,才会创建新的变量)
    第二组结果:对于数组本身,那就是 $aa 这个变量和 debug_zval_dump 函数对其引用,所以数组的引用数是 2,但是为什么元素的引用数是 1 呢?之前直接 debug_zval_dump 输出的为什么会更多呢?因为 debug_zval_dump 输出后,没有变量接收 debug_zval_dump(demoArray()); 这里 demoArray() 的返回值(没有变量引用 debug_zval_dump 函数里面 demoArray() 调用的结果)所以,这里引用计数变成 2,也就是数组 $aa 和 debug_zval_dump 分别对数组和数组里面的元素进行引用

    S.3 -----------------------
    代码是这样

    echo "\nS.3 -----------------------\n";
    unset($aa['a']);
    debug_zval_dump(demoArray());
    debug_zval_dump($aa);

    输出是这样

    array(2) refcount(1){
    ["a"]=>
    string(8) "我是 a" refcount(2)
    ["b"]=>
    string(8) "我是 b" refcount(3)
    }
    array(1) refcount(2){
    ["b"]=>
    string(8) "我是 b" refcount(2)
    }
    这里是看 unset($aa['a']) 对引用计数的影响
    在进行了 unset($aa['a']) 之后
    第一组数据,直接输出 debug_zval_dump(demoArray()); 的结果,和 S2 中接近,但是数组中 a 元素的引用变成了 2,也就是说明 unset 有效果了,引用数组中的 a 元素的变量少了一个
    第二组数据也就是 $aa 的引用情况,和预想的相同,a 没了,b 不变

    ---------------------

    总结---------------------------------------

    1. 上面三组输出,每一组 debug_zval_dump(demoArray()); 的输出结果都是一样的,可以侧面证明,每次 demoArray() 返回的数组,实际上都是独立的一个数组
    2. 使用 $aa 变量存储了 demoArray() 返回的数组后,debug_zval_dump(demoArray()); 数组的引用计数器并未增加,证明 $aa 保存的数组和 demoArray() 返回的数组并没有关系
    但是数组中元素的引用计数器变化证明,使用 $aa 存储了 demoArray() 返回的数组后,可以认为 $aa 保存数组的元素
    3. 使用 unset($aa['a']) 后,数组中元素引用计数器变化,也证明了在这个时候 $aa 和 demoArray() 返回的数组是没关系的

    撒花完结~~~~~~

    补充下,我不是大神,大家一起交流学习才能提高,因为近期在写 php 的项目,很多经验是在使用其他语言开发的时候带过来的,但是基础概念是相通的,你说的那个参考文档没看过,因为在我用过的语言没有遇到过需要先使用临时变量获取函数结果(当然你说了我懒得去查这是个什么概念是我的锅),再使用结果的情况(我从 PHP 5.6 开始使用,去年升级公司服务器到 PHP7 就更没接触过了),这里涉及到了内存管理的一些知识,如果是 C 可以不用这么复杂的解释,直接打印内存地址就可以了
    noark9
        14
    noark9  
       2017-05-11 22:29:47 +08:00
    @543400
    我所说的 “每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西” 这句话背后的东西,也就是上面所说的东西的结果
    另外从感性上理解,如果能使用 unset(demoArray()['a']) 把 demoArray() 返回的数组都改变了,那么函数的调用就会变得不可信任 + 难以维护,所以一般情况下,我们很少使用全局变量去操控函数内的变化
    hzw94
        15
    hzw94  
       2017-05-11 23:38:21 +08:00
    我怎么觉得, @noark9 是在自然的回答楼主的问题,不知道怎么就引爆了 @543400 楼主。
    miaotaizi
        16
    miaotaizi  
       2017-05-12 09:17:10 +08:00
    @hzw94 因为楼主觉得弱鸡根本就没理解楼主说的是啥, 然后就 boooooooooooom!
    noark9
        17
    noark9  
       2017-05-12 09:34:53 +08:00 via iPhone
    @hzw94 😂😂😂
    WytheHuang
        18
    WytheHuang  
       2017-05-12 10:32:48 +08:00
    莫名刺激楼主 G 点...哈哈哈瞬间爆炸。我觉得 @noark9 回答问题很好,又没有喷,也没有嘲讽。
    543400
        19
    543400  
    OP
       2017-05-12 11:16:07 +08:00 via Android
    @noark9 信息量太大 我等等操作一遍试试看,不过打这么多字,辛苦你了,谢谢。
    @hzw94
    @miaotaizi
    @WytheHuang

    非常好,之前发这个问题一直没人回答,只有我爆炸了才有人吃瓜看热闹的过来水回复。

    主要是一开始 return array()这段我看不懂是什么意思,之后追问却不正面回答我的问题,让我感觉这是来寻乐浪费我时间。而我一直强调 php 文档里面有这段数组间接引用,结果别人一直在否认却自己不去查。。。。。。能不气吗?

    另外补充一点,用的文档是最新 5 月份的,因为官方的文档没有语法高亮,阅读起来有点枯燥,所以用第三方美化版,里面的翻译内容基本都一样,都是翻译起来很诡异。

    最后因为我没有核验回复的信息,信息量太大我需要消化,但是我昨晚在看面相对象的时候,注意到这种间接引用数组的方式应该是为面向对象准备,不然平时谁也不会心态蹦到用这种方式增加工作量。再者 php5.5 增加这种方式,应该也是有用武之地。

    然后我爆炸之后反而有人回复我了,搞不懂这种吃瓜心态。
    noark9
        20
    noark9  
       2017-05-12 11:39:44 +08:00
    @543400 并不是你爆炸我才接着回复,而是我发现你对这个问题理解上不太对,想把问题讨论清楚而已
    看了文档所谓间接引用,原文用的词叫 dereferencing 意思也就说,函数返回的数组值,在 php 5.5 以前只是地址,并不能直接使用,在 php 5.5 后解释器自动的做了一次解除引用( reference 在有内存管理的语言里面一般叫引用,其实就是通过传递地址来传递变量或是对象,dereference 就是解除传递来地址的引用,变成实际可用的值或者对象)但是呢,实际上 php 5.5 以前必须这么使用,个人理解应该是解析器没办法去做这个操作(解析器开发者的锅)所以并没有什么用武之地,这只能算是一种语法糖
    其次,我没有否仍你所说的东西,所谓间接引用确实没听过,这个问题本质对我来说就是函数返回了一个数组对象,这是长时间开发得到的经验
    另外建议楼主找本系统点的入门书去学习,文档并不会教你怎么编程,只是告诉你有什么 API 怎么使用,就像有人给了你一堆积木,但是不告诉你怎么去建造大楼一样
    noark9
        21
    noark9  
       2017-05-12 11:53:10 +08:00
    @543400 再次,上面也说了大家讨论问题目的是学习知识,提高自己,做技术需要沉下来,才能更好积累
    关于如何正面回答你的问题 “每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西” 这句话其实基本足够了,但是这句话是建立在需要有基本的开发知识来理解的,所以我发现楼主对内存,变量,函数的基础并不清楚,并且试图找到并不合理的解决方案,所以才有了昨晚两大长断的回答,当然也是因为最近在研究 php 内存管理刚好可以用这个来给楼主解答下
    从你看文档来说,感觉楼主应该是用 php 的文档在入门开发,所以才建议楼主找个系统点的入门书去学习,文档在你有了一定的基础之后,是一个参考利器,就酱
    jhdxr
        22
    jhdxr  
       2017-05-12 13:49:33 +08:00
    @noark9 你耐心真好 orz


    @543400 吃瓜群众表示第一次进来什么都没说就走了的原因是,我也完全没提说过『间接引用』这种说法,而且代码里还有语法错误(数组的 key/value 中间用=>而非=),所以我就直接飘走了。

    然后再一次说明,关于『间接引用』这个说法,强烈建议参考 @noark9 的解释,官方文档里我搜了一下唯一用到的一处应该是在 http://php.net/manual/zh/language.types.array.php,这个我认为是一个错误的翻译,并且现在在 svn 上已经修正(同步到网页版还需要一段时间)

    我也强烈建议你去买本入门的书看一看,手册里有很多东西是很细节的,对于初学者(尤其是完全没有任何经验的初学者)来说会非常难以理解,而你无法分辨哪些是重点哪些是可以略过的细节的话阅读就会很难。。。
    tempdban
        23
    tempdban  
       2017-05-12 15:17:08 +08:00
    这头像一看就得被喷啊...
    z5864703
        24
    z5864703  
       2017-05-12 16:41:07 +08:00
    别人指出你的语法错误,你文档都不再重新去看,却总以为自己是对的?
    本来一个很简单的问题,楼主你搞这么复杂,还说别人敷衍了事?
    文档写的间接引用,到你这正文变成了间接调用?
    文档也没教你正文这样的创建数组写法吧。
    没底子想打别人脸反而被打脸?
    而且到现在还不肯承认自己的错误!能有点学习的态度么
    543400
        25
    543400  
    OP
       2017-05-12 19:48:02 +08:00
    @z5864703 第一我已经强调很多遍了我文档已经翻了,并且找不到对这种方式有过详细的解释,我从没以为我的是对的,我任何一句话都是对回复者有效的提问,请不要乱喷,看字就乱讲.第二我从头到尾没有说过别人敷衍了事,我一直在强调的是详尽并且合理的答案,ok?你又仔细看过我们的对话吗?你这样无脑指责又算怎么一回事? 还有 调用,引用就是一回事,你非得要在这里咬文嚼字来体现你的人文素养吗?我一直都是在寻找合理的答案,但是遇到你这种无脑的围观着,你觉得我该不该怼回去?
    543400
        26
    543400  
    OP
       2017-05-12 19:56:01 +08:00
    @noark9 关于爆炸的那句话我不是对你说的,只是我受不了吃瓜群众闹事不嫌事大的心态,对于任何的答案我都是保持有探究性的质疑态度,并且是经过合理的实践思考我才会更加希望能够得到一个明确的答案,所以我不想双方在这件事上互相浪费时间,互联网是一个平等的世界,我愿意接受,但拒绝委曲求全,该质疑就质疑,这是我的态度,如果在这件事上得罪了人,请见谅,但是对于你的耐心以及无私我是很敬佩,也非常感谢,但这些东西都不应该成为我对知识上的质疑,这完全是两方面的事,我该质疑的就会质疑,即便暴露出我智商的抓急,但我还是会去质疑,该感谢我一并感谢,这两种态度我都拎得清,不过还是特别感谢你的回复
    543400
        27
    543400  
    OP
       2017-05-12 20:00:51 +08:00
    @noark9
    @jhdxr

    关于入门书这一块我也是有体会的,主要是我心态有点记,想尽快掌握清除 php 的思想路线,所以是直接看文档去自学,这一点事实确实有点效果,现在有很多的 php 基本阅读起来困难不大,不过认真阅读了 @noark9 回复之后,察觉到自己只是会用,但是不懂用,在这之后我会认真去看完整一本入门书
    mingyun
        28
    mingyun  
       2017-05-12 23:47:02 +08:00
    @noark9 学习了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2958 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 00:34 · PVG 08:34 · LAX 17:34 · JFK 20:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.