Свой фреймворк. Реализация мультиязычности, шаблонизатора и ролей пользователей

в 10:55, , рубрики: php, Веб-разработка, Песочница, метки: ,

На протяжении пары лет занимаюсь веб-разработкой. Из-за специфики поставленных задач, решил не использовать никаких фреймворков для разработки back-end части проектов. Конечно, так же повлияло отсутствие хороших навыков работы с существующими фреймворками на момент начала работы. А вот какие-то свои заготовки на тот момент уже были. И тут началось изобретение велосипеда в виде создания своего мини фреймворка.

Это является моей первой статьёй. В ней я решил поделиться реализацией тех моментов, которые я считаю, у меня получились хорошо:

  • Мультиязычность интерфейса
  • Шаблонизатор
  • Роли пользователей

Мультиязычность

Контент всегда одинаковый, его в расчёт можно не брать. Задача состояла в том, что бы была возможность менять язык интерфейса. Единственным правильным решением я видел установку уникального значения, наверное можно сказать ключ, в необходимое место в шаблоне. В зависимости от выбранного языка на то место подставляется нужное значение. В итоге необходимы таблицы, которые будут содержать те самые ключи и значения к ним.

Далее пришлось выбирать, где эти таблицы хранить. В файле или в базе данных. Я реализовал оба варианта и решил провести тесты, то есть измерить скорость работы скрипта. К моему удивлению, вариант с использованием базы данных оказался быстрее чем вариант с файлами. Я почему-то думал изначально, что с файлами будет быстрее. Конечно возможно, что я использовал не правильную практическую реализацию. К тому же наверняка можно сказать, что скоростью работы скрипта можно пренебречь, ведь она будет практически не заметна при работе. Но мне хотелось какое-то основание для выбора, к тому же хранить всё это в базе данных мне показалось удобнее.

При инициализации работы скрипта он вытягивает все необходимые ему строки в зависимости от языка и помещает всё в массив примерно таким образом:

foreach ($translations_array as $translation) {
   $lang[$translation['key_translation']] = $translation['value_translation'];
}

А далее идёт подстановка необходимых значений в шаблонизаторе.

Шаблонизатор

Требования, предъявляемые к шаблонизатору это:

  • отделение html от php
  • возможность использовать тот же шаблон несколько раз
  • вкладывать шаблоны в друг друга, тем самым конструируя нужное отображение

Логика реализации очень популярна. Необходимые значения подставляются в шаблоны по указанным в них ключах. Шаблоны выглядят примерно как-то так:

<html>
  <head>
    <title>{title}</title>
  </head>
  <body>
      {content}
  </body>
</html>

Для подстановки значений в шаблон я использую данную функцию:

function tpl_parse($template, $array=array(), $language=true) {
	global $lang;

	$templates_dir = 'templates/';

	if (file_exists($templates_dir.$template.'.tpl') {
		$template_file = file_get_contents($templates_dir.$template.'.tpl');
	} else {
		return 'No template find '.$template.'.tpl';
	}

    if ($language) {
    	$array = $array+$lang;
    }
    if (sizeof($array) > 0) {
		foreach($array as $key => $value) {
			$template_file = str_replace('{'.$key.'}', $value, $template_file);
		}			
    }
	return $template_file;
}

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

Конечно, тут нету явного отделения отделения логики отображения, чем могут похвастаться известные шаблонизаторы. Построение необходимой структуры делает сам скрипт обработки данных. Но я считаю данный подход очень удобным для себя.

Роли пользователей

Одним из самых главных требований к разрабатываемым продуктам является разделение ролей пользователей. В зависимости от уровня доступа пользователя это подразумевает:

  • Отображение разных данных
  • Ограничение действий с данными

Каждый пользователь состоит в группе, которая определяет его возможности и ограничения. И всё это контролируется на уровне маршрутизации запросов от клиентов.

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

Хотелось всё сделать как можно проще, поэтому я решил при необходимости использовать разные шаблоны для каждой из групп. Функция шаблонизатора приняла такой вид:

function tpl_parse($template, $array=array(), $language=true) {
	global $lang;

	$templates_dir = 'templates/';

	if (file_exists($templates_dir.'groups_templates/'.$_SESSION['group_user'].'/'.$template.'.tpl')) {
		$template_file = file_get_contents($templates_dir.'groups_templates/'.$_SESSION['group_user'].'/'.$template.'.tpl');
	} elseif (file_exists($templates_dir.$template.'.tpl')) {
		$template_file = file_get_contents($templates_dir.$template.'.tpl');
	} else {
		return 'No template find '.$template.'.tpl';
	}

    if ($language) {
    	$array = $array+$lang;
    }
    if (sizeof($array) > 0) {
		foreach($array as $key => $value) {
			$template_file = str_replace('{'.$key.'}', $value, $template_file);
		}			
    }
	return $template_file;
}

Итоги

Таким образом все части проекта связаны между собой. Возможно кому-то покажется это крайне не удобно. Но я хочу отметить, что очень сильно на мои решения повлияли описание и поставленные требования к проекту. Поэтому и техническое решение возможно получилось слегка ограниченным, но как я считаю крайне удобным для реализации поставленной задачи. Без кучи лишних возможностей, которые наверняка никогда не были бы использованы.

Автор: g27

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js