Zobrazují se příspěvky se štítkemPHP. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemPHP. Zobrazit všechny příspěvky

úterý 5. června 2007

OOP v PHP5 díl.7 - návrhové vzory (design patterns)

Při programování objektovým způsobem se dost často dostanete do fáze, kdy si nebudete jistí, jak máte danou třídu či samotnou práci s instancí provést. Může se jednat o triviální problémy typu: připojení k DB či složitější věci jako návrh MVC Frameworku.

Na tyto problémy mysleli čtyři chlapíci (Erich Gamma, Richard Helm, Ralph Johnson a John Vlissides), kteří jsou autory knihy Design Patterns: Elements of Reusable Object-Oriented Software. Kniha se brzy stala natolik oblíbenou, že je dodnes povážována za nejlepší dílo ohledně OOP. Více o této historii se můžete dozvědět např. na Wikipedii.

Samotné návrhové vzory nejsou standardem, ale doporučením, jak při psaní máte postupovat. Já se nyní pokusím sepsat, jak je to
s návrhovými vzory v PHP. Vyberu jen ty nejjednodušší a nejčastěji používané a ukáži, jak je to s jejich implementací.

1. Singleton (jedináček)

Jak již název napovídá, jedná se o objekt, který je vytvořen pouze jednou. Tento návrhový vzor můžete využít například u připojení k databázi, kde si jasně řeknete, že byste neradi, aby Vám PHP otevíralo více spojení.

class Pripojeni {
private static $instance = null;
private function __construct() {}
public static function getInstance() {
if (self::$instance == null) {
$class = __CLASS__;
self::$instance = new $class;
}
return self::$instance;
}
}


Samotný fígl spočívá v tom, že instance samotného objektu je uložena jako statický atribut třídy a objekt je vytvořen pouze v případě, že je atribut null. Konstruktor třídy je nastaven jako private, aby se nikdo nemohl snažit vytvořit objekt pomocí new Pripojeni();. Samotní vývojáři v PHP ale přišli na to, že Singleton nelze na 100% vytvořit. Důvody proč tomu tak je, můžete najít v PHP dokumentaci, zejména v komentářích.

2. Factory

Tento vzor slouží k tomu, že vytvořím jednoduchou třídu, ve které vytvořím metodu, která podle přijímaného parametru vrací ten či onen objekt.

class Factory {
const MYSQL = "mysql";
const ORACLE = "oracle";
public static function getDBMS($dbms) {
if ($dbms == self::MYSQL) {
return new MySQL();
} else if ($dbms == self::ORACLE) {
return new Oracle();
} else {
throw new Factory_Exception("Neznamy ovladac");
}
}
}


Z kódu je jasné, že samotný vzor lze použít například k připojení na ruznorodé databáze.

3. Transfer object

Pokud skutečně chceme programovat objektově a programovat co nejefektivněji, nevyhneme se tomuto vzoru. Jedná se v podstatě o jednoduché třídy, které mají za úkol preprezentovat přenášená data. Nějčastěji se můžeme s tímto vzorem setkat v ORM nástrojích, kde jsou jednotlivé tabulky mapovány jako třídy a jedna instance je ekvivalentní jednomu řádku v databázi.

class Zamestnanec {
private $osobniCislo;
private $jmeno;
private $prijmeni;
/**
* @var Stredisko
*/
private $stredisko;
// ... setry getry


Často se také můžeme setkat s tím, že samotné objekty jsou příliš složité (tzn. odkazují se na další objekty jako v případě zaměstnance a střediska). Pokud se tak stane a naše aplikace přenáší velké množství dat, je nasnadě použít tzv. DTO (data transfer object), což je v podstatě jednoduchý objekt, který nemá jako atributy třídy další objekty, ale primitivní datové typy. V případě zaměstnance by to bylo číslo střediska, což je primární a unikatní klíč střediska. O tom, jak tvořit samotné DTO je spíše otázka té či oné aplikace a její složitosti a náročnosti.

4. Facade

Při vývoji softwaru se programátoři dostávali do situací, kdy potřebovali mít jednotlivé vlastnosti na jednom místě. Ať už z důvodu přehlednosti, rychlosti či provázanosti. Vzor facade řeší roztříštěnost vaší aplikace. Představme si, že máme vytvořit modul na správu zaměstnanců, která bude řešit jak editace zaměstnance, tak třeba i střediska. Jedna z možností je, že budeme zpětně složitě dohledávat objekty na editaci jednotlivých kategorií a nebo si vytvoříme jasně definovaná pravidla:
class ZamestnanecEdit {
public function add(Zamestnanec $zam) { /* prida zamestnance */ }
public function remove(Zamestnanec $zam) { /* smaze zamestnance - muze vyhodit vyjimku ZamestnanecEditException */ }
public function save(Zamestnanec $zam) { /* ulozi zmeny daneho zamestnance */ }
public function find($cisloZamestnance) { /* return Zamestnanec */ }
public function findAll() { /* vrati array vsech zamestnancu */ }
}


Tento jednoduchý objekt pracuje se zamestnanci. Třídu na editaci středisek si jistě dovedete představit. Nyní se vrátím k zadanému úkolu. Naprogramovat modul pro editaci zamestnance i s editaci střediska. Jedna z možností je, na view vrstvě volat tyto třídy pro práci a nebo si pěkne zhlukovat dané objekty do jednoho.
class ZamestnanciEditaceFacade {
/**
* @var ZamestnanecEdit
*/
private $zamestnanecEditace;
/**
* @var StrediskoEdit
*/
private $strediskoEditace;

public function __construct() {
$this->zamestnanecEditace = new ZamestnanecEditace();
$this->strediskoEditace = new StrediskoEditace();
}

public function addZamestnanec(Zamestnanec $zamestnanec) {
$this->zamestnanecEditace->add($zamestnanec);
}

public function addStredisko(Stredisko $stredisko) {
$this->strediskoEditace->add($stredisko);
}
// .....


Samozřejmě by se dalo najít spoustu příkladů použití. Pokud při programování někdo přemýšlí hlavou, dojde mu, že takto postupovat, znamená, že co nejvíce odstinuji view vrstvu od aplikační logiky.

5. Iterator

Posledním návrhovým vzorem, kterým se zde budu zabývat je Iterator. Již dříve jsem psal, že PHP 5 má k dispozici rozhranní Iterator, které podporuje tento návrhový vzor. Takže, oč jde. Nejednou se stane, že potřebujeme na určitou kolekci dat použít nejaký cyklus, ve kterém bych mohl daná data procházet. Na jednu stranu, mohu sice použít vlastní logiku na procházení daty, ale také mám možnost připravit si jakousi formičku pro určitá data, která se budou procházet. Příkladem může být, že vytvořím objekt s počátečním datumem (1.2.2007) a konečným datem (5.7.2007) a budu chtít daná data procházet po dni. Nebo budu chtít procházet písmena od B do X po jednotlivém pismenu. Na tyto a další operace se náramně hodí použít tzv. Iterator. Iterátor jako takový má podle interface přesně definované metody, které musí třída implementující rozhranní Iterátor obsahovat:

