Обработка ошибок в php, это весьма занятная вещь. С одной стороны, в этом языке есть все, чтобы обработать и вывести ошибку. С другой, в нем есть такой тип ошибок, который ни коим образом не обрабатывается. Это Fatal Error, или ошибки синтаксиса. 

Ошибки таких типов не попадают в обработчики, они просто выводятся как есть. 

Дисклеймер

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

Итак, в прошлых уроках мы создали макет приложения, пару страниц, роутер и шаблонизатор. Мы даже объявили такой класс

class Except extends Exception{}

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

Когда в коде мы обрабатывали какую-то бизнес логику, мы выкидывали исключение, таким кодом

throw new Except('Error message');

это приводило к тому, что на экране выводилась подобная запись 

вывод ошибок в Ideal фреймворк до версии 1.0.2

Fatal error: Uncaught exception 'Except' with message 'File Z:\home\analize\ideal/application/views/page/pages/B2.php not found' in Z:\home\analize\ideal\ideal\classes\Controller.php:29 Stack trace: #0 Z:\home\analize\ideal\ideal\classes\Controller.php(43): Controller->_renderPartial('Z:\home\analize...', Array, true) #1 Z:\home\analize\ideal\application\views\page\read.php(2): Controller->renderPartial('pages/B2') #2 Z:\home\analize\ideal\ideal\classes\Controller.php(26): include('Z:\home\analize...') #3 Z:\home\analize\ideal\ideal\classes\Controller.php(43): Controller->_renderPartial('Z:\home\analize...', Array, true) #4 Z:\home\analize\ideal\ideal\classes\Controller.php(53): Controller->renderPartial('read', Array, true) #5 Z:\home\analize\ideal\application\controllers\PageController.php(4): Controller->render('read', Array) #6 [internal function]: PageController->actionRead('B2') #7 Z:\home\analize\ideal\ideal\classes\Controller.php(7): call_user_func_array(Array, Array) #8 Z:\home\analize\ideal\ideal\classes\App.php in Z:\home\analize\ideal\ideal\classes\Controller.php on line 29

Это встроенный обработчик ошибок php, вывел для нас эту исчерпывающую информацию. Здесь есть все что нам потребуется для того, чтобы выяснить, что же произошло: само сообщение, стек вызова функций с файлами и методами. Мы видим даже параметры, которые поданы в тех или методах стека. Все что нужно есть, но выводится это не очень красиво.

Для того, чтобы сделать это более удобоваримым, нам потребуется установить обработчик исключений, через метод set_exception_handler. Мы обрабатываем не только исключения, но и ошибки php (все, кроме fatal), поэтому установим еще обработчик set_error_handler.

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

Для начала переименуем класс Model в ideal/classes/Model.php в Registry и файл назовем также ideal/classes/Registry.php При разработке можете скидывать на этот класс все, что связано с настройками, с запросами, и т.п.

В местах его использования также все переименуем

<?php
class Registry{
	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.php

$this->config = new Registry(array_merge($default_config, $custom_config));
//...
$this->uri = new Registry(Router::gi()->parse($_SERVER['REQUEST_URI']));

и в application/models/user.php

class User extends Registry{

Теперь ничего нам не мешает создать новый класс ideal/classes/Model.php

<?php
class Model{
	private $_data = null;
	function __construct() {
		$this->_data = new stdClass();
	}
	function __set($name, $value) {
		$this->_data->$name = $value;
	}
	function __get($name) {
		return property_exists($this->_data, $name) ? $this->_data->$name : null;
	}
}

отличие от Registry пока лишь в том, что мы используем объект место ассоциативного массива.

Теперь при обращении к полю экземпляра такой модели

$model = new Model();
$model->id = 5;

вызывается магический метод __set и внутреннему объекту $data в поле $id записывается нужное значение.

Зачем это делать? - спросите вы

 Одну вещь, которую я часто вижу, когда просматриваю чужой код на php, это не правильное использование функции  method_exists(), и это требует немного разъяснений.

Это типичный пример того, о чем я тут говорю

if (method_exists($object, 'SomeMethod')){
  $object->SomeMethod($this, TRUE);
}

Цель у этого куска кода довольно проста - понять: имеет ли некий объект (переменная $object) метод с названием SomeMethod, если так то вызвать его, подав несколько аргументов на вход

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

Как мы обычно делаем, если надо реализовать такую логику:

if ($a) {
 $b = $a;
} else {
 $b = $c;
}

чтобы не плодить if-else блоков, мы делаем так

$b = $a ? $a : $c;

Где-то я читал что подобная конструкция не читабельна, но она очень удобна. Я так и пишу, смущает разве повторение оператора $a. Если это переменная то черт с ней, но если это какой-то метод или функция, то получается два вывода. Что совсем не гуд.

В JS есть удобная конструкция на этот случай

var b = a || c;

Если a отлично от false, то в b будет записано оно, если нет то с. В php такое не сработает. Там в $b запишется результат логического сравнения.

Но оказывается в PHP есть аналогичная конструкция

$b = $a ?: $c;

Та дааам! Получите и распишитесь. Кто бы знал.

Yii2 позволяет легко создать механизм регистрации/входа/профиля через расширение yii2-user.

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

  • /user/registration/register Регистрация
  • /user/registration/resend Повторная отправка инструкций по регистрации
  • /user/registration/confirm Подтверждение пароля
  • /user/security/login Форма авторизации
  • /user/security/logout Выход(работает только через POST)
  • /user/recovery/request Востановление пароля
  • /user/settings/profile Настройки профиля
  • /user/settings/account Настройки аккаунта (email, username, password)
  • /user/settings/networks Привязанные социальные аккаунты
  • /user/profile/show Профиль пользователя (требует id)
  • /user/admin/index Менеджер пользователей

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

Подкатегории

Все о разработке на фреймворке Yii