Теперь требуется функция, с помощью которой можно будет определить существует файл, на который указывает символическая ссылка, или нет. Некоторый аналог функции linkinfo() для windows. Если есть идеи, пишите!
Работая над своим проектом и решая очередную задачу, я столкнулся необходимостью использования символических ссылок на файлы. Все бы ничего, но для windows php-функции для работы с символическими ссылками не реализованы. На сервере unix, однако разработка ведется в среде windows на Денвере.
Немного погуглив, я обналужил - в винде таки есть поддержка символических ссылок!!! Правда нормальная поддержка симлинков появилась сравнительно недавно, и если у вас WinXP, то вам ничего не светит.
Итак, для работы вам понадобится Windows Vista или старше. ИМХО, конечно, лучше Windows 7. В этих версиях появилась утилита mklink, с помощью которой мы и будем выкручиваться.
if(!exec("dir $link /a-d",$out,$err) OR !preg_match('/<SYMLINK>/i',utf8_encode($out[5])))returnfalse;//$out[5] - это нужная нам строка в выводе
returntrue;
}
Необходимая строка вывода, по которой мы определяем является ли файл символической ссылкой, у меня появляется на 5 позиции ($out[5]). Не знаю для всех ли версий интерпретаторов командных строк это будет верно. В крайнем случае можно будет сделать обход по массиву $out.
В функциях мы проверяем операционную систему, на которой работает php и номер сборки windows (6xxx - vista, 7xxx - windows 7).
Надо сказать, что эти функции работают в десятки раз медленнее, чем их юниксовый аналог. Однако для вас это может оказаться не принципиальным. Я, например, провожу эти операции в цикле по списку из 1000 файлов - минуту-две ждать приходится =(
JustUserR, спасибо! Действительно, самое рациональное решение с array_keys() и циклом for. Теперь мы не зависим от внутреннего указателя массива, массив лишний раз не копируем и нам не нужны никакие специальные счетчики текущей позиции!
значит необьходимо при входе на шаг рекурсии сохранить позицию счетчика (Она будет показывать позицию счетчика у рекурсивной функции более верхнего уровня) потом сбросить его и провести свой цикл и вернуть индекс обратно
Что-то я не догоняю :( Как же все-таки вернуть индекс обратно? Что-то у меня никак не вырисовывается картина. JustUserR, можно ли поподробнее?
Придумал еще один банальный способ, не добавляя массив в параметры функции. В первом варианте добавил после глобализации строчку $items_copy = $items; и в цикле уже работаем с $items_copy. Но это опять же плодит массивы до неизвестного количества, а хотелось бы работать с одним массивом оперируя лишь его указателем.
По поводу:
JustUserR пишет:
Вероятно ваш способ будет работать оптимально если попробовать передавать массив по ссылке с помощью & - хотя по смысло это схоже с проблемной ситуацие но реализация вероятно без бага
однако нет. Ситуация аналогичная. В PHP5 работает, в PHP 4.4.9 - нет.
Ch_chov пишет:
А for с массивами вроде даже быстрей работает чем foreach.
Возможно, но не всегда. foreach перебирает элементы массива по порядку, а for по счетчику, т.е. по индексу. А если в массиве элементы начинаются не с нуля или есть пропуски (некоторые элементы были unset)? А если ключи строковые, а не числовые? Тогда прибегаем к использованию еще одной функции - each(). Неужели использование двух функций будет работать быстрее чем одна? Но это уже оффтоп... Простите, for это не функция ))
JustUserR, я так и подумал. В каждой последующей рекурсии items() перебор массива $items начинается не с первого элемента, и после n-ной рекурсии, когда последний элемент массива был достигнут, циклы foreach предыдущих рекурсий тоже завершаются.
Я так понимаю, мое решение является нерациональным, т.к. $items будет каждый раз копироваться и это приведет к излишнему потреблению памяти? Особенно если очень много элементов в массиве?
JustUserR пишет:
как вариант можно было при входе сохранять позицию с помощью current и при выходе выставлять ее на сохраненную
Насколько я знаю, current() возвращает значение текущего элемента. Не понимаю, как с помощью него можно сохранить позицию? Может вы имели ввиду функцию key()?
Если я с помощью key() сохраню индекс последнего обработанного элемента перед следующей рекурсией, то как после нее с помощью этого индекса вернуть указатель на этот элемент?
В принципе, я представляю как это все можно сделать при помощи for со счетчиком, но я стараюсь им не пользоваться для перебора массивов без особой необходимости, тем более, что для этой цели предназначен foreach.
Теперь и на Денвере и на сервере корректно выводятся все элементы:
- Первый
- Третий
- Четвертый
- Второй
- Пятый
- Шестой
Вопрос в том, почему так происходит?
Есть подозрение, что дело во внутреннем указателе массива $items, но насколько я знаю, foreach использует копию массива (т.е. не вносит изменений в исходный массив) и сбрасывает внутренний указатель массива на начало перед обходом.