  • rewind() - nastavuje na první položku v seznamu

  • current() - vrací aktuální položku seznamu

  • key() - vrací klíč pole

  • next() - vrací následující položku seznamu

  • valid() - zjišťuje, zda existuje ještě nějaká položka


Podle těchto jasných pravidel jsem schopen vytvořit třídu, která bude procházet libovolný seznam dat podle určitých kriteríí či podle vlastní logiky. Velkou výhodou je znovupoužitelnost a také zapouzdřenost. Jiný programátor, kterému tuto třídu poskytnete vůbec nemusí vědět, jak daná logika pracuje, stačí, že implementuje Iterator a již je schopen, podle zadaných vstupních parametrů s třídou pracovat.

Návrhových vzorů samozřejmě existuje mnohem více. Navíc PHP je objektově dost omezené, takže ne vždy je zrovna ideální řešení právě ten či onen vzor. Někdy bývá lepší si některé věci prostě naprogramovat po svém. Na druhou stranu, bývá dobrým zvykem, že pokud se budu řídit určitými kriterii, které jsem v minulých článcích popsal, měl by vývojář míti klidné spaní. Na mysli mám zejména dodržování specifik jako jsou setry, getry, nazvosloví či dokumentace.
I když není objektově orientované programování zrovna jednoduchá záležitost, tak věřím, že pro nikoho není překážkou se základní principy naučit.

To by bylo k PHP asi tak vše. Jelikož jsem slíbíl, že daný díl dopíšu, stalo se tak. Nyní jsem již situován jiným směrem, takže PHP je pro mě pouze vedlejší záležitost. Přeji mnoho úspěchů při objektovém programování, ať už v jakémkoli jazyce.

Poslední radou by mělo být asi následující: OOP není cíl, ale prostředek k dosažení cíle. Proto neberte OOP jako něco spásného. Ba naopak, dost často se dostanete do problémů, které nebude jednoduché vyřešit.

čtvrtek 12. dubna 2007

PDT a OOP

Každý, kdo chce efektivně pracovat s objekty, musí použít nástroj, který mu umožní automaticky doplňovat potřebné informace. Jinými slovy, použije nějaké IDE, které usnadní práci při psaní kódu.

Když si představím, že vytvořím objekt, který obsahuje několik metod, rád bych tyto metody rovnou volal. U jazyků, které dodržují striktně typovou kontrolu, je to jednoduché. Každý parametr metody musí mít typové označení, stejně tak návratová hodnota. U PHP je situace o dost horší. Jediné, co mi samotné PHP umožňuje je, že u parametru metody mohu definovat o jaký typ objektu se jedná. Navíc jsem omezen pouze na objekty a pole.
Jenže metody mi často vrací další objekty a tyto objekty někde dál používám. Samotný plugin od ZENDu (PHP Development Tool = PDT) na to jde od lesa. Dovolí mi používat komentáře, ve kterých si jasně definuji, o jaký typ se vlastně jedná. Lepší než další povídání bude ukázka.

class TridaA {
public function foo() {}
}
class TridaB {
private $tridaA;
public function __construct() {
$this->tridaA = new TridaA();
}
public function zavolejFoo() {
$this->tridaA->foo();
}
}


Z ukázky je jasné, že atribut třídy B je vlastně objekt z třídy A. Eclipse mi sice umožní automaticky zavolat metodu foo();, ale pouze v konstruktoru, protože dál už nevidí. V metodě zavolejFoo(); mám prostě smůlu. Mám ale možnost samotný atribut třídy okomentovat, čímž vyjádřím, že se jedná o objekt třídy A a pak již vše funguje, jak má.


/**
* @var TridaA
*/
private $tridaA;


Další věcí budiž parametry metody. Na začátku jsem psal, že PHP sice dovoluje definovat typ pro parametr metody, ale ne vždy tak činíme. Pokud typovou kontrolu na parametr metody definovat nechci, ale chci, aby Eclipse poznalo, že se jedná o tu či onu instanci objektu, jednoduše metodu okomentuji.


/**
* @param TridaA $tridaA
*/
public function setTridaA($tridaA) {
$tridaA->foo();
}


U definování samotného parametru metody je třeba mít na paměti, že musím také definovat, o jaký parametr se vlastně jedná.

Poslední věcí je návratová hodnota metod. K tomuto mohu opět použít komentář a říci tak Eclipse, o jaký návratový typ se vlastně jedná.


/**
* @return TridaA
*/
public function getTridaA() {
return new TridaA();
}


Pokud tedy pracujete s objekty a používáte k tomu jazyk, který má dynamické typování, jistě Vás často naštve, že nevíte, co vlastně v danou chvíli proměnná obsahuje. Toto Vám sice nezaručí, že nebudete chybovat při zjišťování typů, ale zaručí, že samotné programovací prostředí Vám řekne, co teď vlastně používáte.

Jestli jste neměli v oblibě komentáře, tak nyní si je určitě zamilujete :)

O psaní komentářů by se dala napsat celá kniha, ale o tom zase jindy.

úterý 27. března 2007

OOP v PHP5 díl.6 - viditelnost a klíčová slova

Pokud budeme mluvit o objektech jako o zapouzdřených componentách, musíme nějakým způsobem zajistit, aby daná komponenta poskytovala jen to, co skutečně má. Pokud bychom ignorovali viditelnost jako takovou, vznikl by nám mezi jednotlivými třídami chaos, který by zapříčinil nepoužitelnost.

Vezmu to pěkne od začátku, mám atributy třídy a metody třídy. Obě tyto vlastnosti každého objektu mají volitelnou viditelnost, která je rozdělena do tří úrovní:

  • public

  • protected

  • private



Public
Jakákoli vlastnost objektu nastavená viditelností public mi umožňuje říci, že: "každý má právo k této vlastnosti přistupovat".

Protected
Narozdíl od public, má protected omezení jen na viditelnost v samotné třídě a třídách, které jsou potomkem.

Private
K vlastnostem označeným jako private může přistupovat pouze a jedině vlastní třída.

Když jsem v minulých dílech tvrdil, že atributy třídy by měly být označeny vždy jako private, neříkal jsem úplně pravdu. Při tvorbě vlastních tříd se dost často setkáme s problémem, kdy bych potřeboval použít daný atribut jako parametr metody. Jinými slovy řečeno, podle parametru mi metoda vykoná to či ono.

class HTML_Form_Input {
private $value;
.....
public function __construct($value) {
$this->value = $value;
}

public function setValue($value) {
$this->value = $value;
}

public function getValue() {
return $this->value;
}
.....
}


Tato jednoduchá třída implementovala private jako viditelnost pro atribut třídy a public jako atribut pro konstruktor a setry a getry. Teď ovšem nastává problem, kdy bych potřeboval identifikovat typ samotného inputu. Jedna z možností by byla, že bych metodě setType(String) vždy posílal vlastním stringem, o jaký typ se vlastně jedná. Toto sice lze, ale my se budeme snažit o co nejlepší znovupoužitelnost a možnost nastavení těchto typů přímo ve třídě, abychom nemuseli při refactoringu dohledávat všechny různé překlepy, atd.

class HTML_Form_Input {
const TYPE_HIDDEN = "hidden";
....
}
$input = new HTML_Form_Input("jmeno");
$input->setType(HTML_Input_Form::TYPE_HIDDEN);


Konstanta jako taková je neměná a je přístupná mimo vytvořený objekt. Pokud bych chtěl danou konstantu volat přímo ve třídě, využiji k tomu self::.

S dalším klíčovým slovem, se kterým se můžete setkat, je static. Statický atribut či metoda je taková vlastnost, která mi zapříčiní, že ji mohu získat aniž bych musel vytvářet objekt. Její hodnota je tedy nezávislá na tom, zda objekt existuje či nikoli. Pokud bych to převedl do praxe, můžu pomocí statického atributu třídy zjišťovat, kolikrát jsem vytvořil objekt z dané třídy.

Další ukázky si nechám do příštího dílu, který budu věnovat Design Patterns, neboli návrhovým vzorům. Ukážu např. implementování Iteratoru, který lze nativně v PHP 5 nalézt.

pondělí 19. března 2007

PHP & Java: SHA-1

Při vývoji javovské aplikace jsem narazil na problém autentifikace uživatelů. Problém spočíval v tom, že mám tabulku uživatelů, která obsahuje hash hesla, který je hashován pomocí PHP.

echo sha1(sha1("heslo"));


Čekal jsem, že v Java API naleznu podobnou metodu na hash Stringu, bohužel jsem hledal marně :)

Jelikož jsem si nevěděl rady, poprosil jsem na konferenci na java.cz o malou pomoc. Po odpovědi obsahující link, na tvorbu hashe ze Stringu, jsem moc moudrý nebyl :(
Potom jsem dostal ovšem odpověď v podobě třídy, kterou jsem nakonec po své úpravě byl schopen aplikovat.

package org.dostal.dochazka.crypt;

import java.security.MessageDigest;
/**
* Statické metody pro výpočet hash
*
* @author Ales Dostal;
*/
public class HashUtil {

public static final String HASH_TYPE = "SHA-1";

/**
* konstruktor
*/
private HashUtil() {}

/**
* vypocita SHA-1 hashovaci klic z byte[] a vrati jej jako HEXa retezec
*
* @param pass heslo ve String
* @return HEXa řetězec
*/
public static String SHA1AsString(String pass) {
return SHA1AsString(pass.getBytes());
}

/**
* vypocita SHA-1 hashovaci klic z byte[] a vrati jej jako HEXa retezec
*
* @param pass heslo v byte[]
* @return HEXa retezec
*/
public static String SHA1AsString(byte[] pass) {
return hex(SHA1(pass));
}

/**
* vypocita SHA-1 hashovaci klic z char[] a vrati jej jako HEXa retezec
*
* @param pass heslo v char[]
* @return HEXa retezec
*/
public static String SHA1AsString(char[] pass) {
return SHA1AsString(String.valueOf(pass));
}

/**
* Vypočte SHA-1 hashovací klíč z řetězce
*
* @param secret pomocný klíč
* @return pole bytů
*/
private static byte[] SHA1(byte[] pass) {
byte[] mac = new byte[20];
try {
MessageDigest sha = MessageDigest.getInstance(HASH_TYPE);
sha.update(pass);
mac = sha.digest();
} catch (Exception e) {
e.printStackTrace();
}
return mac;
}

/**
* Převede pole bytů na HEXa řetězec.
*
* @param data pole bytů
*/
private static String hex(byte[] data) {
StringBuilder sb = new StringBuilder();
for (byte b : data) {
sb.append(Character.forDigit((b & 240) >> 4, 16));
sb.append(Character.forDigit((b & 15), 16));
}
return sb.toString();
}

}


Nyní jsem schopen přistupovat k porovnání hashe jak z PHP, tak z Javy. Sice je to taková maličkost, ale občas dost důležitá :)

echo sha1("heslo");

System.out.println(HashUtil.SHA1AsString("heslo"));

úterý 6. března 2007

OOP v PHP 5 - teorie dědičnosti a ORM

Když se vrátím na začátek, kde jsem tvrdil, že objekty jsou jakýsi obal nad procedurálním kódem, tak se musím zamyslet nad tím, jak umožnit, abych nemusel stále dokola zabalovat jednu a tu samou věc. Třídy bych měl vždy navrhovat tak, aby obsahovali jen to nejnutnější a nebyly zbytečně vázany na jiné třídy. Navíc třídy by něměli obsahovat pevnou vazbu na třídy, které jsou navrženy v jiných úrovních.

Příklad:
Do třídy pro zobrazení stromové struktury nebudu cpát třídu, která mi vrací data stromu. Raději ve třídě stromu napíši metodu, která bude umět přijmout data a zobrazit je. Na získání dat vytvořím jinou třídu.
Když budu později potřebovat zobrazit strom s jinými daty, prostě použiji již hotovou třídu stromu, která přijímá data.


Tím dokážu vytvořit znovupoužitelný kód. K tomu, abych mohl takto tvořit třídy, ale musím znát všechny možnosti objektů. Nyní se vratím k další možnosti objektů a tou je dědičnost.

Dědičnost je vlastnost, která mi umožňuje rozšířit třídu a pozměnit její chování. Nic víc, nic míň.

Na začátku jsem napsal, že třídy by měli být co nejořezanější, neměli by obsahovat věci, které by ji svázali natolik, že by obsahovala zbytečné a nevyužitelné vazby. Pokud ovšem v projektu potřebuji danou třídu rozšířít a to tak, že dané rozšíření budu využívat vícekrát, prostě napíši si novou vlastní třídu, která bude dědit vlastnosti z minulé třídy.

Příklad:
Mám třídu na zobrazování filtrace nad daty. Teď je ovšem problém, že v některých případech filtruji přes ty samé položky (př. název). Jednou možností je, pořád do objektu posílat objekt (komponentu) název. Jelikož už vím, co je dědičnost, mohu ji využít. Vytvořím novou třídu, která bude dědit třídu filtrace a navíc bude automaticky vkládat komponentu pro název.


Toto je jedna z možností jak dědičnost využít, přiznávám, že ne moc efektivní, jistě existují i jiné možnosti, ale jako příklad je to postačující.

