Kirjautuminen

Haku

Tehtävät

Koodit: HTML, PHP: Sivupohjat nettisivujen teon apuna

Kirjoittaja: Teuro

Kirjoitettu: 07.03.2009 – 14.12.2011

Tagit: ohjelmointitavat, koodi näytille, vinkki

Keskustelussa tulee toisinaan esiin tilanteita, joissa koodin luettavuus on kärsinyt pahasti, koska sisältöä, toiminnallisuutta ja ulkoasua ei ole eriytetty mitenkään toisistaan. Tämän vinkin tarkoituksena on hiukan valottaa miten asiaa voisi lähteä muuttamaan.

Sivupohjien käyttö vapauttaa nettisivujen ohjelmoijan keskittymään varsinaiseen ohjelmoinnin toteutukseen, koska graafikko tai joku muu on tehnyt valmiin pohjan, johon vain lisätään generoitu sisältö. Tämä kyseinen sivupohja tosin toimii aivan yhtä hyvin perinteisten .html sivujen kanssa. Sivupohjan ainoa vaatimus on, että generoitujen tai staattisten sivujen on noudatettava hyvää XML merkkausta. Toisin sanoen sivun tullessa näkyviin on se takuulla XHTML 1.0 Strict mukainen dokumentti.

Mallin avulla voidaan myös liittää jokaiselle sivulle samat yhteiset asiat, kuten vaikkapa käyttäjien tunnistus tai muokkauslinkki jokaiseen elementtiin. Malli on luonnollisesti myös laajennettavissa helpohkosti isommaksi, koska sillä ei ole juurikaan kytköksiä esitettävään sisältöön. Ainoa konkreettinen yhteys on rajapinta sisällössä olevaan sisältösolmuun, jonka tulee olla jokaisella sivulla saman niminen.

Sivusto muunnetaan mallien avulla toimivaksi .htaccess tiedostolla, jolla kerrotaan minkätyyppiset tiedostot käytetään mallin kautta.

Koodin seassa on jonkun verran kommentteja, mutta koodin pitäisi olla melko selkeää luettaavaa. Viimeisessä koodilistauksessa on pieni esimerkkisivu, jossa vielä demonstroidaan mallin toimintaa käytännössä. Esimerkki valaisee samalla hieman DOM rajapinnan käyttöä nettisivujen teossa.

Kaikenlaiset vinkit ja kommentit tästä ovat enemmän kuin tervetulleita, koska järjestelmä on käytössä sivulla, joka löytyy profiilistani. Siellä ja omalla palvelimellani tuntuu toimivan oikein hyvin.

Koodivinkin pohjana toimii http://appro.mit.jyu.fi/sovellukset/demot/demo9/

htaccess

Action oma-template http://localhost/template.tmpl

AddHandler oma-template .php

pohja.xml

<?xml version="1.0" encoding="UTF-8"?>
<!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">
  <head>
    <title xml:id="title" id="title"></title>
  </head>
  <body>
    <p><a href="index.php"><img src="tyylit/kuvat/manssi_logo.jpg" alt="manssi_logo" /></a></p>
    <ul class="navigointi">
      <li><a href="ekasivu.php" title="Ensimmäinen sivuni">Eka sivu :)</a></li>
    </ul>
    <div xml:id="content" id="content">
    </div>
  </body>
</html>

template.tmpl

<?php
	/* Käsittelyyn otettavan tiedoston polku */
	$tiedosto = $_SERVER["PATH_TRANSLATED"];

	ob_start("template");

	require( $tiedosto );

	ob_end_flush();

function template( $buffer ){
 	/* Tyylit scriptit jne... */
	require( "liita/asetukset.php" );

 	$pohja = new Domdocument( "1.0", "UTF-8" );
 	$pohja -> formatOutput = true;

 	/* Ladataan pohjalle tuleva tiedosto */
	$pohja -> load( "pohja.xml" );

 	$sisalto = new Domdocument( "1.0", "UTF-8" );

 	/* Ladataan puskurista tullut sisältö */
	$sisalto->loadHTML( $buffer );

 	/* Tyylien asetus sivupohjaan */
 	$tyyli = $pohja -> createElement( "link" );
 	$tyyli -> setAttribute( "rel", "StyleSheet" );
 	$tyyli -> setAttribute( "href", "tyylit/" . $asetukset['tyyli'] );
 	$tyyli -> setAttribute( "type", "text/css" );

 	$pohja->getElementsByTagName("head")->item(0)->appendChild($tyyli);

 	/* Importoidaan sisältö sivupohjaan */
 	$teksti = $pohja->importNode($sisalto->getElementsByTagName("div")->item(0), true);

 	/* Noudetaan otsikkoelementti pohjasta. TÄSSÄ EI OLE SISÄLTÖÄ VIELÄ */
 	$otsikko = $pohja -> getElementById("title");
 	$pohja->getElementById("title")->removeAttribute("xml:id");

 	/* Haetaan puskurista tullut otsikon sisältö */
 	$otsikkoSisalto = $sisalto -> getElementsByTagName( "title" )->item(0)->textContent;

 	/* Lisätään tyhjään otsikkoon puskurista tullut otsikko */
 	$otsikko -> appendChild($pohja->createTextNode($otsikkoSisalto));

 	/* Liimataan elementit malliin kiinni */
 	while ($teksti->firstChild) {
		$pohja->getElementById("content")->appendChild($teksti->firstChild);
	}

	$pohja->getElementById("content")->removeAttribute("xml:id");

	return $pohja->saveXML();
}

