Singleton и конфиги

Den1xxx

Постоялец
Регистрация
15 Янв 2014
Сообщения
289
Реакции
167
Добрый день.
Хочу поговорить об оптимизации загрузки конфигов.

В движке часто используются конфиги, как правило, в виде сериализованных файлов.
Количество — 50+
Многие загружаются редко, другие каждый раз, а некоторые несколько раз за сессию.
Чтобы не читать файл несколько раз подряд в течение сессии, решил спроектировать загрузку конфигов по шаблону «синглтон».

Пример:
PHP:
class fn_store_config  {
    public $file_config = 'fnstoreconf.ini';
    public $default_config =
        array(
            'title'=>'Stores',
            'store'=>'1',
            'prefix'=>'store_',
            'perpage'=>100,
        );   
    public $config;
    static private $instance;

    public static function getInstance() {       
        if(empty(self::$instance)) {
            self::$instance = new self;
        }
        return self::$instance;
    }   

    public static function get_config() {       
        if(empty(self::$instance)) {
            self::$instance = new self;
        }
        return self::$instance->config;
    }   
       
    private function __construct() {
        if (is_file(CONFIG_PATH.$this->file_config)) {
            $this->config = unserialize(file_get_contents(CONFIG_PATH.$this->file_config));
        } else {
            $this->config = $this->default_config;
        }
    }

    private function __clone(){}
}

Всё работает. При вызове fn_store_config::getInstance() отдаёт объект, при вызове fn_store_config::get_config() — массив.

Замечательно, обрадовался я. И сразу возник вопрос: как поставить создание кинфигов на поток?
Например, задаём имя файла конфига — расширяем класс и готово.
Попробовал создать класс, расширить — отдает значения родительского класса вместо своих.
Как сделать подобную фабрику правильно?
 

Den1xxx

Постоялец
Регистрация
15 Янв 2014
Сообщения
289
Реакции
167
Странно, что никто не ответил.
Тема вроде актуальная — загрузка конфигов в память, чтобы не читать несколько раз за сессию.
Решение было найдено, и я обошёлся без классов и модных синглтонов.
Привожу функцию, которая будет загружать конфиг из файла, хранить и при повторной попытке загрузки отдавать из памяти.
PHP:
/*
* Загружает сериализованный конфиг
* Адрес файла использем в качестве ключа
*/
function load_serialized_config($file) {
    //Переменная для постоянного хранения конфигов
    static $config = array();
    if (array_key_exists($file,$config)) {
        //?
    }    elseif (is_file(CONFIG_PATH.$file)) {
        $config[$file] = unserialize(file_get_contents(CONFIG_PATH.$file));
    } else {
        $config[$file] = array();
    }
    return ($config[$file]);
}
Уверен, кому-то ещё пригодится!
 

javx

Мой дом здесь!
Регистрация
28 Авг 2015
Сообщения
510
Реакции
266
Используй мемкеш. Или опкеш (компиляция в байткод только первый раз). Конфиги меньшая из бед, всегда смотри через профайлер какой участок кода работает неоправданно большое время и рефакторь его.
 

Den1xxx

Постоялец
Регистрация
15 Янв 2014
Сообщения
289
Реакции
167
Используй мемкеш. Или опкеш (компиляция в байткод только первый раз). Конфиги меньшая из бед, всегда смотри через профайлер какой участок кода работает неоправданно большое время и рефакторь его.
Спасибо за внимание к проблеме. Однако применить почти все Ваши советы не представляется возможным.
Я разрабатываю движок, который собираюсь скоро выложить в открытый доступ.
Т. е. он будет применяться людьми, как правило, на виртуальном хостинге.
Там мемкеш или опкеш не всегда есть.

Рефакторинг тоже показывает, что повторное чтение файла слегка «подтормаживает» систему (особенно если диски не SSD).
Между тем, 54 файла занимают всего 38кб — почему бы не хранить это в памяти, чтобы не лезть на диск раз за разом?

Тут видишь какая проблема. Static переменные в функциях применяются редко. Поэтому пользоваться ими многие самоучки, как я, не умеют. Городим велосипеды, как в Яве, хотя простое решение лежит на поверхности. А ООП ради ООП в PHP — зло. PHP не висит постоянно в памяти, поэтому функциональный подход работает быстрее и менее затратен.
 
