创建一个HTML选择元素生成器

生成一个HTML单选元素的过程与生成单选按钮的过程类似。但标签的结构不同,因为需要生成一个SELECT标签和一系列OPTION标签。

如何做...

1.首先,创建一个新的Application\Form\Element\Select类,该类扩展Application\Form\Generic

2. 我们之所以要扩展Generic而不是Radio,是因为元素的结构完全不同。

namespace Application\Form\Element;

use Application\Form\Generic;

class Select extends Generic
{
  // code
}

3. 类的常量和属性只需要稍微添加到 Application\Form\Generic中即可。与单选按钮或复选框不同,不需要考虑间隔符或所选文本的位置。

const DEFAULT_OPTION_KEY = 0;
const DEFAULT_OPTION_VALUE = 'Choose';

protected $options;
protected $selectedKey = DEFAULT_OPTION_KEY;

4. 现在我们把注意力转移到设置选项上。由于HTML选择元素可以选择单个或多个值,所以$selectedKey属性可以是字符串或数组。因此,我们不为这个属性添加类型提示。然而,重要的是,我们要确定是否已经设置了多重属性。这可以通过继承父类的$this->attributes属性获得。

5. 如果已经设置了多重属性,就必须将name属性表述为一个数组。因此,如果是这种情况,我们将在名称后面加上[]

public function setOptions(array $options, $selectedKey = self::DEFAULT_OPTION_KEY)
{
  $this->options = $options;
  $this->selectedKey = $selectedKey;
  if (isset($this->attributes['multiple'])) {
    $this->name .= '[]';
  } 
}

在PHP中,如果HTML select multiple属性被设置,而name属性没有被指定为一个数组,那么将只返回一个值。

6. 在我们定义核心的getInputOnly()方法之前,我们需要定义一个方法来生成select标签。然后我们使用sprintf()返回最终的HTML,使用$pattern$namegetAttribs()的返回值作为参数。

7. 我们用<select name="%s" %s>替换$pattern的默认值。然后,我们在属性中循环,将它们添加为键值对,中间有空格。

protected function getSelect()
{
  $this->pattern = '<select name="%s" %s> ' . PHP_EOL;
  return sprintf($this->pattern, $this->name, 
  $this->getAttribs());
}

8. 接下来,我们定义一个方法来获取将与选择标签相关联的选项标签。

9. 你还记得,$this->options数组中的key代表返回值,而数组中的value部分代表屏幕上出现的文本。如果$this->selectedKey是数组形式,我们检查值是否在数组中。否则,我们假设$this->selectedKey是一个字符串,我们简单地判断它是否等于键。如果选定的键匹配,我们添加选定的属性。

protected function getOptions()
{
  $output = '';
  foreach ($this->options as $key => $value) {
    if (is_array($this->selectedKey)) {
        $selected = (in_array($key, $this->selectedKey)) 
        ? ' selected' : '';
    } else {
        $selected = ($key == $this->selectedKey) 
        ? ' selected' : '';
    }
        $output .= '<option value="' . $key . '"' 
        . $selected  . '>' 
        . $value 
        . '</option>';
  }
  return $output;
}

10. 最后我们准备覆盖核心的getInputOnly()方法。

11. 你会注意到,这个方法的逻辑只需要捕获前面代码中描述的getSelect()getOptions()方法的返回值。我们还需要添加最后的</select>标签。

public function getInputOnly()
{
  $output = $this->getSelect();
  $output .= $this->getOptions();
  $output .= '</' . $this->getType() . '>'; 
  return $output;
}

如何运行...

将上述代码复制到Application/Form/Element文件夹下新建一个Select.php文件。然后定义一个chap_06_form_element_select.php调用脚本,设置自动加载和锚定新类。

<?php
require __DIR__ . '/../Application/Autoload/Loader.php';
Application\Autoload\Loader::init(__DIR__ . '/..');
use Application\Form\Generic;
use Application\Form\Element\Select;

接下来,使用第一个示例中定义的数组$wrappers定义包装器。你也可以使用在创建HTML单选元素生成器配方中定义的$statusList数组。然后你可以创建select元素的实例。第一个实例是单选,第二个是多选。

$status1 = new Select('status1', 
           Generic::TYPE_SELECT, 
           'Status 1',
           $wrappers,
           ['id' => 'status1']);
$status2 = new Select('status2', 
           Generic::TYPE_SELECT, 
           'Status 2',
           $wrappers,
           ['id' => 'status2', 
            'multiple' => '', 
            'size' => '4']);

查看是否有来自$_GET的状态输入,并设置选项。任何输入都将成为选定的键。否则,选定的键就是默认值。你会记得,第二个实例是多重选择,所以从$_GET获得的值和默认设置都应该是数组的形式。

$checked1 = $_GET['status1'] ?? 'U';
$checked2 = $_GET['status2'] ?? ['U'];
$status1->setOptions($statusList, $checked1);
$status2->setOptions($statusList, $checked2);

最后,一定要定义一个提交按钮(如本章创建通用表单元素生成器示例中所示)。

实际的显示逻辑与单选按钮示例相同,只是我们需要渲染两个独立的HTML选择实例。

<form name="status" method="get">
<table id="status" class="display" cellspacing="0" width="100%">
  <tr><?= $status1->render(); ?></tr>
  <tr><?= $status2->render(); ?></tr>
  <tr><?= $submit->render(); ?></tr>
  <tr>
    <td colspan=2>
      <br>
      <pre>
        <?php var_dump($_GET); ?>
      </pre>
    </td>
  </tr>
</table>
</form>

下面是实际输出。

此外,您还可以看到元素在查看源页面中的出现方式。

最后更新于