Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Перегнать константы в массив.

 PHP.SU

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


 Страниц (2): [1] 2 »   

> Без описания
dropoff
Отправлено: 17 Июня, 2013 - 14:59:08
Post Id



Посетитель


Покинул форум
Сообщений всего: 310
Дата рег-ции: Дек. 2010  


Помог: 0 раз(а)




Всем привет.

Создал тему тут, так как сам что-то не могу сделать.

В общем есть много файлов, которые содержат кучи констант. В некоторых файлах названия констант повторяются. Эти файлы подключаются отдельно, по этому конфликтов нет.

Мне нужно все константы перегнать в массив по такому примеру

Например файлы
news.php

Содержание
PHP:
скопировать код в буфер обмена
  1. define('HEAD', 'Новости');
  2. define('HEAD_TITLE', 'Новости сайта');


Файл
articles.php

Содержание
PHP:
скопировать код в буфер обмена
  1. define('HEAD', 'Статьи');
  2. define('HEAD_TITLE', 'Статьи сайта');


В результате нужно получить по каждому файлу свой массив такого вида
PHP:
скопировать код в буфер обмена
  1. $result = array(
  2.         'news_head' => 'Новости',
  3.         'news_head_title' => 'Новости сайта',
  4.  
  5.         'articles_head' => 'Статьи',
  6.         'articles_head_title' => 'Статьи сайта',
  7. );


Т.е. название файла является частью ключа, чтобы избежать повторений.
Но. В константах не только текст. Но много и html тегов и всяких кавычек и т.д...!

Буду благодарен за помощь и советы!

(Отредактировано автором: 17 Июня, 2013 - 15:00:34)

 
 Top
dubasua
Отправлено: 17 Июня, 2013 - 15:20:04
Post Id



Посетитель


Покинул форум
Сообщений всего: 454
Дата рег-ции: Апр. 2012  


Помог: 7 раз(а)




Зачем Вам предопределять константы? Не проще их сразу загонять в переменную?
 
 Top
EuGen Администратор
Отправлено: 17 Июня, 2013 - 15:23:50
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Нативно никак. Суть в том, что для того, чтобы узнать, какие константы определяются в файле, его нужно подключить, а после подключения константы определятся. Таким образом, последующие файлы уже не смогут определить свои константы.
Если это действительно нужно, то можно воспользоваться runkit. Код с его использованием будет примерно такой:
PHP:
скопировать код в буфер обмена
  1. function uinclude($sFile, $bSideEffect=true, $sSideName='rgConstants', $sSideDelimiter='_')
  2. {
  3.         $rgConstants = get_defined_constants();
  4.         include($sFile);
  5.         $rgConstants = array_diff(get_defined_constants(), $rgConstants);
  6.         array_map('runkit_constant_remove', array_keys($rgConstants));
  7.         if($bSideEffect)
  8.         {
  9.                 array_walk($rgConstants, function($mValue, $sKey) use ($sFile, $sSideName, $sSideDelimiter)
  10.                 {
  11.                         $GLOBALS[$sSideName][$sFile.$sSideDelimiter.$sKey] = $mValue;
  12.                 });
  13.                 return null;
  14.         }
  15.         return $rgConstants;
  16. }

- но это не рекомендуется, так как, во-первых, архитектурно некорректно, а во-вторых, ставит приложение в зависимость от PECL-расширения (у меня, к примеру, оно не смогло быть установлено из-за зависимостей, поэтому код выше - теоретический).

Ещё один способ - разбирать код регулярным выражением (искать define-конструкции), но это тоже плохой путь, поскольку гораздо корректнее выстроить логику так, чтобы константы использовались только по требованию и там, где действительно нужно, а изменяемые данные были либо в БД, либо в переменных (например, брались из конфига).


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
dropoff
Отправлено: 17 Июня, 2013 - 15:23:55
Post Id



Посетитель


Покинул форум
Сообщений всего: 310
Дата рег-ции: Дек. 2010  


Помог: 0 раз(а)




не понял на счет переменных. зачем это нужно?

в массив для того, что с ним удобно работать и переопределять когда нужно по ключам значения. + добавлять\удалять из массива что нужно...
(Добавление)
EuGen, суть в том, чтобы убрать вообще кучи файлов и кучи констант и работать с одним массивом.
Т.е. вместо кучи файлов с константами создать один с массивом.

(Отредактировано автором: 17 Июня, 2013 - 15:26:17)

 
 Top
dubasua
Отправлено: 17 Июня, 2013 - 15:28:32
Post Id



Посетитель


Покинул форум
Сообщений всего: 454
Дата рег-ции: Апр. 2012  


