SCRIPTING:

Kirsty Hume
PRINT FORM TAGS IN A COMPLEX HTML ENVIRONMENT DRAWING THEIR VALUES FROM SQL DATABASE QUERIES
This is a PHP printer class for HTML form fields more flexible than the other script featured here Print In A HTML Form Incoming Sql Query Fields.
Whereas the former script was apt to print a flush of form fields in groups of the same type, this PHP class here can truly insert whatever type of form fields at whatever point of a HTML document, drawing the texts and the values of the form tags from a queried SQL database.
In case the form tags to print are select menus, features to criss cross SQL table form fields so to assign to the option values and to the option texts different SQL queried fields is available.
A printer for truly complex html environments that require flexibility on the server side scripting.
November 2004
{ @ }

The model above is Kirsty Hume
LOADS OF KIRSTY HUME ON THE NET


PURPOSE OF THE CLASS
What the class does and how it was developed

This script was developed together with a javascript script that is featured in the file Javascript Class For SQL and mySQL PHP Form Submission Dynamic Interfaces With Dynamic Additions And Removals Of Form Fields Via DOM And DHTML.
I guess this gives a sense of the type of flexibility I was looking for when dealing with a complex html form environment.

We all know that printing forms on a server side script can be a frustrating experience as far as elegance of coding is concerned: it invariably seems that we are bound to write continuously highly specific scripts that are never truly reusable in a different context yet still concerning html form environments.
This class cannot truly get rid of this: a form is inevitably a highly specific layout. Yet, this class can introduce some degree of elegance and generality in our tasks, thus making them much easier to deal with.

A Childe Hassam  painting
A Childe Hassam painting
Let me stress it significantly differs from another PHP class featured here on the file Print In A HTML Form Incoming Sql Query Fields Or Arrays By Using A Php Class Interface.
Whereas the latter assumed you already had fully formatted queries, this one allows to pass directly the SQL queries too.
Whereas the latter was meant to provide you with a class that could be ready to print sets of html tags that were basically identical (all input fields, for instance) for a section of a page (though you could, of course, include more sections in the same page), this one truly allows you to articulate sequences of different form tags at whatever pace and recurrence you may need.

The name of this class is: formFactory.

Though anticipating is never a good technique, I think this time persuing these few lines can give to you an immediate sense of what you can achieve: it is a PHP script using this class, whereas I obviously extracted only a small fragment and changed minor things. You may perhaps guess what it does at a glance, and if you can guess at a glance, it means you can also implicitly attain a sense of how this class can introduce that "some degree of elegance and generality" I mentioned earlier: does it appear significantly ordered, and easily fit to meddle with any wider HTML contexts?


So, it is possible you already learned how this class works: once initialized, you can just invoke the method named printer (more details about it later on) with two arguments, a query to get from the database the details you want to insert into it (more about this later on) and the form tag type wanted, and it would just print it.
Details about the tag attributes meant to be added to the tag can be passed as an optional third argument of that class method.

Now, if it has been so easy to understand how it works and how widely it can be used within a complex HTML environment, don't you think it could truly help you simplify the appearances of a PHP script meant to produce complex form layouts out of a database?


CLASS CODEX AND INITIALIZATION
The codex, and how to initialize the class, how to scatter its methods throughout a html environment

First your class code, whose name as said is: formFactory.

A Georges de Feure painting
A Georges de Feure painting

lines (with comments and blank lines):
A Alexei Jawlensky painting
A Alexei Jawlensky painting

You initialize the class, using here the usual foo placeholder as class instance name:
$foo = new formFactory('host', 'proxyUsername', 'proxyPassword','databaseToUse')
Since the class establishes connections to query SQL tables, the initialization of the class requires the log in of a proxy that can query the database. Do not forget to pass also the last argument, the database to use, though if you don't that would default to: "mysql".

In a previous version of this class, the login of a proxy was mandatory, but now it is no longer.
That is, you can also initialize an instance of this class without passing to the constructor any argument at all, if you want:
$foo = new formFactory();
In this case the class methods (documented further on) will assume that what they will be later called in to manipulate as their own arguments, will never been queries to be still issued to the database, but already fetched SQL fields.
More about it when documenting the class method named printer

Whichever way, once you have successfully initialized the class, all you have to do to scatter your html form tags wherever you want in the overall html document structure, is to locate where in such structure you want a form tag to appear, and in such location insert the php commands to print something; example:
<strong>hello world</strong>
Wouldn't you like to insert below a form tag:
<br><table><tr><td>
<?$foo->printer('select * from dunno', 'text', 'class="dunno"');?>
</td></tr></table>

