0

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

<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 原则也不公平。但他不相信我,并要求我向他指出一篇权威文章或任何有权威的东西来支持我的主张/理解。

编辑:

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

4

4 回答 4

1

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

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

之后:

<?php FormElements::username() ?>
于 2013-07-02T01:24:05.353 回答
1

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

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

今天我会做不同的事情,例如,我会更多地利用魔术方法来简化代码并使其更灵活(例如 FormField 类在我看来看起来太Java了)。

这是代码:

https://github.com/theconejou/form_generator

这是核心课程。

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

PS:嗯......我在很长一段时间后正在阅读代码,今天我肯定会做不同的事情:某些类中的方法太大,简单性太低,对于php来说太Java......无论如何......

于 2013-07-02T01:45:30.903 回答
1

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

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

(忽略这样做是否是个好主意。)

看看事情变得多么容易?

我们可以更进一步,可以添加这样的 User类:

class User {

    protected $infos = array();

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

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

当然,您必须遵循这种顺序:

$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将通过Formand扩展的类Email,添加接口等。

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

于 2013-07-02T01:40:17.533 回答
1

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

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

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.class.php、SelectFormField.class.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(); ?>
于 2013-07-02T04:27:10.590 回答