Implementing a "Wizard" in PHP Using the MVC Pattern
I've written a lot of PHP-driven websites over the last few years, mostly because PHP is so good for rapid web development. Sure, I've used ASP, JSP, and tons of other technologies, but when I needed to rewrite my resume database (yep, I don't have a resume, I have a resume database), PHP was the first on the short list due to its impressive speed of development.
The problem, however, is that PHP (like Perl) can quickly become write-only code if you let it. I'd like to have some hope of actually maintaining this site as time goes on, so I decided to implement the site based loosely on the Model-View-Controller (MVC) design pattern. This is probably overkill, but it works great when the site will be asking the user a lot of questions like mine does. The point here was to write a site that will ask a variable number of delivery and formatting questions and finally spit out some output. MVC works here because the number of questions is variable (determined by the Model), the code to direct responses is always the same (the Controller), and the look-and-feel of the questions should be uniform (the View).
The control flow of a page is shown below:
I therefore broke up the wizard portion of the site up into four files:
- stepdata.php, which is just an array tree (arrays within arrays) of the wizard data. This isn't, strictly speaking, part of MVC, but the data has to come from somewhere...
- stepmodel.php, which figures out what step the user is at and comes up with the relevant data from stepdata.
- stepcontroller.php, which calls the other two and stuffs form input into the session.
- stepview.php, which generates the html along with the generic header/footer code (header.php and footer.php respectively).
While I certainly could have gone farther and made these all PHP objects, I thought that was a bit too much overkill. Stepcontroller.php just calls the other modules using php's include() function. Have a looksee at the relevant code here:
The output module (which is the point of this exercise, right?) just pulls stuff from the session and creates the output using XML and XSLT, then directs it to a MIME email (PHP MIME code from phpguru.org). This part isn't MVC, but it's also not interactive, so MVC wouldn't be appropriate.
I'll save you the pain of looking through XSLT that generates plain text or (ugh) rtf output (it's messy), but I can show off output.php. The XML it generates as an intermediate step looks something like this:
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="html.xsl"?> <resume> <name>William J. Black</name> ... <url1>http://wjblack.com</url1> <items> <section name="Professional Employment"> <subsection>2002 to Present</subsection> <company>Sun Microsystems</company> ... </section> <section name="Education"> <subsection>2005 to Present</subsection> <company>San Jose State University</company> ... </section> </items> </resume>
The stylesheet that transforms this into text or rtf is ugly, but it is doable given enough <xsl:text> elements. Other than some header/footer templates, this is pretty much all there is to the resume display "wizard." I'm glad I picked MVC as the pattern for the wizard--it's not only vastly more readable, but maintenance should be a breeze.