esimerkki.php

<?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", "Esimerkki");
$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", "Demosivu malleista");
$con -> appendChild($h1);

$p = $sivu -> createElement("p", "Mallin avulla luotu nettisivu, jos luet tätä, niin malli toimii oikein.");
$con -> appendChild($p);

echo $sivu -> saveXML();
?>

Kommentit

tsuriga [11.03.2009 15:34:46]

#

Pohjassa on latin9 kun taas template ja esimerkki puskevat UTF-8. Suosittelisin taas esim. Zendin konventioita. Ylimääräiset välit aiheuttavat vaan pitkiä rivejä ja hankaloittavat lukemista, sitä varten on syntaksiväritys. Ja samojen konventioiden mukaan; kun kyse on Document Object Modelista, niin Domdocument -> DOMDocument.

Kommentoinen tarkemmin, kunhan kerkiää tutustua systeemiin.

Teuro [11.03.2009 18:31:57]

#

Mitäs perkuletta molemmissa oli alkujaan UTF-8 merkkaus laitettu, mutta jostain syystä oli toiseen lipsahtanut ISO-8859-1 merkkaus. Kiitos kommentista!

punppis [03.04.2009 21:04:22]

#

Kyllä tuollaisen high-tech systeemin koodin lukeminen on mielestani paljon työläämpää, kuin perus PHP-virityksen.

Mutta tämä on tietysti vain minun mielipide.

Teuro [04.04.2009 22:32:54]

#

Tämä aukeaa ehkä helpommin, jos kokeilet sitä omalla palvelimella. Tämän tarkoituksena onkin siirtää sivujen yhteiset osat yhteen paikkaan, jolloin sivujen päivitys helpottuu aivan olennaisesti.

Voisiko vinkkiä sinusta parantaa jollakin tavalla? Kerro toki, niin katson josko kirjoittaisin tuon vaikka uusiksi vielä.

zokier [07.04.2009 22:06:26]

#

vaikuttaa hirveän monimutkaiselta ihmo verrattaen yksinkertaiseen homaaan. voin katsoa itse jos osaan tehdä hienompaa :)

zokier [07.04.2009 23:29:31]

#

edit: olihan siinä joku ajatuskin näköjään jota en huomannut aluksi. Eli ei tämä sitten ihan vastaa tuota, mutta jätän nyt kuitenkin jos vaikka saa jotain ideaa.

tässä olisi oma versio, ei mitenkää niin hyvä kun toivoin kun en ole php:hen onneksi joutunu koskeamaan pitkään aikaan *oksennus*

// pohja.xml
<?xml version="1.0" encoding="UTF-8"?>
<!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">
  <head>
    <title xml:id="title" id="title"></title>
  </head>
  <body>
    <ul class="navigointi">
      <li><a href="ekasivu.php" title="Ensimmäinen sivuni">Eka sivu :)</a></li>
    </ul>
    <div xml:id="content" id="content">
    </div>
  </body>
</html>
// render.php
<?php
function renderXML($filename, $array)
{
    $pohja = new DOMDocument("1.0", "UTF-8");
    $pohja->formatOutput = true;

    $pohja->load($filename);

    foreach($array as $key => $value) {
        $elem = $pohja->getElementById($key);
        if(is_string($value)) {
            $elem->nodeValue = $value;
        } else if(is_a($value, "DOMNode")) {
            $elem->appendChild($value);
        } else if(is_a($value, "DOMNodeList")) {
            foreach($value as $node) {
                $elem->appendChild($pohja->importNode($node, TRUE));
            }
        } else {
            continue;
        }
        $elem->removeAttribute("xml:id");
    }

    return $pohja->saveXML();
}
?>
<?php
require("render.php");

