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?

Jakub Vrána, Výuka, 26.3.2010, on-line

Diskuse

ikona Ondřej Mirtes:

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

ikona Jakub Vrána:

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

Tomáš Fejfar:

"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

ikona Jakub Vrána:

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

ikona Jakub Vrána:

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

ikona v6ak:

Co má být to __soapCall?
28.3.2010 10:41:44

ikona Petr Suchý:

http://www.php.net/manual/en/soapclient.soapcall.php
28.3.2010 17:32:10

ikona v6ak:

Díky, ale stejně furt nechápu, proč nemohli znovupoužít __call.
28.3.2010 17:46:07

ikona Jakub Vrána:

__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

ikona v6ak:

Pak mi ale nedávají smysl ta dvě podtržítka v soapCall.
29.3.2010 15:55:20

ikona Jakub Vrána:

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

ikona v6ak:

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

ikona Jakub Vrána:

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

ikona Jakub Vrána:

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
avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.