Asi lepším příkladem je struktura dat v databázi. Dnes jsou nejrozšířenejší relační typy databází. Jistě jsou velmi efektivní, rychlé a snadné na práci, ale pro nás jsou dost nevyhovující, proto existuje ORM (objektově relační mapování), což není nic jiného, než, že tabulku v databázi převedeme na objekt.

CREATE TABLE zamestnanec (
cislo int NOT NULL,
jmeno varchar(100) NOT NULL,
prijmeni varchar(100) NOT NULL,
PRIMARY KEY(cislo)
);



class Zamestnanec {
private $cislo;
private $jmeno;
private $prijmeni;
/* + setry a getry ke vsem atributum */
}


Nyní vytvoříme tabulku "uzivatele". U uživatelů budeme potřebovat navíc heslo, počet přihlášení, poslední přihlášení. V databázi tedy vytvoříme tabulku "uzivatele", která bude mít primární klíč osobní číslo, které bude zároveň cizím klíčem s vazbou do tabulky zaměstnanců na osobní číslo.

Potom pro výpis uživatelů použijeme něco takového:
SELECT u.*, z.jmeno, z.prijmeni
FROM uzivatele u
INNER JOIN zamestnanci z ON u.cislo = z.cislo


To je v pořádku, databázi máme, ale jak to uděláme v našem projektu, kde máme objekty? Velice jednoduše, použijeme dědičnost.

class Uzivatel extends Zamestnanec {
private $heslo;
private $pocetPrihlaseni;
private $posledniPrihlaseni;
/* setry a getry */
}


Nyní jsem vlastně rozšířil zamestnance o další atributy aniž bych musel znovu psát jeho vlastnosti (např. v Jave na toto existují tzv. entity classes, u nich by bylo toto rozdělení více podobné struktuře DB, což v PHP zařídit jen tak nepůjde). Dědičnost se definuje tak, že mám jednoho předka, který obsahuje vlastnosti, které se mi budou hodit i ve třídě, která je dědí. Pokud by se mi stalo to, že budu dědit z třídy, která obsahuje vlastnosti, které nebudu nikdy potřebovat, je dědičnost navržena špatně.

Tento článek berte spíše s nadhledem, opravdu se domnívám, že dědičnost je tak záludná záležitost, že bych se na ni na začátku úplně vykašlal. V pozdějších článcích se k tomto tématu vrátím a ukážu, jak něco takového využít v praxi. Příklady, které jsem zde uvedl nejsou úplně nejtypičtější, ale jistě lepší, než ukázky typu: Matka => Dcera, které postrádají použitelnost v praxi.

Příště už o něčem jednoduchém, viditelnosti a klíčových slovech static, final, apod.

pondělí 12. února 2007

OOP v PHP 3 - interface

Interface (rozhranní) je jedna z věcí, která je často přeceňována nebo nedoceňována. Oč vlastně jde?

Představte si, že se dostanete do situace, kdy budete potřebovat určit, že objekt "umí" něco, co se od něj očekává, ale nejsme si jistí, zda to tak je :)

Uvedu příklad:
Mám objekty manželka, děti, papoušek, pes a tchýně. Všechny objekty mohu považovat za součást rodiny. Problém nastává ve chvíli, kdy bych potřeboval vědět, kdo z uvedených rodinných příslušníků umí vařit. Vaření si mohu představit jako metodu, která mi provede danný úkon a vytvoří (vrátí) objekt jídlo.

Toto je klasický příklad, kdy mohu použít (implementovat) interface. Nejdříve si vytvořím vlastní interface, které bude obsahovat metodu uvarJidlo().

