PHP体系结构,以及按引用传递和按值传递

时间:2009-09-08 09:34:24

标签: php pass-by-reference

寻求PHP架构师的建议!

我对PHP并不十分熟悉,但已经接管了用该语言编写的大型分析包的维护。该体系结构旨在将报告的数据读入大型键/值数组,这些数组通过各种解析模块传递,以提取每个模块已知的报告参数。已知参数将从主阵列中删除,任何模块无法识别的剩余物都会被转储到一种显示“未知”数据点的全能报告中。

有几种不同的方法用于调用这些解析器模块,我想知道哪些被认为是“正确”的PHP结构。有些是使用pass-by-reference,有些是pass-by-value,有些是函数,有些是对象。所有这些都以某种方式修改输入参数。

一个超简化的例子如下:

#!/usr/bin/php
<?php

$values = Array("a"=>1, "b"=>2, "c"=>3, "d"=>4 );


class ParserA {
    private $a = null;
    public function __construct(&$myvalues) {
        $this->a = $myvalues["a"];
        unset($myvalues["a"]);
    }
    public function toString() { return $this->a; }
}

// pass-by-value
function parse_b($myvalues) {
    $b = $myvalues["b"];
    unset($myvalues["b"]);
    return Array($b, $myvalues);
}

// pass-by-reference
function parse_c(&$myvalues) {
    echo "c=".$myvalues["c"]."\n";
    unset($myvalues["c"]);
}

// Show beginning state
print_r($values);

// will echo "1" and remove "a" from $values
$a = new ParserA($values);
echo "a=".$a->toString()."\n";
print_r($values);

// w ill echo "2" and remove "b" from $values
list($b, $values) = parse_b($values);
echo "b=".$b."\n";
print_r($values);

// will echo "3" and remove "c" from $values
parse_c($values);
print_r($values);

?>

输出将是:

Array
(
    [a] => 1
    [b] => 2
    [c] => 3
    [d] => 4
)
a=1
Array
(
    [b] => 2
    [c] => 3
    [d] => 4
)
b=2
Array
(
    [c] => 3
    [d] => 4
)
c=3
Array
(
    [d] => 4
)

我真的很不舒服使用这么多不同的调用方法,其中一些使用“&amp; pointer”式函数对调用函数参数有隐藏效果,有些需要主体写出他们的输出,有些独立编写输出。

我更愿意选择一种方法并坚持下去。为了做到这一点,我还想知道哪个是最有效的;我阅读PHP文档表明,由于它使用了copy-on-write,因此使用指针直接传递对象和重新读取返回值之间的性能差异应该不大。我也更喜欢使用面向对象的结构,但对构造函数的输入参数的隐藏更改感到不舒服。

在三种调用方法中,ParserA(),parse_b()和parse_c(),如果有的话,它们是最合适的样式吗?

4 个答案:

答案 0 :(得分:3)

我不是真正的PHP专家,但从我的经验来看,传递价值更好。这种方式代码不会有副作用,这意味着它更容易理解和维护,并在其上做各种疯狂的事情,比如将它用作map函数的回调。所以我全都采用parse_b做事的方式。

答案 1 :(得分:0)

仅供参考:在PHP中,无论如何,对象总是通过引用传递。此外,如果您有一个包含对象和标量值的数组,则标量值按值传递,但是按引用传递对象。

答案 2 :(得分:0)

作为PHP的一般规则,除非确实需要,否则不要使用引用。 PHP中的引用也不是大多数人所期望的:

  

“PHP中的引用是一种以不同的名称访问相同变量内容的方法。它们不像C指针;相反,它们是符号表别名。”“

另见:php.net: What References Are

简而言之:
处理这个PHP的正确方法是使用创建一个对象,该对象按值传递变量或使用array_map操作数组(array_map允许您将回调函数应用于数组元素。)

答案 3 :(得分:0)

我会投票反对一般提出的方法,但对于他们,我认为parse_b最好的主意。

我认为将“数据”数组包装在一个可以让你轻松“弹出”键的类中更好的设计。所以解析器最终看起来像:

class ParserA {
  private $a = null;
  public function __construct(My_Data_Class $data) {
    $this->a = $data->popValue("a");
  }
  public function toString() { return $this->a; }
}

示例实现

class My_Data_Class {
  protected $_data;
  public function __construct(array $data) {
    $this->_data = $data;
  }
  public function popValue($key) {
    if (isset($this->_data[$key])) {
       $value = $this->_data[$key];
       unset($this->_data[$key]);
       return $value;
    }
  }
}