CakePHP с перехватом ошибок в AppError Автосоздание таблиц

В начале (когда я только познакомилась с пирожками) мне очень нравились страницы ошибок, которые так ненавязчиво намекали — а не создашь ли ты таблицу в базе данных? может быть стоит подумать о контроллере? и прочие очень нужные подсказки. Но потом, когда моя джедаистость в кейке выросла, а количество файлов для проектов сократилось до минимума — мне стало неприятно. В простых, однотипных решениях я не хочу делать одни и те же вещи каждый раз, я знаю какая таблица мне нужна. Контроллер — да он вовсе один, слегка распухший. Итак, что нам нужно — это перехват ошибок.

Для этого создаем в корне приложения (/app) файл app_error.php Обратите внимание, в этом месте, на верхнем уровне над всеми моделями/контроллерами/вьювами и прочим барахлишком у нас могут быть еще два (2!) нужных файла app_controller.php и app_model.php. Они наследуются всеми (еще раз подумайте!) соответствующими классами Вашего приложения. Безграничные возможности минимизации писанины, не правда ли? Но о них чуть потом. Итак, мы создали файл ошибки, и теперь мы должны прописать главный класс ошибок

class AppError extends ErrorHandler

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

<?php
class AppError extends ErrorHandler {
	function missingTable($params) {
		if ($params['className'] == 'User') {
			if (!class_exists('ConnectionManager')) {
				require LIBS . 'model' . DS . 'connection_manager.php';
			}
			$path = TMP . 'cache' . DS . 'models';
			$dir  = dir($path);
			while (false !== ($entry = $dir->read())) {
				if (is_file($path . DS . $entry)) {
					unlink($path . DS . $entry);
				}
			}
			$dir->close();
			$connection = ConnectionManager::getInstance();
			$database   = $connection->getDataSource('default');			
			$sql = "
				CREATE TABLE `" . DB_PREF . "users` (
					`id` int(16) NOT NULL auto_increment,
					`email` varchar(255) collate utf8_unicode_ci NOT NULL,
					`password` varchar(255) collate utf8_unicode_ci NOT NULL,
					PRIMARY KEY(`id`),
					UNIQUE KEY `email` (`email`)
				) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
			";
			$database->execute($sql);
 
			App::import('Component', 'Auth');
			$Auth = new AuthComponent();
			$sql = "
				INSERT INTO 
					`" . DB_PREF . "users` (`id`, `email`, `password`) 
				VALUES
					(1, 'user', '" . $Auth->password('pass') . "')
			";
			$database->execute($sql);
 
			$this->controller->redirect('/');
		}
		parent::missingTable($params);
	}
}
?>

Что тут происходит? Если нужна таблица пользователей, например, мы только что скопировали проект простых сайтов на новый хостинг для установки и нет там еще такой таблицы — то мы ведь сами умные и знаем как таблица должна выглядеть. Да будет свет! Да появится таблица нужная! Схемы таблиц можно хранить в отдельном файле, добавлять логику к созданию — но посмотрите, как прекрасен этот мир) В коде есть маленькая заплатка — в самом начале очищается кеш таблиц базы данных, ведь то что мы создали таблицу так хитро не убирает ошибку «такой таблицы нет» в списке. Поэтому чистота — наш друг)

2 комментария “CakePHP с перехватом ошибок в AppError Автосоздание таблиц”

  1. Интересный tip. Но ИМХО проще залить дамп базы при переезде. А вот в ядре кейка этому есть применение. Например когда сессии используют БД, то таблица cake_sessions могла бы и автоматом создаться. Тем более, что скачиваемых пакетов кейка (1.3) файла sql с дампом cake_sessions на своем старом месте я не обнаружил.

    Ответить
    • кому как удобнее, сама возможность полезна (мне очень нравится уменьшать свою работу, а в одном скрипте переездов больше чем изменений главных таблиц)

      Ответить

Оставить комментарий

XHTML: Вы можете использовать такие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">