Tag Archive for 'php'

Custom frontends for Zend_Cache

As we all know, server-side caching is a useful technique for optimizing the performance of web apps. Whenever some expensive operation is called for – a db query, a remote web service call, etc – caching the results of the operation means that the next time you need them, you can get them relatively cheaply from the cache.

Zend_Cache: A basic usage example

Zend Framework contains a Zend_Cache component that supports a variety of frontends and backends. Typical usage for filesystem-based caching is something like the following:


// create the cache object
$frontend = array(
    'lifetime' => 86400, // seconds
    'automatic_serialization' => true,
);
$backend = array(
    'cache_dir' => '/path/to/your/cache',
);
$cache = Zend_Cache::factory('Core', 'File', $frontend, $backend);

// now use the cache object
$cacheId = 'someCacheId';
$data = $cache->load($cacheId);
if (false == $data){
    $data = someExpensiveOperation();
    $cache->save($data, $cacheId);
}

In practice, I tend to put the cache creation portion into a factory/container class of some kind, while the usage/consumption is often in a repository or service class. But for clarity, it is shown all in line, as if it were in a controller.

The first time you run through this code, the data will not have been saved in cache (a cache miss, as they say), so you will be forced to incur the cost of the someExpensiveOperation() call. But the next time you run through it – assuming the cache has not expired beyond its lifetime – then you will register a cache hit and bypass the expensive operation.

All cool.

Yeah, but…

But there is one thing that has always bugged me about this typical flow: generating the $cacheId. For example, if someExpensiveOperation() is a db call to fetch an article, then the $cacheId will probably employ the id or slug of the article:

// $slug is the slug of the article, something like 'my-cool-article'
$cacheId = 'article_byslug_' . str_replace('-', '_', $slug);  // Zend_Cache does not like cache id's with hyphens

Generating a cache id strikes me as part of the internal details of the “caching process”. As such, it seems to me like the knowledge of how to do that should be embedded inside the caching object itself. It’s his business to know how to load data from cache, save data to cache, and remove data from cache. Connecting an id to that data should be part of his job. So, why should I have to construct cache id’s for him?

Even further, why am I seeing cache id’s at all? Couldn’t the cache object simply offer me an interface with methods like:


public function loadArticlebySlug($slug);
public function saveArticleBySlug($article);
public function removeArticleBySlug($article);

Isn’t there some easy way to make this happen?

Custom cache frontends to the rescue!

It turns out that Zend_Cache::factory() actually does allow me to create custom frontends that implement whatever interface I want. I can define my interface:

interface Project_Cache_Frontend_ArticleInterface
{
    public function loadArticlebySlug($slug);
    public function saveArticleBySlug($article);
    public function removeArticleBySlug($article);
}

Then implement in a class extending Zend_Cache_Core:

class Project_Cache_Frontend_Article extends Zend_Cache_Core implements Project_Cache_Frontend_ArticleInterface
{
    public function loadArticlebySlug($slug)
    {
        return $this->load($this->getCacheIdBySlug($article->slug));
    }

    public function saveArticleBySlug($article)
    {
        return $this->save($article, $this->getCacheIdBySlug($article->slug));
    }

    public function removeArticleBySlug($article)
    {
        return $this->remove($this->getCacheIdBySlug($article->slug));
    }

    protected function getCacheIdBySlug($slug)
    {
        return 'article_byslug_' . str_replace('-', '_', $slug);
    }
}

Note the protected method getCacheIdBySlug($slug). All the knowledge of how to create cache id’s is wrapped up in the cache object. It just exposes a functional interface that describes what you want to do, not how you want it done.

Now, tell the Zend_Cache::factory() method to use my custom frontend:

// frontend and backend options as before
$frontend = array(
    'lifetime' => 86400, // seconds
    'automatic_serialization' => true,
);
$backend = array(
    'cache_dir' => '/path/to/your/cache',
);
$cache = Zend_Cache::factory('Project_Cache_Frontend_Article', 'File', $frontend, $backend, true, false, true);

Note that we are specifying the complete name of our implementing cache class, as well as three boolean values.

The first boolean value – true in this case – tells the factory that we are using a custom frontend.

The second boolean value – false in this case – tells the factory that we are not using a custom backend.

The third boolean value – true in this case – tells the factory to use autoloading to instantiate the frontend and backend objects.

Fully constructed by the factory, cache usage is cleaner:


$data = $cache->loadArticleBySlug($slug);
if (false === $data){
    $data = someExpensiveOperation();
}

No cache id’s, no mixing of concerns.

