StatementInterface-rajapinta on sama kuin PDOStatementin.
Seuraava määrittely on suora lainaus PDOStatementin dokumentaatiosta:
PDOStatement::fetchObject mixed PDOStatement::fetchObject([ string $class_name = "stdClass" [, array $ctor_args ]])
Minkä takia seuraavat kolme oman StatementInterface-rajapinnan määrittelyä ei ole yhteensopivia PDOStatementin vastaavan kanssa...
StatementInterface::fetchObject public function fetchObject($class_name = "stdClass", array $ctor_args);
Fatal error: Declaration of PDOStatement::fetchObject() must be compatible with StatementInterface::fetchObject($class_name = 'stdClass', array $ctor_args)
StatementInterface::fetchObject public function fetchObject($class_name = "stdClass", array $ctor_args = array());
Fatal error: Declaration of PDOStatement::fetchObject() must be compatible with StatementInterface::fetchObject($class_name = 'stdClass', array $ctor_args = Array)
StatementInterface::fetchObject public function fetchObject($class_name = "stdClass", array $ctor_args = null);
Fatal error: Declaration of PDOStatement::fetchObject() must be compatible with StatementInterface::fetchObject($class_name = 'stdClass', array $ctor_args = NULL)
Kun taas kaikki seuraavat kolme ovat yhteensopivia.
StatementInterface::fetchObject public function fetchObject($class_name = "stdClass", $ctor_args); public function fetchObject($class_name = "stdClass", $ctor_args = array()); public function fetchObject($class_name = "stdClass", $ctor_args = null);
Ts. kun $ctor_args:n tyyppi array pudotetaan määrittelystä pois niin funktiosta tulee yhteensopiva vaikka PDOStatementin dokumentaatiossa parametrin tyyppi on määritelty arrayksi.
PDOStatementin funktion määrittelyssä ei arvatenkaan ole käytetty type hintiä oikeasti, se on vain dokumentaatiossa havainnollistavana tekijänä. (Vaikkakin usein PHP:n dokumentaatioissa tyyppivihjeet ovat väärin, jolloin ne eivät havainnollista yhtään mitään.)
Huomannet varmaan, että dokumentaatiossa jokaiselle parametrille on mainittu tyyppi, vaikkei skalaareiden tyyppiä koodissa voi funktioiden määrittelyssä pakottaakaan.
Toki huomaan, mutta kun parametrin kerran voi pakottaa kuitenkin arrayksi niin ihmetyttää miksei sitä sitten ole tuossa tehty. No samapa tuo, tietää sitten ens kerralla :D
Esimerkiksi siitä syystä, ettei suurimmalla osalla koodareista ole mitään käsitystä siitä, mitä he yrittävät tehdä. Tavallisesti arrayta odottava funktio heittää warning-tason virheen, jos sille syöttää jotain muuta, mutta type hintin rikkomisesta seuraa fatal error. Tämä on siis aika merkittävä muutos toiminnallisuudessa.
No mutta funktio tuskin tekee mitään järkevää, jos odottaa parametrinaan taulukkoa, mutta saakin esimerkiksi olion. Lopputulema on "fatal error" jokatapauksessa.
No mutta! Olio voi välillä käyttäytyä kuin taulukko tai vain osittain kuin taulukko. Olio ei kuitenkaan voi koskaan kelvata funktiolle, jos parametrin tyyppi on pakotettu arrayksi. Tämä tekeekin arrayn tyypittämisestä käytännössä täysin mahdotonta useissa tapauksissa.
Php:stä löytyvät rajapinnat ArrayAccess, Countable ja Iterator, jotka kaikki toteuttavat joitakin osia ns. taulukkorajapinnasta, ja joita hieman epämääräisesti osa muttei kaikki php:n taulukoita käsittelevistä funktioista tukevat. PDO-luokkien funktiot eivät niitä hyväksy.
ArrayAccess mahdollistaa olion datan käpistelyn käyttäen taulukkonotaatiota.
class MyMapObject implements ArrayAccess { ... } $data = new MyMapObject(); $data['foo'] = 'Bar';
Iterator sallii antaa olion foreach-silmukalle, joka osaa tällöin käydä sen rivi kerrallaan läpi.
class MyIterableObject implements Iterator { ... } $data = new MyIterableObject(); foreach ($data as $i => $row) { ... }
Countable ainoastaan mahdollistaa taulukko-olion koon laskemisen count()-funktiolla.
Näissä kaikissa on tosiaan se ongelma, että php:n funktiot ja kielirakenteet saattavat tukea tai olla tukematta näitä rajapintoja. Jotkin heittävät virhettä, että hyväksyvät vain taulukoita, toiset olettavat datan joko taulukoksi tai tavalliseksi olioksi ja tekevät mitä ikinä tekisivät taulukolle tai tavalliselle oliolle.
Esimerkiksi empty($data) palauttaa olion kohdalla aina FALSE välittämättä sen toteuttamista rajapinnoista tai sisältämästä datasta.
Array_key_exists() näköjään hyväksyy myös olion mutta tarkistaa vain, onko oliolla nimetty jäsenmuuttuja, joka on käsiteltävissä suoraan muuttujana. Oudosti se ei edes triggeröi taikametodia __isset(). In_array() ei hyväksy oliota lainkaan vaan heittää virheen.
On myös melko yleistä, että PHP:n funktiot tarkistavat syötteen tyypin ja jättävät (varoituksen annettuaan) vääränlaisen parametrin kokonaan huomiotta, kuin sitä ei olisi annettukaan, tai palauttavat jonkin hieman yllättävän tuloksen. PHP:n ideologiahan tuntuu olevan, että tärkeämpää on saada peelot koodaamaan kuin saada toimivaa koodia.
Kiitos Alchemist. En osannut ajatella ollenkaan noita olioiden taulukkorajapintoja. Jos dokumentaatiossa on array parametrina niin ei ihan välittömästi tule mieleen, että parametriksi saattaa kelvata myös olio tietyin ehdoin.
Funktioiden epäjohdonmukainen tuki näille rajapinnoille tekee kuitenkin niiden käytöstä lähinnä vältettävää ilmeisesti. Ihmeellisiä virityksiä kaikenkaikkiaan nämä taulukkorajapinnatkin.
Cartter kirjoitti:
Funktioiden epäjohdonmukainen tuki näille rajapinnoille tekee kuitenkin niiden käytöstä lähinnä vältettävää ilmeisesti. Ihmeellisiä virityksiä kaikenkaikkiaan nämä taulukkorajapinnatkin.
Näkökulmia on niin monenlaisia... Minä olen itse alkanut vältellä epäjohdonmukaisesti käyttäytyviä funktioita, jotta voisin tarvittaessa käyttää myös olioita taulukon tilalla.
Ei silti kannata yrittää tehdä jokaisesta funktiosta sellaista, että se toimisi niin tavallisella taulukolla kuin myös tarvittavan rajapinnan toteuttavalla oliolla.
Aihe on jo aika vanha, joten et voi enää vastata siihen.