Vyjadřovací schopnosti objektů pro API

Školení, která pořádám

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, diskuse: 22 (nové: 0)

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))

ikona Jakub Vrána OpenID:

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').

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...

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

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 ;-)

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 ;)

ikona Jakub Vrána OpenID:

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.

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)

ikona Jakub Vrána OpenID:

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"])?

ikona v6ak:

Co má být to __soapCall?

ikona Petr Suchý:

http://www.php.net/manual/en/soapclient.soapcall.php

ikona v6ak:

Díky, ale stejně furt nechápu, proč nemohli znovupoužít __call.

ikona Jakub Vrána OpenID:

__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.

ikona v6ak:

Pak mi ale nedávají smysl ta dvě podtržítka v soapCall.

ikona Jakub Vrána OpenID:

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.

ikona v6ak:

Aha, to pak jo. No, je to takové zvláštní, ale aspoň to už chápu. Díky.

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...

ikona Jakub Vrána OpenID:

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.

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!

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

ikona Jakub Vrána OpenID:

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.

cucací potřeby:

Existuje na tyto konvence pojmenovávání nějaká ""norma"", best practice nebo doporučený postup?

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 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.