Creating Zend_Tool Providers
When I was at Symfony Live this past February, I assisted Stefan Koopmanschap in a full-day workshop on integrating Zend Framework in Symfony applications. During that workshop, Stefan demonstrated creating Symfony "tasks". These are classes that tie in to the Symfony command-line tooling — basically allowing you to tie in to the CLI tool in order to create cronjobs, migration scripts, etc.
Of course, Zend Framework has an analogue to Symfony tasks in the Zend_Tool component's "providers". In this post, I'll demonstrate how you can create a simple provider that will return the most recent entry from an RSS or Atom feed.
First things first
Caveat: this entire post assumes you are using a unix-like operating system, such as a Linux distribution or Mac OSX. Most of the instructions should work in Windows, but I have not tested on that platform.
First, a little setup. Zend_Tool
needs some configuration. To get started, you
need to run the following command (if you haven't already):
$ zf create config
This will create a configuration in $HOME/.zf.ini
. If you pop that file open,
you should see an entry for php.include_path
. This is the include_path
Zend_Tool
will use, and should include your ZF installation; any providers you
create should be on this path — or you should modify it to add a path to your
providers.
Create the provider
Providers are incredibly simple. The easiest way to create one is to create a
class extending Zend_Tool_Framework_Provider_Abstract
, and then to simply
start creating methods.
A few rules are good to know, however:
-
If you need to throw an exception, throw a
Zend_Tool_Project_Exception
. This integrates with the CLI tooling to provide nice, colorful error messages. -
While you can
echo
directly from your methods, the suggested practice is to use the response object and append content to it. This will ensure that if we later write an XML-RPC, SOAP, or web frontend toZend_Tool
, you will not need to make any changes to your code. This is as easy as:$response = $this->_registry->getResponse(); $response->appendContent($content);
In my provider, I'm wanting to grab the first entry of a given feed. Instead of needing to remember the feed URL, I'd like to use a mnemonic; this will be my sole argument to the provider. I'll have it default to my own feed. The code ends up looking like this:
class Phly_Tool_Feed extends Zend_Tool_Framework_Provider_Abstract
{
protected $_feeds = array(
'weierophinney' => 'http://weierophinney.net/matthew/feeds/index.rss1',
'planetphp' => 'http://www.planet-php.net/rdf/',
);
/**
* Read the first item of a feed
*
* @param string $feed Named identifier for a feed
* @return bool
*/
public function read($feed = 'weierophinney')
{
if (!array_key_exists($feed, $this->_feeds)) {
throw new Zend_Tool_Project_Exception(sprintf(
'Unknown feed "%s"',
$feed
));
}
$feed = Zend_Feed_Reader::import($this->_feeds[$feed]);
$title = $desc = $link = '';
foreach ($feed as $entry) {
$title = $entry->getTitle();
$desc = $entry->getDescription();
$link = $entry->getLink();
break;
}
$content = sprintf("%s\n%s\n\n%s\n", $title, strip_tags($desc), $link);
$response = $this->_registry->getResponse();
$response->appendContent($content);
return true;
}
}
I'm leveraging Zend_Feed_Reader
here, and simply creating some formatted text
output.
Now that the provider is created, I need to put it in the file
Phly/Tool/Feed.php
, relative to a directory in the include_path
configured
by Zend_Tool
.
Tying the provider to the tool
Now that we've got the provider written and somewhere Zend_Tool
can
potentially find it, we need to tell Zend_Tool
about it. Open up the
$HOME/.zf.ini
file again, and add the following line:
basicloader.classes.1 = \"Phly_Tool_Feed\"
This tells Zend_Tool
that there's an additional provider it should be aware
of. Note in particular the .1
portion of the key; basicloader.classes
is an
array. One gotcha I discovered is that, unlike Zend_Config
, you cannot use the
[]
notation. In other words, the following does not work:
basicloader.classes[] = "Phly_Tool_Feed"
You need to specify keys manually, and they need to be unique.
Getting help
Now, time to test out if it all works. If you've done the above steps, you can now execute the following:
$ zf \? feed
Note: I use zsh, and need to escape the question mark; you may not need to in other shells.
If all is well, you'll get the following:
Actions supported by provider "Feed"
Feed
zf read feed feed[=weierophinney]
If you're not seeing this, check to make sure that your provider is on an
include_path
as defined in your .zf.ini
file; if you still have issues, ask
on the fw-general
mailing list or in the #zftalk IRC channel on Freenode.
Using the provider
Once your provider is working, fire it up:
$ zf read feed
or
$ zf read feed planetphp
You should get something that looks like this (the actual entry will vary):
State of Zend Framework 2.0
The past few months have kept myself and my team quite busy, as we've turned
our attentions from maintenance of the Zend Framework 1.X series to Zend
Framework 2.0. I've been fielding questions regularly about ZF2 lately, and
felt it was time to talk about the roadmap for ZF2, what we've done so far,
and how the community can help.
Continue reading "State of Zend Framework 2.0"
http://weierophinney.net/matthew/archives/241-State-of-Zend-Framework-2.0.html
Closing notes
One "gotcha" you may experience is that there is currently no support for
specifying project-specific providers within applications created with
Zend_Tool
— a feature that would be quite useful for creating project-specific
tasks.*
That said, Zend_Tool
providers are an incredibly useful and easy way to write
CLI tools based on Zend Framework. Hopefully this post will help demystify the
component and its usage, and get you thinking about what tasks you would like
to write.
* You can fake it by creating an alternate configuration file in
your project, informing the environment of it, and calling the zf
commandline
tool — something that can be done in a single line:
$ ZF_CONFIG_FILE=./zf.ini; zf <action> <provider> ...