PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи

Страниц (103): В начало « ... 95 96 97 98 99 100 101 102 [103]

> Найдено сообщений: 1539
Uchkuma Отправлено: 11 Июня, 2010 - 10:59:25 • Тема: Cимволические ссылки в Windows • Форум: Пользовательские функции

Ответов: 1
Просмотров: 500
Теперь требуется функция, с помощью которой можно будет определить существует файл, на который указывает символическая ссылка, или нет. Некоторый аналог функции linkinfo() для windows. Если есть идеи, пишите!

...

В общем пока назрело только это:
PHP:
скопировать код в буфер обмена
  1. function link_info($link){
  2. //если не винда, запускаем стандартную функцию linkinfo()
  3. if(!preg_match('/^win/i', PHP_OS)) return is_file(readlink($link));
  4. //винда ниже висты - неудача
  5. if(substr(php_uname(), -4)<6000) return false;
  6.  
  7. $fd = @fopen($link, 'r');
  8. //если дескриптор файла открылся, значит он существует
  9. if($fd){
  10. fclose($fd);
  11. return true;
  12. } else {
  13. return false;
  14. }
  15. }

...

Обнаружена странная вещь - функция linkinfo() выдает правду даже при отсутствующем файле, на который указывает ссылка.
Строкузаменил на
Uchkuma Отправлено: 03 Июня, 2010 - 10:12:09 • Тема: Cимволические ссылки в Windows • Форум: Пользовательские функции

Ответов: 1
Просмотров: 500
Работая над своим проектом и решая очередную задачу, я столкнулся необходимостью использования символических ссылок на файлы. Все бы ничего, но для windows php-функции для работы с символическими ссылками не реализованы. На сервере unix, однако разработка ведется в среде windows на Денвере.

Немного погуглив, я обналужил - в винде таки есть поддержка символических ссылок!!! Правда нормальная поддержка симлинков появилась сравнительно недавно, и если у вас WinXP, то вам ничего не светит.

Итак, для работы вам понадобится Windows Vista или старше. ИМХО, конечно, лучше Windows 7. В этих версиях появилась утилита mklink, с помощью которой мы и будем выкручиваться.

Функция symlink для windows:
PHP:
скопировать код в буфер обмена
  1. if(!function_exists('symlink')){
  2. function symlink($file, $link){
  3. //если винда младше висты - неудача
  4. if(preg_match('/^win/i', PHP_OS) AND substr(php_uname(), -4)<6000) return false;
  5. //меняем слеши на виндовый манер
  6. $file = str_replace('/', '\\', $file);
  7. $link = str_replace('/', '\\', $link);
  8.  
  9. if(!exec("mklink $link $file", $out, $err) OR $err!=0) return false;
  10.  
  11. return true;
  12. }
  13. }

Функция is_link для windows:
(функцию называем islink, ибо ф-я is_link есть и в windows-версии php, хотя она и не имеет смысла)
PHP:
скопировать код в буфер обмена
  1. function islink($link){
  2. //если не винда, используем стандартную is_link()
  3. if(!preg_match('/^win/i', PHP_OS)) return is_link($link);
  4. //винда младше висты - неудача
  5. if(substr(php_uname(), -4)<6000) return false;
  6. //меняем слеши на виндовый манер
  7. $link = str_replace('/', '\\', $link);
  8.  
  9. if(!exec("dir $link /a-d", $out, $err) OR !preg_match('/<SYMLINK>/i', utf8_encode($out[5]))) return false; //$out[5] - это нужная нам строка в выводе
  10.  
  11. return true;
  12. }

Необходимая строка вывода, по которой мы определяем является ли файл символической ссылкой, у меня появляется на 5 позиции ($out[5]). Не знаю для всех ли версий интерпретаторов командных строк это будет верно. В крайнем случае можно будет сделать обход по массиву $out.

В функциях мы проверяем операционную систему, на которой работает php и номер сборки windows (6xxx - vista, 7xxx - windows 7).