interface UmiVarit
{
public function uvarJidlo(Jidlo $jidlo);
{
?>


Nyní mám rozhranní, které je potřeba implementovat na ty třídy, které budou moci vařit jídlo.

class Manzelka implements UmiVarit
{
public function uvarJidlo(Jidlo $jidlo)
{
return "manzelka uvarila: ". $jidlo->getNazev();
}
}?>


Takže nyní, když zavolám objekt (rodinného příslušníka), jsem schopen určit, který z nich vařit umí a který nikoli.

$rodina[] = new Manzelka();
$rodina[] = new Tchyne();
$rodina[] = new Pes();
foreach($rodina as $val) {
if($val instanceof UmiVarit) {
echo "umi varit: ". $val->uvarJidlo(new ChlebaVeVajicku());
}
}
?>


Interface můžete chápat jako svou vlastní kontrolu, kde si programátor označuje jednotlivé třídy podle toho, co mají umět. Myslím si, že úplnému pochopení, k čemu vlastně interface mohu využít a jak použít je otázkou praxe. Jak se říká: nic se nemá přehánět. A to platí i zde. Na druhou stranu, ignorace implementování rozhranní vede k chaosu a nižší funkčnosti.

Co se týče pravidel, jsou zde jasně danná specifika:

  • interface může obsahovat konstanty a veřejné metody

  • třída implementující interface musí obsahovat metody podle interface

  • třída může implementovat více rozhranní, které se oddělují čárkou (např. UmiVarit, PrepinaTelevizi)



Samotné PHP obsahuje několik předdefinovaných rozhranní, z nichž nejzajímavější je Iterator.

Tak by bylo k interface vše. Samozřejmě, dalo by se zde napsat spoustu dalších možností a využití, ale stačí, když si budu pamatovat, že Interface usnadňuje a označuje třídy tak, abych byl schopen použít jejich specifické vlastnosti.

Příště již ke zmíněným abstraktním třídám a dědičnosti, která je asi tím nejsložitějším tématem v OOP vůbec.

úterý 30. ledna 2007

OOP v PHP 2 - základy

Minule jsem ukázal základní vlastnosti OO kódu. Dnes se pustím do bližší specifikace, základů psaní OO kódu.

Na začátku je dobré brát v potaz, že OO kód by měl být samodokumentovatelný. To znamená, že kód je srozumitelný nejen pro počítač, ale také pro člověka. Pokud budu vycházet z tohoto základu, tak mi z toho vychází, že budu muset dodržovat základní principy při psaní OO kódu.

Začnu pěkne od začátku:

Třídy:

Název třídy se vždy uvádí velkým písmenem.
Název třídy je podstatné jméno, nikoli sloveso.
Pokud název třídy obsahuje více slov, používá se tzv. VelbloudiNotace.

Další důležitou roli hraje samotný název, který by neměl kolidovat s jiným názvem třídy. Ve skutečných OO jazycích je toto řešeno pomocí např. balíčků (packages) v Javě. Samotný balíček má i další vlastnosti, ale nám by stačilo, kdyby v PHP existoval alespoň v základní úrovni. Uvedu název balíčku, do kterého danná třída spadá a když budu potřebovat někde vytvořit objekt z této třídy, uvedu název třídy i s balíčkem. Název balíčku vlastně odpovídá adresářové struktuře, kde je má třída uložena (např. org.dostal.Zamestnanci by bylo v adresáři /org/dostal/Zamestnanci.class). Krásné, že?

Bohužel PHP nic takového nemá. Proto je třeba volit jiný postup. Budeme vycházet z toho, že třídy vkládáme do vlastní adresářové struktury a tuto strukturu odvodíme pomocí názvu třídy. Jako oddělovač jsem zvolil "_", což asi nejlépe odpovídá tomu, jak identifikovat strukturu, kde mám třídu uloženou.

Příklad:
Vytvořím adresar "Model", do něj vytvořím adresář "Table". Poté vytvořím soubor s názvem "Filtr.php". Nakonec do souboru vytvořím třídu "class Model_Table_Filtr {}". Díky tomu jsem schopný identifikovat, kde třída "Filtr" vlastně leží.

Další zásadou je, že jeden soubor = jedna třída. Nemá smysl o tomto polemizovat, je to způso, který se osvědčil nejenom v PHP.

Atributy tříd:

Atributy tříd by měly být vždy zapouzdřené, jinak řečeno, zvenku by k nim měl existovat pouze přístup přes setry a getry.
Atribut třídy začíná malým písmenem a pokračuje opět velbloudí notací.
Toto do začátku stačí.

Metody:

Název metody začíná vždy malým písmenem.
Opět se využívá velbloudí notace.
Název metody by mělo být sloveso (např. filtruj, zobraz, atd.), samozřejme to neplatí vždy.
Metody začínající na set... jsou setry, nastavující nějakou hodnotu.
Metody začínající na get... jsou getry, vracející nějakou hodnotu.
Metody začínající na add... přidávají k nějaké hodnotě, další hodnotu.
Metody načínající na is.. jsou kontrolní a vracejí Boolean (true, false) hodnotu.
Metoda toString() vrací informaci o třídě.
Existují další metody, tzv. magické metody začínající dvěma podržítkama, které proberu později.
Jsou i jiné specifika, které teď nemá cenu rozebírat, pro začátek toto stačí.

I když jsou tyto informace dost nudné, jsou velice důležité pro další vývoj v objektově orientovaném programování.

Existuje spoustu doporučení a spousty standardů, čeho se držet, ale já vycházím z javovské konvence, která mi osobně přijde nejlepší.

Nyní opět malá ukázka toho, jak by měl vypadat standardní OO kód.

class Auto
{
private $barva;
private $rychlost = 0;

public function __construct() {}

public function setBarva($barva)
{
$this->barva = $barva;
}

public function getBarva()
{
return $this->barva;
}

public function setRychlost($rychlost)
{
$this->rychlost = (int) $rychlost;
}

public function getRychlost()
{
return $this->rychlost;
}

public function isRychlost()
{
return (boolean) $this->rychlost;
}
}
?>


Příště už se pustím do samotného programování a proberu věci jako: typová kontrola, abstraktní třídy nebo interface.

pondělí 29. ledna 2007

OOP v PHP 1.

Spousta lidí tvrdí (stejně jako já), že psát objektově v PHP je šílenost a samotné PHP nemá tak dobrou podporu ani model k objektovému přístupu. Koncepce tohoto skriptovacího jazyka je postavena tak, abych byl schopen co nejrychleji nabastlit kód, který je schopen funkčního nasazení. Přesto je zde možnost psát objektově a od verze 5 dokonce i s vlastnostmi blížícími se objektově orientovaným jazykům typu Java či C++.

Předtím, než mohu začít psát objektově, musím mít elementární znalosti o tom, co jsou objekty, instance, jak funguje dědičnost, apod. Pokusím se zde popsat tyto znalosti tak, abych byl schopen na nich stavět.

Dost častá chyba je, když programátor pochopí OOP jako něco složitého či nereálného k použití. Ještě větší chybou je, když vývojář začne stavět projekt na objektech, aniž by měl dostatek znalostí k tomu, jak efektivně využít všech vlastností (toto byla i má chyba).

Takže o co vlastně jde? Na začátku můžete objekty chápat jako balíčky, které obsahují funkce a promenné, s kterými se dá pracovat v zájmu balíčku (objektu). Jinými slovy řečeno: "Objekty jsou obal nad procedurálním (obýčejným) kódem.".

OOP obsahuje spoustu nového názvosloví, které je potřeba znát, abych byl schopen rozluštit, o čem se dva objektoví programátoři mluví :)

// toto je trida
class Zamestnanec
{
// toto je atribut tridy
private $cislo;

// konstruktor tridy
public function __construct() {}

// metoda tridy
public function setCislo($cislo)
{
$this->cislo = $cislo;
}

// metoda tridy
public function getCislo()
{
return $this->cislo;
}

}
?>


Pokud má třída metody začínající set či get, tak je nazývame jako setry a getry. Tyto setry a getry nastavují a vracejí hodnoty, respektive pracují s atributem třídy, který by se měl vždy definovat jako "private".

Tímto jsem popsal základní názvosloví kolem třídy. V druhém kole popíši, jak třídu použiji.

$z = new Zamestnanec();
$z->setCislo(123);
echo $z->getCislo();


Takže, co je co? :) Promenná $z můžeme nazvat instancí objektu. Instance je jinak řečeno odkaz na objekt. Objekt je "new Zamestnanec()". Někdo by si zde mohl myslet, že objekt poznám tak, že obsahuje "new", ale není toúplně tak pravda. Např. objekt může být vytvářen jako jedináček (Singleton), který může být vytvořen pouze jednou. Takový objekt se vytváří interně a proto ho zvenku nevytvářím pomocí new (o tom, ale až později).

Dále je vidět, že pomocí instance (odkazu na objekt) volám metody set a get. Z vnějšku mohu volat pouze metody, které jsou public (veřejné). Důvody, proč je něco private, něco private a něco public, popíšu později.

To by bylo do začátku asi vše. Byli byste nyní schopni napsat třídu Auto obsahující atribut rychlost a metody na nastavení a vrácení rychlosti? Stejně tak i tuto třídu použít? ;)

středa 3. ledna 2007

Web development v Javě očima PHPčkáře

Rozhodl jsem se sepsat pár poznatků, které jsem při studiu Javy zatím získal. Jelikož z mého postoje je jasné, že PHP se pro mě stalo spíše zlem, hledal jsem jiný směr programování a oblíbil si právě zmiňovanou Javu. Důvody proč, jsem psal minule, dnes se spíše zaměřím na samotnou Javu a PHP nechám již pomalu odumírat :)

Vezmu to od začátku, jak se PHPčkář může postupně dostat k pochopení platformy jako je Java, aniž by trávil měsíce bádáním či vyhazoval tisíce za různá školení.

