Расширение director_helper. Ошибочка, не понятно где...

Не о CI, но о PHP, интерфейсах и веб-проограммировании

Расширение director_helper. Ошибочка, не понятно где...

Сообщение XenoneX » 13 окт 2009, 23:31

Написал расширение для director_helper.
Он включает одну единственную функцию - создание иерархии папок на сайте.
Функция make_dir() должна принимать массив в виде, который выдает нам функция directory_map() (если ей кто-нибудь хоть раз пользовался), либо текст с путем до папки, которая должна быть создана (причем папки, которые содержат данную папку тоже могут не существовать). Как раз последняя фича (я про ввод пути до папки) и не работает. Пишет, что не хватает памяти, но я думаю, что это я дурак, что-то там накосячил.
Гляньте, товарищи, я никак ошибку не могу найти. Я по-максимуму закомментил, если что - спрашивайте.
Кстати, с массивом работает как часы.
Код: Выделить всё
<?php 

/* 
|    Функция конвертирования из массива в ассоциативный массив
_______________________________________________________________
|    $arr - array, состоящий из названия папок вида:
|    
|    $arr[номер_подпапки] = 'имя_подпапки';
|
|    $i = номер текущего индекса массива (или уровня подпапки)
*/

function make_array($arr, $i=1)
{
    // Назначаем переменную    
    
    $result 
= array();
    
    
// Если $arr[номер_подпапки] задано, то
    
    if 
(isset($arr[$i]))
    {
        
        
// Создаем новый элемент массива, который будет равен результату следующего витка функции
        
        $result
[$arr[$i]] = make_array($arr, $i++); // Здесь возникает ошибка Allowed memory size of 8388608 bytes exhausted (tried to allocate 120 bytes) in Sites/system/application/helpers/MY_directory_helper.php on line 8
        
        return $result
;
    }
    return '';
}

/* 
|    Функция создания иерархии папок
_______________________________________________________________
|    $data - array, состоящий из названия папок вида:
|
|    $data = array(
|        'имя_папки'=> array(
|            'имя_подпапки' => array (
|                'имя_последней_подпапки' => '',
|                'имя_еще_одной_последней_подпапки' => ''
|            )
|        )
|    );
|
|    (В проекте) Так же $data может быть string, превращающийся
|    в массив после разбиения с помощью  split();
|
|    $main_folder - string, задающий начало иерархии вида:
|
|    ./имя_папки/имя_подпапки/так/далее...
|    
|    по умолчанию './', т.е. корневой каталог CI
|    все пути расчитываются от него
|
|    $rule - int, задающий права доступа для всех каталогов
*/

function make_dir($data, $main_folder = './', $rule = 0777)
{
    
    
// Если последняя папка в ветви
    
    if 
($data == '')
    {
        
        
// Возвратить ПРАВДА
        
        return true
;
    }
    
    
// Если текст
    
    elseif 
(is_string($data))
    {
    
        
// Применяем защиту от дурака
        
        $data 
= trim($data);
        $data = strip_tags($data);
        
        
// Делим на массив
        
        $path 
= split("/", $data);
        
        
// Создаем массив для передачи в переменную
        
        $data 
= make_array($path);
        
        
// Перенаправляем данные обратно в функцию
        
        return make_dir
($data, $main_folder, $rule);
    } 
    
    
// Если массив
    
    elseif 
(is_array($data)) 
    
{
    
        
// Записываем все имена элементов массива в массив
    
        $folder_names 
= array_keys($data);
        
        
// Для каждого элемента массива берем его название
        
        foreach 
($folder_names as $folder_name)
        {
                        
            
//    Если каталог еще не существует
            
            if 
(!is_dir($main_folder.$folder_name.'/'))
            {    
                    
                
// То создаем его
            
                mkdir
($main_folder.$folder_name.'/', $rule);
            }
            
            
// Если элемент является массивом
            
            if 
(is_array($data[$folder_name]))
            {
            
                
// Создаем переменную пути
                
                $to_folder 
= $main_folder.$folder_name.'/';
                
                
// Передаем оставшийся массив, путь и роли обратно в функцию
                
                make_dir
($data[$folder_name], $to_folder, $rule);
            }
        }
        
        
// Возвратить ПРАВДА
        
        return true
;
    }
    
    
// Возвратить ЛОЖЬ
    
    return false
;
}

/* End of file MY_directory_helper.php */
/* Location: ./system/application/helpers/MY_directory_helper.php */
 
XenoneX
 
