быстрого и простого решения
Вы могли бы сделать ваша жизнь проще и используйте 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>';
Улучшение: Развязка Каталог Filtering от переключателе здания
Если вы хотите, чтобы отделить логику фильтрации из цикла 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
, текущий элемент будет отфильтрован на итерации.
Вы создаете переключатель, как это тогда:
echo '<select name="vids" size="4">';
foreach($iterator as $file) {
printf("<option>%s</option>\n", htmlentities($file->getBasename()));
}
echo '</select>';
Альтернатива подклассы FilterIterator
Если вы слишком ленивы, чтобы написать отдельную FilterIterator
или думают, что это просто не стоит для в конкретном случае или уже есть валидаторы где-то и не хотят дублировать их код, но все же хотят отделить фильтрацию и создание SelectBox, вы также можете использовать этот пользовательский FilterChainIterator
и добавить к нему обратные вызовы:
$iterator = new FilterChainIterator(new DirectoryIterator('/path/to/videos'));
$iterator->addCallback(function($file) {
return $file->isFile() === TRUE &&
$file->getBasename() !== '.DS_Store';});
Создание SelectBox будет таким же, как показано выше.
Улучшение: Создание создания переключателя многоразового
Кроме того, если вы хотите сделать многоразовое создание переключателя, почему бы не создать помощник для него. Ниже приведено очень простое, которое использует DOM для создания фактического HTML. Вы проходите в любом итераторе, и он будет создавать HTML для вас, когда вы называете это render()
метод или использовать его в контексте строки:
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();
}
}
А потом печать переключателя из итератора так просто, как
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>
Почему идентичная (===) оператор в '$ файл-> ISFILE() === TRUE,? Я бы предположил, что просто '$ file-> isFile()' будет работать одинаково. –
+1 для DirectoryIterator –