Prvním předpokladem k úspěšnému začátku je znalost OOP programování. Není zrovna snadná věc, přejít z procedurálního vývoje na objektový a přitom změnit jak logiku myšlení, tak pozměnit způsob programování. Zde osobně doporučuji podívat se právě na Javu či jiné čisté OOP jazyky jako C++ či C#. Jistě se Vám lépe bude učit na něčem, co je v oblasti OOP vývoje osvědčené. Všechny získané znalosti jdou víceméně použít i v PHP, takže se vývojář nemusí obávat, že bude muset ukončit vývoj v PHP.
Já osobně volil knížku od Rudolfa Pecinovského: myslíme objektově v jazyku Java 5.0. Musím přiznat, že jsem zejména pochytil dobré návyky při návrhu tříd a pochopil oč v oblasti OOP vůbec jde. Tyto znalosti jdou pak aplikovat ve větší míře i na PHP (samozřejmě, že např. polymorfismu si v PHP moc neužijeme :)).

Druhým krokem je praxe v OOP a tvorba tříd podle design patterns „návrhové vzory“, což jsou doporučení, které by měl programátor znát a pokud je to jen možné, držet se jich. Díky design patterns jsem mohl skutečně efektivně aplikovat OOP do praxe.

Tyto dva kroky mi zabrali 1 rok. Někomu se může zdát taková doba přehnaně dlouhá, avšak, pracující člověk, od kterého se očekávají výsledky, si nemůže dovolit jen tak trávit celé dny učením. Navíc ta praxe je zde dost důležitá a osobně si myslím, že během jednoho či dvou měsíců, by si dobré návyky v oblasti OOP vývoje, mohl osvojit jen génius.

Pak jsem přešel k něčemu složitějšímu a to byla knížka Java programujeme profesionálně od Bretta Spella. Kniha má přibližně 1000 stran a je to publikace určená vývojářům swingových aplikací. Samozřejmě, se swingem v Javě si hrál každý a tak i já jsem si hrál se základními komponenty jako jTable, jTree, apod. Samotné nasazení je pro mě však nemyslitelné, protože umět programovat front-end aplikace, ještě neznačí úspěch.

Přesměroval jsem se tedy zpět na web development. Zde je situace dost drsná, názvy frameworků, různá řešení, apod. jsou jen dobrým základem, jak si v této oblasti udělat v hlavě guláš :)

Po vyzkoušení různých tutoriálů na netbeans.org (vytvoření CRUD aplikace a základní tutoriály na JPA či JSF) jsem hledal něco obsáhlejšího. Naštěstí se na internetu dá nalézt spoustu knih ve formátu PDF, které stojí za to, si přečíst. Zde bych jen upozornil na skutečnost, že v češtině si toho moc nepřečtete.

Takže jsem začal s PDFkama...

Takže první věc, kterou je dobré vědět, je, že web development má několik částí. Nejsou to jen JSP stránky, ale také servlety či další objekty, které mají tu či onu vlastnost. Než začít psát čisté JSP-servlety, všude jsem se dočetl o doporučení, použít nějaký ten framework, používající MVC pattern. O tom, co je MVC jsem už něco věděl, ale co se týče výčtu frameworků (Struts, JSF, Seam, Spring, Struts 2, Tapestry, atd. atd.), nevěděl jsem po čem sáhnout.
Nakonec jsem si vybral JSF, opět na doporučení. Jedná se komponentově orientovaný framework a na rozdíl od Tapestry je vyvíjen přímo Sunem, což mu dodává určitou standardizaci.

JSF má vlastní tagy, pomocí kterých lze definovat JSP stránku. Tyto tagy mají spoustu vlastností a je možné libovolně vytvářet nové a nové. Hodnoty či atributy těchto tagů se definují backend beany. Jsou to třídy, které mají definované atributy třídy a k nim setry a getry. Kromě těchto základních atributů existuje ještě možnost definovat metody s parametry ActionEvent, které pracují na základě uživatelských akcí. Celá problematika je samozřejmě mnohem rozsáhlejší. Existuje zde vlastnost jako je navigation, která určuje navigaci stránek podle aktuálního stavu modelu, apod. celá tato problematika je krásně popsaná v knize JSF in Action, u které jsem vlastně nyní i já (cca. 150 stránka z 1076 :)).

Uvidíme, kam se moje znalosti dostanou, zatím kromě pár tutoriálů a vlastních zkoušek s JPA či JSF, jsem získal nadhled nad základním rozdělením webového vývoje v Javě.

Tímto článkem jsem chtěl jen ukázat to, že zkoušení nových věci by se neměl bát nikdo, kdo to s programováním myslí vážně. Tento obor je dost progresivní a tak se musíme chovat i my vývojáři. Spoustu lidí dělá chyby, ale tou nejzásadnější je, zkoprnět a přestat se snažit získávat nové znalosti.

čtvrtek 21. prosince 2006

PHP vs JSP

Vím, že po internetu existuje spoustu srovnání programovacích jazyků. Já se ani nechci tak moc pouštět do srovnání jako osvětlit některé věci, které mi lezou v poslední době dost krkem.

Zejména se jedná o lži, které hlásají pubertální mladící, kteří si přečetli jeden článek, naprogramovali 100 řádků kódu a provádějí srovnání různých řešení mezi sebou. Často házejí špínu na věci, které neznají ani koncepčně, natož z pohledu vývojáře.

Když jsem začal s programováním, začal jsem na PHP, které se mi zdálo jako nejlepší volba. PHP bylo populární, rychle se rozvíjející jazyk, perspektivní, jednoduchý a dalo se najít spoustu tutoriálů po internetu.

Na začátku jsem byl vlastnostmi tohoto jazyka naprosto uchvácen a směle jsem prohlašoval, že je to geniální dílo :)

Dnes jsem již o mnoho skeptičtější a směle prohlašuji: PHP je bordel, který jsem se raději neměl učit. Důvodů, proč si něco takového myslím je několik a já proberu jen ty nejpalčivější:

  • každá nová verze je často nekompatibilní se starými skripty

  • dodnes neexistuje namespaces a to co jsem viděl v připravované verzi PHP6 mě nijak nenadchlo

  • OOP model je na příšerné urovni a programátor musí dodržovat spousty pravidel, aby se nenechal unést nesmyslnostmi jazyka

  • neexistuje schopný framework pro data (ORM, DAO)

  • php už od základu míchá aplikační a prezentační logiku dohromady

  • funkce v php nedokáží vracet výjimky, jen ty, které si sám napíši

  • znovupoužitelnost vlastních tříd je dost problematické, už z důvodu konceptu celého PHP



Mohl bych takto pokračovat dál a dál, ale to není záměrem mého příspěvku. Spíše než to, chci říci, že PHP nemá cenu tlačit někam, kam nepatří. A nyní bych ho už netlačil asi ani na web.