A Thomas Eakins painting
A Thomas Eakins painting
Of course, by default the class prints immediately as soon as it has grabbed a query.

There can be cases though when you may desire to delay printing (let's imagine, in the situation above, that you wanted to nest each produced form tag within a html table cell rather than just in the whole html table).
One way to delay printing, is by issuing this command prior to calling in the printer method:

$foo->print=0;

That is, setting a class property named print to zero.
There is actually another, more practical way, to inhibit printing, and which is described further on; but for now let's document this one.

You can then store a result of the printer method (which now will run but will not print) into a variable, because the set of produced tags is returned by the method.
Such returned output is in the shape of an array of tags.

$store=$foo->printer('select * from dunno', 'text', 'class="dunno"');

You have now stored in a variable named $store the whole array of produced tags for that call to the method printer.

Now, you can re-enable printing again: since the method printer has already run (in the no print mode) and you have stored its outcome elsewhere, you can go on printing other things or just elaborate what is now into the variable $store:

$foo->print=1;

That is, resetting the class property print to 1, you reenabled immediate printing when/if running printer again.

Once you have stored the outcome, you could recursively scan it with a loop and print each tag,adding before and after it whatever you may want.
An example, which is interesting for it can also build html table specifying how many cells must go per row:
$f->print=0;
$store=$f->printer('select * from followers', 'text', 'class="dunno"');
$f->print=1;

$cellsPerRow=2;/*each row 2 cells?*/
print '<table border=10 cellspacing=5><tr>';
for($i=0, $cells=1; $i<sizeof($store)-1; $i++, $cells++){
print '<td>'.$store[$i].'</td>';
print (!($cells % $cellsPerRow))?'<tr></tr>':'';/*make new row?*/
}
print '</tr>;
print </table>;

Of course, if you have this type of layout exigencies, a bit of scripting complexity expelled from the door comes back sneaking in from the window.
Yet, if you decide to use Css, this problem of "excessive" scribbling could be solved as long as browsers would support in the expected way the css property float, which would allow you to align tags as if in cells and rows without resorting to tables - though this Css implementation can still vary from browser to browser, whereas tables don't.

Using float, you could just insert your forms in mere <SPAN> tags whose style is set to float either right or left.
The table above could for instance be made in this way:

print '<div style="width:320; padding:0;">';
$f->printer('select * from followers', 'text', 'style="width:150;float:left"');
print '</div>';

Which is significantly shorter, and whereas a wrapping <DIV> layer has a width X set to an amount that would necessarily force the included floating elements, whose width Y is set to (slightly less) than an half of it, to float in rows of two (for: X/Y=320/150=| 2 |).

You will now apprehend how the naming of the form fields namely how the assignment of the value and name attribute pairs of each form tag operates in this class.Of course you know form tags have a name to identify them (likewise variables) and a value shown in plaintext:
<input type="text" value="Italy" name="country">


METHODS OVERVIEW
How to use all the features

You have basically just one method that is to be documented: printer.
It takes the following arguments:
  1. $query: a full query to the database, or a set of already fetched SQL fields in the shape of an associative array.

    If you use this latter way, you may have to pass also the argument discussed later on and named $htmlTagName.
    Also, this latter way can be exploited only if the constructor has been initialized without passing to it any argument at all, whereas if the arguments have been passed, being them all proxy login related arguments, the printer method would assume that whatever is passed as its first argument $query, is a SQL query that must still be issued to the database (thenceforth the meaning of proxy login arguments passed as contextual to the class initialization, got it?)

    Given the nature of the method and of the whole class purpose, it is pretty obvious that, if this argument will be a query (namely the class instance was initialized passing login arguments), then arguably 99% of the times, if not just always, this query will be a selection from the database.

    So, two simple instances:

    $foo->printer('SELECT x FROM y');/*$foo must have been initialized passing all its arguments in order to pass QUERIES to printer*/

    $foo->printer(array('x'=>'a value'));/*$foo must have been initialized passing no arguments in order to pass ALREADY FETCHED queries to printer*/


    As hinted, in this latter case you may have to pass fourth argument to the printer method, namely the argument named $htmlTagName.
  2. $tag: a String; it accepts as values only the type of allowed html form tags, namely:
    • "text"
    • "textarea"
    • "select"
    • "radio"
    • "checkbox"
    • "hidden"
    • "button" (though it's rather unlikely you want to produce buttons with this class)
  3. $tagTrailer: defaults to an empty string.
    If passed should be a String which will include whatever element you may want to add to the produced tag as its attributes: instance, for a textarea, you may want to specify at least rows and cols:
    "cols='40' rows='10'"
    Of course, you can also add javascript event handlers, css style declarations, class names, that is: just whatever you would put into a form tag as its attributes.
  4. $htmlTagName: defaults to an empty string.

    By default the method will assign the name and value attributes to each produced form tag in the following manner: given a query like, say:
    "select foo1 from aTable" the table name (aTable) is used, then the SQL queried field name (foo1) is appended, then a set of empty square brackets is added:
    aTablefoo1[]
    would then be assigned as the name attribute of the tag.

    Of course, the value that within the SQL table such field (foo1) carried, is what will be given instead as the value of the form tag (for textareas, what will be shown inside them).

    This is the default procedure. Though you may be puzzled, if you are to use this script you will discover that eventually this was precisely what you needed to discriminate safely your fields.
    It is designed to accommodate multiple form fields that may belong to the same SQL table: in fact you know, I guess, that a selection onto a database may well produce multiple matching results, like when you issue a query whose result you may easily guess by its nature:
    select plateNumber from cars where car='chrysler'
    this query would pretty likely yield many matching records!
    Multiple matching records produce what is an array.
    And in PHP, to signify a form field belongs to an array of multiple records, we add exactly a set of empty square brackets to its name:
    carsplateNumber[]

    Once such a form is submitted (posted) to another PHP script, this latter script will expect each posted field will appear as an array to scan (which could well be also an array of one entry only, no problem).

    Keep in mind that if your query would extract more fields, say:
    "select foo1, foo2 from aTable"
    then for each queried field you will generate a form tag of the designed type (aren't you extracting two SQL fields? You get two form fields too then), and therefore you will have alternate tags with the default names (considering the example above):
    aTablefoo1[]
    aTablefoo2[]

    Repeat.

    If you don't like this overall naming convention (though it relies on a well known and sensible PHP naming convention), you can pass this argument and what you pass as this argument, will be assigned as the tag name, plain and simply.

    If you do this, yet, it is up to you to decide whether such name must have also the ending square brackets:
    "myname[]"
    because you know the query passed as first argument will yield manifold fields, or just as a name without any trailing square brackets:
    "myname"

    My suggestion is: whenever you decide to pass this argument, always pass it with the ending square brackets notation: you are to discover this considerably simplifies things while compromising nothing.

    In fact, any subsequent or possible scanning by other php scripts of the thus named form fields (imagine a form populated via this class, which has to be submitted to another php script on its own) only has to take into account, being then all the posted fields arrays, whether each posted form fields is reported as an array of one entry alone
    (that is, whether $_POST['formFieldNAME'], whereas formFieldNAME is a placeholder name, is an array of one element - which means in the submitted form there was only one field with such name)
    or as an array of many entries
    (that is, whether $_POST['formFieldNAME'], whereas formFieldNAME is a placeholder name, is an array of more elements- which means in the submitted form there were manifold fields with such name)
    The performance difference when having to scan posted fields that should be unique and yet are presented anyway as arrays of at least one entry is, on my PC, of one tenth of a second each 100,000 iterations.
    That is, scanning 100,000 times an array of one entry so to extract first and assign then the only value held by the array foreach($array as $x){$y=$x;}, takes after 100,000 rounds one tenth of a second more than a direct assignment $x=$y does.
    I consider it a gain, for if you lose one tenth of a second each 100,000 similar operations, you also do not have to check any longer via previous conditional statements (if/else) whether the posted form field resulted being an array or an isolated element (not an array); in fact if all are arrays, all are dealt with via a loop, and no check is needed about whether... a loop is needed.
    To bypass this argument and reach the next ones, pass it as zero or as an empty string.
    There is a special case: the SELECT tag.

    It is perfectly possible, with a select tag, that you want to assign a name to the SELECT tag itself, and to each option nested in it a different set of values/texts (options have no name property, but only two attributes named value and text).

    Yes, those complexify the matter, but not because of this script conception but because of the very same nature of the select tag.
    If you print a select tag, keep in mind the class has these rules and/or caveats, :
    • The default name (if this argument $htmlTagName is not passed) assigned to the SELECT tag is only the SQL table name plus the brackets: that is, just:
      aTable[]

      With a select tag, it is the select tag itself only that wants a name, not nested its options tags.
    • The naming convention exposed above is then applied to the options too only if a class variable named
      var $selectionCross
      is set to zero, which for instance could be achieved by:
      $foo->selectionCross=0;

      Yet by default such class variable does not hold zero, but 1, thus the default behaviour when assigning values and names to an option tag is the next one.
    • By default, unless you set the class variable selectionCross to zero, the <option> tags are populated as follows: the class presumes that every sql query issued to be printed in a select form tag, is issued on two form fields:
      select foo1, foo2 from aTable
      Of course also the wildcard * rather than foo1, foo2 would do as long as the queried SQL table includes only two SQL fields.
      Then the value derived from the first queried field is assigned as the value of the produced option, and the value derived from the second queried field is assigned as text of the option.

      What is implied in this tactic is less strange than you may guess: options, in an html document, can have verbose text and very concise values - or it is possible, somewhat vice versa, that the value of an option is not fit to be show as text, consider this:
      <option value="http://www.unitedscripters.com/phps/print2.html"> print in php </option>
      A webpage address is not a nice text (option texts should be descriptive, not cryptic), but does a good mating value. It is therefore well possible that when you're printing options, you have to assign values and texts in this criss crossed way - and this class by default presumes this is your case!
      We could perhaps imagine that the query related with that example might look:
      select address, title from mySite

      Anyway you can switch this behaviour any time by:
      $foo->selectionCross=0;
  5. $selectedIndex: a Number or an Array of numbers. Defaults to zero.
    It is the default selected option numerical index in the given select menu, if you are producing a select form tag.

    If you pass this argument and you are happy with the default tag naming convention, you have to bypass the previous method argument by passing it as zero or as an empty string.

    To produce multiple selections in a select menu that allows them (ie where the property named multiple is in the tag: <select multiple>), pass this argument as an array whose each entry is a number reflecting the option index to be selected.
    This array is sorted, so even if by mistake you include the index numbers in a non perfectly ordered way, the ordered one will be produced.
    Numbers mistakenly beyond the scope of the available options will be ignored.
  6. $noprint: if you pass this as number 1 (or any number other than zero), the method will not print but only return the result.
A full example (though not always you'll need passing all the arguments, usually the first three suffice, thus producing one single elegant line):
$foo->printer(
"select foo1, foo2 from aTable",
"textarea",/*each field will have its textarea then*/
"cols='40' rows='12' class='foo' onClick='alert(\'hi\')'",
"optional_preferred_tag_name",
0,/*for SELECT: default selected option index. Could be an array too: array(1,5,10 ...)*/
0 /*prints immediately*/
);

The only other elements you have to keep in mind are still for the select form tags:
  • There is a class variable named $selectDummy.
    $foo->selectDummy='dunno';
    If you set it to something other than an empty string, the class will produce, when printing a select menu, a topmost option in the menu whose value will be an empty string and whose text will be the one passed to this class variable.
    This is very useful to produce topmost text options not meant to post actual data such as: "Select Your Preferred Option".
    I introduced this because querying a database never produces such insignificant values meant to be dummies: all data in a database is significant, or would not be there.

    Very particular case: if you use the dummy and you also pass the argument $selectedIndex to the printer and you want to select the first option after the dummy only (that is, that one and no other ones), then pass such $selectedIndex argument as an array of two zeroes:
    array(0,0)
    With the dummy option, any array different from that one will produce multiple selected indexes excluding the dummy (which is what you probably want!). So:
    array(0,3,6)
    would correctly consider as index zero the first option soon after the added dummy (which being added is regarded sort of a belated addition not to be considered in the indexing scheme, correctly).
    And again:
    array(1)
    would correctly select the option 1, namely the second after the dummy for indexes in programming start with zero, and 1 would mean second option.

    Morale, to mean option zero as the one soon after the dummy, do use:
    array(0,0)
    This is the only caveat.
  • This class does not produce the starting and closing form tags:
    <form></form>
    so it is implied you print them in the page yourself.
  • If youpass the second argument of printer like the string "div" or like the string "span", it would produce such a tag rather than a form tag.
    Obviously enough, each of such tags would wrap one of the values drawn from the database queried fields.
    I thought it was an interesting option, easy to include, and therefore worth adding.

    No name or id is assigned to such tags, nor a class name: to specify further attributes, you'd need to populate such tags with their further details (if any) by passing the third argument of the method.

    If you have Css rules that affect either div or span tags, such generated tags will be affected by these rules, of course, unless you override these rules in the generated tags by setting for the latter, via the third method argument, a style property accordingly suited.
A Jean Beraud painting
A Jean Beraud painting, Symphony In Red