The more Zend Framework projects I work on, the more I find myself needing to run part of the application on the command line. Whether it’s imports at 2am or batch printing in the background, there’s plenty of need to offload parts of your application. But what if you need to use some of the business logic tied up in your ZF app? What if you need access to some logic in a model?
One solution is to create a helper file that will build up the M layer of your MVC stack. Basically, parallel what happens in the index.php file in a full blown ZF app, but don’t run the application. Then you include this helper file in your command line scripts and you’ll have access to your business logic.
After including the helper file, you’ll have access to the registry items that are set in your bootstrapping logic.
<?php
// Define path to application directory
defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
// application environment - default to production if not set
defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
/** Zend_Application */
require_once 'Zend/Application.php';
// boot application application
$application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
$application->bootstrap();
This is all fine and good, but you’re going to have to change the default APPLICATION_ENV to the config area you’re in when you run this. I think this is a pain in the butt, so I like to add a little helper code that introspects the .htaccess file in the public folder.
Here’s the code:
<?php
// determine application environment from htaccess
if (!defined('APPLICATION_ENV') && file_exists(APPLICATION_PATH . '/../public/.htaccess')) {
preg_match('/SetEnv APPLICATION_ENV (.+)/', file_get_contents(APPLICATION_PATH . '/../public/.htaccess'), $matches);
define('APPLICATION_ENV', $matches[1]);
}
If you’re using Zend_Controller_Plugins and have events tied to routeStartup event that you’d like to use without routing the application, you can get access to them through Zend_Controller_Front like this:
<?php
// THIS CODE IS ONLY NECESSARY IF YOU USE PLUGINS
// usually we don't init the db until there is a routing request
// but there's no routing, so we manually boot the db, log and cache
$front = Zend_Controller_Front::getInstance();
$initPlugin = $front->getPlugin('My_Plugin_Initialize');
$initPlugin->initLog()
->initDb()
->initCache();
Here it is all put together:
<?php
// Define path to application directory
defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
// determine application environment from htaccess
if (!defined('APPLICATION_ENV') && file_exists(APPLICATION_PATH . '/../public/.htaccess')) {
preg_match('/SetEnv APPLICATION_ENV (.+)/', file_get_contents(APPLICATION_PATH . '/../public/.htaccess'), $matches);
define('APPLICATION_ENV', $matches[1]);
}
// application environment - default to production if not set
defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
/** Zend_Application */
require_once 'Zend/Application.php';
// boot application application
$application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
$application->bootstrap();
// THIS CODE IS ONLY NECESSARY IF YOU USE PLUGINS
// usually we don't init the db until there is a routing request
// but there's no routing, so we manually boot the db, log and cache
$front = Zend_Controller_Front::getInstance();
$initPlugin = $front->getPlugin('My_Plugin_Initialize');
$initPlugin->initLog()
->initDb()
->initCache();
Finally, save the above code as cmd_line_bootstrap.php and include it when you build your command line scripts. Keep in mind that this is not a replacement for your application bootstrap file; it’s a bootstrap for files that run at the command line.
<?php
require_once('cmd_line_bootstrap.php');
/**
* Zend application now loaded
*
* ALL REGISTRY ELEMENTS ARE BE SET
* I.E. DB, CONFIG, ETC
*
* INCLUDE PATHS ARE SET
*/
$db = Zend_Registry::get('db'); // no need to set the include path for Zend_Registry
Zend_Debug::dump($db); // access is already setup to our db