PHP::HTMLElements

Nem titkoltan »azonnal beleszerettem« az ASP.net nyújtotta lehetőségekbe. Leginkább a code behind modell az, ami rögtön megfogott. Ezzel kapcsolatban jönne most néhány gondolat, a címből sejthető témával.

Az elején mondom, hogy akiket a kísérőszöveg nem érdekel, a kódot ide kattintva böngészhetik, nem bonyolult, nem nagy és UTF-8-as, a böngészőben színezve jelenik meg.

Klakkolás után tömény kódokkal és súlyos gondolatokkal folytatom.

PHP-ben amikor egy-két HTML elemet (leginkább legördülő listát) kicsit macerás kezelni. Tudom, hogy léteznek frameworkök, illetve kismillió megoldás, de én általában szeretek a dolgok mögé látni, megérteni azok működését, így valamelyik nap kíváncsiságból összeraktam néhány osztályt, ami akár jó alap is lehet. Vagy nem, majd elválik.

Na, de miről is van szó. Tegyük fel hogy szeretnénk egy listát, amiben a blog kategóriái jelennek meg, de úgy, hogy ha éppen egy bejegyzést módosítunk, akkor a listában az aktuális kategória legyen kiválasztva. Ehhez valószínűleg mindenki írna valami olyan kódot, amiben lenne egy adag SQL, egy adag PHP és egy adag HTML. Mondjuk így:

function getCategories($selectedID = null) {
    $q = query('SELECT id, name FROM cat;');
    if($isResult) {
		echo '<select name="select_cat_id">';
		while($r) {
			$selected = ($selectedID == $r[0]) ? ' selected="selected' : null;
			echo '<option value="' . $result[0] . '"' . $selected. '>' . $r[1] . '</option>';
		}
		echo '</select>';
    }
	else {
		return false;
    }
}

Nem a legszebb megoldás, és ismételten: biztos van erre kismillió jobb út, de ez az egyik legalapvetőbb.

Oké, ezt tegyük is félre. Gondolkodjunk egy kicsit teljesen máshogy. Egyrészt objektumorientált világban, másrészt ezzel elmondtam mindent. A HTML struktúrájára tökéletesen illeszthető egy PHP-kód, mely annak OOP nyújtotta lehetőségeit kihasználva próbálja voltaképpen szimulálni egy HTML elem létrehozását. Ráadásul ne felejtsük el, hogy általában van tíz-tizenöt elem, amivel dolgozunk, ezeknek is javarészt ugyanazon tulajdonságaival. Persze a megoldás, amit most szeretnék bemutatni, inkább igyekszik univerzális lenni. Fontos azért azt is megjegyezni, hogy ezek a kódok gyakorlatilag egy agymenés után néhány perc gépelés eredményeként születtek, lenne még mit átgondolni és megtervezni rajtuk, de úgy vélem jó alap lehet.

Lépcső a Mennyországba

Legeslegelőször a CSS az, amivel foglalkozni kell, ezt ugyanis később majdnem minden használni fogja. Első körben gondolkodjunk nagyon minimális dolgokban: minden elemnek van egy style tulajdonsága, amelybe tetszőleges CSS-t írhatunk a CSS-pedig tulajdonság-érték párokból áll. Ezek alapján akkor már csak annyi a dolgunk, hogy lefordítjuk ezt PHP-re. Íme:

class HTMLElementCSS{

    private $properties = array();
    private $values = array();

    public function addProperty($property, $value) {
		if(strlen($property) > 0 && strlen($value) > 0) {
			array_push($this->properties, $property);
			array_push($this->values, $value);
		}
    }

    public function removeProperty($property) {
		$key = array_search($property, $this->properties);
		if($key !== false) {
			$this->properties[$key] = null;
			$this->values[$key] = null;
		}
		return false;
    }

    public function getStyle($onlyStyle = true) {
		if(count($this->properties) > 0) {
			$style = null;
			$i = 0;
			foreach($this->properties as $p) {
				if($p !== null) {
					$v = $this->values[$i];
					$style .= $p . ':' . $v . ';';
				}
				$i++;
			}
			return ($onlyStyle) ? $style : ' style="' . $style . '"';
		}
		else {
			return false;
		}
    }

Mint mondtam, semmi komoly, csak a legszükségesebbek. A használata eléggé egyértelmű, ezért arra most külön nem térnék ki, talán csak annyiban, hogy ugyan az osztály példányosítható, de haszna csak valamelyik HTMLElement osztálynál lesz

És mondá az úr: hát, É emel!!

Itt is van a lényeg. Elsőre úgy gondoltam, hogy egy interfésszel kellene próbálkozni, de ez több szempontból sem bizonyult megfelelőnek, hiszen van egy rakatnyi tulajdonság (id, class, style, name stb.), amiket jó lenne valahol először leírni, aztán később csak hivatkozni rá. Így egy absztrakt HTMLElement osztály született, amelyet később minden elem örökölni fog.

abstract class HTMLElement {
	public $ID;
	public $style;
	public $class;

	private $name;
	private $value;
	private $innerHTML;

	private $selected;

	function setInnerHTML() {
	}
	
