Warning: include_once(): Unable to allocate memory for pool. in /usr/share/php/Zend/Loader/PluginLoader.php on line 384 Call Stack: 0.0000 632144 1. {main}() /home/padraic/public_html/survivethedeepend.com/zfbook/website/public/index.php:0 0.0002 647208 2. Bootstrap::run() /home/padraic/public_html/survivethedeepend.com/zfbook/website/public/index.php:12 0.0109 2415456 3. Zend_Controller_Front->dispatch() /home/padraic/public_html/survivethedeepend.com/zfbook/website/library/Bootstrap.php:19 0.0214 2816608 4. Zend_Controller_Plugin_Broker->postDispatch() /usr/share/php/Zend/Controller/Front.php:957 0.0214 2816608 5. Zend_Layout_Controller_Plugin_Layout->postDispatch() /usr/share/php/Zend/Controller/Plugin/Broker.php:331 0.0215 2817336 6. Zend_Layout->render() /usr/share/php/Zend/Layout/Controller/Plugin/Layout.php:142 0.0221 2825984 7. Zend_View_Abstract->render() /usr/share/php/Zend/Layout.php:793 0.0222 2867752 8. Zend_View->_run() /usr/share/php/Zend/View/Abstract.php:833 0.0222 2868368 9. include('/home/padraic/public_html/survivethedeepend.com/zfbook/website/application/views/layouts/default.phtml') /usr/share/php/Zend/View.php:108 0.0267 2881080 10. Zend_View->layout() /home/padraic/public_html/survivethedeepend.com/zfbook/website/application/views/layouts/default.phtml:101 0.0267 2881472 11. Zend_View_Abstract->__call() /home/padraic/public_html/survivethedeepend.com/zfbook/website/application/views/layouts/default.phtml:101 0.0267 2881472 12. Zend_View_Abstract->getHelper() /usr/share/php/Zend/View/Abstract.php:336 0.0267 2881608 13. Zend_View_Abstract->_getPlugin() /usr/share/php/Zend/View/Abstract.php:569 0.0268 2881880 14. Zend_Loader_PluginLoader->load() /usr/share/php/Zend/View/Abstract.php:1118 Warning: include(): Unable to allocate memory for pool. in /usr/share/php/Zend/View.php on line 108 Call Stack: 0.0000 632144 1. {main}() /home/padraic/public_html/survivethedeepend.com/zfbook/website/public/index.php:0 0.0002 647208 2. Bootstrap::run() /home/padraic/public_html/survivethedeepend.com/zfbook/website/public/index.php:12 0.0109 2415456 3. Zend_Controller_Front->dispatch() /home/padraic/public_html/survivethedeepend.com/zfbook/website/library/Bootstrap.php:19 0.0126 2539000 4. Zend_Controller_Dispatcher_Standard->dispatch() /usr/share/php/Zend/Controller/Front.php:946 0.0160 2735136 5. Zend_Controller_Action->dispatch() /usr/share/php/Zend/Controller/Dispatcher/Standard.php:289 0.0162 2744024 6. Zend_Controller_Action_HelperBroker->notifyPostDispatch() /usr/share/php/Zend/Controller/Action.php:523 0.0162 2745936 7. Zend_Controller_Action_Helper_ViewRenderer->postDispatch() /usr/share/php/Zend/Controller/Action/HelperBroker.php:277 0.0163 2745936 8. Zend_Controller_Action_Helper_ViewRenderer->render() /usr/share/php/Zend/Controller/Action/Helper/ViewRenderer.php:963 0.0167 2746416 9. Zend_Controller_Action_Helper_ViewRenderer->renderScript() /usr/share/php/Zend/Controller/Action/Helper/ViewRenderer.php:924 0.0168 2746416 10. Zend_View_Abstract->render() /usr/share/php/Zend/Controller/Action/Helper/ViewRenderer.php:903 0.0168 2787872 11. Zend_View->_run() /usr/share/php/Zend/View/Abstract.php:833 0.0168 2788488 12. include('/home/padraic/public_html/survivethedeepend.com/zfbook/website/application/views/scripts/book/view.phtml') /usr/share/php/Zend/View.php:108 0.0168 2789016 13. Zend_View->partial() /home/padraic/public_html/survivethedeepend.com/zfbook/website/application/views/scripts/book/view.phtml:1 0.0168 2789528 14. Zend_View_Abstract->__call() /home/padraic/public_html/survivethedeepend.com/zfbook/website/application/views/scripts/book/view.phtml:1 0.0173 2796824 15. call_user_func_array() /usr/share/php/Zend/View/Abstract.php:342 0.0173 2797312 16. Zend_View_Helper_Partial->partial() /usr/share/php/Zend/View/Abstract.php:342 0.0174 2800816 17. Zend_View_Abstract->render() /usr/share/php/Zend/View/Helper/Partial.php:103 0.0174 2842312 18. Zend_View->_run() /usr/share/php/Zend/View/Abstract.php:833

