通过数组定义类选项是一个坏习惯吗?
当我们看一下 Dojo、Mootools、jQuery、JS Prototype 等 Javascript 框架时,我们发现选项通常是通过这样的数组定义的:
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;
}
}
第一个示例的优点是您可以传递任意数量的选项,并且该类只会提取它需要的选项。
例如,从 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']);
此模式有名称吗?您认为这是一个不好的做法吗?
为了简单起见,我在示例中保留了验证等内容。
When we take a look at Javascript frameworks like Dojo, Mootools, jQuery, JS Prototype, etc. we see that options are often defined through an array like this:
dosomething('mainsetting',{duration:3,allowothers:true,astring:'hello'});
Is it a bad practice to implement the same idea when writing a PHP class?
An example:
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;
}
}
The regular approach:
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;
}
}
The advantage in the first example is that you can pass as much options as you want and the class will only extract those that it needs.
For example, this could be handy when extracting options from a JSON file:
$options = json_decode($options);
$hello = new Hello($options);
This is how I do this regulary:
$options = json_decode($options);
$hello = new Hello();
if(isset($options['message'])) $hello->setmessage($options['message']);
if(isset($options['person'])) $hello->setperson($options['person']);
Is there a name for this pattern and do you think this is a bad practice?
I have left validation etc. in the examples to keep it simple.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
有好的方面,也有坏的方面。
优点:
setName
、setThis
、setThat
等,尽管您可能仍想包含它们$ .extend
传递给带有默认值数组的方法的选项在您的情况下,您将使用array_merge()
)坏处:
在我看来,这是一项很棒的技术。我最喜欢的方面是,您不需要提供具有不同签名的重载方法,并且签名不是一成不变的。
There are good and bad aspects.
The good:
setName
,setThis
,setThat
, etc., although you might still want to include them$.extend
the options passed to a method with an array of default values. In your case, you would usearray_merge()
)The bad:
In my opinion, it's a great technique. My favorite aspect is that you don't need to provide overloaded methods with different signatures, and that the signature isn't set in stone.
这种方法没有任何问题,特别是如果您有很多参数需要传递给构造函数。这还允许您在构造函数中为它们设置默认值和
array_merge()
(有点像所有 jQuery 插件)如果您想要这种“模式”的实时示例,查看 symfony 框架,他们几乎在所有地方都使用它:这里是 sfValidatorBase构造函数的示例
There's nothing wrong with that approach, especially if you have a lot of parameters you need to pass to a constructor. This also allows you to set default values for them and
array_merge()
them inside a constructor (kinda like all jQuery plugins do)If you want live examples of this "pattern", check out symfony framework, they use it almost every where: here's an example of sfValidatorBase constructor
当您给出参数名称时,它称为“命名表示法”与“位置表示法”,其中参数必须按特定顺序排列。
在 PHP 中,您可以传递“选项”参数来实现与其他语言(如 Python)相同的效果,您可以在其中使用真正的命名表示法。这不是一个坏习惯,但通常在有充分理由的情况下这样做(即在您的示例中或有很多参数且不需要按任何特定顺序设置的情况下)。
When you give the arguments names it's called "Named Notation" v.s. "Positional Notation" where the arguments must be in a specific order.
In PHP you can pass an "options" parameter to give the same effect as other languages (like Python) where you can use a genuine Named Notation. It is not a bad practice, but is often done where there is a good reason to do it (i.e. in your example or a case where there are lots of arguments and they do not all need to set in any particular order).
我不知道这个名字,但我真的怀疑这是一个不好的做法,因为当你不想声明一个小或快速的函数或类属性时通常会使用它
I don't know the name, but i really doubt it is a bad practice, since you usally use this when you wan't to declare a small o quick function or class property
如果有强制选项,它们应该在构造函数的参数列表中。然后添加具有默认值的可选选项。
如果所有选项都是可选的,那么创建一个采用数组的构造函数会很有用。创建对象比使用“普通构造函数”更容易:您可以只提供您想要的选项,而使用“普通构造函数”如果您想提供 $Optional2,则必须提供 $Optional1 (甚至设置它)为默认值)。
If there are mandatory options, they should be in the constructor's parameter list. Then you add the optional options with default values.
If all of your options are optional, then it can be useful to create a constructor taking an array. It would be easier to create the object than with a "normal constructor" : you could provide just the options you want, while with a "normal constructor" if you want to provide $optional2, you have to provide $optional1 (even setting it to the default value).
我不会说这是不好的做法,至少如果你相信数据的来源的话。
另一种可能性是根据选项数组键动态调用设置器,如下所示:
I wouldn't say its bad practice, at least if you trust the source of the data.
Another possibility would be dynamically calling the setters according to the options array key, like the following:
为什么不两者都做呢?使用静态工厂“命名构造函数”让你的构造函数鱼与熊掌兼得:
$newHello = Hello::createFromArray($options);
首先,您的构造函数按顺序包含选项。然后将这样的静态方法添加到同一个类中:
这将使新开发人员和 IDE 感到高兴,因为他们仍然可以看到构建对象所需的内容。
我同意这里答案的总体态度,无论哪种方式都是可行的解决方案,具体取决于您的需求,并且哪种方式对您的应用程序更有利。
Why not do both? Have your constructor cake and eat it too with a static factory "named constructor":
$newHello = Hello::createFromArray($options);
You first have your constructor with the options in order. Then add a static method like this to the same class:
This will keep new developers and IDE's happy as they can still see what it takes to construct your object.
I agree with the general attitude of the answers here in that either way is a viable solution depending on your needs and which is more beneficial for your app.