Надо сказать, что эти функции работают в десятки раз медленнее, чем их юниксовый аналог. Однако для вас это может оказаться не принципиальным. Я, например, провожу эти операции в цикле по списку из 1000 файлов - минуту-две ждать приходится =(

Жду комментарии. Спасибо!
Uchkuma Отправлено: 01 Апреля, 2010 - 21:38:20 • Тема: Перебор глобального массива в цикле foreach в рекурсии • Форум: Программирование на PHP

Ответов: 13
Просмотров: 6434
JustUserR, спасибо! Действительно, самое рациональное решение с array_keys() и циклом for. Теперь мы не зависим от внутреннего указателя массива, массив лишний раз не копируем и нам не нужны никакие специальные счетчики текущей позиции!
PHP:
скопировать код в буфер обмена
  1. function items($sub=0){
  2. global $items, $items_keys;
  3.  
  4. $out = '<ul>';
  5.  
  6. for($i=0; $i<count($items_keys); $i++){
  7. $item = $items[$items_keys[$i]];
  8. if($item['sub']!=$sub) continue;
  9.  
  10. $out .= '<li>'.$item['title'].'</li>';
  11.  
  12. $out .= items($item['id']);
  13. }
  14.  
  15. $out .= '</ul>';
  16.  
  17. return $out;
  18. }
  19.  
  20. $items_keys = array_keys($items);
  21. echo items();

Тема закрыта!
Uchkuma Отправлено: 01 Апреля, 2010 - 10:31:57 • Тема: Перебор глобального массива в цикле foreach в рекурсии • Форум: Программирование на PHP

Ответов: 13
Просмотров: 6434
Champion пишет:
Для этой цели предназначен for. foreach преднезначен для тех случаев, когда ты не знаешь ключи массива.

Так и есть, я могу не знать ключи массива.
Uchkuma Отправлено: 31 Марта, 2010 - 22:25:45 • Тема: Ошибка пхп (при использовании своей функции внутри другой) • Форум: Программирование на PHP

Ответов: 5
Просмотров: 408
Верно, preg_replace_callback вместо preg_replace. И обратную ссылку лучше вида $1 указывать, а не \1.
Uchkuma Отправлено: 31 Марта, 2010 - 21:52:18 • Тема: Перебор глобального массива в цикле foreach в рекурсии • Форум: Программирование на PHP

Ответов: 13
Просмотров: 6434
JustUserR пишет:

значит необьходимо при входе на шаг рекурсии сохранить позицию счетчика (Она будет показывать позицию счетчика у рекурсивной функции более верхнего уровня) потом сбросить его и провести свой цикл и вернуть индекс обратно

Что-то я не догоняю :( Как же все-таки вернуть индекс обратно? Что-то у меня никак не вырисовывается картина. JustUserR, можно ли поподробнее?

Придумал еще один банальный способ, не добавляя массив в параметры функции. В первом варианте добавил после глобализации строчку $items_copy = $items; и в цикле уже работаем с $items_copy. Но это опять же плодит массивы до неизвестного количества, а хотелось бы работать с одним массивом оперируя лишь его указателем.

По поводу:
JustUserR пишет:

Вероятно ваш способ будет работать оптимально если попробовать передавать массив по ссылке с помощью & - хотя по смысло это схоже с проблемной ситуацие но реализация вероятно без бага

однако нет. Ситуация аналогичная. В PHP5 работает, в PHP 4.4.9 - нет.
Ch_chov пишет:
А for с массивами вроде даже быстрей работает чем foreach.

Возможно, но не всегда. foreach перебирает элементы массива по порядку, а for по счетчику, т.е. по индексу. А если в массиве элементы начинаются не с нуля или есть пропуски (некоторые элементы были unset)? А если ключи строковые, а не числовые? Тогда прибегаем к использованию еще одной функции - each(). Неужели использование двух функций будет работать быстрее чем одна? Но это уже оффтоп... Простите, for это не функция ))
Uchkuma Отправлено: 31 Марта, 2010 - 16:00:36 • Тема: Перебор глобального массива в цикле foreach в рекурсии • Форум: Программирование на PHP

Ответов: 13
Просмотров: 6434
JustUserR, я так и подумал. В каждой последующей рекурсии items() перебор массива $items начинается не с первого элемента, и после n-ной рекурсии, когда последний элемент массива был достигнут, циклы foreach предыдущих рекурсий тоже завершаются.