Помог: 7 раз(а)




Тогда создайте класс синглтон, и записывайте туда значения, и организуйте ограничение на перезапись.
 
 Top
EuGen Администратор
Отправлено: 17 Июня, 2013 - 15:28:48
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




dropoff
EuGen пишет:
изменяемые данные были либо в БД, либо в переменных (например, брались из конфига).

- ничто не мешает ведь.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
dubasua
Отправлено: 17 Июня, 2013 - 15:41:19
Post Id



Посетитель


Покинул форум
Сообщений всего: 454
Дата рег-ции: Апр. 2012  


Помог: 7 раз(а)




PHP:
скопировать код в буфер обмена
  1. class NewConstant {
  2.        
  3.         static private $_result = array();
  4.        
  5.         static private __construct(){}
  6.        
  7.         static public set( $key, $value ){
  8.                 if ( isset ( self::$_result[$key] ) )
  9.                         return false;
  10.                 self::$_result[$key] = $value;
  11.         }
  12.        
  13.         static public get ( $key ) {
  14.                 if ( isset ( self::$_result[$key] ) )
  15.                         return self::$_result[$key];
  16.                 return NULL;
  17.         }
  18. }


И вместо этого
dropoff пишет:
define('HEAD', 'Новости');
define('HEAD_TITLE', 'Новости сайта');


Используйте это
PHP:
скопировать код в буфер обмена
  1. NewConstant::set('new_head','Новости');
  2. NewConstant::set('new_head_title','Новости сайта');

(Отредактировано автором: 17 Июня, 2013 - 15:41:39)

 
 Top
DelphinPRO
Отправлено: 17 Июня, 2013 - 15:43:49
Post Id



Активный участник


Покинул форум
Сообщений всего: 7187
Дата рег-ции: Февр. 2012  


Помог: 353 раз(а)




dropoff пишет:
суть в том, чтобы убрать вообще кучи файлов и кучи констант и работать с одним массивом.

вы рефакторите код что-ли?
напишите простой скрипт-утилитку, который ообойдет все фаши файлы, регулярками распарит код определения констант и запишет все это в виде массива в отдельный файл. Потом удалите ненужные файлы, и оставьте новый, сгенеренный (Вариант сделать все это вручную, видимо, не рассматривается Улыбка )

ПС бэкап не забудьте сделать Улыбка

(Отредактировано автором: 17 Июня, 2013 - 15:45:11)



-----
Чем больше узнаю, тем больше я не знаю.
 
 Top
dropoff
Отправлено: 17 Июня, 2013 - 15:53:20
Post Id



Посетитель


Покинул форум
Сообщений всего: 310
Дата рег-ции: Дек. 2010  


Помог: 0 раз(а)




dubasua. У меня при открытии определенной страницы инклудится файл это страницы с константами. Там собраны настройки для нее. Это в любом случае не удобно и дописывать до этот системы еще какую-то считаю не правильным. Почему и хочу просто в массив все забить.

EuGen, смысл не в том, чтобы частично решить это все, а в том, чтобы полностью изменить эту систему с кучи файлов и констант на один массив.
Можно конечно массив получить через get_defined_constants(), но блин там не разобрать будет, так как константы юзерские все равно в одной куче.

DelphinPRO, по сути да, "рефакторю")). Вручную конечно такой объем обрабатывать не вариант))) Там сотни строк в десятках файлов...

Попробуйте сейчас что-то сделать с get_defined_constants().
Сейчас в голову пришло - прочитать директорию с файлами, пройтись по массиву с файлами и получить на каждый массив с get_defined_constants и все собрать в массив.
может что и получится))
(Добавление)
DelphinPRO пишет:
ПС бэкап не забудьте сделать

Ага)) Спасибо!
 
 Top
DelphinPRO
Отправлено: 17 Июня, 2013 - 16:05:35
Post Id



Активный участник


Покинул форум
Сообщений всего: 7187
Дата рег-ции: Февр. 2012  


Помог: 353 раз(а)




вы не сможете поочереди подключать файлы, в которых определены одинаковые константы. Вам выше уже сказали.

Получаете массив с файлами (scandir, glob)
По очереди читаете файлы и парсите определения констант

PHP:
скопировать код в буфер обмена
  1. $result = array();
  2.  
  3. //в цикле читаем файлы
  4. $file_content = file_get_contents($filename);
  5. preg_match_all("/define\s*\(\s*['|\"](?'key'[_a-z\d]+)['|\"]\s*,\s*['|\"](?'value'[_a-z\d])['|\"]\s*\)/Usi", $file_content, $m);
  6. // $m - масcив со всеми константами из файла
  7. // опять же циклом пробегаемся и запихиваем в результирующий массив
  8. // Добавляя префикс - имя файла
  9. $resutl[$filename .'_' .$m['key']] = $m['value'];
  10.  
  11. // потом превращаем массив в код
  12. $code = var_export($result, true);
  13.  
  14. // и записываем в файл
  15. file_put_contents('vars.php', $code);


Код весьма условный, но общая мысль должна быть понятна.

(Отредактировано автором: 17 Июня, 2013 - 16:08:22)



-----
Чем больше узнаю, тем больше я не знаю.
 
 Top
EuGen Администратор
Отправлено: 17 Июня, 2013 - 16:59:19
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Я бы не стал полагаться на регулярные выражения - потому как eval и прочие ухищрения таким способом не обработать. Более универсально - действительно использовать include, но в отдельном процессе. Например,
PHP:
скопировать код в буфер обмена
  1. $sResultFile = 'result.php';
  2. $sSearchPath = __DIR__.DIRECTORY_SEPARATOR.'constants'; //adjust this
  3. $rDir        = new RecursiveDirectoryIterator($sSearchPath);
  4. $rIterator   = new RecursiveIteratorIterator($rDir);
  5. $rMatch      = new RegexIterator($rIterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);
  6. file_put_contents($sResultFile, '$rgConstants=array();'.PHP_EOL);
  7. foreach($rMatch as $rgFile)
  8. {
  9.         system('php -r "
  10.                        \$rgConstants=get_defined_constants();
  11.                        include(\''.$rgFile[0].'\');
  12.                        \$rgConstants=array_diff(get_defined_constants(), \$rgConstants);
  13.                        \$rgConstants=array_combine(array_map(function(\$sKey)
  14.                        {
  15.                                return \''.strtoupper(join('.', array_slice(explode('.',basename($rgFile[0])), 0, -1))).'_\'.\$sKey;
  16.                        }, array_keys(\$rgConstants)), array_values(\$rgConstants));
  17.                        file_put_contents(\''.$sResultFile.'\', \'\$rgConstants=array_merge(\$rgConstants,\'.var_export(\$rgConstants, true).\');\'.\"'.PHP_EOL.'\", FILE_APPEND);"
  18.                > /dev/null &');
  19. }

- на выходе получается что-то наподобие:
PHP:
скопировать код в буфер обмена
  1. $rgConstants=array();
  2. $rgConstants=array_merge($rgConstants,array (
  3.   'C0_HEAD' => 'head one',
  4.   'C0_HEAD_TITLE' => 'title one',
  5. ));
  6. $rgConstants=array_merge($rgConstants,array (
  7.   'C1_HEAD' => 'head two',
  8.   'C1_HEAD_TITLE' => 'title two',
  9. ));

- исходный каталог имел файлы:
CODE (bash):
скопировать код в буфер обмена
  1. user@host:/path$ ls -1 ./constants
  2. c0.php
  3. c1.php


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
dropoff
Отправлено: 17 Июня, 2013 - 17:43:58
Post Id



Посетитель


Покинул форум
Сообщений всего: 310
Дата рег-ции: Дек. 2010  


Помог: 0 раз(а)




EuGen, у меня создается только result.php с содержимым $rgConstants=array(); и все.
 
 Top
EuGen Администратор
Отправлено: 17 Июня, 2013 - 17:52:31
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




dropoff
Нужно, чтобы путь к файлам $sSearchPath был корректно указан. Если у Вас Windows, то путь к интерпретатору (команда php -r в коде) нужно указывать полностью, так как обычно он не присутствует в PATH-переменной. Кроме того, в Windows из system нужно убрать окончание > /dev/null &


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
dropoff
Отправлено: 17 Июня, 2013 - 18:16:27
Post Id



Посетитель


Покинул форум
Сообщений всего: 310
Дата рег-ции: Дек. 2010  


Помог: 0 раз(а)




У меня винда. установлен openserver

Путь $sSearchPath указываю полностью. вместо слешей ставлю как у вас DIRECTORY_SEPARATOR. Проверял, выдает полностью пусть от корня

> /dev/null & убрал. Результата нет.

Прошу прощения. В виндовс унжно заменять php -r на путь или добавлять?
 
 Top
EuGen Администратор
Отправлено: 17 Июня, 2013 - 18:26:34
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Полный путь к интерпретатору, ключ -r оставить. Наподобие C:\path\to\executable\php -r Если в пути встречаются пробелы, то заменить DOS-представлением как вариант (C:\Program Files будет C:\Progra~1)


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Напишите за меня, пожалуйста »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB