В прошлой статье мы разобрали структуру фреймворка, но не его реализацию. Для того чтобы фреймворк начал функционаровать, нам потребуется его доработать. Для начала подключим файл конфигурацию. Мы обозначили файл, как config.php, но никак его не использовали.

По опыту разработки сразу оговорюсь, удобно использовать два файла конфигурации: первый для общих настроек - название сайта, адрес домена, время жизни куков, и второй для настроек подключения к БД. Это в первую очередь качается разработки на фреймворке. Так как для такой системы важно быстро развернуть ее на локальном компьютере и зачем перенести на сервер. При таком переносе, один из конфигов будет общим, а второй будет заполнен лишь единожды для каждого сервера. Поэтому определим два файла config.php и config.db.php

Структура этих файлов должна быть как можно проще. Идеальный вариант - ini файлы. Но для них нужно писать отдельные парсеры и они доступны из вне. Поэтому не будем изобретать велосипед, а сделаем простой php ассоциативный массив с парами ключ-значение.

Дла начала опишем config.db.php

<?php
return array(
	'host' => 'localhost',
	'user' => 'root',
	'password' => '',
	'dbname' => 'ideal',
	'pref' => 'idl_' // префикс для всех таблиц фреймворка
);

Чтобы иметь в наличии лишь один файл конфигурации, в файле config.php используем уже имеющийся файл config.db.php

<?php
return array(
	'sitename' => 'Тестовая страница php фреймворка',
	'encode' => 'utf-8',
	'cookietime' => 3600, // время жизни куков администратора в секундах
	'version' => '1.0.0 ',
	'default_module' => 'index',
	'default_controller' => 'index',
	'default_action' => 'index',
	'db' => include 'config.db.php',
	// ...
);

Теперь файл конфигурации можно подключить к примеру так

class App extends Singleton{
    public $config = null;
    function start(){
        $this->config = include APP.'config.php';
        Router::gi()->parse();
        $controller = app::gi(Router::gi()->controller.'Controller');
        $controller->__call('action'.Router::gi()->action);
    }
}

Теперь в любом месте нашего фреймворка можно использовать необходимые настройки.

<?php
// код
echo app::gi()->config['sitename'];

К примеру доработаем наш роутер. В предыдущей статье, мы указали, что фреймворк не сможет работать без htaccess. Но это не совсем так, там, он прекрасно работает без него. Дело в том, что мы не написали логику класса Router. Исправим досадное упущение.

Логика будет такая: на вход роутера подается ЧПУ (Человеко понятные URL) разделенные слешами сущности Модель/Контроллер/Действие/ID, этого в большинстве случаев достаточно. Когда не заданы модуль, контроллер или все три, будет использоваться значения по умолчанию из файла конфигурации.

<?php
class Router extends Singleton{
	public $controller;
	public $action;
	public $id;
	
	private $reg_paths = array(
		'([a-z0-9+_\-]+)/([a-z0-9+_\-]+)/([0-9]+)' => 'controller/action/id',
		'([a-z0-9+_\-]+)/([a-z0-9+_\-]+)' => 'controller/action',
		'([a-z0-9+_\-]+)' => 'controller',
	);
	
	function parse(){
		$path = $_REQUEST['route'];
		
		$this->controller = app::gi()->config['default_controller'];
		$this->action = app::gi()->config['default_action'];
		$this->id = 0;
		
		foreach($this->reg_paths as $regxp=>$keys) {
			if (preg_match('#'.$regxp.'#Uuis', $path, $res)) {
				$keys = explode('/',$kyes);
				foreach ($keys as $i=>$key) {
					$this->$key = $res[$i+1];
				}
			}
		}
	}
}

Массив  $reg_paths содержит в себе регулярные выражения, по которым разбирается строка $path. Если по какой-то из них будет найдено совпадение, то все поля заполняются по ней. Практически также работает роутер из Yii, только регулярки там заменены другими паттернами. К примеру ([a-z0-9+_\-]+) там записывается как <controller>. Это сделано лишь для удобства программиста. В конечном итоге, в недрах Yii происходит обратная замена.

Для большего удобства  массив $reg_paths можно вынести в файл конфигурации, как сделано в Yii.

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

class Model{
	private $data = array();
	function __construct($data = array()) {
		$this->data = $data;
	}
	function __get($name){
		return isset($this->data[$name])?$this->data[$name]:null;
	}
	function __set($name,$value){
		$this->data[$name] = $value;
	}
}

Тогда загрузка конфигурации в App немного изменится.

class App extends Singleton{
    public $config = null;
    function start(){
        $this->config = new Model(include APP.'config.php');
        Router::gi()->parse();
        $controller = app::gi(Router::gi()->controller.'Controller');
        $controller->__call('action'.Router::gi()->action);
    }
}

А обращение к элементам конфига станет более интуитивным. Продемонстрируем на примере файла представления.

<!doctype html>
<html lang="en">
<head>
	<meta charset="<?=app::gi()->config->encode?>">
	<title><?=app::gi()->config->sitename?></title>
</head>
<body>
	<?=$content?>
</body>
</html>

На этом пока все. Все подробности, как обычно, в исходниках. Статьи по этой теме будут появляться при наличии интереса у читателей блога, и вопросах в комментариях.  Всего доброго.

Рассказать друзьям
author.jpg

Платная консультация по вопросам 2500 руб/час

Прочитали статью и остались вопросы? Меня зовут Валерий и я её автор. С радостью объясню Вам в скайпе все затруднительные моменты, которые остались за рамками статьи!

Подробнее ...

Добавить комментарий


Комментарии