Maybe it’s a whole lot of work just to tuck away some cache id generation. But I confess that it feels better to me.

What is dependency injection?

For quite some time, I have been working on getting my head around best practices for structuring my web applications. One of the strongest messages that has come through is to use dependency injection to facilitate unit testing.

As many others have noted, dependency injection is a very simple concept. If one thing (the “consumer”) depends upon something else (the “dependency”) to do its work, then the consumer should be given the dependency. The consumer should depend upon an agreed set of functionality that the dependency performs, but it should not care how the dependency actually gets the job done.

An easy example

A radio receives transmissions and plays sounds through its speakers. Nothing special there. But it needs a power source to function. The power source’s adapter has to fit into the hole on back of the radio. And there has to be some compatibility of voltages and currents and all that electrical magic. The radio is the consumer and the power source is the dependency. You can’t run the radio without the power source.

Note that, in principle, the power source could be a pack of AA batteries. Or it could be a solar cell. Or it could be a collection of gerbils running on flywheels. As long as it outputs the right voltage and current and the plug fits into the hole, then all is cool. The radio is not concerned by the power source implementation as long it lives up to what we expect a power source to do (i.e., its interface).

How about some code?

Using our radio and power source example, we could imagine PHP objects and interfaces as follows:

interface PowerSourceInterface
{
	public function getPower($numberOfPowerUnits);
}

class PowerSourceGerbils implements PowerSourceInterface
{
	protected $_gerbils;

	public function __construct($gerbils)
	{
		$this->_gerbils = $gerbils;
	}

	pubic function getPower($numberOfPowerUnits)
	{
		// Make the gerbils run like hell on the flywheel
		// to generate the requested amount of power.
	}
}

class Radio
{
	protected $_powerSource;

	public function __construct(PowerSourceInterface $powerSource)
	{
		$this->_powerSource = $powerSource;
	}

	public function play()
	{
		// Call upon $this->_powerSource->getPower()
		// Feed that power into the various electrical
		// components of the radio and push the sound
		// out through the speakers.
	}
}

The idea is that by clearly defining the responsibilities, we can create independent object that fulfill those responsibilities. Even better, by defining interfaces, we can set up a contract for what a particular consumer expects his dependencies to be able to do for him.

So, who cares? Unit testing cares.

Suppose you are a company that makes radios. You hire the best radio engineers and work out all the details for what makes a radio great. Maybe you have amazing noise-reduction algorithms that filter out static. Maybe your radios have balance and equalizer controls to allow the user to tweak the sound he gets out of your box. Maybe your radios are super efficient so that they pull less power from the power source, allowing them to play longer before recharge. Or maybe you simply put them in colorful plastic shells featuring photos of some random pop star.

The point is that your expertise is in the areas highlighted above. You make no representation to be experts in power generation; you are a power consumer. The quality of your work can only be fairly judged when the power source functions properly. Hey, man, if the power source tanks, then all bets are off, right?

So as part of your manufacturing process, you do a whole bunch of unit-testing on your radios using a “mock” power source, a power source that definitely functions correctly. This approach – explicitly defining and passing dependencies, combined with supplying mock dependencies during unit testing – clearly defines responsibilities and allows you to focus on fulfilling yours without worrying that the problem lies in someone else’s area of responsibility.

What’s the downside?

Well, creating objects is now a bit of a pain the neck. Consider what is required now just to play a radio.

$gerbils = new GerbilCollection();  // guess we need a Gerbil class and a GerbilCollection class, too
$powerSource = new PowerSourceGerbils($gerbils);
$radio = new Radio($powerSource);
$radio->play();

So, every time I want to play a radio, I need to construct a power source (which might have its own dependencies, like the gerbils in this case), feed that power source into the radio, and then hit the play button.

I gotta do all these steps just to play a freaking radio? Can’t I do the radio setup once – create and plug in the power source – and then when I want to listen to some music, all I have to do is hit play?

I will address this in the next post: Poor Man’s Dependency Injection using Zend Framework.

Unit testing for placeholder-based view-helpers in Zend Framework

Just got bitten by an interesting little issue.

I have a Zend Framework view-helper that I use to add a CSS class to an HTML <body> tag. Usage in a view-script is:

$this->bodyTag()->addClass('someclass');

Then in a layout, I’d output it using:

<?= $this->bodyTag() ?>

The class itself is very simple:


/**
 * A body tag
 *
 * @author David Weinraub <david@papayasoft.com>
 */
