В моем приложении есть видео с именами папок. Я хочу, чтобы raed весь файл только в этой папке, которую я сделал почти, он не показывает какую-либо папку в папке видео, кроме .DS_Store, в настоящее время я применил, если условие, чтобы скрыть это, но я хочу идеальное решение, может ли кто-нибудь помочь: – мой код : —-
$dir = "../videos/"; $dh = opendir($dir); print '<select size="4" name="vidfile">'; while (($file = readdir($dh)) !== false) { if (is_file($dir.'/'.$file) && $file != "." && $file != "..") { if ($file!=".DS_Store") { print "<option>{$file}</option>"; } } } print '</select>'; closedir($dh);
Быстрое и простое решение
Вы можете упростить свою жизнь и использовать 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
или подумайте, что это просто не стоит для конкретного случая или у вас уже есть валидаторы, и вы не хотите дублировать их код, но все же хотите разделить создание фильтров и SelectBox, вы также можете использовать этот пользовательский интерфейс FilterChainIterator
и добавить к нему обратные вызовы:
$iterator = new FilterChainIterator(new DirectoryIterator('/path/to/videos')); $iterator->addCallback(function($file) { return $file->isFile() === TRUE && $file->getBasename() !== '.DS_Store';});
Создание SelectBox будет таким же, как показано выше.
Улучшение: создание CreateBox для многократного использования
Кроме того, если вы хотите сделать создание 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(); } }
И затем печать SelectBox из Iterator так же проста, как и
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>
<?php $dir = '../videos/'; if($dh = opendir($dir)){ echo '<select size="4" name="vidfile">'; while(($file=readdir($dh)) !== FALSE){ $file = $dir . '/' . $file; if(!is_file($file) || substr($file, 0, 1) == '.'){ continue; } printf('<option>%s</option>', htmlentities($file)); } echo '</select>'; closedir($dh); } ?>
Во-первых, если opendir терпит неудачу, не продолжайте мусор. Он игнорирует нефайлы (каталоги) и файлы, начинающиеся с точки (включая., .., .htaccess и т. Д.).
Вот вариант, который работает с glob()
вместо этого, имеет массив исключенных файлов и собирает все элементы option
а затем выводит их как один. Кроме того, glob()
позволяет фильтровать определенные расширения файлов через синтаксис привязки, как показано в строке с комментариями.
$dir = "../videos"; $mask = "*"; // $mask = "*.{wmv,mpeg,mpg}"; // get only files of these types $files = glob($dir."/".$mask); $excluded_files = array(".DS_store"); $html = null; if (count($files) > 0) foreach ($files as $file) { $filename = basename($file); if (in_array($filename, $excluded_files)) continue; $html.="<option>".htmlentities($filename)."</option>"; } echo $html;
Просто if ($file[0] == ".") continue;
вместо этих 2, если это, вероятно, то, что вы ищете.
Хотя я бы сделал это несколько иначе, в двух частях.
получение данных:
<?php $dir = "../videos/"; $dh = opendir($dir); $filesarr = array(); while (($file = readdir($dh)) !== false) { if ($file[0] != ".") $filesarr[] = $file; } closedir($dh); ?>
и отображаемая часть данных:
<select size="4" name="vidfile"> <?php foreach ($filesarr as $file): ?> <option><?php echo $file ?></option> <?php endforeach ?> </select>
мне кажется более чистым