Vyjadřovací schopnosti objektů pro API
Když chceme v objektu zpřístupnit předem neznámé x
, tak máme vedle tradičního způsobu (definice metody, která bude x
přijímat jako parametr) i řadu dalších možností:
<?php
$obj->x; // definicí metody __get() a příbuzných
$obj->x(); // definicí metody __call()
$obj["x"]; // implementací rozhraní ArrayAccess
$obj("x"); // od PHP 5.3 definicí metody __invoke()
?>
Např. v knihovně SOAP je jistě mnohem pohodlnější volat $soap->search($query)
než $soap->__soapCall("search", array($query))
. SimpleXML toho také obratně využívá a $xml->tag
používá pro přístup k vnořeným značkám, $tag["attr"]
pro přístup k atributům a $tag[0]
pro přístup k jednotlivé značce.
Přemýšleli jste ale někdy o tom, proč to není naopak, proč se nepoužívá $xml["tag"]
a $tag->attr
? Co je přirozenější, nemůže se to plést?
A jak u jiných knihoven? Je lepší $table["column"]
nebo $table->column
nebo by mělo fungovat oboje? A co odkazy na jiné tabulky – je lepší $article["author"]->name
nebo $article->author["name"]
? Nebo snad $article->author->name
? Jak pak ale poznáme, jestli je $article->author
odkaz na cizí záznam nebo samotné ID?
A co závislé záznamy? Bude lepší používat $article->comments()
nebo si vystačíme s $article->comments
a teprve podle pokusu o iteraci poznáme, že má jít o dotaz do jiné tabulky a ne o získání sloupce ze stejné tabulky?
Diskuse
K poslednímu odstavci - určitě nad tím dumáš kvůli Finoqu, který jsi předváděl na PS :) Metoda comments() je nesmysl, nic to nevyjadřuje, je to podstatné jméno v množném čísle. Přístup k property comments je mnohem hezčí. A neměla by za tím být nějaká magie, mělo by to vždy vracet to samé. Pokud má programátor v tabulce sloupec comments a zároveň přes cizí klíče spojenou tabulku comments, tak by si zasloužil nakopat :) (= vyhodit InvalidStateException :o))
26.3.2010 19:17:45
Proč by ve sloupci comments nemohl být dopočítaný počet komentářů článku a v tabulce comments potom samotné komentáře?
Nepoužívání sloves pro metody je podle mě hlavní důvod, proč se neujalo jQuery... Vždyť si vemte, co je to za nesmysl - $('a').attr('href').
26.3.2010 21:28:57
jája:
tak ono se jQuery neujalo?
btw. myslela jsem, že tento příspěvek bude obsahovat nějakou dobře míněnou radu...
27.3.2010 01:02:31
Honza Marek:
U toho jQuery se na to dá rychle zvyknout. Bez parametru je to getter, s parametrem setter. Výhodou je, že je pak kód o hodně kratší. No a říct, že se jQuery neujalo, to bych si fakt nedovolil :-D
27.3.2010 09:22:51
LuKo:
Nechci mluvit za Jakuba, ale trpím silným pocitem, že ten Jakubův příspěvek je ironie, čímž by se mnohé vysvětlovalo ;-)
27.3.2010 12:00:01
"Nebo snad $article->author->name? Jak pak ale poznáme, jestli je $article->author odkaz na cizí záznam nebo samotné ID?" označovat idčka jako something_id ;) Pak se tohle nemusí řešit a vypadá to nejlíp ;)
26.3.2010 23:23:03
Jenže taková knihovna musí být obecná a musí počítat s tím, že ve sloupci comment bude odkaz do tabulky comment a že vedle tabulky comments bude existovat i stejnojmenný sloupec.
28.3.2010 23:54:40
pekelník:
$article->comments() - tohle by mohla být tabulka
$article->comments - tohle by měl být určitě sloupeček
$article['comments'] - tohle by taky mohla být tabulka
Mně se více líbí možnost 1)
27.3.2010 12:23:46
Mě to takhle taky přijde přirozenější, jedna implementace to tak už dokonce má, ale není divné, že SimpleXML to má v hodně podobné situaci naopak ($xml->tag a $tag["attr"])?
29.3.2010 00:01:49
Co má být to __soapCall?
28.3.2010 10:41:44
Díky, ale stejně furt nechápu, proč nemohli znovupoužít __call.
28.3.2010 17:46:07
__soapCall přijímá víc parametrů, které by __call v budoucnu mohlo používat pro něco jiného. Podle mě je správně, že to je jiná metoda. Ale __call mimochodem existuje taky.
28.3.2010 23:59:07
Pak mi ale nedávají smysl ta dvě podtržítka v soapCall.
29.3.2010 15:55:20
Ta jsou tam právě kvůli schopnosti volat metody přímo. Takže normální metody se volají jejich jménem a PHP metody začínají dvěma podtržítky. Když by se metoda jmenovala soapCall, tak by její název mohl kolidovat se vzdálenou metodou. Takhle může teoreticky kolidovat taky, ale předpokládá se, že vzdálené metody dvěma podtržítky začínat nebudou.
29.3.2010 16:14:37
Aha, to pak jo. No, je to takové zvláštní, ale aspoň to už chápu. Díky.
29.3.2010 17:17:39
juzna:
ja pouzivam nazvy sloupcu camelCase s malym pocatecnim pismenem, pak:
$clanek->autor - idcko autora = sloupec z DB
$clanek->Autor - zde uz je objekt
$clanek->Autor->jmeno, $clanek->Autor->firma
muzu to pak retezit:
$clanek->Autor->Firma->Adresa->ulice
Trosku horsi je to u zkratek (IP, MAC, DNS), ze sloupce v DB holt musim mit ip, mac, dns...
29.3.2010 12:08:36
Zajímavé. Ale určení chování podle závislosti na velikosti písmen je podle mě ještě horší než podle [] VS ->.
Navíc první velké písmeno používám výhradně pro názvy tříd.
29.3.2010 12:15:32
juzna:
Prvni velke pismeno pouzivam pro nazvy trid a tabuky v databazi. Mala pismena pro promenne a sloupecky v DB. Pak to vetsinou pasuje.
$clanek->autor - promenna, sloupec, tedy bude to ID
$clanek->Autor - tabulka Autor, trida Autor, pak je to tedy instance tridy Autor ktera reprezentuje zaznam z tabulky Autor.
Take se mi to nezda jako _spravne_ reseni, ale lepsi jsem nenasel. Hodne me zajima vysledek teto diskuze!
29.3.2010 13:01:32
juzna:
libi se mi, jak to ma udelane javascript:
obj->x je ekvivalentni obj['x']
Kdyz predem vim strukturu, muzu psat:
clanek->Autor->jmeno
kdyz mam nejake specialni atributy (co obsahuji treba pomlcku):
clanek['special-id']
a kdyz pristupuji dynamicky tak:
clanek[varName]
Nevim, zda je neco podobneho mozne i v PHP
29.3.2010 12:14:00
V PHP je to možné triviálně, navíc se dá psát i $obj->$var. Mě se tohle taky líbí, na druhou stranu třeba v tom SimpleXML to dělá dvě různé věci a dává mi to smysl.
29.3.2010 12:18:02
cucací potřeby:
Existuje na tyto konvence pojmenovávání nějaká ""norma"", best practice nebo doporučený postup?
21.4.2010 02:53:57