Сообщения: 16
Зарегистрирован: 15 июл 2009, 09:35
Откуда: Москва

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение XenoneX » 13 окт 2009, 23:34

Забыл сказать, что работал на *NIX, для Windows все может быть через одно место. Проверки на ОС хочу реализовать только в будущем, пока хотя бы дописать.

А скрипт в этой теме поместил потому, что это не разработка CI, а скорее я накосячил где-то в логике, используя стандартные php методы
XenoneX
 
Сообщения: 16
Зарегистрирован: 15 июл 2009, 09:35
Откуда: Москва

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение Big_Shark » 14 окт 2009, 01:38

Ошибка выдается на первом круге использования функции make_array
Продебагте запуск данной функции с отслеживание параметров переданных ей.
Скорее всего у вас рекурсия зацикливается и сжирает всю память.
Отвечу на ваши вопросы по CodeIgniter и Kohana3
Благодарности принимаются тут: 41001216991355 (ЯД)
Big_Shark
Модератор
 
Сообщения: 1307
Зарегистрирован: 03 фев 2009, 02:12
Откуда: Владивосток

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение XenoneX » 14 окт 2009, 16:47

Спасибо! Я это знал, просто может мне кто-нибудь предложит скрипт по-лучше или по-проще (хотя это одно и тоже, я думаю)?
XenoneX
 
Сообщения: 16
Зарегистрирован: 15 июл 2009, 09:35
Откуда: Москва

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение michail1982 » 15 окт 2009, 00:49

а какой смысл в
Код: Выделить всё
 elseif (is_array($data))  
?
мне кажеться, что после
Код: Выделить всё
$data make_array($path); 

можно сразу делать первую итерацию вместо рекурсивного вызова

и ещё возник вопрос, зачем создавать каталоги при каждой итерации? что, mkdir(folder/subfolder) не работает?
я бы обходил массив(типа граф) в глубину и при достижении последнего каталога создавал бы всё сразу
Аватара пользователя
michail1982
 
Сообщения: 533
Зарегистрирован: 25 ноя 2008, 15:36

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение Big_Shark » 15 окт 2009, 01:18

