Areas Requiring Assistance
- Feature Suggestion / Critique
Anyone with enough experience to, understand the common difficulties PHP form developers can face. The ability to know which problems deserve to be solved and suggest better ways of doing things. - OO Design esp. Pattern Integration
Someone with experience writing OO code and making use of design patterns who can guide on how to best tackle the design issues I am facing as the package grows and assist with some of the more important design/functionality decisions. - Testing esp. Unit Testing
I am interested in anybody who can either advice on how to go about Unit Testing a package or is interested in actually doing it themselves. - Documentation
Someone to create documentation
If you are not interested but know someone who that may be, please make them aware of this project, Thanks.
If you are interested PM me!
My Aspiration
My primary reason for beginning work on OsisForms was the simple fact that I couldn't find a good, freely available, package for generating / validating web forms. It is a task that all of us do, some of us do it a lot and yet everything I managed to find for this task was either overly complex, not object oriented, not easily extended, or poorly documented.
My aspirations for OsisForms are as follows:
- Fill the gap in the market and create something of high quality that thousands of developers could benefit from.
- Make more complex, user-friendly forms programmer friendly too and improve the quality of the average form found on the web for the benefit of all web users.
- Get Zend other companies interested and become famous!
Excellent question. The final version of OsisForms hopes to fulfill all my desires:
- Remove the repetition
This is an obvious one that anyone who has written any amount of procedural web form code will know all too well. Lots of the idiosyncrasies of HTML, user agents and the sheer number of tiny decisions that have to be made can make the process of creating forms really dull and repetitive. Often that little extra bit of quality or flexibility gets left behind because we just can't be bothered. - Insulate the programmer from HTML and by doing so guarantee standards compliant, CSS-friendly, flexible output
Imagine how useful it would be to some development houses to be able to refer their junior staff (who may not know or a have a poor knowledge of HTML) to OsisForms safe in the knowledge that only really nice XHTML output will come out. - Provide an accompanying CSS and JavaScript library
This is really just an extension of the last point. Obviously it is not possible to insultate the developer from CSS because they are obviously going to want to tweak so here we provide modular and well documented standard library that makes things look acceptable to the widest possible audience and allow it to be tweaked however desired. A standard JS library also greatly increases the level of usability OsisForms is able to provide and its possible applications and once again we can ensure a very high minimum standard of JavaScript. - Make it rich enough for web applications
There are two parts to this. One is that is must be possible for OsisForms to fit into the MVC pattern and the second that it provides a rich enough feature pallet to cover at least 80% of all possible scenarios. - Keep it simple
I don't want OsisForms to overstep its scope boundaries, it is supposed to make producing web forms easier and more fun. One very important decision I have made is that OsisForms will not do the validation for you. Validation == logic and logic can be used to express/model any behaviour. Attempting to replace logic with "ValidationRules" and "ConditionalValidationRules" is not where I want to go. Instead OsisForms provides everything to make validation logic simpler and more readable by- Handling all repopulation
- Providing predefined extendible classes for testing and filtering data
- Providing a simple but powerful mechanism for informing users of errors and checking end validity
- Encourage security awareness
Security conscious developers will make fewer security critical mistakes by using OsisForms. Developers unaware of security issues will be forced to confront their ignorance. Of course code using OsisForms does not guarantee code security it just makes it easier to obtain and harder to ignore.
Existing Features
Currently OsisForms is about 40% complete. All the major groundwork is in place and it is already capable of generating/validating medium complexity forms. I have implemented 34 classes in all (some of them quite small).
The OsisForm's Class Hierarchy

Some of the names need changing so that the major object appears first and the hierarchy structure itself is undergoing work
The remainder of this post shows examples of some of the things that can be already be achieved with OsisForms:
Simplest Possible Form
Code: Select all
require 'OF_Autoload.php';
$f = new OF_Form('f');
{
$txtName = new OF_SmallText('txtName', 'Name');
$butSubmit = new OF_Button('butSubmit', 'Submit');
$f->addEntities($txtName, $butSubmit);
}
if ($f->submitted()) {
print_r($f->getInput());
}
echo $f->render();Code: Select all
require_once 'OF.php';
OF::setCharacterEncoding('UTF-8');
/* BEGIN: This is the contents of OF_Autoload.php */
function __autoload($class) {
if (OF::isDecendentClass($class)) {
OF::loadClass($class);
} else {
// any existing autoload code you had
}
}
/* END */
$f = new OF_Form('f');
{
$fsPersonal = new OF_Fieldset('fsPersonal', 'Personal');
{
$txtFirstName = new OF_SmallText('txtFirstName', 'First name');
$txtFirstName->addFilter('getAlpha');
$txtSurname = new OF_SmallText('txtSurname', 'Surname');
$txtSurname->addFilter('getAlpha');
$dateDob = new OF_DateTime('dateDob', 'Date of Birth');
$fsPersonal->addEntities($txtFirstName, $txtSurname, $dateDob);
$fsPersonal->set('width', 10); // set width attrib on everything in fsPersonal
}
$butSubmit = new OF_Button('butSubmit', 'Submit', OF_Button::TYPE_SUBMIT);
$f->addEntities($fsPersonal, $butSubmit);
}
if ($f->submitted()) {
// validation
if ($txtFirstName->isEqualTo('Fred')) {
$txtFirstName->addError('I told you, you\'re barred!');
}
$input[] = $dateDob->getInputAsIso();
$input[] = $txtSurname->getInput();
if (!$f->getNumErrors()) {
// insert into db and redirect away
echo 'No errors!';
}
}
echo $f->render();
if (isset($input)) print_r($input);
Here's the code:
Code: Select all
<form method="post" action="." class="entity" id="f"><fieldset class="entity" id="fsPersonal"><legend>Personal</legend><div class="field"><ul class="valerror"><li>I told you, you're barred!</li></ul><label for="txtFirstName">First name</label><input type="text" size="10" id="txtFirstName" name="txtFirstName" class="entity" value="Fred" /></div><div class="field"><label for="txtSurname">Surname</label><input type="text" size="10" id="txtSurname" name="txtSurname" class="entity" value="2433Bloggs" /></div><div class="field"><label for="dateDob">Date of Birth</label><div id="dateDob" class="datetime"><input type="text" id="dateDob1" name="dateDob1" maxlength="4" size="3" title="4-digit Year" onfocus="this.select()" value="1986" /> - <select name="dateDob2" id="dateDob2" title="Month of Year"><option value="0"> </option><option value="1">January</option><option value="2" selected="selected">February</option><option value="3">March</option><option value="4">April</option><option value="5">May</option><option value="6">June</option><option value="7">July</option><option value="8">August</option><option value="9">September</option><option value="10">October</option><option value="11">November</option><option value="12">December</option></select> - <input type="text" id="dateDob4" name="dateDob4" maxlength="2" size="1" title="Day of Month (0-31)" onfocus="this.select()" value="1" /></div></div></fieldset><div class="button"><button type="submit" id="butSubmit" class="entity" name="butSubmit" value="1">Submit</button><input type="hidden" name="hid_butSubmit" value="1" /></div></form>Array
(
[0] => 1986-02-01 00:00:00
[1] => Bloggs
)
Code: Select all
require 'OF_Autoload.php';
$f = new OF_Form('f');
{
$txt = new OF_SmallText('txt'); // normal field
$txt->width = 10;
$arrayTxt = new OF_Array('arrayTxt'); // an array
// appends the array with 9 cloned instances of $txt
$arrayTxt->populate($txt, 9);
// OF_Arrays are strongly typed, they can only stored one kind of
// field. The field type they store is determined by the first field entered
// into the array. So this next command will throw an exception because it is
// not a SmallText
try {
$arrayTxt->populate(new OF_Button('button'), 1);
} catch (OF_Exception $e) {
// ignore
}
// OF_Array implements ArrayAccess, Iterator and Countable so you can
// do this:
$arrayTxt[] = $txt;
$arrayTxt[5]->width = 20;
unset($arrayTxt[4]);
$arrayTxtLen = count($arrayTxt);
$butSubmit = new OF_Button('butSubmit', 'submit');
$f->addEntities($arrayTxt, $butSubmit);
}
$f->submitted();
echo $f->render();
if ($f->submitted()) {
// Once the array has been checked for submission you can get information out
// of it:
echo 'Num true:' . $arrayTxt->getNumTrue() . ' of ' . $arrayTxtLen . '<br />';
echo 'Num false:'. $arrayTxt->getNumFalse() . ' of ' . $arrayTxtLen . '<br /><br />';
echo 'Input: ' . print_r($arrayTxt->getInput());
}Code: Select all
if (!$f->getNumErrors()) {
$db->createReport($f->getInputDb());
}
class DB
{
public function createReport(OF_StdInputDb $f) {
$q = "
INSERT INTO `Report` (
`title`,
`description`,
`guestPassword`,
`isComparative`
) VALUES (
{$f->fsIdentity->txtTitle},
{$f->fsIdentity->txtDescription},
{$f->fsSecurity->txtGuestPass},
{$f->fsIdentity->selComparative}
)";
...