Chapter 8. Developing A Blogging Application

8.1. Introduction

Now that you are familiarised with the Zend Framework, it's time to stop with the shallow end adventures and hit the deep end. Don't worry, we'll allow you to keep the floats, for now.

The subject of Part 2 of the book is writing a blog application. The reason I selected a blog is because it's an extremely familiar application to most of us. By eliminating uncertainty over what is being developed, we can focus more on the implementation of well understood features. Nonetheless, jumping into any project blindfolded is still not a good idea. I've wanted a personal little blog I built myself (I find these things fun) for a while so let's get started.

8.2. Planning

To plan our little project, we must first ask the most obvious question. What is the goal of the project?

Our goal is to design and build a blogging application allowing the user to write articles and publish them online.

I like to keep my goals short and to the point. If its obvious, all the better. It's primary purpose is to ourselves reminded of why we're doing this and offer context in any future discussions over features.

While a short goal keeps you focused on what you're trying to achieve at the end of the day, we still need to add more detail so we know where to start. Rather than get mired down in a lengthy specification document, we just need a few sketched out lines further defining how the application will operate.

  1. The author writes entries through the blog interface.

  2. Entries are published, once completed by the Author, to HTML pages.

  3. Published entries will be distributed through aggregated RSS 2.0 and Atom 1.0 feeds.

  4. Only an author may write and publish entries.

  5. Readers may write comments to be displayed below entries on their HTML pages.

  6. Reader comments will be distributed through aggregated RSS 2.0 and Atom 1.0 feeds.

At this stage we enough material to play with. We could keep adding to the list until it's pages long but this is the core functionality that achieves our initial goal.

Given our list of required features, illustrated as simple statements of what various users can do, we can start identifying the building blocks of the application. Since we are using the Zend Framework, we can take a few shortcuts and focus on what really matters - the application specific needs. The is where we find ourselves looking down the throat of Domain Modelling. Keeping it simple, we can start to identify the entities in our system, and the data associated with them.

Note, it's important as this point to clarify that we are not looking at databases. Databases are a tool allowing a Model to store itself between requests, but at this stage we are not designing tables or writing SQL. We'll why this is not so in the next chapter where we delve in far greater depth into the question of how to implement the Model.

The entities we could identify (and which may become our domain objects in the future) include:

  • Author

  • Entry

  • Reader

  • Comment

We might possibly eliminate Reader because in our application the Reader is an anonymous user. The only thing we might want to maintain for anonymous users is some session data. Then again, if using a database is optional in a Model, perhaps having a Reader object to encapsulate an anonymous user's session data is not a bad idea - afterall, where else will we handle this. The Controller? As we've seen in a previous chapter - the Controller is NOT the Model.

The other three however are obvious candidates. We can detail these candidate entities to flesh out what data they might need at a minimum. I should note that when discussing the Model, I am assuming all entities will be objects, so there is no reference to foreign keys (this is a database concern) since each object can contain another object referencing any related or linked entities.

  • Author






  • Entry



    published date


  • Comment




    published date


There's probably lots more we could add, but these are unimportant for the moment. We only need to see the basic data set and how it may related to other Models in our domain.

The final part of this initial analysis may take a look at what sort of "pages" our application will need to generate. This is a tricky part in a sense, depending on how we defined the term "page". Do we include pages or URLs that only response to Ajax requests? What about any web service API, for example some future implementation of the AtomPub protocol so we can blog outside of the application? Again, if we're uncertain about anything, we'll defer it until a later time. So the main pages we know for certain are needed might include:

  • Blog Index

  • Entry Page

  • Author Login

  • Entry Editing

  • Comment Approval

  • RSS Entry Feed

  • Atom Entry Feed

  • RSS Comment Feed

  • Atom Comment Feed

We now have at least some idea of what we need to do. No longer blind and staring blankly at an IDE, we can settle down and do some coding. In the next chapter, we'll start by getting our Model ready. Thereafter we can work on the application presentation.

8.3. Incremental Development and YAGNI

Any blog will boast of any number of features, tempting us to over specify our new application. Doing so has its problems since a) we're dividing our attention, b) we're attempting to predict needs that are not confirmed, and c) extra specifications are worthless unless the core Blog application makes an appearance. So we will develop the Blog incrementally, assigning required features to iterations we will complete in discrete measured steps, all the while ensuring the application is stable and unit tested before we start another outstanding iteration.

This all runs with a partner from the eXtreme Programming world, "You Ain't Gonna Need It" (or YAGNI). YAGNI teaches that dwelling too much on features that are not currently necessary has a number of severe disadvantages. First you are spending time on it, which means you either have too many developers (I never said that!) or you are having existing developers spend time on future features at the expense of currently needed features. This time can be expended on development, testing, requirements gathering, documentation, etc. All for something we do not need now. Secondly, we're ignoring that the future is uncertain. What if it turns out we never needed the future feature? What if a client changes their mind about something more basic and completely renders a whole set of these future features redundant? What if implementing the future feature actually prevents another feature, which we discover is needed later, from being added? In other circumstances, adding the new feature requires additional support work to make it possible, perhaps even snowballing into more new not-currently-needed features to support whatever we're adding.

Incremental development works here since I am the client (arguably being one's own client is the worst possible case). However, many projects will have other people as the client and their requirements may vary substantially over time. Incremental development is an excellent process but it still involves writing an application before its requirements are fully known, understood and documented. Not all clients will be capable or willing to go along with such an uncertain process, or will find it difficult to work closely with you to ensure it works. Another effect of incremental development is that we need to pay some attention to the atomicity of our unit tests. A common mistake is trying to test too much by layering assertion after assertion in a single test. In a very limited scenario this does little harm, but once it expands to page views and workflow, we can find ourselves constantly editing existing tests to reflect the current requirements. Editing old tests is not a good sign - it signals that they were not focused enough to begin with.

This process is more than suitable for our blog. It's a simple application where we can afford to meet new requirements as they materialise in future chapters.

8.4. Checking Our Toolbox

While it would be great to do everything with Zend Framework, the truth is we'll need a few extra tools from time to time. Since I am a self confessed jQuery lover who doesn't have a clue about Dojo, you should keep the most recent jQuery version on standby when we get around to playing with Ajax requests and UI manipulation. I will also be using the Blueprint CSS Framework to keep my CSS editing to a minimum and maintain a simple layout without struggling for hours over grids. Another thing I rarely do without is a good HTML filtering library, something the Zend Framework does not currently offer. I will be using HTMLPurifier 4.0.0 for this purpose. Last, but by no means least, I will be using PHPUnit for all unit testing so be sure you have it installed from the PHPUnit PEAR channel.

I'll note this and their installation procedure in more detail as they are needed.

8.5. This Is Not The Reference Guide

This is a very short chapter, and I'll conclude by emphasising the book's introduction. Since the purpose of the book is to assist those in the "deep end", I do assume you have a passing familiarity with the Zend Framework. I also assume you are capable of reading the Reference Guide independently, and therefore I will not spend an exhaustive amount of time on every single component we meet unless it is used consistently. One example is Zend_Db - which has a massive entry in the Reference Guide detailing its API, examples, and methods of use. Rather than take a whole chapter (or five) to explain Zend_Db and its component classes, the next chapter is far more interested in showing how to use Zend_Db's classes to create a Model. Our Model does not even need a lot of Zend_Db knowledge to follow.

If you need Zend_Db specifically in some detail, refer to the Reference Guide. Eventually I'll add a supplementary chapter/appendix to the book if its warranted but there is little I could offer over what the Reference Guide gives you (it's very detailed and clear).

It should also be obvious that this will not be a simple blog tutorial. Web application framework examples are rife with simple blog examples but this is geared towards a more fully featured application which will need to make extensive use of Zend Framework components.

Powered by jQuery Powered by Zend Framework Powered by Nginx Http Server