2

寻求 PHP 架构师的建议!

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

有几种不同的方法用于调用这些解析器模块,我想知道哪些被认为是“正确的”PHP 结构。有些使用按引用传递,有些使用按值传递,有些是函数,有些是对象。它们都以某种方式修改输入参数。

一个超级简化的例子如下:

#!/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
)

使用了这么多不同的调用方法,我真的很不舒服,其中一些使用“&pointer”风格的函数对调用函数参数有隐藏的影响,一些需要主体编写它们的输出,还有一些独立编写它们的输出。

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

在 ParserA()、parse_b() 和 parse_c() 这三种调用方法中,如果有的话,哪种风格最合适?

4

4 回答 4

3

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

于 2009-09-08T09:48:01.707 回答
0

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

于 2009-09-08T09:59:10.730 回答
0

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

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

另请参阅:php.net:参考是什么

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

于 2009-09-08T10:05:47.643 回答
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;
    }
  }
}
于 2009-09-08T10:08:56.237 回答