Skip to content

Instantly share code, notes, and snippets.

@pepe84
Created July 4, 2011 09:57
Show Gist options
  • Save pepe84/1063159 to your computer and use it in GitHub Desktop.
Save pepe84/1063159 to your computer and use it in GitHub Desktop.
PHP Zend: Resources lazy loading
<?php
class App
{
/** @var Zend_Application */
static protected $_application;
public function __construct()
{
// Using INI
$config = APPLICATION_PATH . '/config/application.ini';
// Create application
include_once APPLICATION_ROOT . '/library/Zend/Application.php';
self::$_application = new Zend_Application(APPLICATION_ENV, $config);
}
/**
*
* @return Zend_Application
*/
public function getApplication()
{
return self::$_application;
}
/**
* Shortcut for the application config
*
* @param string $key A dot-separated path to a config value
* @param string $default The value to return if the key was not found
* @return Zend_Config | mixed
*/
static public function config($key)
{
static $config;
if (!$config) {
$config = self::$_application->getOption('parameters');
$config = $config['config'];
}
$keys = explode('.', $key);
foreach ($keys as $k) {
if (!isset($config[$k])) {
trigger_error("Unable to find config key '$key'", E_USER_NOTICE);
return NULL;
}
$config = $config[$k];
}
return $config;
}
/**
* Get Zend application resource
*
* @param string $resource
* @return Zend_Application_Resource_ResourceAbstract
*/
static public function get($resource)
{
return self::$_application->getBootstrap()->getResource($resource);
}
/**
* Shortcut for the application cache
*
* @return Zend_Cache_Core
*/
static public function cache()
{
return self::get('cachemanager')->getCache('mycache');
}
/**
* Shortcut for the application log
*
* @return My_Zend_Log
*/
static public function log()
{
return self::get('log');
}
/**
* Magic PHP static call method
*
* @version PHP 5.3 or higher
* @param string $fn
* @param array $args
* @return object
*/
static public function __callStatic($fn, $args)
{
// Remove the "get" prefix
if (strpos($fn, 'get') === 0) {
$fn = substr($fn, 3);
}
return self::get($fn);
}
/**
* Magic PHP call method
*
* @param string $name
* @param array $arguments
*/
public function __call($name, $arguments)
{
// Use application by default
$app = $this->getApplication();
return call_user_func_array(array($app, $name), $arguments);
}
}
[production]
; PHP INI Settings
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
; Define include paths for the application
includepaths[] = APPLICATION_PATH
includepaths[] = APPLICATION_PATH "/models"
includepaths[] = APPLICATION_PATH "/models/mappers"
; Namespaces for autoload
appnamespace = ""
; Autoloader Options
autoloaderNamespaces[] = "My"
autoloaderNamespaces[] = "PHPTAL"
; Bootstrap Location
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
; Plugins
pluginPaths.My_Zend_Application_Resource = APPLICATION_ROOT "/library/My/Zend/Application/Resource"
; All resources used by Zend_Application are loaded on every request
autoloadResources[] = 'frontController'
autoloadResources[] = 'session'
autoloadResources[] = 'view'
autoloadResources[] = 'layout'
autoloadResources[] = 'db'
; Symfony ServiceContainer using SfBootstrap
;container = "My_Symfony_sfServiceContainer"
...
<?php
class My_Zend_Application_Bootstrap_Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/**
* Bootstrap implementation
*
* This method may be overridden to provide custom bootstrapping logic.
* It is the sole method called by {@link bootstrap()}.
*
* @param null|string|array $resource
* @return void
* @throws Zend_Application_Bootstrap_Exception When invalid argument was passed
*/
protected function _bootstrap($resource = null)
{
if (null === $resource && $this->hasOption('autoloadResources')) {
// Bootstrap all? No, lazy loading...
$resource = $this->getOption('autoloadResources');
}
parent::_bootstrap($resource);
}
/**
* Execute a resource and apply custom configurations
*
* @param string $resource
* @return void
* @throws Zend_Application_Bootstrap_Exception When resource not found
*/
protected function _executeResource($resource)
{
$resourceName = strtolower($resource);
if (!in_array($resourceName, $this->_run)) {
// Load resource into container
parent::_executeResource($resource);
// Modify resource object if needed
$resourceMethod = '_config' . $resource;
if (method_exists($this, $resourceMethod)) {
// Get resource from container
$object = parent::getResource($resource);
// Flag resource to avoid circular dependencies
$this->_started[$resourceName] = true;
// Modify resource
$override = $this->$resourceMethod($object);
// Unflag resource
unset($this->_started[$resourceName]);
// Update container
$this->setResource($resource, $override ?: $object);
}
}
}
/**
* Retrieve a resource from the container
*
* If no value was returned, this will return an Exception.
*
* @param string $name
* @return null|mixed
*/
public function getResource($name)
{
try {
// Ensure that resource is loaded...
$this->bootstrap($name);
} catch(Zend_Application_Bootstrap_Exception $e) {
// Resource not found
return null;
}
return parent::getResource($name);
}
/**
* Set a resource into container
*
* @param string $name
* @param object $object
*/
public function setResource($name, $object)
{
$resource = strtolower($name);
$container = $this->getContainer();
if ($this->hasResource($resource)) {
$container->{$resource} = $object;
}
}
}
<?php
class My_Zend_Application_Bootstrap_SfBootstrap extends My_Zend_Application_Bootstrap_Bootstrap
{
/**
* Sets resource container
*
* We are extending this method so we can use Symfony's dependency injection
* container instead of Zend_Registry. If the $container argument is a
* string it's evaluated as the path to a php file defining the container.
* If the argument is an object the default parent behaviour is used.
*
* @param string|object $container
* @return My_Zend_Application_Bootstrap_SfBootstrap (fluent interface)
*/
public function setContainer($container)
{
if (is_string($container)) {
// Setup Symfony's DI autoloader
include_once 'Symfony/DependencyInjection/sfServiceContainerAutoloader.php';
sfServiceContainerAutoloader::register();
// Convert tree-like config structure to a hashmap (dot separated)
$params = $this->_flattenArray($this->getOption('resources'));
$container = new $container($params);
}
parent::setContainer($container);
return $this;
}
/**
* Flattens a multidimmensional array separating nesting levels with a dot
*
* @param array $params
* @param string $path
* @return array
*/
protected function _flattenArray($params, $path = '')
{
$keys = array_keys($params);
$values = array();
foreach ($keys as $k) {
$values[$path . $k] = $params[$k];
if (is_array($params[$k])) {
$arr = $this->_flattenArray($params[$k], $path . $k . '.');
$values = array_merge($values, $arr);
}
}
return $values;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment