$toolkit = lmbToolkit :: instance();
$connection = $toolkit->getDefaultDbConnection();
Особенностью тулкита является то, что его интерфейс четко не определен, а зависит от так называемых инструментов - **tools**. Тулкит по сути состоит из наборов инструментов, вернее tools можно **регистрировать** в тулките. Именно tools определяют, что умеет тулкит (какие методы у него можно вызывать). Для регистрации нового набора инструментов в тулките существует метод lmbToolkit :: merge($tools).
Например, создадим свой tools и зарегистрируем его в lmbToolkit:
class MyTools extends lmbAbstractTools
{
function getSomethingUseful()
{
return [...];
}
}
lmbToolkit :: merge(new MyTools()); // :: instance() для добавления уже вызывать не нужно
[...]
// Где-то в клиентском коде
$toolkit = lmbToolkit :: instance();
$my_object = $toolkit->getSomethingUseful();
Наборы инструментов можно заменять, то есть мы можем зарегистировать в тулките другой tools, который будет поддерживать интерфейс MyTools и для клиентского кода эта подмена будет совершенно прозрачной.
Начальное заполнение тулкита наборами инструментов производится в файле limb/web_app/toolkit.inc.php.
Этой информации пока нам вполне достаточно, чтобы понять наши дальнейшие действия. Более подробно о тулките в [[..:..:packages:toolkit|описании пакета Toolkit]].
Для нашего примера мы создадим наш собственный набор инструментов ShopTools и сделаем так, чтобы он поддерживал метод getUser(), который будет возвращать пользователя из сессии.
==== Работа с сессией в Limb ====
Limb не запрещает вам работать с сессиями через глобальную переменную $_SESSION, однако представляет другой, лучший с нашей точки зрения способ, со своими преимуществами.
Для работы с сессией, в Limb есть специальный объект session, который можно получить через тулкит:
$session = lmbToolkit :: instance()->getSession();
$session->set('my_var', $value); // Поставить значение в сессию
$session->destroy('my_var'); // Удалить значение из сессии
Работа с сессией осуществляется при помощи пакета [[..:..:packages:session|SESSION]].
Преимущества использования пакета SESSION:
* Возможность легкой смены способа хранения сессионных данных. На данный момент поддерживается хранение сессионных данных в базе данных и при помощи файлов.
* Автоматическое подключение необходимых классов до десериализации сессии. Вам не нужно больше об этом заботиться.
* Единый set/get интерфейс для установки и получения данных из сессии. Это позволяет в случае необходимости, например, передать сессию в WACT-шаблон в качестве контейнера с данными.
* Легкое установление и сброс фикстур при модульном тестировании.
==== Хранение пользователя в тулките ====
Для того, чтобы хранить информацию о том, какой пользователь загеристрирован в приложении, нам необходимо хранить только его идентификатор. Этого будет вполне достаточно. А объект класса User мы будем хранить в ShopTools, которые мы зарегистрируем в тулките. Это позволит нам получить доступ к пользователю в любом месте программы.
Итак, класс **ShopTools**.
Файл shop/src/toolkit/ShopTools.class.php:
user))
return $this->user;
$session = lmbToolkit :: instance()->getSession();
if($user_id = $session->get('user_id'))
{
try
{
$this->user = new User($user_id);
$this->user->setIsLoggedIn(true);
}
catch(lmbARException $e)
{
$this->user = new User();
$session->remove('user_id');
}
}
else
$this->user = new User();
return $this->user;
}
}
?>
Класс ShopUser наследуется от **lmbAbstractTools**, который используется в качестве базового для большинства наборов инструментов. lmbAbstractTools добавляет в тулкит поддержку всех методов класса (свои и методы дочернего класса), что нам в данном случае и нужно.
Метод getUser() по сути реализует lazy loading для пользователя. Если идентификатор пользователя находится в сессии, значит пользователь был уже залогинен в приложении - и мы загружаем его запись из базы данных. Если же идентификатора пользователя в сессии нет - значит можно создать пустой объект класса User.
Обратите внимание на блок try, catch, который ловит исключение класса lmbARException. Если пользователь с указанным удентификаторов был удален, то при инициализации User с идентификаторов, будет сгенерировано исключение lmbARException. В этом случае мы также должны инициализировать пустой объект класса User и удалить значение user_id из сессии.
==== Регистрация ShopTools в тулките ====
Наш набор инструментов ShopTools необходимо зарегистрировать в тулките. Обычно для этих целей создается файл **toolkit.inc.php** в корневой директории пакета или приложения.
Файл shop/toolkit.inc.php:
Добавим включение файла toolkit.inc.php в файл common.inc.php.
Файл shop/common.inc.php:
Теперь у нас есть все чтобы начать реализовывать процедуру аутентификации пользователей, отображение профайла на страницах сайта и проверку прав доступа к панели управления.
===== Аутентификация пользователей =====
==== Изменения в классе User ====
Для начала внесем изменения в класс User, чтобы он хранил информацию о том, зарегистрирован ли пользователь или нет, а также функционал по аутентификации:
class User extends lmbActiveRecord
{
[...]
protected $is_logged_in = false;
[...]
function login($login, $password)
{
$hashed_password = User :: cryptPassword($password);
$criteria = new lmbSQLFieldCriteria('login', $login);
$criteria->addAnd(new lmbSQLFieldCriteria('hashed_password', $hashed_password));
if($user = lmbActiveRecord :: findFirst('User', array('criteria' => $criteria)))
{
$this->import($user);
$this->setIsNew(false);
$this->setIsLoggedIn(true);
return true;
}
else
{
$this->setIsLoggedIn(false);
return false;
}
}
function logout()
{
$this->removeAll();
$this->is_logged_in = false;
}
}
==== Контроллер LoginController ====
За аутентификацию пользователей будет отвечать контроллер LoginController :
request->hasPost())
{
$user = $this->toolkit->getUser();
$this->useForm('login_form');
$this->setFormDatasource($this->request);
$this->_validateLoginForm();
if(!$this->error_list->isValid())
return;
$login = $this->request->get('login');
$password = $this->request->get('password');
if(!$user->login($login, $password))
{
$this->flashError('Login or password incorrect!');
return;
}
$this->toolkit->getSession()->set('user_id', $user->getId());
$this->flashMessage('You were logged in!');
if($user->getIsAdmin())
$this->toolkit->redirect(array('controller' => 'admin'));
else
$this->toolkit->redirect('/');
}
}
protected function _validateLoginForm()
{
$this->validator->addRequiredRule('login');
$this->validator->addRequiredRule('password');
$this->validator->validate($this->request);
}
function doLogout()
{
$user = $this->toolkit->getUser();
$user->logout();
$this->toolkit->getSession()->remove('user_id');
$this->response->redirect('/');
}
}
?>
Большинство кода должны быть уже понятным, но некоторые моменты мы поясним.
Методы **flashError($message)** и **flashMessage($message)** класса lmbController для вас новые. При помощи них можно передавать ошибки или другие сообщения в шаблон, наподобие того, как это происходит в Rails (конечно, если вы в курсе). Методы lmbController :: flashError($message) и lmbController :: flashMessage($message) на самом деле делегирует его в тулкит. Поэтому мы могли бы написать, например, $this->toolkit->flashError($message) и результат был бы тот же. Сообщения, выводимые через flashError() и flashMessage() хранятся в сесии и удаляются из нее в момент их отображения в шаблоне. Для отображения ошибок нам придется модифицировать шаблон page.html, о чем мы расскажем ниже.
Логика работы LoginController :: doDisplay() должна быть понятной: если процедура аутентификации прошла успешно, мы должны сохранить идентификатор пользователя в сессии. Аналогично, если пользователь выходит из приложения (doLogout()), мы должны удалить его идентификатор из сессии.
После аутентификации мы перебрасываем пользователя на стартовую страницу:
* если он администратор - на /admin
* если он не администратор - на главную страницу.
Теперь создадим шаблон login/display.html, что позволит нам завершить процедуру аутентификации пользователя.
После этого нам останется только один момент - отображать данные пользователя на страницах панели управления и выводить ссылку на выход из системы. Но для этого нам потребуются дополнительные знания, поэтому этот функционал мы добавим чуть позже.
==== Шаблон login/display.html ====
Файл shop/template/login/display.html:
==== Шаблон flash_box.html и вывод произвольных сообщений для пользователя ====
Создадим также шаблон flash_box.html, который будет использовать для вывода дополнительных ошибок, тех которые, например добавляются при помощи методов lmbController :: flashMessage() или lmbController :: flashError().
Файл shop/template/flash_box.html:
- {$message}
Для получения сообщений мы использовали тег [[..:..:packages:web_app:flash_box|
[...]
{$title}
[...]
Такие же изменения можно произвести с шаблоном admin_page.html, если потребуется.
===== Промежуточные результаты =====
Попробуем зайти на страницу /login нашего приложения и ввести любые данных в поля для ввода логина и пароля:
{{{limb3:ru:tutorials:shop:login_error.png|Ошибка входа в систему}}}
Мы можете также попробовать ввести логин и пароль учетной записи, созданной ваши ранее. В этом случае вы увидите надпись "You were logged in!".
===== Далее =====
Теперь у нас есть функционал по аутентификации пользователей, но толку от него немного. Мы должны внедрить в наше приложение проверку прав доступа к панели управления, а также отобразить информацию для текущего пользователя.
Итак, следующий шаг: [[step4-3|Шаг4.3 Проверка прав доступа]].