	function render($echo = false) {
	}
}

A dolog még mindig roppant egyszerű. Persze lenne kismilliárdtrillió tulajdonság még, de elsőre csak néhányat vettem fel.

Kezdjünk bele

A következő kód az egyik legegyszerűbb és legtöbbet használt elem lesz, a bekezdés. Egy bekezdésnek van valamilyen tartalma, lehet esetleg stílusa, osztálya és azonosítója. Ezeket akár első körben rögtön meg is adhatjuk, de persze az is lehet, hogy először csak megcsináljuk azt a bekezdést, és később adunk neki mondjuk színt. (Például egy bejelentkezés űrlapjánál a hibás adatokra vonatkozó felhívást először nem jelenítjük meg, csak ha már volt egy hibás próbálkozás.) A kód:

class HTMLParagraph extends HTMLElement {

    public function setInnerHTML($content) {
		$this->innerHTML = $content;
    }

    public function render($echo = false) {
		$ID = ($this->ID !== null) ? ' id="' . $this->ID . '"' : null;
		$class = ($this->class !== null) ? ' class="'. $this->class . '"' :null;
		$style = $this->style->getStyle(false);
		$element = sprintf('%s

', $ID, $class, $style, $this->innerHTML); if($echo) { echo $element; } else { return $element; } } public function __construct ($innerHTML = null, $ID = null, $class = null, $render = false, $echo = false) { $this->setInnerHTML($innerHTML); $this->ID = $ID; $this->class = $class; $this->style = new HTMLElementCSS(); if($render) { $this->render($echo); } } }

Első körben ha valaki ránéz, lehet hogy fejbe akar lőni. Minek ennyi sor egy árva bekezdés kiírásához? Valahol tejesen jogos, de ennek az igazi erejét akkor fogjuk látni, amikor megcsináljuk a korábban említett legördülő listát, ami pedig így néz ki:

class HTMLSelectOption extends HTMLElement {

    public function setInnerHTML($innerHTML) {
		$this->innerHTML = $innerHTML;
    }

    public function render() {
		$value = ($this->value !== null) ? ' value="' . $this->value . '"' : null;
		$selected = ($this->selected !== false) ? ' selected="selected"' : null;
		$element = sprintf('%s', $value, $selected, $this->innerHTML);

        return $element;
    }

    public function __construct ($value = null, $innerHTML = null, $selected = false) {
		$this->value = $value;
		$this->setInnerHTML($innerHTML);
		$this->selected = $selected;
    }
}


class HTMLSelect extends HTMLElement {
    
    public function addOption($value, $innerHTML, $selected = false) {
		if(strlen($value) > 0 && strlen($innerHTML) > 0) {
			$option = new HTMLSelectOption($value, $innerHTML, $selected);
			array_push($this->options, $option);
			return true;
		}
		else {
			return false;
		}
    }

    public function getOptions() {
		$optionValues = null;
		foreach($this->options as $option) {
			$optionValues .= $option->render();
		}
		return $optionValues;
    }

    public function render($echo = false) {
		$ID = ($this->ID !== null) ? ' id="' . $this->ID . '"' : null;
		$name = ($this->name !== null) ? ' name="' . $this->name . '"' : null;
		$class = ($this->class !== null) ? ' class="'. $this->class . '"' :null;
		$style = $this->style->getStyle(false);
		$options = $this->getOptions();
		$element = sprintf('%s', $ID, $name, $class, $style, $options);

		if($echo) {
			echo $element;
		}
		else {
			return $element;
		}
    }

    public function __construct ($ID = null, $name = null, $class = null) {
		$this->ID = $ID;
		$this->name = $name;
		$this->class = $class;

		$this->style = new HTMLElementCSS();

		$this->options = array();
    }
}

És hoppá, a fentebb említett kód rögtön gusztusosabban néz ki, sőt, egy lépéssel közelebb vagyunk a code behind modellhez, de akár még az MVC-hez is (persze attól ez nagyon messze van, mint maga a PHP):

function getCategories($selectedID = null) {
    $q = query('SELECT id, name FROM cat;');
    if($isResult) {
		$selectElement = new HTMLSelect();
		while($r) {
			$selected = ($selectedID == $r[0]) ? true : false;
			$selectElement->addOption($r[0], $r[1], $selected);
		}
		return $selectElement->render();
    }
    else {
		return false;
    }
}

És így tovább.


Még mindig szeretném hangsúlyozni, hogy ezeket leginkább agymenésnek szántam, semmi komoly szándék nincs mögötte. Talán annyi, hogy esetleg egy kis fórumot beindítana az ezzel kapcsolatos ötletekkel, gondolatokkal. Ilyen módon tehát nyugodtan jöhet bármilyen nemű hozzászólás, amíg nem megyünk el olyan irányba, hogy ez mennyire felesleges és mennyire szar, mert annak nem lenne sok értelme.

A fájl letölthető, ide kattintva is.

« »

mefiblog logó

Írja és rendezi Mefi, avagy Nádai Gábor © 2005-2024

A blogot büszkén pörgeti a WordPress motorja, Anders Norén sablonjának átbuherált változatával.