$dummyDoc = new DOMDocument("1.0", "UTF-8");
$root = $dummyDoc->createElement("root");
$root->appendChild($dummyDoc->createElement("h1", "Demosivu malleista"));
$root->appendChild($dummyDoc->createElement("p", "Mallin avulla luotu nettisivu, jos luet tätä, niin malli toimii oikein."));

$content = $root->childNodes;

$data = array("title" => "Esimerkki", "content" => $content);

echo renderXML("pohja.xml", $data);
?>

en ole ihan varma että olisiko sinun rakenteessa jotain hienoa jota en nyt pikaisesti tajunnut, mutta imho oma on vähän yksinkertaisempi(hyvässä mielessä)

Triskal [05.05.2009 16:53:36]

#

Perimmäisin ajatushan tässä uskoakseni on se, että näin toimimalla ei tarvitse kirjoittaa yhtä paljon HTML:ää ja PHP:tä sekaisin. Ja sehän on aina hyvä. Tämä lähestymistapahan on itse asiassa esim ASP.NETin peruslähtökohtia.

Kuriositeetti:

Pohja.xml:n ei tarvitse välttämättä olla XML:ää, eikä edes hyvinmuodostettu, koska meillä on DOMDocument::loadHTMLFile. https://www.php.net/manual/en/domdocument.loadhtmlfile.php

Teuro [08.05.2009 07:07:44]

#

Triskal kirjoitti:

Perimmäisin ajatushan tässä uskoakseni on se, että näin toimimalla ei tarvitse kirjoittaa yhtä paljon HTML:ää ja PHP:tä sekaisin.

Näin on asian laita.

Triskal kirjoitti:

Pohja.xml:n ei tarvitse välttämättä olla XML:ää, eikä edes hyvinmuodostettu, koska meillä on DOMDocument::loadHTMLFile. https://www.php.net/manual/en/domdocument.loadhtmlfile.php

Mitä konkreettista hyötyä on tuottaa epävalidia html höttöä, kun DOMDopcument::Load() hoitaa hommaan himaan ja asetuksista riippuen jopa kertoo tehdyt merkkausvirheet.

LaNu [20.11.2009 20:37:34]

#

On tuolla kyllä aikas työläs koittaa vääntää sivuja. Esimerkki pätkä soittolistan generoinnista:

<?php
$li = $list->appendChild( new DOMElement( 'li', "&nbsp;-&nbsp;" ) );
$artistSpan = $li->insertBefore( new DOMElement( 'span', $artist ),
                                 $li->firstChild );
$artistSpan->setAttribute( 'class', 'artist' );
$titleSpan = $li->appendChild( new DOMElement( 'span', $title ) );
$titleSpan->setAttribute( 'class', 'title' );
?>
Lopputuloksena siis:
<li>
  <span class="artist">funk machine</span>&nbsp;-&nbsp;
  <span class="title">dance on the groove and do the funk</span>
</li>

Sama perinteiseen malliin:

<?php
$li = "<li><span class='artist'>$artist</span> - "
    . "<span class='title'>$title</span></li>\n";

Itseasiassa jälkimmäinen olisi se, mitä tuohon ylempäänkin oli tarkoitus laittaa, mutten keksinyt, miten tuon väliviivan saa edes DOM:lla toteutettua. Javascript tyylinen innerHTML-funktio olisi aika pop :D

Edit: keksinpäs sittenkin.. Ei vaan ensimmäisenä tullut mieleen ajatella, että tuolla $li:llä on lapsi.. Eihän tuo asioita mitenkään yksinkertaistanut. Viisi riviä vs. oneliner.. Edelleenkin se innerHTML tekisi tuosta vähän käyttökelpoisemman muussakin kuin akateemisessa näpräyksessä.. :-)

Teuro [22.11.2009 20:35:15]

#

<?php
/**
    * Aloitusjutut ...
    * $sivu = newDOMDocument
    * $con = $sivu->createElement("div");
    * $body->appendChild($con);
    * .
    * .
    * .
*/
$ul = $sivu->createElement("ul");
$con->appendChild($ul);
while($listan_alkioita){
    $li = $sivu->createElement("li", "$artist - $title");
    $ul->appendChild($li);
}

Eli ei se nyt niin kamalan paljon hankalampi olekaan. Lisänä tulee tietty vielä tagien automaaginen sulkeminen.

Hena [26.12.2010 22:23:37]

#

Onko hankala lisätä eri koodeja kuten vaikkapa kävijälaskuri, google-mainokset, bannerinvaihto jne?
Tuo kirjautumislomake voisi olla ihan näkyvillä.
Tuo demosivu ei toimi.

kayttaja-11960 [01.06.2014 16:37:40]

#

Myös sisennykset kannattaa muistaa!

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta