Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: PHP: Lomakeluokka

Sivun loppuun

Teuro [10.03.2009 20:39:29]

#

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();
}
?>

tsuriga [11.03.2009 17:21:50]

#

Satunnaisia huomioita (koska minähän en tunnetusti muuta tee kuin nillitä :), näin alkutekijöiksi:

Teuro [11.03.2009 18:30:23]

#

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.

tsuriga [11.03.2009 21:57:56]

#

<?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.

Teuro [12.03.2009 11:21:33]

#

Tuo olikin hyvä esimerkki! Muutan tuon luokan ja muokkaan sen tänne.

tsuriga [12.03.2009 16:32:37]

#

Jaha ja unohdin tuolta CLomakkeen parametreista ne actionit ja metodit, noh muokkaanpa ne tuohon ylläolevaan.

Hienoa nähdä oliopohjaisuuden yleistyvän PHP:ssä.

Teuro [12.03.2009 16:46:22]

#

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.

tsuriga [12.03.2009 17:03:10]

#

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.

tsuriga [18.03.2009 00:47:03]

#

Mistäs tuo uusi globaal $con on tuonne piirtometodiin tullut? Ei sitä DOMDocumentia tarvitse aina parametrilla antaa, DOMElementin ownerDocument-attribuutilla päästään helpommalla.

Teuro [18.03.2009 15:57:31]

#

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.

tsuriga [18.03.2009 19:44:43]

#

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 :)!

Teuro [18.03.2009 20:10:38]

#

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ää).

mrl586 [19.07.2009 23:47:36]

#

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

Teuro [02.08.2009 07:34:35]

#

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.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta