快速简便的解决方案
您可以让您的生活更轻松,并使用DirectoryIterator 浏览目录。
echo '<select name="vids" size="4">';
foreach( new DirectoryIterator('/path/to/videos') as $file) {
if( $file->isFile() === TRUE && $file->getBasename() !== '.DS_Store') {
printf("<option>%s</option>\n", htmlentities($file->getBasename()));
}
}
echo '</select>';
改进:从 SelectBox 构建中解耦目录过滤
如果您想将过滤逻辑与foreach 循环分离,您可以将FilterIterator 子类化以将该逻辑封装到它的accept() 方法中。然后 DirectoryIterator 必须包装到 FilterIterator 中。重点当然是可重用性:
class MyFilter extends FilterIterator
{
public function accept()
{
return $this->current()->isFile() === TRUE &&
$this->current()->getBasename() !== '.DS_Store';
}
}
$iterator = new MyFilter(new DirectoryIterator('/path/to/videos'));
当您在过滤迭代器上使用foreach 时,它将自动触发accept()。如果accept() 返回FALSE,则当前元素将在迭代中被过滤掉。
然后像这样创建 SelectBox:
echo '<select name="vids" size="4">';
foreach( $iterator as $file) {
printf("<option>%s</option>\n", htmlentities($file->getBasename()));
}
echo '</select>';
子类化 FilterIterator 的替代方法
如果你懒得写一个单独的FilterIterator 或者认为它对于特定情况不值得,或者已经在某个地方有验证器并且不想复制他们的代码,但仍然想解耦过滤和选择框的创建,你也可以使用这个自定义的FilterChainIterator 并为其添加回调:
$iterator = new FilterChainIterator(new DirectoryIterator('/path/to/videos'));
$iterator->addCallback(function($file) {
return $file->isFile() === TRUE &&
$file->getBasename() !== '.DS_Store';});
SelectBox 的创建与上图相同。
改进:使 SelectBox 创建可重用
另外,如果你想让 SelectBox 创建可重用,为什么不为它创建一个 Helper。下面是一个非常简单的,它使用 DOM 创建实际的 HTML。您传入任何迭代器,当您调用它的 render() 方法或在字符串上下文中使用它时,它将为您创建 HTML:
class SelectBox
{
protected $iterator;
public function __construct(Iterator $iterator)
{
$this->iterator = $iterator;
}
public function render()
{
$dom = new DOMDocument;
$dom->formatOutput = TRUE;
$dom->loadXml('<select name="vids"/>');
$dom->documentElement->appendChild(new DOMElement('option', 'Pick One'));
foreach($this->iterator as $option) {
$dom->documentElement->appendChild(
new DOMElement('option', $option));
}
return $dom->saveXml($dom->documentElement);
}
public function __toString()
{
return $this->render();
}
}
然后从 Iterator 打印 SelectBox 就像
echo new SelectBox(new MyFilter(new DirectoryIterator('/path/to/videos')));
这很灵活,因为所有东西都有迭代器。比如
echo new SelectBox(new ArrayIterator(array('foo', 'bar', 'baz')));
会给出一个整齐的格式
<select>
<option>Pick One</option>
<option>foo</option>
<option>bar</option>
<option>baz</option>
</select>