Našel jsem na: www.jakpsatweb.cz diskuzi o jsp-servletech. Názory o tom, že Java je framework nebo, že jsp je lepší šablonovač mě vážně pobavili. Nejsem žádný expert na jsp-servlety, spíše s nimi začínám, ale tohle už je moc :(

Srovnávat skripovací jazyk PHP s platformou jako je Java, je asi jako srovnávat cukroví s plechem na pečení (přece jen jsou vánoce :)).

Existují mýty o tom, že v JSP nelze napsat, to co v PHP. Je to omyl. Ba co více, je to neznalost konceptu JSP a PHP. JSP už od samého začátku (nepočítaje první verzi) vyzchází z patternu MVC (model-view-controller), který zaručuje oddělení aplikační od prezentační logiky. Navíc řešení webové aplikace v jave umožňuje více možností, jak danou aplikaci programovat (např. JSF).

Nebudu zde zabíhat do detailů, protože nejsem na Javu žádný znalec a primárně v ní "zatím" nevyvíjím, ale co vím jistě, je, že mi java umožňuje programovat nejen webové aplikace. Umožňuje mi použít JPA, umožňuje mi použít skutečně kvalitní IDE ve formě NetBeans či Eclipse. apod. apod.

Dalším mýtem bývá, že se Java nehodí na malé webové aplikace typu e-shop apod. Já v tomto stále nevidím problém. Ale vezmu to z druhé strany. Budu psát v PHP OOP kód. Budu se snažit využívat controllery a budu používat oddělení aplikační logiky od prezentační + použiji vlastní vrstvu na data ve formě jakéhosi paskvilu ORM s DAO. Než toto připravím, pokud nemám připravené vlastní skripty, zabere mi to spoustu času. PHP mi samozřejmě umožňuje danou aplikaci napsat procedurálním způsobem, který bude mixovat všechny vrstvy do sebe. Super, mám vše během chvilky, ale přestanu zvedat telefony ve chvíli, kdy po mě zákazník bude chtít další úpravy a další vylepšení. Raději tedy vše udělám podle MVC a budu dodržovat základní patterny, abych se vyhnul námaze při dalších úpravách. V podstatě to samé mohu udělat pomocí JSP-servletů aniž bych musel pracně dodělávat či mapovat "pofidérní" frameworky na dané vrstvy aplikace. Jak dlouho mi daná aplikace bude trvat v JSP, pokud použiji stávající frameworky, které jsou pro to přímo určené? Jak dlouho mi bude trvat sestavit aplikaci z vlastních tříd, které jsem použil minule?

Jediný důvod, proč se JSP nehodí na malé webové aplikace je ten, že neexistuje tak masivní podpora hostingů jako u PHP. To je nejzásadnější důvod, proč vlastně je JSP hozené pod PHP v oblasti vývoje web. aplikací po internetu. Lidé, kteří tvrdí, že se něco na něco nehodí by měli předem znát daný jazyk, aby mohli toto tvrdit. Já tyto výkřiky slyším pouze od lidí, kteří neumí OOP či neumí JSP.

Ukončím to malým srovnáním: kolik znáte programátorů, kteří přešli z OOP zpět na procedurální programování? Kolik znáte lidí, kteří přešli z Javy na PHP?

Nakonec jen malá ukázka pro PHPčkáře. Za jak dlouho byste byli schopni udělat toto, co Roman Štrobl v NetBeans?

pondělí 11. prosince 2006

HTML Framework 3 - Textarea

Posledním formulářovým políčkem, kterým se chci zabývat je textarea.

Využití tohoto prvku je dobré při uložení delšího textového řetězce s omezenou či neomezenou délkou. Existují i tzv. textarea wysiwyg editory, což je upravená textarea pomocí javascriptu, umožňující psát HTML kód pomocí vizuálních prvků. Je to dost specifická oblast, kterou se ale zabývat nechci. Spíše mi šlo o to, vytvořit si vlastní textareu, která bude míti možnost kontrolu maximálního počtu znaků na klientovi.

Stejně jako v předchozích případech, jsem si vytvořil v adresáří /lib/HTML/Form soubor Textarea.php a soubor Textarea.js. Již podle názvu je jasné, co dané soubory budou obsahovat.

Nebudu zde uvádět ukázku třídy HTML_Form_Textarea, ale nabídnu je rovnou ke stažení: HTML_Form_Textarea (php, js)

Samotné použití je opět velice jednoduché:

$textarea = new HTML_Form_Textarea("textove_pole", $_POST["textove_pole"]);
echo $textarea->getTextArea();


Pokud bych nechtěl použít js kód, nebo změnit jinou vlastnost, není to samozřejmě problém:

// zmeni maximalni pocet znaku
$textarea->setMaxPocetZnaku(500);
echo $textarea->getTextArea();

// vypne js omezeni
$textarea->setPosuvnik(false);


Šťouralové by samozřejmě namítli, že chybí ošetření vloženého textu. Například pomocí htmlspecialchars. Já jsem toto omezení zde vynechal. Záleží totž na tom, jak textareu chci využít, zda povolím některé HTML tagy, či nikoli. A toto by měla míti na starost vlastní definice v Model vrstvě (MVC).

Nyní oblast formulářových prvků opustím a budu se více zabývat tabulkami a způsobu, jakým jsem definoval jejich použití, společně s dalšími vlastnostmi, jako je export do XLS souborů, apod.

čtvrtek 7. prosince 2006

HTML Framework 2 - Input

Dalším formulářovým políčkem, které chci probírat je input. Možností, jak jej využít je mnoho, stačí se podívat třeba sem.

Opakovaného psaní, stejně definovaného políčka, se opět vyhneme pomocí definování vlastní třídy na tento formulářový prvek. Složitější oproti select-option je zejména v tom, že má mnohem více možností (text, submit, password, checkbox, ...).

V adresáři /lib/HTML/Form jsem si vytvořil soubor Input.php, zde uvádím jeho část:
class HTML_Form_Input
{

/***************************** ATRIBUTY TRIDY *****************************/

/** typ inputu podle ktereho se odviji jeho vlastnosti */
private $type;

/** nazev inputu */
private $name;

/** hodnota inputu value u checkox moznost checked */
private $request;

/** velikost inputu */
private $size;

/** maximalni pocet znaku inputu */
private $maxlength;

/** policko bude sede, nepujde menit */
private $disabled;

/** obsah pole nepujde menit */
private $readOnly;

/** zarovnani jako u obrazku */
private $align;

/** nastaveni class z CSS */
private $classCss;

/** stylovani tlacitka pomoci CSS */
private $style;

/** JS kod inputu */
private $javaScript;

/****************************** METODY TRIDY ******************************/

/**
* konstruktor tridy pro vytvoreni inputu
*
* @param String $name nazev inputu
* @param String $request vkladana hodnota value nebo checked
* @param int $size nepovinny parametr velikost policka
* @param int $maxlength nepovinny parametr maximalni pocet znaku
*
*/
public function __construct($name, $request, $size = null, $maxlength = null)
{
$this->name = $name;
$this->request = $request;
$this->size = $size;
$this->maxlength = $maxlength;

$this->type = "text";

$this->disabled = false;
$this->readOnly = false;

}
}


