Tämän koodivinkin tarkoituksena on siirtää monilla web-sivuilla tarvittavien lomakkeiden luominen erilleen varsinaisesta ohjelmakoodista. Lomakeluokasta voidaan luoda erillisia lomakeolioita, sekä lomake-elementeille on omat luokkansa.
18.3.2009
koodivinkki kirjoitettu kokonaan uusiksi kiitokset tsurigalle upeista kommenteista.
11.10.2009
Ja vielä kerran vedetty uudestaan koko vinkki. Nyt käytössä uusin versio tuosta luokasta.
14.11.2010
Nyt tätä voi käyttää ilman DOM rajapintaa
Clomake.php
<?php /** * Luo lomakkeen, joka hallinnoi kaikkia lomakkeen elementtejä * @author Juha Teurokoski * @version 1.2.0 */ class CLomake{ protected $_lomake; protected $_kasittelija; protected $_metodi; private $tarkista = false; private $nayta; private $id; private $elementit; private $sivu; /** * Luo uuden lomakkeen * @param sivu DOMDocument tyyppinen olio, joka luo uusia solmuja * @param kasittelija Käsittelevän sivun osoite hyvin usein kutsuva sivu itse * @param metodi Lähetyksen tyyppi (poikkeuksetta post) * @param nayta Haluttaessa lomake saadaan piiloon oletuksena esillä * @param id Tarvittaessa lomakkeelle saadaan id esimerkiksi css varten */ public function __construct($sivu, $kasittelija, $metodi = 'post', $nayta = 'block', $id = false){ if($sivu != NULL){ if(!$sivu instanceof DOMDocument){ throw new Exception('Virheellinen sivuelementti annettu lomaketta ei voi luoda'); } $this->sivu = $sivu; }else{ $this->sivu = new DOMDocument("1.0", "UTF-8"); } $this->_lomake = $this->sivu->createElement('form'); $this->_kasittelija = $kasittelija; $this->_metodi = $metodi; $this->nayta = $nayta; $this->id = $id; } /** * Palauttaa sivun käsittelijälle lomake-elementin * @return DOMElement palauttaa DOMElement olion (form) */ public function haeElementti(){ return $this->_lomake; } public function anna_lomake() { $this->sivu->appendChild($this->_lomake); return $this->sivu->saveXML(); } /** * Lisää annetun taulukollisen lomake-elementtejä lomakkeelle * @param elementit Lomake-elementit * @param tarkista Ennen lähetystä lomakkeen elementtejä ei (tietenkään) tarkasteta */ public function lisaaElementit(array $elementit, $tarkista = false){ $virhe = false; $this->_lomake->setAttribute('action', $this->_kasittelija); $this->_lomake->setAttribute('method', $this->_metodi); $this->_lomake->setAttribute('style', 'display: ' . $this->nayta); $this->_lomake->setAttribute('enctype', 'multipart/form-data'); if($this->id){ $this->_lomake->setAttribute('id', $this->id); } /** * Kaivetaan lomakkeen luojan juurielementti */ $sivu = $this->_lomake->ownerDocument; /** * fieldset elementtien kirjanpitoon ensin -1, koska elementtien määrän lasketaan 0:a */ $fs = -1; foreach($elementit AS $elementti){ if(!$elementti instanceof ClomakeElementti){ throw new Exception('Virheellinen lomake-elementti'); }else if($elementti instanceof Cinfo){ $fieldset = $sivu->createElement("fieldset"); $legend = $sivu->createElement("legend", $elementti->annaNimi()); $fieldset->appendChild($legend); $this->_lomake->appendChild($fieldset); ++$fs; } if($tarkista){ $elementti->asetaArvo($_POST[$elementti->annaNimi()]); } if($tarkista && $elementti->annaArvo() == "" && $elementti->annaVaatimus()){ $elementti->asetaVirhe($elementti->annaNimi() . " ei voi olla tyhjä"); $virhe = true; } $setit = $this->_lomake->getElementsByTagName("fieldset"); $solmu = $setit->item($fs); if ($solmu == NULL) { throw new Exception("Solmu on NULL"); } $this->_lomake->appendChild($elementti->ankkuroi($solmu)); } $kpl = $sivu->createElement("p"); $input = $sivu->createElement('input'); $input->setAttribute('type', 'submit'); $input->setAttribute('value', 'Valmis'); $kpl->appendChild($input); $input = $sivu->createElement('input'); $input->setAttribute('type', 'reset'); $input->setAttribute('value', 'Uusiksi'); $kpl->appendChild($input); $this->_lomake->appendChild($kpl); if($tarkista && !$virhe){ return true; } } } /** * Lomake-elementtien pohjaksi tehty luokka * @author Juha Teurokoski * @version 1.0.0 * @param _lomake Clomake tyyppinen olio elementtien sijoittamista varten * @param _nimi Elementin nimi * @param _arvo Elementin arvo * @param _virhe Puuttuva tai muutoin virheellinen syöte * @param _vaaditaan Elementille voidaan vaatia arvo oletuksena false */ abstract class CLomakeElementti{ protected $_lomake; protected $_nimi; protected $_arvo; protected $_virhe; protected $_vaaditaan = false; abstract function ankkuroi(DOMElement $ankkuri); /** * Palauttaa elementin arvon kutsujalle */ public function annaArvo(){ return $this->_arvo; } /** * Asettaa elementille arvon lomakkeen tarkistusvaiheessa */ public function asetaArvo($arvo){ $this->_arvo = $arvo; } /** * palauttaa elementin arvo */ public function annaNimi(){ return $this->_nimi; } /** * Puuttuvan tai virheellisen arvon aiheuttama virhe */ public function asetaVirhe($virhe){ $this->_virhe = $virhe; } /** * Palauttaa elementin sisältävän virheen */ public function annaVirhe(){ return $this->_virhe; } /** * palauttaa onko elementille pakko antaa arvo */ public function annaVaatimus(){ return $this->_vaaditaan; } } /** * Salasanaa varten * @author Juha Teurokoski * @version 1.0.2 */ class Cpassword extends CLomakeElementti{ /** * Luo uuden salasanakentän sijoittaa elementille nimen ja arvo * @param nimi Elementin nimi * @param arvo Elementin arvo */ public function __construct($nimi, $arvo){ $this->_nimi = $nimi; $this->_arvo = $arvo; } /** * Typerää, mutta pakollinen metodi lisäysvaiheessa kutsujaan jokaisesta elementistä tarkasta() metodia */ public function tarkasta(){ return true; } /** * Lisää elementin lomakkeelle * @param ankkuri Solmu, johon kyseinen elementti lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; $kpl = $sivu->createElement("p"); $ankkuri->appendChild($kpl); $input = $sivu->createElement('input'); $input->setAttribute('type', 'password'); $input->setAttribute('name', $this->_nimi); $input->setAttribute('value', $this->_arvo); $kpl->appendChild($input); $tn = $sivu->createTextNode($this->_nimi); $kpl->appendChild($tn); $ankkuri->appendChild($kpl); return $ankkuri; } } /** * Luo uuden osion lomakkeelle pitää olla ainakin yksi tällainen * @author Juha Teurokoski * @version 1.0.1 */ class Cinfo extends ClomakeElementti{ /** * Luo uuden osion * @param nimi Osion nimi tulee legend-kenttään */ public function __construct($nimi){ $this->_nimi = $nimi; } /** * Lisääminen tehdään kutsumalla ankkuroi metodia. Tämä elementti lisätään käsin kts ylempää. * @param ankkuri Solmu, johon kyseinen elementti lisätään */ public function ankkuroi(DOMElement $ankkuri){ return $ankkuri; } /** * Typerää, mutta pakollinen metodi lisäysvaiheessa kutsujaan jokaisesta elementistä tarkasta() metodia */ public function tarkasta(){ return true; } } /** * Tekstikenttää varten * @author Juha Teurokoski * @version 1.2.4 */ class Ctext extends CLomakeElementti{ /** * Luo uuden tekstikentän * @param nimi Elementin nimi * @param vaaditaan Pitääkö elementille antaa arvo * @param arvo Elementin oletusarvo * @param tmp_nimi Elementin vaihtoehtoinen nimi, jos oikea nimi sisältää ääkkösiä / muita hankalia merkkejä */ public function __construct($nimi, $vaaditaan, $arvo, $tmp_nimi = false){ $this->_nimi = $nimi; $this->_vaaditaan = $vaaditaan; $this->_arvo = $arvo; $this->_tmp_nimi = $tmp_nimi; } /** * Lisääminen tehdään kutsumalla ankkuroi metodia. Tämä elementti lisätään käsin kts ylempää. * Elementille tulee automaattisesti '*' merkki, jos se on pakollinen * Elementin nimi valitaan sen mukaan onko tmp_nimi asetettu * Elementin arvo tulee sen mukaan onko lomake lähetetty * Elementin nimi muunnetaan oikeaksi (välilyönti -> _) * Nimen lisäksi tulostetaan virhe, jos kenttää ei ole täytetty ja lomake on lähetetty * @param ankkuri Solmu, johon kyseinen elementti lisätään */ public function ankkuroi(DOMElement $ankkuri) { $sivu = $ankkuri->ownerDocument; $kpl = $sivu->createElement('p'); $_nimi = $this->_tmp_nimi ? $this->_tmp_nimi : $this->_nimi; $input = $sivu->createElement('input'); $input->setAttribute('type', 'text'); $input->setAttribute('name', $_nimi); $_nimi = str_replace(" ", "_", $_nimi); $_arvo = isset($_POST[$_nimi]) ? $_POST[$_nimi] : $this->_arvo; $input->setAttribute('value', $_arvo); $kpl->appendChild($input); if ($this->_virhe) { $kpl->setAttribute("class", "pun"); $tn = $sivu->createTextNode(" " . $this->annaVirhe()); } else if($this->_vaaditaan) { $tn = $sivu->createTextNode("* " . $this->_nimi); }else{ $tn = $sivu->createTextNode($this->_nimi); } $kpl->appendChild($tn); $ankkuri->appendChild($kpl); return $ankkuri; } } /** * Monivalintakenttä radio, checkbox ja select elementtejä varten * @author Juha Teurokoski * @version 1.3.2 */ class CmultipleElement extends ClomakeElementti{ /** * Luo uuden monivalintakentän * @param nimi Elementin nimi * @param arvo Elementin arvo */ public function __construct($nimi, $arvo){ $this->_nimi = $nimi; $this->_arvo = $arvo; } /** * Lisääminen tehdään kutsumalla ankkuroi metodia. Tätä elementtiä ei varsinaisesti lisätä mihinkään * Lisäys tulee käyttävän luokan kautta * @param ankkuri Solmu, johon kyseinen elementti lisätään */ public function ankkuroi(DOMElement $ankkuri){} } /** * Pudotusvalikko * @author Juha Teurokoski * @version 1.1.0 */ class Cselect extends CLomakeElementti{ private $_lista; private $_joukko; private $_valittu; /** * Luo uuden pudotusvalikon * @param nimi Elementin nimi * @param lista Monivalintaelementit * @param tmp_nimi Vaihtoehtoinen nimi elementille * @param valittu Oletusarvo elementille */ public function __construct($nimi, array $lista, $tmp_nimi = false, $valittu = false){ $this->_nimi = $nimi; $this->_lista = $lista; $this->_joukko = $tmp_nimi; $this->_valittu = $valittu; } /** * Lisää listan lomakkeelle * @param ankkuri Solmu, johon olio lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; $kpl = $sivu->createElement("p"); $select = $sivu->createElement('select'); $_nimi = ($this->_joukko) ? $this->_joukko : $this->_nimi; $select->setAttribute('name', $_nimi); $_nimi = str_replace(" ", "_", $_nimi); $_arvo = isset($_POST[$_nimi]) ? $_POST[$_nimi] : $this->_valittu; for($a = 0; $a < count($this->_lista); $a++){ $option = $sivu->createElement('option', $this->_lista[$a]->annaNimi()); $option->setAttribute('value', $this->_lista[$a]->annaArvo()); if($this->_lista[$a]->annaArvo() == $_arvo){ $option->setAttribute("selected", "selected"); } $select->appendChild($option); } $kpl->appendChild($select); $tn = $sivu->createTextNode($_nimi); $kpl->appendChild($tn); $ankkuri->appendChild($kpl); return $ankkuri; } } /** * Valintaruutu * @author Juha Teurokoski * @version 1.4.3 */ class Ccheckbox extends ClomakeElementti{ private $lista; private $otsikko; /** * Luo uuden sarjan valintaruutuja * @param lista Lista valintaruuduista * @param otsikko Joukon otsikko */ public function __construct(array $lista, $otsikko){ $this->_lista = $lista; $this->otsikko = $otsikko; } /** * Lisää listan lomakkeelle * @param ankkuri Solmu, johon olio lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; $h4 = $sivu->createElement('h4', $this->otsikko); $ankkuri->appendChild($h4); for($a = 0; $a < count($this->_lista); $a++){ $kpl = $sivu->createElement('p'); $tn = $sivu->createTextNode(" " . $this->_lista[$a]->annaNimi()); $input = $sivu->createElement('input'); $input->setAttribute('type', 'checkbox'); $input->setAttribute('name', $this->_lista[$a]->annaNimi()); $input->setAttribute('value', $this->_lista[$a]->annaArvo()); $_nimi = str_replace(" ", "_", $this->_lista[$a]->annaNimi()); if(isset($_POST[$_nimi])){ $input->setAttribute("checked", "checked"); } $kpl->appendChild($input); $kpl->appendChild($tn); $ankkuri->appendChild($kpl); } return $ankkuri; } } /** * Radionappi * @author Juha Teurokoski * @version 1.0.3 */ class Cradio extends CLomakeElementti{ private $lista; private $otsikko; private $oletus; /** * Luo uuden setin radionappeja * @param nimi Joukon nimi * @param lista Vaihtoehtojen määrä * @param otsikko Joukon otsikko */ public function __construct($nimi, array $lista, $otsikko, $oletus){ $this->_nimi = $nimi; $this->_lista = $lista; $this->otsikko = $otsikko; $this->oletus = $oletus; } /** * Lisää listan lomakkeelle * @param ankkuri Solmu, johon olio lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; $label = $sivu->createElement('label', $this->otsikko); $ankkuri->appendChild($label); $_nimi = str_replace(" ", "_", $this->_nimi); for($a = 0; $a < count($this->_lista); $a++){ $kpl = $sivu->createElement('p'); $tn = $sivu->createTextNode(" " . $this->_lista[$a]->annaNimi()); $input = $sivu->createElement('input'); $input->setAttribute('type', 'radio'); $input->setAttribute('name', $this->_nimi); $input->setAttribute('value', $this->_lista[$a]->annaArvo()); if($this->oletus == $this->_lista[$a]->annaArvo() || isset($_POST[$_nimi]) && $_POST[$_nimi] == $this->_lista[$a]->annaArvo()){ $input->setAttribute("checked", "checked"); } $kpl->appendChild($input); $kpl->appendChild($tn); $ankkuri->appendChild($kpl); } return $ankkuri; } } /** * Piilokenttä * @author Juha Teurokoski * @version 1.0.0 */ class Chidden extends ClomakeElementti{ /** * Luo uuden piilokentän lomakkeelle * @param nimi Elementin nimi * @param arvo Elementin arvo */ public function __construct($nimi, $arvo){ $this->_nimi = $nimi; $this->_arvo = $arvo; } /** * Lisää listan lomakkeelle * @param ankkuri Solmu, johon olio lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; $input = $sivu->createElement('input'); $input->setAttribute('name', $this->_nimi); $input->setAttribute('type', 'hidden'); $input->setAttribute('value', $this->_arvo); $ankkuri->appendChild($input); return $ankkuri; } } /** * Tekstialue * @author Juha Teurokoski * @version 1.0.0 */ class Ctextarea extends CLomakeElementti{ private $huomautus; private $vaaditaan; private $rivit; private $sarakkeet; /** * Luo uude tekstialueen * @param nimi Elementin nimi * @param arvo Elementin arvo * @param rivit Elementin koko vertikaalisuunnassa * @param sarakkeet Elementin koko horisontaalisuunnassa * @param vaaditaan Pitääkö kenttään syöttää arvo */ public function __construct($nimi, $arvo, $rivit, $sarakkeet, $vaaditaan = false){ $this->_nimi = $nimi; $this->_arvo = $arvo; $this->rivit = $rivit; $this->sarakkeet = $sarakkeet; $this->vaaditaan = $vaaditaan; } /** * Lisää listan lomakkeelle * @param ankkuri Solmu, johon olio lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; if($this->vaaditaan){ $kpl = $sivu->createElement('p', '* ' . $this->_nimi); }else{ $kpl = $sivu->createElement('p', $this->_nimi); } $ankkuri->appendChild($kpl); $kpl = $sivu->createElement('p'); $_nimi = str_replace(" ", "_", $this->_nimi); $_arvo = isset($_POST[$_nimi]) ? $_POST[$_nimi] : $this->_arvo; $textarea = $sivu->createElement('textarea', $_arvo); $textarea->setAttribute('name', $this->_nimi); $textarea->setAttribute('rows', $this->rivit); $textarea->setAttribute('cols', $this->sarakkeet); $kpl->appendChild($textarea); $ankkuri->appendChild($kpl); return $ankkuri; } } /** * Tiedostokenttä * @author Juha Teurokoski * @version 1.0.0 */ class Cfile extends CLomakeElementti{ /** * Luo uuden kentän tiedostoa varten * @param nimi Elementin nimi */ public function __construct($nimi){ $this->_nimi = $nimi; } /** * Lisää listan lomakkeelle * @param ankkuri Solmu, johon olio lisätään */ public function ankkuroi(DOMElement $ankkuri){ $sivu = $ankkuri->ownerDocument; $kpl = $sivu->createElement('p'); $ankkuri->appendChild($kpl); $input = $sivu->createElement('input'); $input->setAttribute('type', 'file'); $input->setAttribute('name', $this->_nimi); $tn = $sivu->createTextNode($this->_nimi); $kpl->appendChild($input); $kpl->appendChild($tn); $ankkuri->appendChild($kpl); return $ankkuri; } } ?>
Tiedot.txt
palaute@sivusto.net|Palaute myynti@sivusto.net|Myynti info@sivusto.net|Info
index.php
<?php require("luokat/lomake.php"); $sivu = new Domdocument("1.0", "UTF-8"); $sivu->formatOutput = true; $html = $sivu->createElement("html"); $sivu->appendChild($html); $head = $sivu->createElement("head"); $html->appendChild($head); $title = $sivu->createElement("title", "Yhteydenottolomake"); $head->appendChild($title); $body = $sivu->createElement("body"); $html->appendChild($body); $con = $sivu->createElement("div"); $con->setAttribute("id", "content"); $body->appendChild($con); $h1 = $sivu->createElement("h1", "Esimerkki"); $con->appendChild($h1); /* Luodaan uusi lomake */ $lomake1 = new Clomake($sivu, "index.php"); /* Haetaan Cselect luokasta luodulle oliolle tietoja */ $tiedot = file( "tiedot.txt" ); for($a = 0; $a < count( $tiedot ); $a++){ $rivi = explode( "|", $tiedot[$a], 2 ); $kenelle[] = new CmultipleElement($rivi[1], $rivi[0]); } /* Ladataan oliot taulukkoon */ $oliot[] = new Cinfo("tiedot"); $oliot[] = new Ctext("etunimi", true, ""); $oliot[] = new Ctext("sukunimi", true, ""); $oliot[] = new Ctext("email", false, ""); $oliot[] = new Cpassword("salasana", ""); $oliot[] = new Cfile("kuva"); $oliot[] = new Ctextarea("kuvaus", "", 7, 55, true); $oliot[] = new Chidden("leima", md5(time())); $sukupuoli[] = new CmultipleElement("mies", 1); $sukupuoli[] = new CmultipleElement("nainen", 0); $oliot[] = new Cradio("sukupuoli", $sukupuoli, "Sukupuoli", 0); $oliot[] = new Cselect("palaute", $kenelle); $harrastukset[] = new CmultipleElement("koripallo", 1); $harrastukset[] = new CmultipleElement("jalkapallo", 2); $harrastukset[] = new CmultipleElement("mikroautoilu", 3); $oliot[] = new Ccheckbox($harrastukset, "Harrastukset"); /* Sijoitetaan lomakkeelle kentät */ $lomake1->lisaaElementit($oliot); $sivu->getElementsByTagName('div') ->item(0) ->appendChild($lomake1->haeElementti()); echo $sivu->saveXML(); ?>
index.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="fi" xml:lang="fi"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Ei DOM rajapintaa</title> </head> <body> <?php try { $kirjaudu = new Clomake(NULL, "index.php"); $kentat = Array(); $kentat[] = new Cinfo("kirjaudu"); $kentat[] = new Ctext("tunnus", true, ""); $kentat[] = new Cpassword("salasana", ""); $kirjaudu->lisaaElementit($kentat); echo $kirjaudu->anna_lomake(); } catch (Exception $e) { echo $e->getMessage(); } ?>
Satunnaisia huomioita (koska minähän en tunnetusti muuta tee kuin nillitä :), näin alkutekijöiksi:
$sivu
-muuttujaa pyöritellään globaalina? Laita sivu lomakeluokan vaadituksi parametriksi sekä lomakkeen
instanssi LomakeElementin
vaadituksi parametriksi. Näin muodostuvat loogiset vaatimussiteet väleille web-sivu — CLomake
ja CLomake — CLomakeElementti
(tietty elementti olisi siis sidottu tiettyyn lomakkeeseen). Tyhjästä ilmestyviä globaaleja muuttujia on erittäin hankala debugata, varsinkin jos et ole alkuperäinen kehittäjä tai kärsit muistinmenetyksestä tai et muuten vain ole koskenut koodiin puoleen vuoteen.LomakeElementti
voisi olla abstrakti luokka, siitä ei liene kuitenkaan tarkoitus olla mahdollisuutta luoda oliota.$sp
ja $oliot
(esim. $elements
olisi tarkempi).Alkuun kiitokset kommenteista, eikä tuota valittaminenkaan ole pahasta itsehän tämän päätin jakaa ja pyytää vielä kommenttia.
Kohta 1 korjattu ehkä pienoisella purkalla, mutta on tuo tosiaan parempi ehkä noin. Kohtaa 2 en ihan suoraan tajunnut, joten voitko hiukan selventää. Kohdassa 3 olet aiavan oikeassa. Minulla oli aluksi tarkoitus kirjoittaa koko koodi Suomen kieliseksi, mutta sitten jossain vaiheessa hiukan repesi.Voisi kai tämän dokumentoidakin, ei kai siitä suurta haittaakaan liene.
<?php class CLomake { protected $_lomake; protected $_kasittelija; protected $_metodi; public function __construct(DOMDocument $sivu, $kasittelija = '', $metodi = 'post') { $this->_lomake = $sivu->createElement('form'); $this->_kasittelija = $kasittelija; $this->_metodi = $metodi; } public function haeElementti() { return $this->_lomake; } /** * Liittää annetut elementit ankkurielementtiin. */ public function lisaaElementit(array $elementit) { $taulu = $this->_lomake ->ownerDocument ->createElement('table'); foreach ($elementit as $elementti) { if (!($elementti instanceof CLomakeElementti)) { $errorMsg = 'Virheellinen lomake-elementti'; throw new CLomakeException($errorMsg); } /* * Arvo tallennetaan tässä vain selkeyden vuoksi, * PHP:ssä oliot annetaan oletusarvoisesti viittauksina, * jolloin $taulu on jo siis valmiiksi sama kuin haettava * arvo. Näitä löytyy koodista muutamia muitakin. */ $taulu = $elementti->ankkuroi($taulu); } $this->_lomake->appendChild($taulu); } } abstract class CLomakeElementti { protected $_lomake; protected $_nimi; protected $_arvo; abstract function ankkuroi(DOMElement $ankkuri); } class CHidden extends CLomakeElementti { public function __construct($nimi, $arvo) { $this->_nimi = $nimi; $this->_arvo = $arvo; } public function ankkuroi(DOMElement $ankkuri) { $sivu = $ankkuri->ownerDocument; $tr = $sivu->createElement('tr'); // ... $ankkuri->appendChild(...) ... return $ankkuri; } } # Ja käyttöesimerkki $sivu = new DOMDocument(); $sivu->loadHTML('sivu.html'); $lomake = new CLomake($sivu); // elementtien luonti tähän... $elementit = array(); $lomake->lisaaElementit($elementit); $sivu->getElementsByTagName('body') ->item(0) ->appendChild($lomake->haeElementti()); $sivu->saveHTML(); ?>
En testannut, mutta toivottavasti idea käy ilmi. Komentoketju on selkeä, ja luokat vaativat parametreinaan oikean tyyppiset oliot. Näin ohjelmoija tietää heti virheilmoituksen nähdessään, missä vika on. Jätin pois sidonnan CLomakkeen ja CLomakeElementtien väliltä, kun en nähnytkään sille enää tarvetta.
Ja ankkuri on ihan hatusta heitetty nimitys, saa keksiä paremman :). Vaikkapa $sidosElementti
ja function sido
, en jaksa enää muokata koodia.
EDIT 01:30: Korjailua.
EDIT 12. 16:50: Lisää drastista korjailua.
Tuo olikin hyvä esimerkki! Muutan tuon luokan ja muokkaan sen tänne.
Jaha ja unohdin tuolta CLomakkeen parametreista ne actionit ja metodit, noh muokkaanpa ne tuohon ylläolevaan.
Hienoa nähdä oliopohjaisuuden yleistyvän PHP:ssä.
Huomasin juu tuon puutteen, mutta tein jo itselleni, ja hyvältä näyttää. Oliot tuovat aika reilusti potkua ohjelmointiin, joskin tällainen systeemi kaiketi tuli myös proseduaalisella koodauksella, mutta olisi melkoisen erilainen toteutus.
Pahoittelen osaamattomuttani, sekä tietysti tätä spammin määrää, mutta vastailet niin nopeasti :).
Huomasin tuossa ylempänä antamassani versiossa paljon muutakin korjattavaa. Oli esim. pakko palata tuohon DOMDocumentin antoon parametrina, jotta sitä varten saadaan luotua uusia elementtejä. Lisäksi luokkaa piti muuttaa jonkin verran, jotta sain korjattua alkuperäisen erheellisen ajattelutapani, missä lomake tuli taulukon sisään eikä toistepäin.
Mistäs tuo uusi globaal $con
on tuonne piirtometodiin tullut? Ei sitä DOMDocumentia
tarvitse aina parametrilla antaa, DOMElementin
ownerDocument
-attribuutilla päästään helpommalla.
Jepulis nyt on koko lomakeluokka kirjoitettu kokonaan uusiksi keskeisiltä osiltaan. Nopean testauksen jälkeen voin todeta että hyvä se on. Sivujen katselija ei takuulla näe eroa itse kirjoitetun lomakkeen ja tämän välillä, mutta kehittäjälle ero on melkoinen.
Edelleen luokka vetää ihan hatusta muuttujia (se $con
, joka takaa sen, että kirjaston käyttäjä joutuu käytännössä lukemaan koko kirjaston koodin läpi, ennen kuin hän voi aloittaa kirjaston käytön), ja syöttää parametreina ylimääräisiä muuttujia piirtometodeille ($sivu
, joka on aina kuitenkin se sama, ja jonka saisi kaivettua esiin myös siitä ensimmäisenä syötettävästä elementistä). Lisäksi joukosta löytyy muutama epäselvä muuttujanimi.
On tämä parempaan suuntaan jo tottakai (sikäli kun ensimmäistä versiota enää muistan :)!
Nyt tämä alkaa saamaan jo lähinnä surkuhupaisia käänteitä, koska mulla on koneella versio, jossa ei ole mitään mainintaa kyseisestä $con muuttujasta. Päivitetty tänne taas viimeisin veriso.
Ekaa versiota tuskin kukaan haluaa nähdäkään paitsi itsemurhatarkoituksessa (tosin nauru pidentää ikää).
Esimerkin koodi ei näytä toimivan uusimmalla PHP:llä:
Warning: Missing argument 2 for CLomake::__construct(), called in /var/www/testi/index.php on line 27 and defined in /var/www/testi/luokat/Clomake.php on line 12 Fatal error: Uncaught exception 'Exception' with message 'Virheellinen sivuelementti annettu lomaketta ei voi luoda' in /var/www/testi/luokat/Clomake.php:14 Stack trace: #0 /var/www/testi/index.php(27): CLomake->__construct('') #1 {main} thrown in /var/www/testi/luokat/Clomake.php on line 14
Kyllä se toimii olet ilmeisesti unohtanut antaa toisen parametrin Clomake::__construct metodille. Tämä on testattu toimivaksi PHP:n versiolla 5.2.x jos puhut versiosta 5.3.x niin nuo virheet eivät johdu php:n versiosta.
Aihe on jo aika vanha, joten et voi enää vastata siihen.