что-то слишком много теоретического внимания одному аспекту всего проекта. Делай уже как хочешь. Если вылезут проблемы - появится опыт и понимание само собой. Что там у тебя следующим номером по программе?
Я хочу хорошо)) Проблем вроде нет, уже работает как задумано. Сам класс локализации доделать, набраться опыта и закончить MCV а то она мутная какае то и без ЧПУ.
с исключениями всё так когда ты их используешь "грамотно": бросил - поймал-прочитал статус - дальше бросил или другое бросил - и/или выполнил блок финализации и тд и тп. а бросить исключение чтоб его просто поймать на самом верху - тут я с игоряшей соглашусь - фолса будет вполне достаточно для отображения неудачного стечения обстоятельств при попытке чтения файла. потому что ты ловишь-то наверху, где у тебя хэндлер стоит, а не вот тут где ты вызвал метод. ведь не факт что программу нельзя дальше выполнять - локализация дефолтная (инглиш тот же) обязана уже присутствовать и хрен с ней что недоступен какой-то диалект каких-то там туземцев. Добавлено спустя 3 минуты 46 секунд: и это кстати еще один плюс адекватного инстумента локализации - он просто покажет дефолт там где нет другого языка. а удобство редактирования? запустил программу, дал ей переживать сайт, и вот у тебя уже все возможные строки. написал дефолт, тут же рядом написал для какого-то другого языка. если нет строки для какой-то локали - программа тебе подскажет. если встретились одинаковые строки - программа предложит тебе определиться а не избыточен ли ты. ты уверен что осилишь такого же уровня локализатор на своих ини-файлах? опыт конечно хороший, спорить не буду.
Не угадал, в этом вся фишка если файла нет то он создаётся. А в конце создания шаблона уже редактируешь файл с локализацией. Особо не чего не менял, практически всё тоже, и работает также. Думаю на этом всё с INI классом, хотя не знаю... Код (PHP): <?php // Класс для работы с .INI файломи, на них строиться конфигурация class INI { private static $cache = array(); // Парсит файл и возвращает масив public static function Load($path) { if(!file_exists($path)) { static::$cache[$path] = array(); return true; } else { static::$cache[$path] = parse_ini_file($path); return static::$cache[$path]; } } // Получает значение элемента по ключу public static function Get($path, $key) { if(!isset(static::$cache[$path])) { static::Load($path); } $array = static::$cache[$path]; if(!isset($array[$key])) return false; return $array[$key]; } // Редактирование элемента public static function Set($path, $new = array()) { if(!isset(static::$cache[$path])) { static::Load($path); } $array = static::$cache[$path]; foreach ($new as $key => $value) { $array[$key] = $value; } static::$cache[$path] = $array; } // Удаляет элемент public static function Remove($path, $array) { if(!isset(static::$cache[$path])) { static::Load($path); } foreach ($array as $key) { unset(static::$cache[$path][$key]); } } // Очищает файл public static function Clear($path) { if(isset(static::$cache[$path])) { static::$cache[$path] = array(); return true; } else { return false; } } // Сохраняет все изменения public static function Save() { foreach (static::$cache as $path => $content) { $current = ""; foreach ($content as $key => $value) { $current .= "$key = \"$value\"\n"; } $save = file_put_contents($path, $current); if($save == false) { return false; } } return true; } }
https://phpbox.info/4iYtT разница конечно есть, но оно того не стоит. Нет. К примеру, как только возникнет необходимость хранить состояние, так сразу придется испытать всю боль этого мира ) Экземпляр класса можно создать лишь однажды и везде обращаться к нему, познайте для себя чудесный мир DI ) Я не к тому, что это всё обязательно, если вы планируете оставаться на cms-ках и простеньких скриптах, то конечно да, можно и так. Но если вы планируете заняться чем-то более серьезным, то надо менять подход с "мне так удобней", на "почему остальным удобней по другому?". К примеру подход mkramer гораздо более прозрачный, общеупотребимый и к тому же на порядок функциональней. При прочих равных я предпочту работать с ним, чем разбираться в том, что удобно вам. p.s. имхо Ganzal, согласен. Я похоже просто не так Игоря понял.
Практически тоже самое реализовано. Если не языка - дефолт русский, даже если нет файла для локализации он создаётся. если нет строки для какой-то локали - такого не может быть, они автоматом добавляются. если встретились одинаковые строки - такого тоже не может быть. И всё это на INI и PHP.
Работа с локализацией это точно не для бд. Мой langage.class.php: Код (PHP): <?php // Класс интернализации class Langage { private static $langs = array('ru', 'en'); public static $lang; public static $path; public static function Load($path) { if (!empty($_GET['lang']) && in_array($_GET['lang'], static::$langs)) { setcookie('lang', $_GET['lang']); static::$lang = $_GET['lang']; } elseif (!empty($_COOKIE['lang']) && in_array($_COOKIE['lang'], static::$langs)) { static::$lang = $_COOKIE['lang']; } else { static::$lang = 'ru'; } static::$path = $path . static::$lang . '.lang.ini'; } public static function Get($string) { $val = INI::get(static::$path, $string); if ($val == false) { INI::Set(static::$path, array($string => $string)); INI::Save(); return $string; } return $val; } } // Алиасы Langage::Get(); function _r($string) { return Langage::Get($string); } function _e($string) { echo Langage::Get($string); } Описание функций: Langage::Load("Директория с языками") - Устанавливает язык и папку с языковыми пакетами. Следует вызывать в начале работы.[/*:m] Langage::Get("Ключ") - Возвращает перевод, создаёт INI файл если его нет, добавляет строку в INI файл если её нет.[/*:m][/list:u] Пример работы: Код (PHP): <?php include('langage.class.php'); Langage::Load('langs/'); _e('Какой то текст'); _e('Текст 2'); _e('Мой текст'); Что делает? Создаст файл langs/ru.lang.ini или langs/en.lang.ini, в дальнейшем будет использовать их.[/*:m] Добавит значения в .ini файл если их там нет.[/*:m] Нам остаётся лишь подправить перевод в .ini файле.[/*:m][/list:u] Есть замечания по поводу этого класса?
Лишние запросы Сложность правки (Можно написать скрипт для редактирования или через PMA) БД будет похожа на свалку Я не понимаю как в БД можно вообще пихать текст для менюшки или футера может ещё каких то кнопок, ещё с переводами на несколько языков, а если я захочу на 5-20 языков приложение перевести? В БД можно только хранить перевод контента - статей, документации, не больше.
кеширование воу, нет. Если ты это называешь таким образом, то я тебя тогда попрошу вернуться к этому вопросу через годик практики и переосмыслить его. Ибо если ты пишешь некий самописный сайт который нуждается в i18n, то видимо это что-то серьёзное, и там вполне можно написать за день (на самом деле за полчаса) полноценный редактор. Не будт. в чем разница? о_О Запросы? Боишься запросов?
Класс роутера. Но не сегодня, может через недельку. Надо погуглить набраться ума, сделать ЧПУ. Ну вот сам код, думаю сразу его в помойку и всё по новой: Код (PHP): <?php // Класс роутера Class Router { private $registry; function __construct($registry) { $this->registry = $registry; } private function error404(){ include(SITE_PATH . DS . 'application' . DS . 'controllers' . DS . '404.php'); $class = 'Controller_404'; $controller = new $class($this->registry); $controller->index(); } private function GET($var){ $result = (empty($_GET[$var])) ? '' : $_GET[$var]; unset($_GET[$var]); if (empty($result)) $result = 'Index'; return $result; } function start(){ $controller = $this->GET('controller'); $action = $this->GET('action'); // Подключаем файл контроллера, если он имеется $controllerFile = SITE_PATH . DS . 'application' . DS . 'controllers' . DS . $controller . '.php'; if(file_exists($controllerFile)){ include($controllerFile); } else { $this->error404(); return; } $class = 'Controller_' . $controller; $controller = new $class($this->registry); // Если экшен не существует - 404 if (!is_callable(array($controller, $action))) { $this->error404(); return; } // Выполняем экшен $controller->$action(); } }
Я тут подумал какая MVC будет без нормального регистра? Вот и решил переделать его убрал Эксепшены и добавил доступ как к обычному массиву. Вот результат: Код (PHP): <?php // Класс хранилища Class Registry Implements ArrayAccess { private $vars = array(); // Запись данных function set($key, $var) { if (isset($this->vars[$key]) == true) { return false; } $this->vars[$key] = $var; return true; } // Получение данных function get($key) { if (isset($this->vars[$key]) == false) { return null; } return $this->vars[$key]; } // Удаление данных function remove($var) { unset($this->vars[$key]); } // Для обращения к обьекту как к массиву function offsetExists($offset) { return isset($this->vars[$offset]); } function offsetGet($offset) { return $this->get($offset); } function offsetSet($offset, $value) { $this->set($offset, $value); } function offsetUnset($offset) { unset($this->vars[$offset]); } }
Я просто только сегодня узнал что это такое. В блогах пишут что это прохо, я им не верю))) Вот в общем что получилось: Код (PHP): <?php // Класс хранилища Class Registry Implements ArrayAccess { protected static $_instance; // Здесь экземпляр класса private $vars = array(); // Само хранилище private function __construct(){} private function __clone(){} public static function GetInstance() { // Проверяем актуальность экземпляра if (null === self::$_instance) { // Создаем новый экземпляр self::$_instance = new self(); } // Возвращаем созданный или существующий экземпляр return self::$_instance; } // Запись данных function Set($key, $var) { $this->vars[$key] = $var; return true; } // Получение данных function Get($key) { if (isset($this->vars[$key]) == false) { return null; } return $this->vars[$key]; } // Удаление данных function Remove($var) { unset($this->vars[$key]); } // Для обращения к обьекту как к массиву function offsetExists($offset) { return isset($this->vars[$offset]); } function offsetGet($offset) { return $this->get($offset); } function offsetSet($offset, $value) { $this->set($offset, $value); } function offsetUnset($offset) { unset($this->vars[$offset]); } }
в смысле "плохо"? Синглтон это такая конструкция, которая позволяет работать с гарантированно одним экземпляром некоего объекта. Синглтон не может быть плохим или хорошим. Это инструмент такой. И кстати не обязательно возвращать этот экземпляр. Если методов мало и они заранее известны и не будут меняться, то опять же можно обернуть методы объекта в статик методы для удобства.
Я об этом уже думал. Но регист это безопасная замена глобальным переменным, и мне хочется чтобы с ним можно было обращаться как с обычной переменной. Разве ArrayAccess будет работать в статистическом классе?