class PapayaSoft_Zend_View_Helper_BodyTag extends Zend_View_Helper_Placeholder_Container_Standalone
{
    public function bodyTag()
    {
        return $this;
    }

    public function toString()
    {
        $tag = array();
        $tag[] = '<body';

        $storage = $this->getContainer();

        if (count($storage) > 0){
            $classes = array();
            foreach ($storage as $class){
                $classes[] = $class;
            }
            $tag[] = sprintf(' class="%s"', implode(' ', $classes));
        }
        $tag[] = '>';
        return implode('', $tag);
    }

    public function addClass($class)
    {
        $this->getContainer()->append($class);
        return $this;
    }
}

I’ve begun moving this kind of stuff out into my own library, which I will manage in its own project under source control. I can then import it into multiple projects, just as I would with the libs for Zend or Doctrine or HTML Purifier.

Consequently, it’s now time – actually long past-due – to really get into the discipline of unit-testing. A simple class like this seems a decent place to start.

Unit-tests for the BodyTag class looked something like this:


/**
 * Test BodyTag class
 *
 * @group Zend_View_Helper
 * @author David Weinraub <david@papayasoft.com>
 */
class PapayaSoft_Zend_View_Helper_BodyTagTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var PapayaSoft_Zend_View_Helper_BodyTag
     */
    private $_bodyTag;

    public function setUp()
    {
        $this->_bodyTag = new PapayaSoft_Zend_View_Helper_BodyTag();
    }

    public function tearDown()
    {
        unset($this->_bodyTag);
    }

    public function testRenderOnNoAddedClasses()
    {
        $this->assertEquals('<body>', (string) $this->_bodyTag);
    }

    public function testRenderOnSingleAddedClass()
    {
        $this->_bodyTag->addClass('myclass');
        $this->assertEquals('<body class="myclass">', (string) $this->_bodyTag);
    }

    public function testRenderOnMultipleAddedClasses()
    {
        $this->_bodyTag = new PapayaSoft_Zend_View_Helper_BodyTag();
        $this->_bodyTag->addClass('someclass')->addClass('anotherclass');
        $this->assertEquals('<body class="someclass anotherclass"<', (string) $this->_bodyTag);
    }
}

Pretty straightforward. Or so I thought.

The last test failed, reporting the following:

BodyTagTest::testRenderOnMultipleAddedClasses()
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-<body class="someclass anotherclass">
+<body class="myclass someclass anotherclass">
It seemed as if result of running the penultimate method testRenderOnSingleAddedClass() was still in effect when testRenderOnMultipleAddedClasses() started. When the testRenderOnSingleAddedClass() method is removed, the testRenderOnMultipleAddedClasses() passes.

What’s going on here? The whole point of tearDown() and setUp() is to reset the test environment to a clean state, in this case by unsetting and re-instantiating the $_bodyTag member variable.

Well, the whole key here turns out to be state of the system. It’s not sufficient to simply reset the object in the member variable if it has made other changes to the state of the system. Sort of like selling the cow that crapped in your living room, but forgetting to clean up the mess he made. And that’s actually what appears to be happening.

The framework’s own unit test for Zend_View_Helper_HeadTitle, another Zend_View_Helper_Placeholder_Container_Standalone-extended class, offers some hint of this. The setUp() method is as follows:

    /**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     * @return void
     */
    public function setUp()
    {
        $regKey = Zend_View_Helper_Placeholder_Registry::REGISTRY_KEY;
        if (Zend_Registry::isRegistered($regKey)) {
            $registry = Zend_Registry::getInstance();
            unset($registry[$regKey]);
        }
        $this->basePath = dirname(__FILE__) . '/_files/modules';
        $this->helper = new Zend_View_Helper_HeadTitle();
    }

So there is some Zend_Registry stuff in there that needs to be cleared, as well. Adding the registry-clearing code from the ZF unit-test into my own solved the problem.

Live and learn.

What to do about ZodiacFacts and #zf on Twitter?

The Twitter hashtag #zf has been used by the Zend Framework for several years now. The Twitter user @ZodiacFacts began using it some time ago, polluting the #zf stream with all that medieval nonsense. Zend Framework Project Lead Matthew Weier O’Phinney tweeted a reply to @ZodiacFacts politely requesting that he/she refrain from using the hashtag and @ZodiacFacts seems to have politely complied.

So, what’s the problem?

As of this writing, @ZodiacFacts has over 170,000 followers – a lamentable indictment on the state of human rationality. It is no surprise that some of them continue to retweet into the #zf stream.

There are not many of them, only a few each day. So, it’s only a minor annoyance. Still, life is filled with enough of minor annoyances that it’s desirable to remove/minimize them when we can.