Я сделал так
Код: Выделить всё
if(substr_count($name,"/"))
{
  
$array_dir=explode("/",$name);
  
array_pop($array_dir);
  
$news_dir='';
  foreach(
$array_dir as $dir)
  {
     
$news_dir.=$dir.'/';
     if(!
is_dir($this->cache_path.$news_dir))mkdir($this->cache_path.$news_dir);
  }

Вот полный код где это используется
Код: Выделить всё
function set($name,$data FALSE,$time 0){
        if(!
$this->enable)return FALSE;
        if(
$time)$time=time()+$time;
        
$data = array("time"=>$time,"cache"=>$data);
        if(
substr($name,-1)=='/')$name=substr($name,0,-1);
        if(!
file_exists($this->cache_path.$name.$this->cache_ext) and substr_count($name,"/"))
        {
            
            
$array_dir=explode("/",$name);
            
array_pop($array_dir);
            
$news_dir='';
            foreach(
$array_dir as $dir)
            {
                
$news_dir.=$dir.'/';
                if(!
is_dir($this->cache_path.$news_dir))mkdir($this->cache_path.$news_dir);
            }
        }
        if(
write_file($this->cache_path.$name.$this->cache_extserialize($data)))
        {
            
$this->counter['save']++;
            return 
TRUE;
        }
        return 
FALSE;
    } 
Отвечу на ваши вопросы по CodeIgniter и Kohana3
Благодарности принимаются тут: 41001216991355 (ЯД)
Big_Shark
Модератор
 
Сообщения: 1307
Зарегистрирован: 03 фев 2009, 02:12
Откуда: Владивосток

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение XenoneX » 15 окт 2009, 18:08

michail1982 писал(а):и ещё возник вопрос, зачем создавать каталоги при каждой итерации? что, mkdir(folder/subfolder) не работает?
я бы обходил массив(типа граф) в глубину и при достижении последнего каталога создавал бы всё сразу

Ну, хотелось выпендриться :) А-ля знаю, как это делается. На самом деле как-то не додумался, как это через прохождения массива делать. :(
XenoneX
 
Сообщения: 16
Зарегистрирован: 15 июл 2009, 09:35
Откуда: Москва

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение XenoneX » 15 окт 2009, 18:17

В общем, переделал все. Теперь функции можно передавать иерархию как в массиве, так и в string-е. Причем если передан массив, а папка начала иерархии не существует, то она создается. Там все закомменчено, так что разобраться можно, надеюсь...


Код: Выделить всё
<?php 

/* 
|    Функция создания иерархии папок
_______________________________________________________________
|    $data - array, состоящий из названия папок вида:
|
|    $data = array(
|        'имя_папки'=> array(
|            'имя_подпапки' => array (
|                'имя_последней_подпапки' => '',
|                'имя_еще_одной_последней_подпапки' => ''
|            )
|        )
|    );
|
|    Так же $data может быть string, превращающийся
|    в массив после разбиения с помощью  split();
|
|    $main_folder - string, задающий начало иерархии вида:
|
|    ./имя_папки/имя_подпапки/так/далее.../ (знак "/" в конце пока обязательно)
|    причем не обязательно, чтобы файл существовал
|    если он не существует, то скрипт его создаст
|    
|    по умолчанию './', т.е. корневой каталог CI
|    все пути расчитываются от него
|   
|    $rule - int, задающий права доступа для всех каталогов
|    по умолчанию  0755
*/

function make_dir($data, $main_folder = './', $rule = 0755)
{
    
    
// Если последняя папка в ветви
    
    if 
($data == '')
    {
        
        
// Возвратить ПРАВДА
        
        return true
;
    }
    
    
// Если текст
    
    elseif 
(is_string($data))
    {    
        
// Применяем защиту от дурака
        
        $data 
= trim($data);
        $data = strip_tags($data);
        
        
// Делим на массив
        
        $path 
= split("/", $data);
        
        
// Созаем переменную, в которую будет записываться текущая папка
        
        $cur_path 
= '.';
        
        
// Для всех элементов массива кроме первого (там точка)
        
        for 
($i=1; $i<count($path); $i++)
        {        
            
// Если такой директории не существует
            
            if 
(!is_dir($cur_path.'/'.$path[$i]))
            {
            
                
// Создаем ее
            
                mkdir
($cur_path.'/'.$path[$i], $rule);
            }
            
            
// Дописываем новый путь
            
            $cur_path 
.= '/'.$path[$i];
        }
        
        
// Уничтожаем переменные (ну мало ли :) )
        
        unset
($cur_path, $data, $path);
        
        return true
;
    } 
    
    
// Если массив
    
    elseif 
(is_array($data)) 
    
{
        
        
// Если каталог, в который будет записанны новые каталоги не существует
        
        if 
(!is_dir($main_folder))
        {

            // То создаем его
            
            make_dir
($main_folder, './', $rule);            
        
}
        
        
// Записываем все имена элементов массива в массив
    
        $folder_names 
= array_keys($data);
        
        
// Для каждого элемента массива берем его название
        
        foreach 
($folder_names as $folder_name)
        {
                        
            
//    Если каталог еще не существует
            
            if 
(!is_dir($main_folder.$folder_name.'/'))
            {
                    
                
// То создаем его
            
                mkdir
($main_folder.$folder_name.'/', $rule);
            }
            
            
// Если элемент является массивом
            
            if 
(is_array($data[$folder_name]))
            {
            
                
// Создаем переменную пути
                
                $to_folder 
= $main_folder.$folder_name.'/';
                
                
// Передаем оставшийся массив, путь и роли обратно в функцию
                
                make_dir
($data[$folder_name], $to_folder, $rule);
            }
        }
        
        
// Возвратить ПРАВДА
        
        return true
;
    }
    
    
// Возвратить ЛОЖЬ
    
    return false
;
}

/* End of file MY_directory_helper.php */
/* Location: ./system/application/helpers/MY_directory_helper.php */
 


Да, ну и к тому же только одна функция, без побочных.

Мне вот интересно, а на Винде будет работать? А то у меня Мак, не знаю, как на Окошках...
XenoneX
 
Сообщения: 16
Зарегистрирован: 15 июл 2009, 09:35
Откуда: Москва

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение michail1982 » 16 окт 2009, 20:49

а зачем столько действий, если строка передаёться???
максимум \ в / преобразовать и действовать ;)
Аватара пользователя
michail1982
 
Сообщения: 533
Зарегистрирован: 25 ноя 2008, 15:36

Re: Расширение director_helper. Ошибочка, не понятно где...

Сообщение XenoneX » 17 окт 2009, 08:52

michail1982 писал(а):а зачем столько действий, если строка передаёться???
максимум \ в / преобразовать и действовать ;)

Да, что-то не подумал :)
XenoneX
 
Сообщения: 16
Зарегистрирован: 15 июл 2009, 09:35
Откуда: Москва


Вернуться в Общие вопросы по PHP и веб-программированию

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 1