Я так понимаю, мое решение является нерациональным, т.к. $items будет каждый раз копироваться и это приведет к излишнему потреблению памяти? Особенно если очень много элементов в массиве?
JustUserR пишет:

как вариант можно было при входе сохранять позицию с помощью current и при выходе выставлять ее на сохраненную

Насколько я знаю, current() возвращает значение текущего элемента. Не понимаю, как с помощью него можно сохранить позицию? Может вы имели ввиду функцию key()?
Если я с помощью key() сохраню индекс последнего обработанного элемента перед следующей рекурсией, то как после нее с помощью этого индекса вернуть указатель на этот элемент?
В принципе, я представляю как это все можно сделать при помощи for со счетчиком, но я стараюсь им не пользоваться для перебора массивов без особой необходимости, тем более, что для этой цели предназначен foreach.
Uchkuma Отправлено: 31 Марта, 2010 - 10:09:26 • Тема: Оцените скрипт авторизации • Форум: Программирование на PHP

Ответов: 32
Просмотров: 1481
Безопасно будет хранить хеш пароля, а не сам пароль.
Uchkuma Отправлено: 31 Марта, 2010 - 09:12:44 • Тема: Перебор глобального массива в цикле foreach в рекурсии • Форум: Программирование на PHP

Ответов: 13
Просмотров: 6434
Есть двумерный массив $items с элементами.
PHP:
скопировать код в буфер обмена
  1.  
  2. $items = array(
  3. array('id'=>1, 'sub'=>0, 'title'=>'Первый'),
  4. array('id'=>2, 'sub'=>0, 'title'=>'Второй'),
  5. array('id'=>3, 'sub'=>1, 'title'=>'Третий'),
  6. array('id'=>4, 'sub'=>1, 'title'=>'Четвертый'),
  7. array('id'=>5, 'sub'=>2, 'title'=>'Пятый'),
  8. array('id'=>6, 'sub'=>2, 'title'=>'Шестой')
  9. );
  10.  

Необходимо построить дерево элементов.
Делаю это так:
PHP:
скопировать код в буфер обмена
  1.  
  2. function items($sub=0){
  3. global $items;
  4.  
  5. $out = '<ul>';
  6.  
  7. foreach($items as $item){
  8. if($item['sub']!=$sub) continue;
  9.  
  10. $out .= '<li>'.$item['title'].'</li>';
  11.  
  12. $out .= items($item['id']);
  13. }
  14.  
  15. $out .= '</ul>';
  16.  
  17. return $out;
  18. }
  19.  
  20. echo items();
  21.  

На Денвере с PHP5 все выводится как и должно:
- Первый
    - Третий
    - Четвертый

- Второй
    - Пятый
    - Шестой

На сервере же (PHP 4.4.9) выводится только по одному первому элементу каждого уровня:
- Первый
    - Третий
    - Четвертый

Проблему решил добавив массив $items в параметр функции items() вместо его глобализации:
PHP:
скопировать код в буфер обмена
  1.  
  2. function items($items, $sub=0){
  3.  
  4. $out = '<ul>';
  5.  
  6. foreach($items as $item){
  7. if($item['sub']!=$sub) continue;
  8.  
  9. $out .= '<li>'.$item['title'].'</li>';
  10.  
  11. $out .= items($items, $item['id']);
  12. }
  13.  
  14. $out .= '</ul>';
  15.  
  16. return $out;
  17. }
  18.  
  19. echo items($items);
  20.  

Теперь и на Денвере и на сервере корректно выводятся все элементы:
- Первый
    - Третий
    - Четвертый

- Второй
    - Пятый
    - Шестой

Вопрос в том, почему так происходит?
Есть подозрение, что дело во внутреннем указателе массива $items, но насколько я знаю, foreach использует копию массива (т.е. не вносит изменений в исходный массив) и сбрасывает внутренний указатель массива на начало перед обходом.

Страниц (103): В начало « ... 95 96 97 98 99 100 101 102 [103]
Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB