PHP, Zend Framework and Other Crazy Stuff
PHP Game Development
Kicking The Bad Habit Of Being An Overworked Paddy
Jan 24th
It’s hard to believe we are already almost 1/12 of the distance into 2008. By now all of you have broken your new year resolutions. I know I’ve broken several at a minimum!
After some months of desperate oft-despairing struggling with work schedules I’ve finally once and for all conquered my lack of free time. It’s an ingenious solution – I’m taking a small break from work before rekindling an interest in financial services in these doubtful times (ask Société Générale if you want to know how doubtful, or the US Federal Rserve).
The outcome of this reorganisation of my career direction is twofold. Firstly I get extra bags of cash. Secondly, I get slightly more vacation time. Thirdly, it won’t require as much overtime. Fourthly, there’s less chance of last-minute-scrambling which became exceptionally evident over the last few months as the Irish market continues to swell (in defiance of the laws of EU Economics). Of course added together this provides more of my most sought after commodity – personal time.
All that’s left is how to use this new-found wealth. In between the extra pub-crawling exercises, engagements as the designated baggage mule on shopping excursions, and the other things an average 20-something is inclined to do, I want to enjoy some travel, take up writing again, and commit some completion time to the open source projects I contribute to.
I’ve been a very bad boy in that regard in the last six months and at one point I became an absolute nightmare for anyone who needed to contact me by email. It was not my finest hour, and I seriously doubt I escaped with a pristine reputation for being dependable. C’est la vie. A few of these “instances” shall we call them, have since been resolved to my satisfaction so I’m 95% back to nominal form as a powerhouse of innovation, inspiration and ingenuity (see, even my ego is back rockin’ at full throttle!). Yep, you can always measure the normality of an Irishman by his level of self-directed sarcasm
.
Anyways, enough self-critical analysis – it weakens the ego – since I’m back in fine form after two extremes (a two month vacation, and a four month chaotic period of non-stop work) I have the luxury of directing some of this time where it was always supposed to be: in supplementing my PHP experience with some open source doodling and manic self-promotion
. The first target of my ire is a small project with Till Klampaeckel (Seek. Kill. Destroy.). After that is PHPSpec 0.3.0 (Exterminate! Exterminate! Exterminate!). After that is that frickin’ promise-but-never-effing-do component for implementing a Yadis service (Off With His Head! Off With His Head!). I swear that thing has been sitting in a personal subversion repo begging for a few final hours of attention!
After that I’m taking a long breather, attending oodles of conferences, and finding something with a lot of words to write.
Astrum Futura Redux
Dec 7th
For the cool folk who have followed the Solar Empire legacy through thick and thin since 1999, those cute .php3 file suffixes, Moriarty’s continuing denegration of all other developers, the revolution that open source brought, the sudden push towards OOP, and the…err…security and bug population… Working on anything hitting it’s 9th anniversary in PHP is really interesting – 9 times the fun and games
.
Astrum Futura was envisaged as a desperately needed update to the long running open source Solar Empire franchise, where players engage each other across a galaxy of 500+ star systems mining resources, building colonies, and generally screaming bloody murder at each other. It’s not the most impressive or ambitious of online games, but it’s always been tenacious and attracted roaming users who like a quick dash of destruction in their daily diet.
In January 2008, the oft delayed development process will once again creak into action. The current tracer code was built originally using the Zend Framework 0.2-0.6 and famously led that Spring to my long running “Complex Views With The Zend Framework” blog series that gave birth to the Zend_View Enhanced proposal, and maybe gave Ralph Schindler a few headaches
. Building anything more complex than a login page was pure heart ache previously.
Now that time is available, the Zend Framework significantly more mature, and we have a lot of legwork carried over from 2006 in the Quantum Game Library (thanks to Jacob Santos), it’s about time we got something concrete done. The usual suspects, if interest levels are high enough, can report to the shiny updated phpBB3 forums at http://forums.astrumfutura.com – same domain as this blog you’re reading.
And we will be applying XP this time – the random running process that usually prevails just doesn’t work out well. So get your Selenium gear in place.
Complex Views with the Zend Framework – Part 5: The Two-Step View Pattern
May 23rd
It’s been a while since I continued this series. Unfortunately real life workloads are unforgiving of the best of intentions
. Part 5 of our series takes a small time-out from approaching a Composite View solution to reusable Views to take a peek at a simpler approach useful for simpler types of web applications. As we’ve discussed previously Composite Views allow the nesting of reusable View elements, effectively building a View based on a hierarchy of Views. But often there are simpler solutions to simpler problems. One such solution is the Two-Step View pattern, sometimes called Layouts if implemented in a specific way (as we do below!).
Imagine a simple website. You have hundreds of pages of unique content, but the header and footer for each page is identical. Applying the Composite View approach has the same problem as applying a standard PHP include or Zend_View::render() call to including these common elements – the calls themselves are scattered across each and every template. This is the hallmark of a Layout – duplicated includes/renders across multiple views:
[geshi lang=php]render(‘standard_header.phtml’); ?>
Here is our unique content! But look, all unique templates
now have the same “standard” headers and footers defined by a
render() call. How do we remove these completely and apply them
automatically instead?
render(‘standard_footer.phtml’); ?>[/geshi]
The key is to take the duplicated calls and other duplicated markup and stick them in a Layout template which will encapsulate all Views automatically. Then the only thing our templates contain is unique content!
[geshi lang=php]
Here is our unique content template! But where have the
standard header and footer includes vanished to?
[/geshi]
All the Layout file needs to do is provide a “hook”, a method placement which signifies where the main View output (which is generated by the current dispatch cycle) should be placed. Since we define two parts the View here we’ll refer to them as the “Layout” and the “Main”. A Layout might look like:
[geshi lang=php]render(‘standard_header.phtml’); ?>
main(); ?>
render(‘standard_footer.phtml’); ?>[/geshi]
The new Zps_View::main() method (Zps_View is a subclass of Zend_View to which we can add customised behaviour) simply tells the View to render its output at this location in the template. This assumes the default Zend_View::render() method now takes a two step approach to rendering (this is where the Two-Step View Pattern comes into play).
1. Render a Layout if one is defined
2. Render the Main template into the Layout
The only funky logic is that the presence of a Layout forces our View object’s render method to take a detour so that Layouts are rendered first. This is a pretty simple change to Zend_View. Here’s our Zps_View class with the revised logic.
Please forgive the lack of proper phpDoc comments – Serendipity won’t play nice with them.
[geshi lang=php]// Zend_View */
require_once ‘Zend/View.php’;
// Zps_View_Interface */
require_once ‘Zps/View/Interface.php’;
class Zps_View extends Zend_View implements Zps_View_Interface
{
//
// The Main Template (i.e. the template file a Controller wishes
// to render).
// _mainFile cannot be set by a public setter so it doubles as
// as a safety valve to prevent unwarranted use of main().
//
// @var string
//
protected $_mainFile = null;
//
// The Layout Template
//
// @var string
//
protected $_layoutFile = null;
//
// Overrides Zend_View::render() to introduce a two step view approach when
// a Layout template has been defined. The two steps are handled using
// separate calls to parent::render() which calls the Zend_View render()
// method without overriding.
//
// @param string $name The script script name to process.
// @return string The script output.
//
public function render($name)
{
if ($this->hasLayout() && !isset($this->_mainFile)) {
$this->_mainFile = $name;
return parent::render( $this->getLayout() );
}
return parent::render($name);
}
//
// Set the filename of a Layout template to be used. The existence of a
// Layout filename will force the over-ridden render() method to detour
// and render the Layout, only rendering the Main template when a main()
// call is issued in the Layout template.
//
// @param $file string
// @return void
//
public function setLayout($file = ‘layout.phtml’)
{
$this->_layoutFile = $file;
}
//
// Return the filename of the Layout. Layouts are like any
// other template script and are located in the same place in
// application filesystem.
//
// @return string
//
public function getLayout()
{
return $this->_layoutFile;
}
//
// Returns true if a Layout has been set for this View.
//
// @return bool
///
public function hasLayout()
{
return isset($this->_layoutFile);
}
//
// Inform the View object that it should render the Main View, i.e.
// render the template handed to the render() method by a Controller.
// This method is only useful if a Layout is being used, otherwise
// expect an Exception.
//
// @return string
// @throws Zps_View_Exception
//
public function main()
{
if (isset($this->_mainFile)) {
return parent::render($this->_mainFile);
}
require_once ‘Zps/View/Exception.php’;
throw new Zps_View_Exception(‘Invalid call: There is no primary View template to render’);
}
//
// Method to clone this View assuming the sub-View (the clone) is from
// the same application Module as the original.
// Here we are simply getting rid of the inherited public variables which
// represent the ancestor View’s model.
// We also disable any Layouts (the inheritance would lead to infinite
// looping otherwise – Apache would bark and die on the spot!)
//
// @return null
//
public function __clone()
{
foreach(get_object_vars($this) as $key=>$value) {
$this->__unset($key);
}
$this->setLayout(null);
}
}[/geshi]
So there we go, functional code for allowing Layouts in a Two-Step View approach. Notice how the render() and main() methods interact. Because it’s both have very specific uses, main() is only useable within templates when injecting the main template into a Layout.
Sample usage is pretty simple – I won’t delve into any details since you just need two additional pieces of work when instantiating a View object:
1. Create a Layout template (you’ll notice a setLayout() default is “layout.phtml” but you’re not bound to that convention by any means.
2. Set the Layout on a View object, e.g.
[geshi lang=php]$view = new Zps_View;
$view->setBasePath(‘/path/to/default/view/directory’);
$view->setLayout(‘layout.phtml’); // this will force render() to perform a Two-Step
$view->render(‘sometemplate.phtml’);[/geshi]
If you followed my previous posts you’ll be able to integrate the Two-Step View/Layout approach pretty easily into your Views. Of course, as usual, a key observation is that in using a Zend_View subclass be sure not to rely on Zend_Controller_Action::initView(). You’ll need to override that method in your own application specific Zend_Controller_Action subclass.
If the lack of a Zps_View_Interface worries you it’s just a declaration of all the public methods above. I won’t post it here, this entry is long enough
.
Any final words? A similar system is also possible using an alternate implementation. Matthew Weier O’Phinney, when I originally started asking about complex views in the Zend Framework, posted a Two-Step View implementation using a dispatchLoopShutdown() plugin. You can read more about this over at the mailing list archives – here’s the exact link to Matthew’s email.
http://framework.zend.com/wiki/display/ZFMLGEN/mail/27145
Finally, this is completely compatible with using a Composite View system. You can imagine creating a component full of widgets or plugin output. Each of these would be aggregated into a Composite View. But that doesn’t mean they don’t all share one thing – a common layout. So Layouts (Two-Step View) and Composite Views play quite nicely together.
Have fun!
If anyone comes up more bright ideas throw them into a comment for the hordes of blog readers to consume!
Alien Assault Traders 0.30 Released!
Apr 4th
Congratulations to Mark Dickenson (aka Panama Jack) and Rick Thomson (aka Tarnus) on their recent release of Alien Assault Traders 0.30. It’s been in development for a while now and it’s cool to see the end product finally let loose
.
Alien Assault Traders is an online browser-based space strategy trading game written in PHP. It’s a fork of Blacknova Traders. If you’re looking for a free open source web game then here’s one to take a peek at. PJ is well known for focusing more than the usual effort on optimisation (he wrote the ADOdb Lite and Template Lite libraries) so it’s a bit easier on your hardware than many alternatives.
I haven’t been tracking development as much as I used to (busy with Astrum Futura, QGL and my Zend Framework proposals) but the new version has a significant overhaul of the previous 0.2x code. Have fun!
PHP Magazine: PHP Game Poll
Feb 21st
http://www.php-mag.net/magphpde/magphpde_news/psecom,id,26905,nodeid,5.html
The International PHP Magazine has started a new poll asking readers to votes for their favourite PHP game. Judging by the list it looks like the top 10 Sourceforge registered open source games. I listed these a while back and noted phpDiplomacy in particular was doing really well. Somehow though I doubt the voting will be brisk. Should I tell them the QGL is not actually a game but a PHP game-oriented library?
.