Kompletní třída ke stažení: HTML_Form_Input

Použití je velmi snadné a opět elegantnější, než psaní HTML kódu:

$test = new HTML_Form_Input("test", $_POST["test"]);
$test->getInput(); // vypise HTML kod input, defaltne typ text


Předefinovat na jiný typ je opět otázka chviličky:

$test->setTypeInput("checkbox"); // tlacitko bude checkox
$test->getInput();

$test->setTypeInput("password"); // tlacitko bude password
$test->getInput();


Možností je opravdu hodně a nemá cenu je zde všechny vypisovat. Opět je otázka, co všechno vývojář potřebuje. Nespornou výhodou, definování těchto malých oblastí, je i fakt, že jsou kdykoli rozšířitelné o vlastnosti, které jsem opomněl definovat při prvním návrhu.

Přístě se podívám na poslední, zajímavý formulářový prvek: textarea a na jeho omezení počtu znaků pomocí javascriptu.

úterý 21. listopadu 2006

HTML Framework 1 - Select-option

Při programování v PHP se dostanete do fáze, kdy Vás přestane bavit znovu a znovu psát HTML kód pro formulářová políčka. Jedním ze způsobů jak si začít tvořit svou vlastní knihovnu takovýchto HTML komponent, je přejít na OOP kód a v závislosti na zkušennostech si předdefinovat to, co se často opakuje. Tím začnete tvořit svůj malý framework pro HTML výstup vašich webových aplikací.

Je jasné, že existuje spoustu hotových řešení, ale já jsem šel cestou (pro PHPčkáře osobitou) vlastní. Mou snahou je, se odprostit od psaní jakéhokoli HTML kódu při programování základních komponent. Při OOP návrhu tříd je dobré rozvrhnout, které třídy budou znovupoužitelné v jakékoli aplikaci a které nikoli. Jelikož se nyní bavím o HTML výstupu, který je pro PHP jako vzduch pro člověka, je jasné, že se jedná o třídy s vysokou znovupoužitelností.

Vytvořím si adresář /lib ve kterém budu mít třídy, které jsou znovupoužitelné v jakékoli webové aplikaci. Jelikož se jedná o HTML kód a formulářové políčko tak adresářovou strukturu definuji takto: /lib/HTML/Form/

První komponentou bude select-option.

Zkrácená ukázka vlastní třídy v souboru SelectOption.php:

/**
* trida vracejici html select-option
*
* @author Dostal Ales
* @version 1.0
* @date 21.11.2006
* @category lib
* @package HTML
* @subpackage Form
*
*/
class HTML_Form_SelectOption
{

/***************************** ATRIBUTY TRIDY *****************************/

// atribut tridy pro nazev selectu
private $nazev;

// atribut tridy pro data, ktera jsou poslana v poli
private $data;

// atribut tridy pro vybrany radek
private $request;

// atribut tridy pro vytvoreni prazdneho radku v optionu
private $firstNullOption;

// vklada do tagu
*/
public function getSelect()
{
$select = "\n";
return $select;
}


Kompletní třída ke stažení: HTML_Form_SelectOption

Budu nadále předpokládat, že máte vyřešený problém s automatickým nahráváním daných tříd přes __autoload().

Nyní již přichází na řadu malá ukázka, jakým způsobem lze komponentu využívat:

$data = array();
$data = array("ales" => "Aleš", "tomas" => "Tomáš");
$select = new HTML_Form_SelectOption("jmeno", $data, $_GET["jmeno"]);
echo $select->getSelect();


Pokud budu chtít například definovat prázdnou nulovou položku, stačí pred zavoláním o HTML kód přídat:

$select->setFirstNullOption("- jméno -");


Možností je samozřejmě více. Od definování javascriptového kodu do tagu select až po změnu dat, při použití jedné instance. Pokud by daná třída nevyhovovala, není samozřejmě problém přidat jakoukoli novou vlastnost (např. přidání k tagu css třídu, style, apod.).

Definování vlastních HTML komponent programátorovi natolik usnadní práci, že k opakovanému psaní HTML se snad již nikdy nevrátí.

Přístě se podívám na trošku složitější HTML tag: input.

čtvrtek 9. listopadu 2006

PHP 5.2

Tak nám vyšla nová verze PHP 5.2, která by měla vylepšit rychlost přímo v ZEND Engine.

Koukal jsem se na změny a je pravda, že pár věcí se zde pohlo k lepšímu. Otázkou však zůstává, zda se z toho paskvilu a neuspořádaného vývoje, v kterém se PHP ocitá dokáže ještě vymanit.

Microsoft sám začal mít o PHP zájem alespoň v podpoře .NET, ale jeden nikdy neví, kam to může zajít (InnoDB v MySQL vs. Oracle).
Jsou zde opravené některé věci, jako např. v abstraktní třídě nemůže existovat statická metoda, magická metoda __toString() nemůže vyhazovat výjimku apod.

Ale co mě stále štve na PHP je ta ignorace type hinting, s tím související přetěžování metod či konstruktorů, dále vyhazování výjimek z php funkcí namísto stupidního Boolean, nemožnost smysluplně vytvořit Singleton, apod.

Pokud se podívám na způsob práce s databází, je často zdůrazněna dobrá podpora MySQL, ale k čemu mi je taková vynikající podpora, když zde nemám pořádný nástroj na ORM, DAO, apod. (např. Hibernate v Jave). Je zde sice jakýsi Propel, ale... Jako standard to bráno není a asi ani nikdy nebude. (Ono MySQL by samo potřebovalo opravit pár věcí, kterými se honosí verze 5. Alespoň integrace nějakého smysluplného jazyka pro psaní stored procedure. V tomto nynějším stavu je to na cvokárnu.)
Jsem zvědavý jaké změny nám přinese PHP 6.0. Těším se zejména na věci jako definování návratových hodnot v metodách, přímou integraci s MySQL a s tím spojený jistý nárůst rychlosti.

Ale na druhou stranu zůstávám skeptický v tom, jestli se PHPko někdy pročistí a vzniknou frameworky, které budou standardem pro práci s danou vrstvou. Pokud ovšem PHP bude i nadále ignorovat type hinting, čistý oop model, zastaralé metody, způsob definování názvů metod, balíčkovací systém pro třídy, apod. tak nikdy nevzniknou frameworky, nikdy se nic nestane standardem a nikdy nebude ničím jiným než jazykem pro lamy :(

Když programátor založí a řídí firmu

Jako malý jsem chtěl být popelářem. Ani ne tak proto, že bych měl nějaký zvláštní vztah k odpadkům, ale hrozně se mi líbilo, jak...