Isoissa projekteissa on paljon lomakkeita. Pelkkä lomakkeiden tulostus ei riitä, vaan tieto pitää myös tarkastaa ja käsitellä.
Tähän mennessä olen echottanut jokaisen formin html:nä ja käsitellyt sen sitten erikseen if(post) -systeemillä. Useamman formin kanssa koodi tuppaa näyttämään lähinnä oksennukselta, joten päätin tehdä tähän oman ratkaisun. Tässä on (ominaisuuksiltaan) yksinkertainen koodi, jonka avulla formin tarkastuksen ja tulostuksen pystyy hoitamaan muutamalla rivillä ja itse formien data (kentät, labelit) pystytään tallentamaan erilliseen tiedostoon.
Tässä nyt ei mitään tajuntaa räjäyttävää settiä ole, eikä kommenttejakaan hirveämmin ole, mutta kun tämä on oikeastaan ensimmäinen omaa tulevaisuuden koodausta helpottava työkalu, niin ajattelin jakaa sen teidän kanssa. Eipä tästä varmaan moni mitään irti saa, mutta sharing is caring.
Koko paskan lähdekoodi löytyy myös täältä.
Tässä on oikeastaan se tärkein, koodi kommentoi itseään mielestäni aika hyvin:
<?php $username = new FormInputText("Username", "text", "user"); $username->setMinLength(6); $username->setMaxLength(20); $username->setRequired(); $username->setValue("Valmiina"); $username->setInfo("Pakollinen kenttä. 6-20 merkkiä."); $password = new FormInputText("Password", "password", "pass"); $password->setMinLength(8); $password->setRegexp("^.*(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!\"#¤%&\/()=?]).*$"); // Vähintään 1 pieni kirjain, 1 iso kirjain, 1 numero ja 1 erikoismerkki (!"#¤%&/()=?) $password->setRequired(); $password->setClass("testi_class"); $file = new FormFile("File: ", "filename"); $file->setFiletypes("image/jpeg", "image/png", "image/gif"); // hyväksytyt tiedostotyypit $file->setLocation("upload"); // hakemisto johon tiedosto lisätään $file->setMaxFileSize(524288); // 512kt, tavuja //$file->setRequired(); $gender = new FormSelect("Gender", "gender"); $gender->addOption("m", "male"); $gender->addOption("f", "female"); $gender->setId("testi_id"); $gender->setDefault("f"); $age = new FormRadio("Age", "age"); $age->addOption("under18", "<18"); $age->addOption("18to63", "18-63"); $age->addOption("over63", ">63"); $age->setDefault("18to63"); $badass = new FormCheckbox("Are you badass?", "badass"); $badass->setChecked(); $submit = new FormSubmit("Fuck yeah!"); //$submit->setAttr("onclick", "alert('test')"); // Kiinnitetään kentät formiin. $form = new Form("this"); $form->setMaxFileSize(1048576); // 1mb, tavuja $form->bind($username); $form->bind($password); $form->bind($file); $form->bind($gender); $form->bind($age); $form->bind($badass); $form->bind($submit); // Tarkistetaan lähetetty data if(!$form->check()) { // Tulostetaan formi - jos formia ei ole lähetetty tai siinä on ollut virheitä $form->printHtml(); } else { // Formi lähetetty, data tarkistettu, käsitellään data. $element = $form->elements[0]; // asetetaan tässä elementiksi ensimmäinen formissa oleva kenttä, esimerkissä siis username echo "Elementin name: ".$element->getAttr("name"); echo "<br/>Elementin arvo: ".$element->getValue(); } ?>
Itse luokat:
<?php class Html { public $attributes = array(); public $tag; function setClass($class) { $this->attributes["class"] = $class; } function setId($id) { $this->attributes["id"] = $id; } function setAttr($attr, $value) { $this->attributes[$attr] = $value; } function getAttr($attr) { if(array_key_exists($attr, $this->attributes)) return $this->attributes[$attr]; else return false; } function printHtml() { echo "<".$this->tag; foreach($this->attributes as $attr => $value) { echo " $attr=\"$value\""; } echo " />\n"; } }; class Form extends Html { public $method; public $action; public $files; public $elements = array(); public $maxFileSize = 0; function __construct($action = "this") { if($action == "this") $action = $_SERVER["PHP_SELF"]; $this->method = "post"; $this->action = $action; $this->files = false; } function setMaxFileSize($size) { $this->maxFileSize = $size; } function getMaxFileSize() { return $this->maxFileSize; } function bind($element) { $this->elements[] = $element; if(get_class($element) == "FormFile") $this->files = true; } function printHtml() { // Formin alku echo '<form action="'.$this->action.'" method="'.$this->method.'"'; if($this->files) echo ' enctype="multipart/form-data"'; echo ' >'; // Max File Size if($this->getMaxFileSize()) echo '<input type="hidden" name="MAX_FILE_SIZE" value="'.$this->getMaxFileSize().'" />'; // Inputit $x = 0; foreach($this->elements as $element) { $x++; $class = get_class($element); // Jos id-attribuuttia ei ole määritelty, niin luodaan sellainen, jotta label-tagi toimisi oikein. if($class != "FormRadio") { $id = $element->getAttr("id"); if(!$id) { $id = $class.$x; $element->setAttr("id", $id); } } // P alku echo '<p>'; // Label if($class == "FormRadio") { $korkeus = count($element->options); echo '<label style="height: '.$korkeus.'em">'; } else { echo '<label for="'.$id.'">'; } echo $element->getLabel().'</label>'; // Input $element->printHtml(); // Mahdollinen virheteksti if($element->getError()) echo '<span class="form_error">'.$element->getError().'</span>'; else { if($element->getInfo()) echo '<span class="form_info">'.$element->getInfo().'</span>'; } // P loppu echo "</p>"; } // Formin loppu echo '</form>'; } function check() { if($_POST) { foreach($this->elements as $element) { $class = get_class($element); $name = $element->getAttr("name"); if($class == "FormInputText") { $value = $_POST[$name]; $element->setAttr("value", $value); if($element->required && empty($value)) { $element->setError("Pakollinen kenttä!"); } elseif(!empty($value)) { $pituus = strlen($value); if(isset($element->regexp) && !preg_match("/".$element->regexp."/", $value)) $element->setError("Syöte ei kelpaa!"); elseif(isset($element->minLength) && $pituus < $element->minLength) $element->setError("Syöte on liian lyhyt!"); elseif(isset($element->maxLength) && $pituus > $element->maxLength) $element->setError("Syöte on liian pitkä!"); } $element->setValue($value); $element->value = $value; } elseif($class == "FormFile") { $error = $_FILES[$name]["error"]; if($error == 4) { if($element->required) $element->setError("Pakollinen tiedosto!"); } else { if($error == 1 || $error == 2) $element->setError("Tiedosto on liian suuri!"); elseif($error == 3 || $error == 6 || $error == 7 || $error == 8) $element->setError("Tiedoston latauksessa tapahtui virhe!"); else { if(isset($element->maxFileSize) && $_FILES[$name]["size"] > $element->maxFileSize) $element->setError("Tiedosto on liian suuri!"); else { $tyyppi = $_FILES[$name]["type"]; if(!in_array($tyyppi, $element->filetypes)) $element->setError("Tiedostotyyppi ei kelpaa!"); else { $tmp = $_FILES[$name]["tmp_name"]; $nimi = $_FILES[$name]["name"]; $kansio = $element->location . "/"; $data = explode(".", $nimi); $paate = $data[count($data)-1]; $nimi = substr($nimi, 0, strlen($nimi)-strlen($paate)-1); while(file_exists($kansio.$nimi.".".$paate)) { $nimi .= rand(1, 10); } if(!move_uploaded_file($tmp, $kansio.$nimi.".".$paate)) { $element->setError("Tiedoston latauksessa tapahtui virhe!"); } else { $element->setValue($kansio.$nimi.".".$paate); } } } } } } elseif($class == "FormSelect" || $class == "FormRadio") { if(empty($_POST[$name])) $element->setError("Virhe valinnassa!"); else { $element->setDefault($_POST[$name]); $element->setValue($_POST[$name]); } } elseif($class == "FormCheckbox") { if(isset($_POST[$name])) { $element->setChecked(); $element->setValue(true); } else { $element->uncheck(); $element->setValue(false); } } } foreach($this->elements as $element) { if($element->getError()) { foreach($this->elements as $element) { if(get_class($element) == "FormFile") { if($element->getValue() && file_exists($element->getValue())) { if(unlink($element->getValue())) { $element->setValue(NULL); } } } } return false; } } return true; } else { // Jos formia ei ole edes lähetetty niin palautetaan false return false; } } }; class FormInput extends Html { public $label; public $errorText; public $value; public $info; function getLabel() { return $this->label; } function getError() { if(!isset($this->errorText)) return false; else return $this->errorText; } function setError($error) { $this->errorText = $error; } function setValue($v) { $this->value = $v; } function getValue() { if(!empty($this->value)) return $this->value; else return false; } function setInfo($i) { $this->info = $i; } function getInfo() { if(!empty($this->info)) return $this->info; else return false; } }; class FormInputText extends FormInput { public $minLength; public $maxLength; public $required = false; public $regexp; function __construct($label, $type, $name) { $this->label = $label; $this->setAttr("type", $type); $this->setAttr("name", $name); $this->tag = "input"; } function setMinLength($min) { $this->minLength = $min; } function setMaxLength($max) { $this->maxLength = $max; $this->setAttr("maxlength", $max); } function setRequired() { $this->required = true; } function setValue($value) { $this->setAttr("value", $value); } function setRegexp($regexp) { $this->regexp = $regexp; } }; class FormFile extends FormInput { public $filetypes = array(); public $location = "."; public $required = false; public $maxFileSize; function __construct($label, $name) { $this->label = $label; $this->setAttr("type", "file"); $this->setAttr("name", $name); $this->tag = "input"; } function setFileTypes() { $this->filetypes = func_get_args(); } function setLocation($loc) { $this->location = $loc; } function setRequired() { $this->required = true; } function setMaxFileSize($size) { $this->maxFileSize = $size; } }; class FormSelect extends FormInput { public $options = array(); public $defaultValue; function __construct($label, $name) { $this->label = $label; $this->setAttr("name", $name); } function addOption($value, $text) { $this->options[$value] = $text; } function setDefault($default) { $this->defaultValue = $default; } function printHtml() { echo "<select"; foreach($this->attributes as $attr => $value) { echo " $attr=\"$value\""; } echo ">"; foreach($this->options as $value => $text) { echo "<option value=\"$value\""; if(isset($this->defaultValue) && $this->defaultValue == $value) echo " selected=\"selected\""; echo ">$text</option>"; } echo "</select>\n"; } }; class FormRadio extends FormSelect { function printHtml() { foreach($this->options as $value => $text) { if(!isset($this->defaultValue)) $this->setDefault($value); $id = "FormRadio_".substr(md5(microtime()), 0, 5); echo "<input type=\"radio\" value=\"$value\" id=\"$id\""; if($this->defaultValue == $value) echo " checked=\"checked\""; foreach($this->attributes as $attr => $value) { echo " $attr=\"$value\""; } echo " /><label for=\"$id\">$text</label><br/>"; } } }; class FormCheckbox extends FormInput { function __construct($label, $name) { $this->label = $label; $this->tag = "input"; $this->setAttr("name", $name); $this->setAttr("type", "checkbox"); } function setChecked() { $this->setAttr("checked", "checked"); } function uncheck() { unset($this->attributes["checked"]); } }; class FormSubmit extends FormInput { function __construct($value) { $this->tag = "input"; $this->setAttr("type", "submit"); $this->setAttr("value", $value); } }; ?>
$_SERVER['PHP_SELF']
-> $_SERVER['SCRIPT_NAME']
. pathinfo.
Aihe on jo aika vanha, joten et voi enää vastata siihen.