The solution, perhaps

A Twitter Bot could be built that polls Twitter for tweets containing both @ZodiacFacts and #zf and then sends a politely worded reply to the Twitter user requesting that he refrain from using the #zf hashtag.

I have actually built a class on which such a bot can be based. And I have registered the Twitter account @zfisforzend to function as the sender.

But since the #zf hashtag should rightly be regarded as a community resource, I don’t really feel that it is my place to deploy the solution on my own. The “community” or even Zend HQ should make the decision about whether to deploy, the phrasing of the message, etc. After all, both of these things affect the public face of the project. Hey, it might even inflame the legions of @ZodiacFact fans to spam the #zf stream, just out of pique.

So, I am posting my current code so that if one of the project leaders wishes to use it – or to develop their own, which would no doubt be better than mine – then they can do so with little effort. I’d be happy to pass off the ownership of the @zfisforzend Twitter account to whatever community member wants to use it for this purpose.


/**
 * Access Twitter API, do twitter search, then reply
 *
 * @author David Weinraub ( david@papayasoft.com )
 */
class PS_TwitterSearchAndReplyBot
{
    /**
     * @var Zend_Service_Twitter
     */
    protected $_twitter = null;

    /**
     * @var string
     */
    protected $_reply = null;

    /**
     * Path to the file containing the id of the tweet to which we have replied
     *
     * @var string
     */
    protected $_sincePath = null;

    /**
     * @var string
     */
    protected $_userAgent = 'PapayaSoft-SearchAndReplyBot/1.0';

    /**
     * Constructor
     *
     * @param string $username Twitter username for the acct sending replies
     * @param string $password Twitter password for the acct sending replies
     * @param string $query the query we use to find tweets.
     * @param string $reply the text of the reply we wish to send
     * @param string $sincePath path to the file where we save the last replied tweet
     */
    public function __construct($username, $password, $query, $reply, $sincePath)
    {
        if ('' == $username){
            throw new Exception('User is required');
        }

        if ('' == $password){
            throw new Exception('Password is required');
        }

        $this->_twitter = new Zend_Service_Twitter($username, $password);
        $this->_twitter->getHttpClient()->setHeaders('useragent', $this->_userAgent);

        if ('' == $query){
            throw new Exception('Query is required');
        }
        $this->_query = $query;

        if ('' == $reply){
            throw new Exception('Reply is required');
        }
        $this->_reply = $reply;

        $this->_sincePath = $sincePath;
    }

    /**
     * Get the matching tweets
     *
     * @return array the matching tweets
     */
    public function getTweets()
    {
        $service = new Zend_Service_Twitter_Search();
        $service->getHttpClient()->setHeaders('useragent', $this->_userAgent);
        if (null == $sinceId){
            $sinceId = (int) $this->readSince();
        }
        $params = array(
            'since_id' => $sinceId,
        );
        return $service->search($this->_query, $params);
    }

    /**
     * Send the reply to a matching tweet
     *
     * @param array $tweet
     * @return void
     */
    public function sendReply($tweet)
    {
        $target = $tweet['from_user'];
        $reply = '@' . $target . ' ' . $this->_reply;

        $result = $this->_twitter->statusUpdate($reply, $tweet['id']);

        if ($result->isSuccess()){
            $this->writeSince($tweet['id']);
            return true;
        } else {
            throw new Exception('Failure posting status reply to target');
        }
    }

    /**
     * Save the id of the last tweet to which we have replied
     *
     * @param int $sinceId
     * @return 
     */
    public function writeSince($sinceId)
    {
        @$fp = fopen($this->_sincePath, 'w');

        if (!$fp){
            throw new Exception('Unable to open since-file for writing');
        }
        fwrite($fp, $sinceId);
        fclose($fp);
        return $this;
    }

    /**
     * Get the twitter id of the last tweet to which we have replied
     *
     * @return int
     */
    public function readSince()
    {
        return file_get_contents($this->_sincePath);
    }

    /**
     * Entry point. Do it all.
     */
    protected function run()
    {
        $tweets = $this->getTweets();
        foreach ($tweets as $tweet){
            $this->sendReply($tweet['from_user'], $tweet['id']);
        }
    }
}

Usage would be something along the following:


$bot = new PS_TwitterSearchAndReplyBot(
    'zfisforzend',
    'thepassword',
    '#zf AND @ZodiacFacts',
    'The ZF hashtag has been used by http://bit.ly/dlRih0 for 2+ years. Please do not use it for ZodiacFacts. Thanks! ;-) ',
    dirname(__FILE__) .'/data/since.dat'
);
$bot->run();

