Написал класс может кому поможет и облегчит усилия. Вот его код:
<pre>
<?php
require_once 'Zend/Loader.php';
require_once 'Zend/Log.php';
require_once 'Zend/Layout.php';
require_once 'Zend/Controller/Action/Helper/ViewRenderer.php';
require_once 'Myak/View.php';
class Myak extends ArrayObject
{
private static $_instance;
private static $_class = 'Myak';
protected $_front, $_config, $_db, $_logger;
protected $_moduleDir, $_varDir, $_templateDir, $_uploadDir,
$_cacheDir, $_logDir, $_sessionDir;
protected $_templateUrl, $_uploadUrl;
public static function setInstance(Myak $instance)
{
self::$_instance = $instance;
self::$_class = get_class($instance);
}
public static function getInstance($new = true)
{
if (null === self::$_instance && $new) {
self::$_instance = new self::$_class;
}
return self::$_instance;
}
public static function unsetInstance()
{
self::$_instance = null;
}
public static function get($index)
{
$instance = self::getInstance();
if (false !== ($getter = $instance->_getGetter($index))) {
return $instance->$getter();
}
if (!$instance->offsetExists($index)) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('No entry is registered for key
"' . $index . '".');
}
return $instance->offsetGet($index);
}
public static function set($index, $value)
{
$instance = self::getInstance();
if (false !== ($setter = $instance->_getSetter($index))) {
$instance->$setter($value);
} else {
$instance->offsetSet($index, $value);
}
return $instance;
}
public function __construct($array = array(), $flags = 0, $class =
'ArrayIterator')
{
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
set_exception_handler(array($this, 'exception'));
set_error_handler(array($this, 'error'));
umask(0);
$this->_unregisterGlobals()
->_stripGlobalSlashes();
parent::__construct($array, $flags, $class);
}
public function exception(Exception $e)
{
try {
$config = $this->getConfig();
$logger = $this->getLogger();
} catch (Exception $e) {
}
if (isset($config->myak->log->enable) && $config->myak->log-
>enable && isset($logger)) {
$logger->emerg($e->__toString());
}
if (isset($config->myak->debug) && $config->myak->debug) {
die('<pre>' . $e . '</pre>');
}
die('Error occurred.');
}
public function error($no, $str, $file, $line)
{
if (!error_reporting()) {
return true;
}
$msg = false;
if ($no == E_RECOVERABLE_ERROR) {
$priority = Zend_Log::CRIT;
$msg = 'Catchable fatal error (E_RECOVERABLE_ERROR,
4096).';
} elseif ($no == E_WARNING || $no == E_USER_WARNING) {
$priority = Zend_Log::WARN;
switch ($no) {
case E_WARNING:
$msg = 'Run-time warning (E_WARNING, 2).';
break;
case E_USER_WARNING:
$msg = 'User-generated warning message
(E_USER_WARNING, 512).';
break;
}
} elseif ($no == E_NOTICE || $no == E_STRICT || $no ==
E_USER_NOTICE) {
$priority = Zend_Log::NOTICE;
switch ($no) {
case E_NOTICE:
$msg = 'Run-time notice (E_NOTICE, 8).';
break;
case E_STRICT:
$msg = 'Run-time notice (E_STRICT, 2048).';
break;
case E_USER_NOTICE:
$msg = 'User-generated notice message
(E_USER_NOTICE, 1024).';
break;
}
} elseif ($no == E_USER_ERROR) {
$priority = Zend_Log::ERR;
$msg = 'User-generated error message (E_USER_ERROR,
256).';
}
$config = $this->getConfig();
if ($msg !== false) {
$msg .= "\nFile: $file\nLine: $line\nMessage: $str";
if (isset($config->myak->log->enable) && $config->myak-
>log->enable) {
$this->getLogger()->log($msg, $priority);
}
}
if (isset($config->myak->debug) && $config->myak->debug) {
return false;
}
return true;
}
public function run()
{
$this->_initFront();
$this->_initView();
$front = $this->getFront();
$front->addModuleDirectory($this->getModuleDir());
$config = $this->getConfig();
if ($config->myak->gzip && extension_loaded('zlib') &&
isset($_SERVER['HTTP_ACCEPT_ENCODING']) &&
(strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false ||
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== false)) {
if (ini_get('zlib.output_compression')) {
$front->returnResponse(true);
} else {
ob_start('ob_gzhandler', 9);
}
}
$this->getResponse()
->setHeader('Expires', 'Thu, 21 Jul 1977 07:30:00 GMT')
->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . '
GMT')
->setHeader('Cache-Control', 'no-cache, must-revalidate')
->setHeader('Cache-Control', 'post-check=0,pre-check=0')
->setHeader('Cache-Control', 'max-age=0')
->setHeader('Pragma', 'no-cache')
->setHeader('Content-type', 'text/html; charset=' .
$config->general->charset);
$response = $front->dispatch();
if ($response !== null) {
$response->setBody(gzencode($response->getBody(), 4));
$response->sendResponse();
}
}
public function offsetExists($index)
{
return array_key_exists($index, $this);
}
public function getFront()
{
if ($this->_front === null) {
require_once 'Zend/Controller/Front.php';
$this->_front = Zend_Controller_Front::getInstance();
}
return $this->_front;
}
public function getConfig()
{
if ($this->_config === null) {
require_once 'Zend/Config.php';
$this->_config = new Zend_Config(array(), true);
}
return $this->_config;
}
public function setConfig($config)
{
if (is_array($config)) {
require_once 'Zend/Config.php';
$configObj = new Zend_Config($config, true);
} elseif (is_string($config) && is_file($config)) {
$ext = false !== strpos($config, '.') ?
substr(strrchr($config, '.'), 1) : $config;
switch ($ext) {
case 'xml':
case 'ini':
$class = 'Zend_Config_' . ucfirst($ext);
Zend_Loader::loadClass($class);
$configObj = new $class($config, null);
break;
case 'php':
require_once 'Zend/Config.php';
// In .php configuration file should be declared
$config var.
require $config;
$configObj = new Zend_Config($config);
break;
default:
require_once 'Myak/Exception.php';
throw new Myak_Exception("Invalid configuration
file \"$config\".");
break;
}
} else {
if (!$config instanceof Zend_Config) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('Invalid configuration
argument.');
}
$configObj = $config;
}
$config = array();
foreach ($configObj->toArray() as $section => $items) {
$config[strtolower($section)] = $items;
}
// Set default section names if they has not been set.
$config += array(
'general' => array(),
'myak' => array(),
);
$config = new Zend_Config($config, true);
//
// Parse general section.
//
$generalConfig = $config->get('general');
if (null === $generalConfig->get('timezone')) {
$generalConfig->timezone = 'Europe/Moscow';
}
// All timezones available at
http://unicode.org/cldr/data/diff/supplemental/territory_containment_un_m_49.html
date_default_timezone_set($generalConfig->get('timezone'));
if (null === $generalConfig->get('charset')) {
$generalConfig->charset = 'utf-8';
}
//
// Parse myak section.
//
$myakConfig = $config->get('myak');
if (null === $myakConfig->get('base_url')) {
$myakConfig->base_url = $this->getBaseUrl();
} else {
$this->setBaseUrl($myakConfig->get('base_url'));
}
if (null === $myakConfig->get('autoload')) {
$myakConfig->autoload = true;
}
if ($myakConfig->get('autoload')) {
Zend_Loader::registerAutoload();
}
$log = $myakConfig->get('log');
if (!$log instanceof Zend_Config) {
$myakConfig->log = new Zend_Config(array('enable' =>
false, 'level' => -1), true);
} else {
if (!isset($myakConfig->log->enable)) {
$myakConfig->log->enable = false;
}
if (!isset($myakConfig->log->level)) {
$myakConfig->log->level = -1;
}
}
if (!isset($myakConfig->debug)) {
$myakConfig->debug = false;
}
if (!isset($myakConfig->template)) {
$myakConfig->template = null;
}
//
// Parse database section.
//
if (null !== ($databaseConfig = $config->get('database'))) {
if (null === $databaseConfig->get('username') || null ===
$databaseConfig->get('dbname')) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('Invalid configuration (check
username or dbname options).');
}
if (null === $databaseConfig->get('host')) {
$databaseConfig->host = 'localhost';
}
if (null === ($driver = $databaseConfig->get('driver'))) {
$databaseConfig->driver = 'pdo_mysql';
} else {
$databaseConfig->driver = strtolower($driver);
}
if (null === $databaseConfig->get('collation')) {
$databaseConfig->collation = 'utf8';
}
if (null === $databaseConfig->get('prefix')) {
$databaseConfig->prefix = '';
}
$drivers = array(
'db2' => array(),
'mysqli' => array('mysqli'),
'odbc' => array(),
'oracle' => array(),
'pdo_mssql' => array('pdo', 'pdo_mssql'),
'pdo_mysql' => array('pdo', 'pdo_mysql'),
'pdo_oci' => array('pdo', 'pdo_oci8'),
'pdo_pgsql' => array('pdo', 'pdo_pgsql'),
'pdo_sqlite' => array('pdo', 'pdo_sqlite'),
);
$this->_loadRequiredExtensions($drivers[$databaseConfig-
>driver]);
}
$this->_config = $config;
return $this;
}
public function getRequest()
{
$front = $this->getFront();
if (null === $front->getRequest()) {
require_once 'Zend/Controller/Request/Http.php';
$front->setRequest(new Zend_Controller_Request_Http());
}
return $front->getRequest();
}
public function setRequest($request)
{
$this->getFront()->setRequest($request);
return $this;
}
public function getResponse()
{
$front = $this->getFront();
if (null === $front->getResponse()) {
require_once 'Zend/Controller/Response/Http.php';
$front->setResponse(new Zend_Controller_Response_Http());
}
return $front->getResponse();
}
public function getDispatcher()
{
return $this->getFront()->getDispatcher();
}
public function getRouter()
{
return $this->getFront()->getRouter();
}
public function getDb()
{
if ($this->_db === null) {
if (null === ($config = $this->getConfig()-
>get('database'))) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('Database configuration was
no set.');
}
require_once 'Zend/Db.php';
$settings = array(
'host' => $config->host,
'username' => $config->username,
'password' => $config->password,
'dbname' => $config->dbname
);
$db = Zend_Db::factory($config->driver, $settings);
$db->query('SET NAMES \'' . $config->collation . '\'');
$db->prefix = $config->prefix;
$this->_db = $db;
require_once 'Myak/Db/Table.php';
Myak_Db_Table::setDefaultAdapter($db);
}
return $this->_db;
}
public function getLogger()
{
if ($this->_logger === null) {
$this->setLogger();
}
return $this->_logger;
}
public function setLogger()
{
$log = 0;
$config = $this->getConfig();
$varDir = $this->getVarDir();
if ($varDir !== null && isset($config->myak->log)) {
$config = $config->myak->log;
if ($config->get('enable')) {
require_once 'Zend/Log/Writer/Stream.php';
$writer = new Zend_Log_Writer_Stream($this->_varDir .
'/log/' . date('Y-m-d') . '.log');
$format = '%timestamp% %priorityName% (%priority%):
%message%' . PHP_EOL . PHP_EOL;
$writer->setFormatter(new
Zend_Log_Formatter_Simple($format));
$level = $config->get('level');
if ($level >= 0) {
$writer->addFilter(new
Zend_Log_Filter_Priority($level));
}
$log = 1;
}
}
if (!$log) {
require_once 'Zend/Log/Writer/Null.php';
$writer = new Zend_Log_Writer_Null();
}
$this->_logger = new Zend_Log($writer);
return $this;
}
public function setModuleDir($path)
{
$moduleDir = $this->_normalizePath($path);
if (!is_dir($moduleDir)) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('Invalid module directory
provided.');
}
$this->_moduleDir = $moduleDir;
return $this;
}
public function getModuleDir()
{
return $this->_moduleDir;
}
public function setTemplateDir($path)
{
$templateDir = $this->_normalizePath($path);
if (php_sapi_name() == 'cli') {
$this->_templateUrl = '';
} else {
$baseUrl = $this->getBaseUrl();
if (empty($baseUrl)) {
$baseUrl = '/';
}
if (false === ($pos = strripos($templateDir, $baseUrl))) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('Bad path (template directory
or base URL).');
}
$this->_templateUrl = substr($templateDir, $pos);
}
$this->_templateDir = $templateDir;
return $this;
}
public function getTemplateDir()
{
return $this->_templateDir;
}
public function getTemplateUrl()
{
return $this->_templateUrl;
}
public function getTemplate()
{
return $this->getConfig()->get('myak')->get('template');
}
public function setVarDir($path)
{
$varDir = $this->_normalizePath($path);
$dirs = array(
'cacheDir' => $varDir . '/cache',
'logDir' => $varDir . '/log',
'sessionDir' => $varDir . '/session',
);
foreach ($dirs as $key => $dir) {
if (!is_writable($dir) || !is_dir($dir)) {
require_once 'Myak/Exception.php';
throw new Myak_Exception("Directory \"$dir\" should be
valid and has write permissions (777).");
}
$key = '_' . $key;
$this->$key = $dir;
}
$this->_varDir = $varDir;
return $this;
}
public function getVarDir()
{
return $this->_varDir;
}
public function getLogDir()
{
return $this->_logDir;
}
public function getSessionDir()
{
return $this->_sessionDir;
}
public function getCacheDir()
{
return $this->_cacheDir;
}
public function setUploadDir($path)
{
$uploadDir = $this->_normalizePath($path);
if (!is_writable($uploadDir) || !is_dir($uploadDir)) {
require_once 'Myak/Exception.php';
throw new Myak_Exception("Directory \"$path\" should be
valid and has write permissions (777).");
}
if (php_sapi_name() == 'cli') {
$this->_uploadUrl = '';
} else {
$baseUrl = $this->getBaseUrl();
if (empty($baseUrl)) {
$baseUrl = '/';
}
if (false === ($pos = strripos($uploadDir, $baseUrl))) {
require_once 'Myak/Exception.php';
throw new Myak_Exception('Bad path (upload directory
or base URL).');
}
$this->_uploadUrl = substr($uploadDir, $pos);
}
$this->_uploadDir = $uploadDir;
return $this;
}
public function getUploadDir()
{
return $this->_uploadDir;
}
public function getUploadUrl()
{
return $this->_uploadUrl;
}
public function getBaseUrl()
{
$front = $this->getFront();
if (null === $front->getBaseUrl() && php_sapi_name() != 'cli')
{
$config = $this->getConfig();
if (!empty($config->myak->base_url)) {
$front->setBaseUrl((string) $config->myak->base_url);
} else {
$front->setBaseUrl(dirname($_SERVER['SCRIPT_NAME']));
}
}
return $front->getBaseUrl();
}
public function setBaseUrl($url)
{
$this->getFront()->setBaseUrl((string) $url);
return $this;
}
protected function _initView()
{
$template = $this->getTemplate();
$templateDir = $this->_templateDir;
$layout = Zend_Layout::startMvc(array('layoutPath' =>
$templateDir . '/' . $template));
$layout->setLayout('index');
$options = array(
'helperPath' => 'Myak/View/Helper',
'helperPathPrefix' => 'Myak_View_Helper',
);
$view = new Myak_View($options);
$viewRenderer = new
Zend_Controller_Action_Helper_ViewRenderer($view);
// For common .phtml files in themes/template_name directory.
$viewRenderer->view->addScriptPath($templateDir . '/' .
$template);
$viewRenderer->view->setEncoding($this->_config-
>get('general')->get('charset'));
$viewRenderer->setViewScriptPathSpec($template .
'/:controller-:action.:suffix')
->setViewScriptPathNoControllerSpec($template .
'/:action.:suffix');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
return $this;
}
protected function _initFront()
{
$front = $this->getFront();
$front->throwExceptions($this->getConfig()->get('myak')-
>get('debug'));
$front->setBaseUrl($this->getBaseUrl());
Zend_Controller_Action_HelperBroker::addPath(
'Myak/Controller/Action/Helper/',
'Myak_Controller_Action_Helper'
);
$this->getRequest();
$this->getResponse();
return $this;
}
protected function _normalizePath($path)
{
return rtrim(str_replace('\\', '/', $path), '/');
}
protected function _loadRequiredExtensions(array $extensions =
array())
{
foreach ($extensions as $extension) {
if (!extension_loaded($extension)) {
require_once 'Myak/Exception.php';
throw new Myak_Exception("Extension \"$extension\" not
found. Check php.ini and run phpinfo() function.");
}
}
return $this;
}
protected function _getGetter($index)
{
static $mapped = array();
if (isset($mapped[$index])) {
return $mapped[$index];
}
$method = 'get' . ucfirst($index);
if (method_exists($this, $method)) {
$mapped[$index] = $method;
return $method;
}
$mapped[$index] = false;
return false;
}
protected function _getSetter($index)
{
static $mapped = array();
if (isset($mapped[$index])) {
return $mapped[$index];
}
$method = 'set' . ucfirst($index);
if (method_exists($this, $method)) {
$mapped[$index] = $method;
return $method;
}
$mapped[$index] = false;
return false;
}
protected function _unregisterGlobals()
{
$rg = @ini_get('register_globals');
if ($rg === '' || $rg === '0' || strtolower($rg) === 'off') {
return $this;
}
// Prevent script.php?GLOBALS[foo]=bar
if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']))
{
exit('I\'ll have a steak sandwich and... a steak
sandwich.');
}
$noUnset = array('GLOBALS', '_GET', '_POST', '_COOKIE',
'_REQUEST', '_SERVER', '_ENV', '_FILES');
$input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV,
$_FILES, isset($_SESSION) && is_array($_SESSION) ? $_SESSION :
array());
foreach ($input as $k => $v) {
if (!in_array($k, $noUnset) && isset($GLOBALS[$k])) {
unset($GLOBALS[$k]);
unset($GLOBALS[$k]); // Double unset to circumvent the
zend_hash_del_key_or_index hole in PHP < 5.1.4.
}
}
return $this;
}
protected function _stripGlobalSlashes()
{
set_magic_quotes_runtime(0);
if (get_magic_quotes_gpc()) {
$_GET = $this->_stripSlashesArray($_GET);
$_POST = $this->_stripSlashesArray($_POST);
$_COOKIE = $this->_stripSlashesArray($_COOKIE);
$_REQUEST = $this->_stripSlashesArray($_REQUEST);
}
return $this;
}
protected function _stripSlashesArray(&$array)
{
return is_array($array) ? array_map(array($this,
'_stripSlashesArray'), $array) : stripslashes($array);
}
}
</pre>
Пример использования:
<pre>
$dir = dirname(__FILE__);
set_include_path($dir . '/application'
. PATH_SEPARATOR . $dir . '/library');
require_once 'Myak.php';
Myak::setInstance(new Myak);
Myak::getInstance()
->setConfig($dir . '/config/myak.php')
->setModuleDir($dir . '/modules')
->setTemplateDir($dir . '/templates')
->setUploadDir($dir . '/uploads')
->setVarDir($dir . '/var')
->run();
</pre>
Конфиг может передаваться несколькими способами:
1. Как массив.
2. Как .ini, .xml или .php файл.
Пример конфига:
<pre>
<?php
$config = array(
'General' =>
array (
'charset' => 'utf-8',
'timezone' => 'Europe/Kiev',
),
'Database' =>
array (
'host' => 'localhost',
'username' => 'gazetka',
'password' => 'password',
'dbname' => 'gazetka',
'collation' => 'utf8',
'prefix' => '',
'driver' => 'MySqli',
),
'Myak' =>
array (
'autoload' => '1',
'template' => 'gazetka',
'gzip' => 1,
'debug' => 1,
'log' => array(
'enable' => 1
),
),
);
</pre>
Класс полезен тем, что вы можете получить любой объект в любом месте
программы:
<pre>
Myak::get('db');
Myak::get('router');
Myak::get('logger');
</pre>
и т. д.
Также можно сохранить любой объект с помощью Myak::set('объект'), т.
е. класс действует как реестр.
Все ошибки автоматом пишутся в лог-файл, который будет лежать в
директории var/log.
Если есть вопросы, пожалуйста задавайте. Жду критики и предложений по
улучшению кода.