Thank you, I had a nice Christmas with my family.
I’m assuming that your Loader class is reading in the questions/ specification for a given survey from somewhere (DB or a file, perhaps) and the Form class then builds the HTML for the form from the specification?
Yes. On purpose, my app doesn’t use a DB. The survey is described in a text file in INI format
// sample_survey.ini
[meta]
name = "Sample Survey"
hello = "Please complete this survey"
goodbye = "Thank you for taking this survey!"
[section_1]
type = 1
title = "Preferences"
questions[] = "What size Coke do you prefer?"
questions[] = "What size popcorn do you prefer?"
questions[] = "What size candy bar do you prefer?"
answers[] = "Small"
answers[] = "Med."
answers[] = "Large"
[section_2]
type = 2
title = "Lifestyle"
questions[] = "What kind of car do you drive?"
answers[] = "I don't drive"
answers[] = "Honda"
answers[] = "Toyota"
answers[] = "Ford"
answers[] = "General Motors"
answers[] = "Other"
[section_3]
type = 3
questions[] = "Things you like about your job"
answers[] = "Short commute"
answers[] = "Good supervisor"
answers[] = "Fulfilling"
answers[] = "High status"
answers[] = "Fun environment"
answers[] = "Pays well"
answers[] = "I don't like my job"
I chose INI over XML format because PHP has a very convenient function that loads an INI format into an array. I accumulate the results of the survey to a CVS file by the same name as the INI file. The difference between type 2 and type 3 is that type 2 accepts only one answer, while type 3 is “check all that apply.”
I'd also have a class in there for loading a view template in which to display the form and any status messages to the user.
Once my form object creates the form, its render method just echoes the form out. By view template, do you mean an HTML skeleton with placeholders where PHP can insert values? I’ll try that but the skeleton would be very minimal, consisting of little more than the html
, head
, and body
tags. Because each survey can be so variable, the entire form has to be built from scratch. However, I only have loops and conditionals mixed in with the HTML code. Still the code is messy and I don’t see how to avoid that. Here’s the procedural code for building the input control for a type 2 survey question.
case 2: // 2 = One question, multiple choice, single answer
// output question
echo '<p>', $qnum++, '. ', $section_data['questions'][0], '<br />',
'<input type="hidden" ', 'name="form_data[', $section_name, '][responses][0]" ',
'value="0">', "\n";
// output answer choices
foreach ($section_data['answers'] as $k => $answer) {
echo '<input type="radio" ',
'name="form_data[', $section_name, '][responses][0]" value="', ($k + 1), '"',
(($form_data[$section_name]['responses'][0] == $k + 1) ? ' checked="checked"' : ''),
(($caller == 'confirm') ? ' disabled="disabled"' : ''), '>', $answer,
(($k < count($section_data['answers']) - 1) ? '<br />' : '</p>' . "\n"), "\n";
}
break;
The HTML the messy code produces, however, is nice and clean, in my opinion.
<h3>Lifestyle</h3>
<p>5. What kind of car do you drive?<br />
<input type="hidden" name="form_data[section_2][responses][0]" value="0">
<input type="radio" name="form_data[section_2][responses][0]" value="1">I don't drive<br />
<input type="radio" name="form_data[section_2][responses][0]" value="2">Honda<br />
<input type="radio" name="form_data[section_2][responses][0]" value="3">Toyota<br />
<input type="radio" name="form_data[section_2][responses][0]" value="4">Ford<br />
<input type="radio" name="form_data[section_2][responses][0]" value="5">General Motors<br />
<input type="radio" name="form_data[section_2][responses][0]" value="6">Other</p>
that would still be part of the class’s responsibility of creating a HTML form from a set of data.
I’m relieved to hear that. The more I search on the single responsibility principle, the more it seems like it’s a holy grail that lots and lots of people don’t follow. There are tons of sample applications out there where the classes model things like cats and dogs, and the dog class has methods for eat, run, bark, and roll over.
Anyway, I realize you’re not a personal tutor, but if I could ask your opinion on one final question. Which is the better practice when methods in two different classes work on the same piece of data: one, pass the data to the method in the second class as an argument and receive it back as a returned value, or two, keep the data as a public property in the first class and have the second class access it in the first class? Here is a contrived example of each.
// example of first way
class A {
public $pi = 3.1415
function whatever() {
$x = new B;
$y = $x->modify($this->pi);
echo 'modified pi to ', $y
}
class B {
function modify($pi) {
$new_pi = transmogrify($pi);
return $new_pi;
}
// example of second way
class A {
public $pi = 3.1415
function whatever() {
$x = new B;
$x->modify();
echo 'modified pi to ', $this->pi;
}
class B {
function modify() {
transmogrify($a->pi);
}
Thanks a lot! You’ve been very helpful. Best wishes for the new year!