DigitallyCreated
Blog

Only showing posts tagged with "PHP"

Drawing Framework

I was going to write about my recent forays into finding a decent PHP IDE, but Eclipse just released a new version (v3.3) of their IDE, so I'll have to try the new version out first.

So instead, I'm going to show off some coding work I've been doing for the last few days. Here, see me going hardcore with four panels of code at once.

I've been working on Aurora, Pulse Development's upcoming CMS. It's written in PHP5 and is fully object-oriented. One of the annoying jobs when writing in PHP is "echo"ing out HTML and dealing with submittable forms. It's messy if you want to do the job properly. When I say properly, I mean it should behave nicely when you stuff up the form entry and it returns back to you. This means having your old values that you entered last time back in their boxes, and the erroring parts highlighted so its easy to see where you stuffed up the form. Some informative error messages wouldn't go astray either.

Previously, I'd written seven "panels" (rectangular areas on a webpage that do something) just using the normal echoing out of text. Since I've stepped up development during the Uni holidays I could see that I was going to go nuts if I had to hack out a tonne more panels in this manner. I needed some support.

In came the Aurora Drawing Framework. I basically designed and wrote a object oriented model for "drawing" a webpage (echoing out stuff). Its main requirements were to make the restoring of past submitted form values automatic and to make the presentation of form errors automatic. Also, since one of Aurora's main design goals is that the UI and control code be very separate so we can easily rip the UI off and write a new one, the Drawing Framework also needed to be easily extensible and changeable. Don't like the way a control is done? Fine! Extend your own class and do it your way. The rest of the framework will still work with you (thanks polymorphism!).

The Drawing Framework also helps eliminate some security concerns, eliminates accidental (HTML) syntax errors, reduces the complexity of the code when dealing with complex forms, and helps keep your page XHTML 1.0 Strict valid. All HTML attributes are automatically run through PHP's htmlentities() function which stops people accidentally or maliciously inserting code into your HTML and hijacking your form. All controls are drawn by the framework (you just set properties) so there will be no markup syntax errors (providing the framework isn't busted :D). Complex functions are built into the framework so they're no more than a function call away (no added cyclomatic complexity). Silly things that invalidate your XHTML like having two <option> tags with the "selected" attribute set in the one dropdown control are prevented, keeping your code "Stricter" (it doesn't force you, though. You can still put a form inside a form...).

After three iterations of design (the first two iterations mostly blurred into each other, as the second iteration evolved as I was implementing), I had bashed out a decent OO design. Here's a nice whiteboard showing the overall class hierarchy. (You probably want to open that in another window so you can see it as I rave on like a lunatic.)

The Control class implements the interface through which the drawing is done, since every "control" is drawable. It also allows an ErrorDrawer to be used. The ErrorDrawer basically knows when errors happen and modifies the form HTML output code to display the errors to the user. Its abstract, so you can create different implementations of the ErrorDrawer that display the error differently. Maybe one will draw a red box around the offending control, and maybe another will put a (.NET style) little red exclamation icon next to the control. Its up to you.

Under Control, there is TextControl, which practically lets you "echo" anything out to the page HTML. It's supposed to be there to let you output text like the text inside a <p> tag. However, you can really use it to output anything (your risk and your responsibility). Then there is HtmlControl which deals with HTML controls. It provides some framework for its child classes to use, like HTML attribute handling and other things.

HtmlControl itself has two main subclasses, CompositeControl and FormControl. CompositeControls are ones that can contain other Controls (the Composite design pattern). FormControls are just that: form controls. FormControl implements the automatic previous value retrieval functionality, among other things.

Under those two classes you can see all the actual implementation classes. These are things that you actually use, like TextBoxes, SubmitButtons, Divs, Paragraphs, etc. Each one draws itself differently (obviously).

So, armed with this new framework, I went back to convert old panels across so that they use it. I was disappointed and pleased at the same time. It took more lines of code to output something simple using the Drawing Framework (but each line was a very short and simple method call) than using the old hacky echo method. However, when the form got more complex (it had error types and automatic past-value retrieval) then the Drawing Framework used less lines of code (still short and sweet lines). It was also now really easy to do those simple in concept but annoying and mistake-prone complex features.

So using the old hacky echoing method I'd probably output a form like this (it's a crappy example I know, but I don't want a massive load of code):

?>
<form action="form.php" method="post">
    <input type="text" name="test" id="TestTB" /> 
</form>
<?php

Using the Drawing Framework for the same form:

$form = new Form(); 
$textBox = new TextBox(); 
$textBox->SetName("test"); 
$textBox->SetID("TestTB"); 
$form->AddControl($textBox); 
$form->Draw(); 

As you can see it takes more lines. But to include error handling and auto past value retrieval it only changes to this:

$errorDrawer = new DivErrorDrawer($this, array("EmptyField", "BadTestData"); 
$form = new Form($errorDrawer); 
$textBox = new TextBox(true); 
$textBox->SetName("test"); 
$textBox->SetID("TestTB"); 
$form->AddControl($textBox); 
$form->Draw(); 

The first line creates the DivErrorDrawer and tells it to get its error info from the current object (which is a panel), and to look for the EmptyField and BadTestData error types being set (these types are created and set by the panel). This ErrorDrawer is given to the form object, which means it will wrap its error illustration code around the form's code.
The "true" value now in the TextBox constructor turns on the auto past value code.

That's it. That's all you have to do. I'm not going to illustrate how you'd do the same thing using the echo method, but let me assure you that it would take more lines of code (not to mention the added code complexity). Actually, come to think of it, you can just make out some code mess on the second from the left code panel in this crappy blurry photo (with added 2x24" goodness! :P). You can kind of estimate the cyclomatic complexity of that code just by looking at the indentation (ick!).

Basically, writing code with the Drawing Framework is a bit like using the Java or .NET XML library, or the code that the Visual Studio form designer writes behind the scenes to create a desktop application form in .NET (which you can do manually, but who'd want to when you've got the designer?).

Although this looks cool and all, and is obviously useful, it seems that I'm really not adding that much value. But look to the future! In the future a "Control" could be more complex things like a Date Picker or a group of existing controls (like a sort of mini-panel) or even a text field that validates itself using Javascript and maybe does some AJAXy stuff (although some extensions would need to be made to the framework for it to support Javascript). The Drawing Framework has the potential to take the complexity out of complex forms (even though it adds complexity (or at least lines of code) to simple forms).

If you suddenly have the yearning to use the Drawing Framework, you'll have to wait a bit. Pulse Development is aiming to sell Aurora to web developers in the future, and the Drawing Framework is only a small part of it! Imagine what Aurora's going to be like!

Working Hard

Even though its the holidays, I have been working harder than ever. Currently, I'm working two days a week at my part-time job and the other three days at the Summer Scholarship at my university. Unfortunately, my preferred living style (going to bed really late and waking up as late as possible) doesn't work well with 5 days a week of full time work, so I've been tired as hell.

Luckily the work is mostly good: in my part-time job I have starting to be elevated from a mere software tester to a software developer. I wrote my first bit of code (in ColdFusion) for them on Monday! The Summer Scholarship is also great. I've been assigned a task where I have to create a simple API for creating games in the Pascal programming language, and to demonstrate that API with a side-scrolling game. The API will be used by next year's PSDs in their Algorithmic Problem Solving subject.

Writing the API in Pascal sucks, because I love real IDEs with code suggesting (Intellisense), and I'm using Crimson Editor (simple as hell text editor) to write my Pascal. Also, Pascal isn't exactly a language that is widespread, so learning it hardcore is (almost) wasted. I can't even use the object oriented features of the language since the APS students won't know OOP yet! The other guys get to write in C#, Java and PHP! But knowing that next year's APS students will use what I write makes it worthwhile and mollifies me.

Most of my blogging over the next three weeks will probably be on the Summer Scholarship's PictBlog at Blogspot, so keep an eye on that. As a side note, Blogspot's blog editor sucks. I had to edit my post there at least six times before it was correct. The worst problem was, for some reason, my text didn't word wrap and it poked out over the right-side navigation menu (overlapping it) and stretched the page. Hopeless.

Outside of work, I have also been busy writing the PHP for Aurora, the CMS that will power web solutions created by Pulse Development (my cousin and I's web design business). Aurora is written in PHP and I was happy to find that PHP 5 has almost all the OOP features that C# has: interfaces, inheritance, polymorphism, etc.

Aurora will power this website once its done (in fact I'll use DigitallyCreated as a kind of test bed for Aurora), so you'll get a nicer blog and news interface, and it'll be a hell of a lot easier for me to update it (hopefully increasing my blog count). Also, you've probably noticed this page getting stupidly long; Aurora will split it automatically over multiple pages. It will also do automatic generation of the RSS feeds for this blog (thank god, I do it manually at the moment!).

Finishing up, I'll leave you with a warning: I read an article over at the INQ about one of their reporters who got RSI (yes, that thing you ignore the warnings about). The afflicted hack wrote an article about his experiences with RSI and it sounds entirely nasty. He ended up with arms that didn't work. Normally, I don't really read this sort of stuff, let alone get worried about it, but this hits close to home since I do a lot of typing and I really don't want to break my livelihood (you can't code C# with speech recognition when your arms are stuffed). I would suggest you read it, so as to avoid it yourself. Find the article here.