只为呈现单个表单元素而编写类是否正确


Is it correct to write a Class just to render a single form element?

所以我和老板无法就如何最好地呈现表单元素达成一致。我们的表格如下:

<form class='myform'>
    <input type=text class="username" />
    <span><img class="question-mark-icon" src='icon.png' /></span>
    <div class="tooltip"><p>Your username.</p></div>
    // Other form elements here
</form>

我们有三种形式,其中有一个或两个相同的元素。现在,它们是通过一个辅助函数渲染的,所以如果我调用username(),它会渲染该元素及其工具提示。所以实际上我们的一种形式是这样的:

<form class='myform'>
     <?php username(); ?>
     // Other form elements here
</form>

我认为它可以正常工作,这就是Wordpress和我读过的其他代码的工作方式,所以我认为这是最好的做法。但他认为,我们应该像OOP中这样使其面向对象:

class FormElements {
    public function username() {
       echo '<input type=text class="username" /><span><img class="question-mark-icon" src='icon.png' /></span>
       <div class="tooltip"><p>Your username.</p></div>';
    }
} 

很明显,要呈现username输入,应该是这样的:

$formEls = new FormElements();
$formEls->username();

因此,有人能清楚地告诉我们为什么这样做比把它放在这样的辅助函数中更好/更糟吗:

function username() {
    echo '<input type=text class="username" /><span><img class="question-mark-icon" src='icon.png' /></span>
        <div class="tooltip"><p>Your username.</p></div>';
}

我的论点是,创建一个类只是为了呈现一个元素,而你可以使用一个简单的辅助函数来实现这一点,这是愚蠢的吗?此外,它也没有公正地对待OOP原则。但他不相信我,并要求我给他指一篇权威文章或任何有权威的东西来支持我的主张/理解。

编辑:

你能告诉我为什么把它放在课堂上是可以的吗?我无法为它定义一个合适的对象模型。我通常为具有明确属性和操作的对象创建类。对于单个表单元素,我不明白为什么要将其封装在类中。

如果该类只有一个方法,则可以使用助手而不是为此创建类。除非你认为你将来会为它添加新功能。在这种情况下,我会试着把它分成这些部分。。。

例如,您可以将其拆分为:

1) 一个Form.class.php文件,它可以包含每个表单字段。可能是这样的。。。即:

class Form {
  private $fields = array();
  private $method;
  private $action;
  public _construct( $action, $method, $arrayWithFieldsData){ //here you should populate with FormField instances the private $fields array, and set the method and action attributes };
  public toHtml() { 
    //here you should RETURN a string 
    $output = '<form action="'.$this->action.'" method="'.$this->method.'" />';
    foreach($this->fields as $f){
      $output .= $f->toHtml();
    }
    return $output.' </form>';
  };
  public validate() { //here you could implement form validation };
}

2) AbstractFormField.class.php或FormFieldInterface.php,其可能具有getHtml()签名

abstract class AbstractFormField {
    public function _construct($arrayOfHtmlAttrs){
      $this->htmlAttr = $arrayOfHtmlAttrs;
    }
    public function toHtml();
}

3) 每个FormField的一个类,它将扩展AbstractFormField或实现FormFieldInterface。即:InputFormField.class.php、HiddenFormField.cclass.php、SelectFormField.cClass.php。

class InputFormField extends AbstractFormField {
    public method toHtml(){
      $out = '<input type="text" ';
      foreach ($this->htmlAttr as $key => $value){
        $out .= " $key = $value ";
      }
      $out .= " />
      return $out;
    }
}

4) 这段代码可以放在你的html上,尽管最好在控制器上隔离它:

<?php 
  $fields = array(
              'username' => array( 'text', array('value' => $username, 'class' => 'username-input', 'id' => "some-id-for-your-fields)),
              'password' => array( 'password', array('value' => $username, 'class' => 'username-pswd', 'id' => "some-id-for-your-field)),
  );
  $myForm = new Form($action, $method, $fields);
?>

5) 这个在你的html:上

  <?php echo $myForm->toHtml(); ?>

我认为最好将它们定义为静态函数:

class FormElements {
    public static function username() {
        // ...
    }
}

稍后:

<?php FormElements::username() ?>

除了如何编写类之外,还有可扩展性的问题。

考虑一下:稍后您会意识到,您还需要向表单中添加一个fullName元素。使用您的方法,您将添加一个名为fullName()的新函数。到目前为止还不错,但如果你需要越来越多呢。你会有很多功能。例如,如果你需要为电子邮件提供类似的功能,事情会变得一团糟,你不知道现在的功能是什么。有了类,这就更容易维护和扩展了。你只能这样做FormElement::username()EMailElement::username()

(如果完全这样做是个好主意,请忽略。)

看看事情变得容易多了?

我们可以进一步推动这一点,并可以添加这样的User类:

class User {
    protected $infos = array();
    public function __construct($infos = array()) {
        $this->infos = $infos;
    }
}

现在,Element类可以扩展user类,并从一个地方获取所有信息,例如用户名。

当然,你必须遵循这样的顺序:

$user = new User(array("username" => "Bob"));
$form_element = new FormElement($user);

你的Element类可能看起来像这样:

abstract class Element extends User {
    protected function getStyle($element);
    protected function getTag($element);
    // etc .. Add implementation as well!!
}

当然,你可以添加一个Element类,它将被FormEmail扩展,添加接口等。

但是在这里使用OOP方法似乎更好。

也许这会有所帮助。我在过去实现了一个表单生成器,它在CodeIgniter-php框架之上工作,它允许定义动态表单;您可以逐个字段进行定义,也可以在一行中从Doctrine ORM模型定义构建表单。它还可以扩展到与其他ORM一起工作。也许给你一些关于如何实现你的想法是不必要的。我不再维护它了。当然:如果你觉得它符合你的需求,可以随意使用。

我两年多前就已经实施了,在一个生产项目中使用了大约一年。这让我有机会反复学习并逐步改进它。稍后,我将其打包到一个提交中,并将其推送到Github。不是最先进的。

今天我会用不同的方式来做,例如,我会更多地利用神奇的方法来简化代码并使其更加灵活(比如FormField类,在我看来它看起来太Java了)。

这是代码:

https://github.com/theconejou/form_generator

以下是核心类。

https://github.com/theconejou/form_generator/tree/master/forms/base

附言:嗯。。。我读了很长一段时间的代码,今天我肯定会做不同的事情:有些类中的方法太大,太不简单,太Java for php。。。无论如何