Then set up a cron job to run this script with some polling frequency.

Note that the message we send should not contain either of the terms “#zf” or “Zend” directly. After all, those are search terms we all use in our Twitter clients. The last thing we want is for all these bot-generated replies to further pollute the targeted hashtag stream.

As you can see, it is general enough to serve as the base for other Twitter Reply bots. I confess that the code is only partially tested, but I think it conveys the idea.

So, whaddya think?

Debugging PHP – Netbeans Code Templates for Zend_Debug and FirePHP

I recently changed my day-to-day PHP IDE to Netbeans and it’s been a pleasure. [Don't ask me what I was using before, too embarrassed to say.]

idea light bulb

In particular, one of Netbeans’ nice features is Code Templates, little snippets of text that you can insert into your document simply by typing a short prefix and then hitting the Tab key. They are actually smarter than just static snippets in that they can contain variables that are dynamically filled/changed as you edit. Hugely useful. I use them constantly for a variety of tasks, but my most common use of code templates is for debugging.

One useful debug tool is FirePHP in conjunction with Firebug, especially for applications using AJAX.

Several weeks ago, Jeremy Kendall (@JeremyKendall) helpfully pointed me to Zend_Debug::dump() which behaves like an enhanced var_dump(). I was actually gratified to see that it resembles one of my own hacks that I have been using for years, though Zend_Debug::dump() is, not surprisingly, more polished.

Following on that, Markus (@derstahlstift) posted a Netbeans code template that uses Zend_Debug::dump().

I admit that they are both cool, but I prefer to identify precisely where I am doing the dump, using PHP’s magic constants __FILE__ and __LINE__. This allows me to easily chase down the dump statements and remove them once the debugging is finished.

So, here are my own versions, both in the form of Netbeans Code Templates.

For FirePHP::send():

FB::send("${VAR default="variable"} = " . $$${VAR} . ":: ${func default="func"} :: " . __FILE__ . "(" . __LINE__ . ")");
${cursor}

For Zend_Debug::dump():

Zend_Debug::dump($$${VARIABLE variableFromNextAssignmentName default="variable"}, "${VARIABLE variableFromNextAssignmentName}", true);
echo "

" . __FILE__ . "(" . __LINE__ . ") :: ${function default="function"} :: ${message default="message"}

";
${selection}${cursor}

Whaddya think? Do you have any tricks/shortcuts that you use for debugging? Let me know.

Cheers!

Zend Framework – Here I Come

Time to elevate my game.

After years of developing and tuning my own PHP-based web development framework which I have used on countless projects, I have decided to move into one of the more established PHP-based web frameworks.

My own framework is a loose collection of classes and methodologies that have worked pretty well so far. I can usually figure out how to do anything that has come up. Although it is a huge step up from so much of the the script-kiddie crap that is still fairly common – among even some successful commercial houses here in Phuket – I must confess that it never felt quite tight enough for me. It never lent itself to the kind of controlled development process I would ultimately like to be doing: source control, automated unit-testing, automated builds, and automated deployments.

There is no shortage of discussion out there about web frameworks: which ones are essentially CMS’s or mere libraries rather than full frameworks; which ones are tightly/loosely coupled; which ones are sufficiently true to established design patterns, to object-oriented principles, to MVC principles, etc; which ones are performance dogs, etc. I’ve read through much of it.

Upshot: I’m sticking with PHP, going with Zend Framework.

I’ve got nothing against the other PHP frameworks. CodeIgniter seems very approachable and has a decent community. CakePHP seems to have a lot of advocates and supportive community. Kohana, too, seems nice. Of course, there are many others.

And if I were really going to go wild, I would leap in Ruby on Rails about which I have never heard a single bad thing. But a leap into a new framework is enough without having to bite off the syntax of another language to boot.

Perhaps some other time I’ll get into all the reasons and do a comparative analysis, though it is just as likely that it will never happen since there are already tons of such resources out there and doing my own comparative analysis at a level that would be satisfactory to me would require becoming expert at all the others.

First step is to use a few of the Zend Framework classes here and there in a few projects, availing myself of the “loosely-coupled, use-at-will” nature of the library. Mostly to familiarize myself with some of the design patterns and to learn what supportive functionality is available outside the context of the full framework stack.

Eventually, I will commit to using the full MVC stack on a green-field project, either a brand new site or a redesign of an existing site. I already have one in mind. Both excited and terrified at the same time.

Go, go, go, …