Последнее редактирование:

nejtr0n

Гуру форума
Регистрация
24 Янв 2014
Сообщения
129
Реакции
82
Чтобы отдавался не родительский класс, а свой, замените self на static в конструкторе singleton.
И почитайте про позднее статическое связывание - Для просмотра ссылки Войди или Зарегистрируйся
 

etok

Создатель
Регистрация
6 Окт 2010
Сообщения
42
Реакции
12
Я обычно закрываю allow_url_fopen в php.ini. Тогда file_get_contents перестает работать. Предпочитаю cURL, а для чтения конфигов Для просмотра ссылки Войди или Зарегистрируйся. Так мне представляется кашернее...


Хороший обзор. В защиту xml могу сказать, что он все еще универсальный промышленный стандарт. Json моден, но нечитаем. То ли дело ini - человеческие букавки, никакой сериализации. Хоть с телефона по SSH заходи и правь что приспичит :)
 
Последнее редактирование:

Den1xxx

Постоялец
Регистрация
15 Янв 2014
Сообщения
289
Реакции
167
Json моден, но нечитаем.
Это только русские символы нечитаемы. Зато простой и безопасный для БД и передачи по сети.
В своё время думал перейти на JSON. Но там были какие-то Для просмотра ссылки Войди или Зарегистрируйся, ну его на...
То ли дело ini - человеческие букавки, никакой сериализации.
Вложенный конфиг на нем по-человечески не сделаешь.
Имхо нечего юзеру конфиги впрямую на сервере читать, для этого есть админка.
А специалисту параметр в сериализованном файле подсмотреть не проблема.

Пока для хранения массива в строке альтернативы для сериализации нет.
Мало того, она ещё и очень быстро работает.
 

etok

Создатель
Регистрация
6 Окт 2010
Сообщения
42
Реакции
12
Имхо нечего юзеру конфиги впрямую на сервере читать, для этого есть админка.

Так я не юзер - я PowerUser :)

А если серьезно, то у нас такой подход. Мы делаем админку под "тупого юзера" и вней все что нужно для оперативного управления. Конфиги же, не относятся к "оперативному". Плюс они могут радикально повлиять на систему. Поэтому к ним имеет доступ только "специально тренированный" человек - админ понимающий в *NIX-ах. Тем самым мы
  1. не тратим время на написание управляющих скриптов для админки в части конфигов
  2. не "парим" мозг простому контент-манагеру объяснениями что это за конфиги такие
  3. стимулируем образование админов-эникейщиков и делаем их более ценными в глазах работадателя (попробуй замени админа по *NIX-ам)
Короче все счастливы. Мне так кажется. А json - это здорово. И работает в 10 раз быстрее чем связка XML - XSLT. Только каждый нож на кухне идеально заточен под что-то свое.
 

Den1xxx

Постоялец
Регистрация
15 Янв 2014
Сообщения
289
Реакции
167
стимулируем образование админов-эникейщиков и делаем их более ценными в глазах работодателя
Короче все счастливы.
...кроме работодателя.
Он мог поручить кому-то на полставки, а нанял спеца на хорошую зарплату.

У меня в движке 100500 разных доступов (доступы на модули, доступы на поля в отдельных модулях, доступ по «уровню доступа» — админом назначается юзверю любое число) — можно формировать из них наборы для ролей «директор», «модератор», «начальник склада» — как «админ» назовёт и настроит, так и будет. Однако напрямую конфиги админ не правит — есть админка, добро пожаловать, в правом уголке ещё и помощь на каждой странице. Человекам с ограниченными правами просто выключается отображение блоков админки, которыми они не могут управлять. Вебмастер же может уже в коде шаблона первоначально настроить под конкретного админа — например, при создании товара выключить заполнение полей, которыми админ всё равно пользоваться не будет. Или прописать стили под проект.

Всё поведение шаблонов хранится в 1 месте — в папке шаблона проекта. При создании нового проекта будут настроены другие шаблоны поведения. Если настраивать вебмастеру лень (или проект имеет ограниченный бюджет), то не пишет ничего. Движок поднимет шаблоны из стандартной папки — всё будет работать «из коробки», но вёрстка примитивная и на таблицах, зато нет заморочек со стилями.
Такая вот реализация MVC.
 
Сверху