Bill Shupp Software engineer, photographer, musician, space geek


PHP’s interactive shell as your application console

When developing a web application, it's common for your feature development to be ahead of any data administration tools you might need.  While some frameworks, such as django, have built in admin tools for managing your application's data, many don't.  At my current job we use Zend Framework, and have rolled our own lightweight model layer which does not have any fancy automatic admin tools.  In addition to supporting database pools and selectors for partitioning of data, it also has transparent caching of data.  While this is good for speed, it precludes you from making any data storage changes without going through this model layer or the cache will get out of sync.  For now, rather than doing any DB queries directly, we do them through CLI jobs built for a specific task (batch updates, etc).  This works fairly well, but often things come up that aren't yet supported in the application's admin tools, such as changing a user's status bits, etc.. Things that a CLI console would be useful for.

I was playing with django's shell recently, and I realized that with the way we have our bootstrapping setup, it's actually pretty trivial to get full access to our data models from PHP's interactive shell.  Because we have multiple entry points to our application (primary entry point, media entry point, testing from CLI, etc), we already consolidated the generic bootstrapping into an init.php file that is used by all of the entry points.  This file contains most of the usual things you'll find in a Zend Framework application's default index.php, such as setting up environment definitions, setting the include path, setting up autoload, etc.  The only thing the entry points do really is instantiate the application and run it.  With our current setup, I can start the interactive shell, require the init.php file, and instantiate and bootstrap the application.  From that point on, I have full access to the application's models, and any changes will keep caching in sync with its data.

Here's an example of changing my password from the console:

$ APPLICATION_ENV='development' php -a
Interactive shell

php > require_once './init.php';
php > EC::getApplication()->bootstrap();
php > $user = new Model_User(array('username' => 'shupp'));
php > $user->setPasswordFromClear('foobar');
php > $user->update();
php > quit


Here's an example of looping over a collection of users and modifying their status bits:

$ APPLICATION_ENV='development' php -a
Interactive shell

php > require_once './public/init.php';
php > EC::getApplication()->bootstrap();
php > $users = new Model_UserCollection(array('username' => array('shupp', 'dwayne')));
php > foreach ($users as $user) {
php {     $user->setStatus(Model_User::STATUS_PASSWORD_EXPIRED);
php {     $user->update();
php { }
php > quit


The interactive shell supports tab completion of file names for things like require_once, which is nice. It also has history support between sessions, so you can use the up arrow to easily navigate to previous lines you've typed. Pretty handy!

Comments (0) Trackbacks (0)

No comments yet.

Leave a comment

No trackbacks yet.