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

正在学习PHP,写了几行代码总是出错,但是换一种方式就不出错了....求解释。。。。。

  •  
  •   yaocaptain · 2011-03-16 12:39:05 +08:00 · 5830 次点击
    这是一个创建于 5008 天前的主题,其中的信息可能已经有所发展或是发生改变。
    代码如下,把run()方法里面的foreach语句换成for就不会错了,但是foreach为什么会错我没搞懂:
    <html>
    <body>
    <p>
    <?php
    //连接数据库
    function db_connect(){
    $result=new mysqli('localhost','***','******','*****');
    if(!$result){
    echo 'could not connect to db<br/>';
    return false;
    }else
    return $result;
    }
    function get_lists(){
    $db=db_connect();
    $lists=array();
    $query="select a ,b from a_table ";
    $result=$db->query($query);
    for($i=0;$i<$result->num_rows;$i++){
    $row=$result->fetch_assoc();
    array_push($lists,$row);
    }
    return $lists;
    }

    function run(){
    $lists=get_lists();

    foreach($lists as $e){
    $e['c']=1;
    }

    // for($i=0;$i<sizeof($lists);$i++){
    // $lists[$i]['c']=1;
    // }
    foreach($lists as $a){
    echo $a['c']."<br/>";//就是这个地方经常跑出问题,说没有'c'这个Index.但是如果不用上面的
    } //foreach语句,而是用注释掉的for语句的话就没有问题了

    }

    run();
    ?>
    </p>
    </body>
    </html>
    21 条回复    1970-01-01 08:00:00 +08:00
    yesmeck
        1
    yesmeck  
       2011-03-16 12:49:31 +08:00
    这是一个提醒而不是一个错误。
    因为你的循环出来的$a里面没有带c这个key的值。
    $query = "select a ,b from a_table ";
    这里只有a,b两个key可以用。
    yesmeck
        2
    yesmeck  
       2011-03-16 12:52:35 +08:00
    哦,还有这句
    foreach ($lists as $e) {
    $e['c'] = 1;
    }
    这样$lists里面并不会多1这个值,
    要这样
    foreach ($lists as $key => $e) {
    $lists[$key]['c'] = 1;
    }
    huacnlee
        3
    huacnlee  
       2011-03-16 13:59:50 +08:00
    咋开始学PHP了啊
    yaocaptain
        4
    yaocaptain  
    OP
       2011-03-16 15:13:42 +08:00
    @yesmeck
    恩,我试了一下你的方法,果然'c'这个索引插进去了。然后我改了一下:
    foreach ($lists as $key => $e) {
    //$lists[$key]['c'] = 1;
    $e['c']=1;
    }
    结果却没有插进去。$e应该等于$lists[$key]的啊?然后我又测了一下$e==$lists[$key],它们是相等的。而且$lists并不是一个关联数组,应该用这个foreach($lists as $e)的语句提取元素吧。。。是不是语法在这里有特殊的地方,还是我有地方理解错了?
    benzhe
        5
    benzhe  
       2011-03-16 16:01:38 +08:00
    @yaocaptain $e 是$lists[$key] 的值
    arikado
        6
    arikado  
       2011-03-16 16:28:57 +08:00
    试试@@
    foreach($lists as &$e){
    $e['c']=1;
    }
    yesmeck
        7
    yesmeck  
       2011-03-16 16:31:51 +08:00
    @yaocaptain
    $e和$lists[$key]只是值相等而已,但内存里的存放位置是不同的

    @arikado
    这样是不行的。。。。
    因为$e并不是数组。。。
    yesmeck
        8
    yesmeck  
       2011-03-16 16:35:21 +08:00
    额,= =@arikado 我说错了
    arikado
        9
    arikado  
       2011-03-16 16:39:17 +08:00
    @yesmeck -。-其实我只看了foreach里面那段......>.<~
    yaocaptain
        10
    yaocaptain  
    OP
       2011-03-16 16:40:23 +08:00
    @benzhe
    @yesmeck
    $lists是一个存放数据库检索结果的二维数组,作为其中的元素$e和$lists[$key]都是一个关联数组,并不是基本类型。我以为它们共用的同一个数组,就像引用或指针一样的,无论使用哪个进行操作都会影响共用的数组.......这样的结果是不是意味着$e是$lists[$key]的完全copy,是两个值完全相同的数组?
    yesmeck
        11
    yesmeck  
       2011-03-16 16:42:19 +08:00
    是直传递的。
    @arikado那样写就是引用了。
    aligo
        12
    aligo  
       2011-03-16 16:51:35 +08:00
    用array_map,通过FP方式来解决这个问题
    $lists = array_map(function($e){
    $e['c']=1;
    return $e;
    }, $lists);

    无污染无副作用,不过用php来写这个实在太不美观了
    还是应该造个php代码生成器
    yaocaptain
        13
    yaocaptain  
    OP
       2011-03-16 16:59:55 +08:00
    @yesmeck
    我试了一下,貌似@arikado那样写仍然是值传递:
    <?php
    $a=array(1,2,3);
    $b=array(2,3,4);
    $c=array();
    array_push($c,$a);
    array_push($c,$b);
    foreach($c as $e){
    $e[0]=7;
    $e[1]=8;
    $e[2]=9;
    }
    echo $c[0][0].$c[0][1].$c[0][2]."<br/>";
    echo $c[1][0].$c[1][1].$c[1][2]."<br/>";

    ?>
    这段代码最终输出的是:
    123
    234
    foreach语句对$c没有进行任何修改
    yaocaptain
        14
    yaocaptain  
    OP
       2011-03-16 17:04:06 +08:00
    @aligo 哈哈有同感!$号敲得我烦死了!
    arikado
        15
    arikado  
       2011-03-16 17:08:01 +08:00
    @yaocaptain 你这段foreach后面是这样($c as $e)而不是($c as &$e) ? 没有漏掉"&" ?
    aligo
        16
    aligo  
       2011-03-16 17:08:48 +08:00
    虽然php的垃圾回收挺不靠谱的,不过php脚本的执行通常是随着http请求结束
    所以尽可能不要用引用传递什么的比较好,对于变量每次变更,按照php默认做法,都指向一个新的引用比较好

    不过php实在太不美观,缺乏表现力,从这个常用的array_map就可以看出-A-

    不知道楼主有兴趣没:http://v2ex.appspot.com/t/9646
    aligo
        17
    aligo  
       2011-03-16 17:12:58 +08:00
    楼主需求应该可以写成
    lists = lists.map(_['c']=1)
    美观直接一目了然,可惜只是我的YY
    aligo
        18
    aligo  
       2011-03-16 17:16:01 +08:00
    另外,连接在php中数据库应该用pdo比较好,fetchAll返回就是数组,不用手动遍历再push
    yaocaptain
        19
    yaocaptain  
    OP
       2011-03-16 17:17:26 +08:00
    @arikado
    - - 不好意思看漏了...多谢提醒!
    yaocaptain
        20
    yaocaptain  
    OP
       2011-03-16 17:25:28 +08:00
    @aligo
    http://v2ex.appspot.com/t/9646
    我心有余而力不足,编程只是入门水平而已- -
    yokle
        21
    yokle  
       2011-05-04 11:25:59 +08:00
    干嘛不直接 fetch_array 出来就是数组。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2706 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:10 · PVG 20:10 · LAX 04:10 · JFK 07:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.