Php 通过数组定义类选项是一种不好的做法吗?
当我们看一看像Dojo、Mootools、jQuery、JS Prototype等Javascript框架时,我们会发现选项通常是通过如下数组定义的:Php 通过数组定义类选项是一种不好的做法吗?,php,class,settings,options,Php,Class,Settings,Options,当我们看一看像Dojo、Mootools、jQuery、JS Prototype等Javascript框架时,我们会发现选项通常是通过如下数组定义的: dosomething('mainsetting',{duration:3,allowothers:true,astring:'hello'}); 在编写PHP类时实现相同的想法是一种糟糕的做法吗 一个例子: class Hello { private $message = ''; private $person = '';
dosomething('mainsetting',{duration:3,allowothers:true,astring:'hello'});
在编写PHP类时实现相同的想法是一种糟糕的做法吗
一个例子:
class Hello {
private $message = '';
private $person = '';
public function __construct($options) {
if(isset($options['message'])) $this->message = $message;
if(isset($options['person'])) $this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
class Hello {
private $message = '';
private $person = '';
public function __construct() {}
public function setmessage($message) {
$this->message = $message;
}
public function setperson($person) {
$this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
常规方法:
class Hello {
private $message = '';
private $person = '';
public function __construct($options) {
if(isset($options['message'])) $this->message = $message;
if(isset($options['person'])) $this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
class Hello {
private $message = '';
private $person = '';
public function __construct() {}
public function setmessage($message) {
$this->message = $message;
}
public function setperson($person) {
$this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
第一个示例的优点是,您可以传递任意多的选项,而类将只提取它需要的选项
例如,从JSON文件提取选项时,这可能很方便:
$options = json_decode($options);
$hello = new Hello($options);
我经常这样做:
$options = json_decode($options);
$hello = new Hello();
if(isset($options['message'])) $hello->setmessage($options['message']);
if(isset($options['person'])) $hello->setperson($options['person']);
这种模式有名字吗?你认为这是一种不好的做法吗
为了简单起见,我在示例中留下了验证等内容。有好的方面,也有坏的方面 好的:
class Hello {
private $message = '';
private $person = '';
public function __construct($options) {
if(isset($options['message'])) $this->message = $message;
if(isset($options['person'])) $this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
class Hello {
private $message = '';
private $person = '';
public function __construct() {}
public function setmessage($message) {
$this->message = $message;
}
public function setperson($person) {
$this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
- 不需要多个方法签名(如支持重载)
- 与前一点保持一致:方法可以按任意顺序使用参数调用
- 可以动态生成参数,而无需指定将出现的每个参数(例如:根据用户输入动态创建参数数组并将其传递给函数)
- 不需要像
、setName
、setThis
等“样板”方法,尽管您可能仍然希望包含它们setThis
- 默认值可以在函数体中定义,而不是在签名中定义(jQuery经常使用这种模式。它们经常
$。扩展
传递给具有默认值数组的方法的选项。在您的情况下,您可以使用
)数组\ u merge()
class Hello {
private $message = '';
private $person = '';
public function __construct($options) {
if(isset($options['message'])) $this->message = $message;
if(isset($options['person'])) $this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
class Hello {
private $message = '';
private $person = '';
public function __construct() {}
public function setmessage($message) {
$this->message = $message;
}
public function setperson($person) {
$this->person = $person;
}
public function talk() {
echo $this->person . ' says: ' . $this->message;
}
}
- 除非您正确地宣传每个选项,否则您的类可能更难使用,因为很少有人知道支持哪些选项
- 当您提前知道需要传递哪些参数时,这是创建参数数组的又一个步骤
- 对于用户来说,默认值的存在并不总是显而易见的,除非提供了文档或者他们可以访问源代码
在我看来,这是一项伟大的技术。我最喜欢的方面是,您不需要提供具有不同签名的重载方法,而且签名也不是一成不变的。我不知道名称,但我真的怀疑这是一种不好的做法,因为如果有强制选项,您通常在不声明小的o quick函数或类属性时使用此方法,它们应该在构造函数的参数列表中。然后添加带有默认值的可选选项
public function __construc($mandatory1, $mandatory2, $optional1="value", $optional2="value") { }
如果所有选项都是可选的,那么创建一个采用数组的构造函数会很有用。创建对象比使用“普通构造函数”更容易:您可以只提供所需的选项,而使用“普通构造函数”如果您想提供$optional2,则必须提供$optional1(甚至将其设置为默认值)。我不会说这是一种不好的做法,至少如果您信任数据源的话 另一种可能是根据选项数组键动态调用setter,如下所示:
public function __construct($options) {
foreach($options as $option => $value) {
$method = 'set'.$option;
if(method_exists($this, $method)
call_user_func(array($this, $method, $value);
}
}
这种方法没有什么错,尤其是当您有很多参数需要传递给构造函数时。这还允许您在构造函数中为它们设置默认值和
array\u merge()
如果你想要这个“模式”的实例,请查看symfony框架,他们几乎在任何地方都使用它:这里是当你给参数命名时,它被称为“命名符号”v.s.“位置符号”,其中参数必须按特定顺序排列
在PHP中,您可以传递一个“options”参数,以提供与其他语言(如Python)相同的效果,在这些语言中,您可以使用真正的命名符号。这不是一个坏的做法,但通常是在有充分理由这样做的情况下进行的(例如,在您的示例中,或者在有很多参数的情况下,它们并不都需要按任何特定的顺序设置)。为什么不同时进行设置?拥有你的构造函数蛋糕,并与静态工厂“命名构造函数”一起享用它:
$newHello=Hello::createFromArray($options)代码>
首先,按顺序设置带有选项的构造函数。然后将这样的静态方法添加到同一个类中:
public static function createFromArray($options){
$a = isset($options['a']) ? $options['a'] : NULL;
$b = isset($options['b']) ? $options['b'] : NULL;
$c = isset($options['c']) ? $options['c'] : NULL;
return new Hello($a, $b, $c);
}
这将使新开发人员和IDE感到高兴,因为他们仍然可以看到构建对象所需要的东西
我同意这里答案的一般态度,即无论哪种方式都是可行的解决方案,这取决于您的需求,并且对您的应用程序更有利。我不这么认为,它在Drupal CMS中被广泛使用!谢谢很高兴知道这么大的一个名字在使用它。IIRC,JS语法不是作为数组,而是作为一个对象的“序列化”表示(例如一直在JSON中使用)。它被称为统一构造函数:@scoates:你确定吗?PHP对“统一构造函数”有自己的定义:+½用于指出正确文档的需要+½同时提及优点和缺点。好的和坏的都排得很好!我想在其中实现它的项目有很好的文档,所以应该不会有任何问题。+1提到这是一种用不支持命名参数的语言获取命名参数的黑客行为。在接触到这种黑客之前,通常没有多少人知道命名参数。