ugrás a tartalomhoz

PHP típuskezelés

visuall · 2016. Dec. 17. (Szo), 14.10
Sziasztok!

Ugye behozták a szigorú típusosságot PHP7-be, megéri ezt használni?
Már úgy értem, hogy nem fogja a teljesítményt megfogni, vagy távol állni a PHP ideológiájától?
Példaként, mivel PHP ökológiájában ez újnak számít, lehetséges, hogy a későbbi implementáció megváltoztatása nem lesz visszafele kompatibilis - feltételezve, hogy jelenleg csupán !egy! darab típus megadása lehetséges?

(persze ezen kérdések a skalár típusokra értendők)

szerk.:
A PHP által nyújtott névterek hogyan hasznosíthatók a gyakorlatban? Megéri használni?
 
1

Szia!Kifejtenéd mit értesz

smokey · 2016. Dec. 18. (V), 01.23
Szia!

Kifejtenéd mit értesz ez alatt? Nem teljesen világos

jelenleg csupán !egy! darab típus megadása lehetséges


A namespacek használata jó. Sok előnye van, köztük szerintem a legnagyobb - legalább is nekem ezen a ponton a legértékesebb - az az autoload. Nagyban megkönnyíti az osztályok rendszerezése alapján történő automatikus fájlbetöltést. (Pl.: Ha a namespace struktúrád követi a könyvtárstruktúrát, akkor egy egyszerű konvenció alapján megoldhatod az összes PHP osztályod automatikus betöltését)

Előny még, hogy egy ugyanolyan nevű osztályt egy alkalmazáson belül többször is létrehozhatsz és használhatsz egy időben, ha azok külön namespaceben szerepelnek. (Pl.: lehet két Request nevű osztályod is, és használhatod is mindkettőt egy időben, ha külön névtérbe rakod)
2

A névterek ezen

visuall · 2016. Dec. 18. (V), 12.06
A névterek ezen felhasználását már ismerem, de mégse tartom megfelelő eszköznek a nyelv gyakorlati megvalósítása miatt. Ennek ellenére biztos, hogy hasznos eszköz lehet.

A másik:
Típusmegadással csupán egyetlen egy skalár, vektor-, vagy objektum-alapú típust adhatunk meg. Mi lenne, ha egy másik típust is meg tudnánk adni?

Eme problémára (így utólag) egyetlen elfogadható választ találtam: a PHP mostantól az objektumorientáltságra fog hajtani. Így elég egyetlen egy, megadott típusú objektumot visszaadni.

Mostmár csak annyi a kérdés, hogy miképpen fog a hibakezelés működni? Milyen módon érdemes megoldani? Kivétel dobásával? Saját "Notice" objektummal? A beépített Error objektummal?
3

Igazából én a PHP-t most is a

smokey · 2016. Dec. 18. (V), 13.54
Igazából én a PHP-t most is a lehető legobjektumorientáltabb módon használom (namespacek, type hint, abstrakció, design patternek, kivétel kezelés, stb).

A hibakezelés szerintem az 5-ös PHP-ben is már jól működik, és nincs szükség saját metodológiára. Természetesen egy jó error handler sose rossz, de ezt is már megoldották a keretrendszerek fejlesztői (pl. Symfony), így csak használni kell azokat.

Egy pillanatra visszalépnék még: tudnád szemléltetni néhány sor példakóddal, hogy mire gondolsz? Biztos nálam a hiba, de írtál néhány kerek mondatot, amiből minden szót értek, viszont nem teljesen értem, hogy mire szeretnél kilyukadni.
4

Igen!

janoszen · 2016. Dec. 18. (V), 14.25
Igen, megeri hasznalni. A PHP-s strict_types nem ugy viselkedik, mint a Hacklang // strict mode-ja, ugyanis nem kotelezo megadnod tipusokat. Vagyis ha van olyan kodod ami nem tipusos, akkor nem adsz meg tipisokat es kesz.
5

Igen, sokkal fejlettebb

Pepita · 2016. Dec. 18. (V), 17.31
Már úgy értem, hogy nem fogja a teljesítményt megfogni, vagy távol állni a PHP ideológiájától?


A teljesítmény sokkal jobb, már "gyárilag is" hamarabb "tesz" típust a változódra, mint az 5.x
Nem kötelező megadnod típust, de annyiból hasznos, mert memóriában csak úgy lehet; ha te előre deklarálod, PHP gyorsabban fordítja.
Részben azért sokkal gyorsabb a 7, mert nagyot fejlődött minden típus tárolása terén.

Az ideológia hála Istennek az értelmes programozás felé mozdult el, én nagyon remélem, hogy mondjuk 8.x től kezdve már kötelező is lesz a típus megadása.

Másik újdonság, hogy fv visszatérési érték is lehet előre megadott típusú, ami megint plusz teljesítmény javulás lehet (ha jól használod).

1 vs több típus: a többnek semennyi értelme sincs. Az az érzésem, hogy nem tudod, miért is van egy változónak típusa... Mindig is volt és lesz is, legfeljebb nem látod / láttad.

Nem "hozták be" a szigorú típusosság ot, mert nem kötelező megadnod.
Akkor lesz jó, ha kötelező lesz, mert végre kikerülhet az interpreter ből a rengeteg konverziós eljárás, na akkor sok sebességet kapunk még. :)
Most ez kb fele út, ha adsz típust mindenhol, akkor csak egy egy feltétel, hogy "már van neki", nem kell vizsgálni. De ez jelenleg minden változón és property n végig megy.

Lett pár kényelmi újítás is, pl lehet constant deklaráció expression is.

Arra érdemes figyelni, hogy változó kiértékelés szigorúan csak balról jobbra történik.
$this->$x[y]->valami () nem azt jelenti, mint 5.x alatt.
6

A több típus megadására

visuall · 2016. Dec. 18. (V), 17.53
A több típus megadására szolgáló kifejezést azért hiányoltam, mert a PHP eddigi függvényei hol booleant, hol stringet adtak vissza. De a mondanivalód 100%-osan helytálló!
A nyelvi kiértékelést a fent említett okok miatt nem is használom, egyrészt, mert kevésbé olvasható, másrészt, mert komplexebb kód esetén nincs is szükség hasonló kifejezésekre.
8

Tobb tipus

janoszen · 2016. Dec. 18. (V), 21.25
Azt erdemes megfontolni, hogy ha tobb tipust adsz vissza, akkor esetleg a program felepitesen kell valtoztatni.
11

+1

Pepita · 2016. Dec. 19. (H), 00.42
Ott a pont, hiba esetén lehet pl kivételt dobni, visszaadott érték simán lehet mindig ugyanaz a típus.
13

Kérdések

Hidvégi Gábor · 2016. Dec. 19. (H), 14.41
ha te előre deklarálod, PHP gyorsabban fordítja
És azzal mit nyersz, hogy gyorsabban fordítja? Hisz úgyis opcache-ből megy a kód, azaz a legelső futáskor némileg gyorsabb lehet.

Akkor lesz jó, ha kötelező lesz, mert végre kikerülhet az interpreter ből a rengeteg konverziós eljárás, na akkor sok sebességet kapunk még. :)
Biztos? Annyit nem spórolhatsz vele, hisz a típusokra való ügyelést neked, a programozónak kell megvalósítanod, ráadásul a konverziót is neked kell elvégezned. És nem vagyok benne biztos, hogy gyorsabb lesz, mint a PHP beépített függvénye. Elég csak arra gondolni, hogy az adatbázisokból a mezők értékeit minden illesztő karakterlánc típussal adja vissza.

Másrészt a kötelező típusok bevezetésével használhatatlanná válna a világ PHP-s kódbázisának 90%-a.

De nem is értem a felvetésed. Ha ennyire hiányoznak a típusok, miért nem programozol inkább mondjuk Go-ban? Hasonló szintaktika, gyorsabb futás, egy csomó érv szól mellette.
17

szőr szálak...

Pepita · 2016. Dec. 19. (H), 21.52
Eléggé gáz lenne, ha változók cache - ből lennének... :)

Más az, ha te tudod, hogy "10" - ed van és neked integer fog kelleni, mint ha a fordító deríti fel, hogy hol lesz felhasználva, ott mi kell majd és most mi.
nem ugyanaz konvertálni; és kideríteni, hogy kell-e és ha igen , akkor mit mire konvertálni és ezután végre hajtani a konverziót. Itt most megint hatalmas túlzásba estél Gábor, és semmi más nem indokolja ezt a hű de kényelmes típus nélküli világot, mint a gyengébb fejlesztők lustasága tanulni...
Egy szóval sem mondtam, hogy le kell majd fejleszteni magadnak, hogy (int) $valami; .

Adatbázis driver ek voltak vannak és lesznek. Ez is a te fixed mindset - ed, hogy mindig is string lesz. Gondolom itt csak a MySQL re gondoltál.

A PHP 7 is kb 90% arányban "kinyírta" az 5.x alatt működő site okat, de távolról sem mondanám, hogy kódbázis 90% - a lenne. Egy eléggé nagynak mondható rendszerrel már migráltunk 7 - re, nagy munka volt, de egyrészt megérte, másrészt a kód max 2% - a változott. Az igaz, hogy ebben az igazán nagy kihívás a "mindent megtalálni" volt - jócskán 1000 feletti class ról beszélek.

Mondjuk Go?
Fenti kódbázist mondjuk most elkezdjük (a full team) le fejleszteni Go ban (v bármi más nyelven), amiben most ugyanolyan tapasztalt mindenki, mint PHP ban (= bulshit), akkor talán jövő karácsonyra kezdhetik tesztelni a tesztelők. Még ha meg is finanszíroznád, akkor sem menne, mert egy évig maga a fejlődés nem állhat meg, az ügyfelek keresnének mást, stb.

A 90% ról még annyit, hogy aki lusta, nem fejlődik tovább, hát tőlem használjon PHP 3 - at akár, csak hát lassan erre saját szervert is kell üzemeltessen. :)

A PHP közösség jelentősen elindult valódi OOP irányba, ezzel együtt jár a típusosság is.
Akkor is, ha lázadsz ellene.
18

Mi ez?

Hidvégi Gábor · 2016. Dec. 19. (H), 22.38
A PHP belső memóriakezelését optimalizálták, de alapvetően nem változott meg. A type hint annyit csinál, hogy ha a kapott paraméter nem a kért típusú, akkor PHP5-ben Fatal errort dob, PHP7-ben pedig kivételt. Nem gyorsabb lesz tőle a kód, hanem lassabb, mivel futásidőben egy plusz ellenőrzést el kell végezni. A hibakeresést ez javíthatja, de a szükséges konverziókat ettől függetlenül el kell végezni.

Ez is a te fixed mindset - ed, hogy mindig is string lesz. Gondolom itt csak a MySQL re gondoltál.
Postgresql-lel dolgoztam már, az is karakterláncokat ad vissza, és az Mssql is. Mi mást adna vissza egy C driver? Az a programozó dolga, hogy az adott környezetben elvégezze a típuskonverziót.

A PHP 7 is kb 90% arányban "kinyírta" az 5.x alatt működő site okat, de távolról sem mondanám, hogy kódbázis 90% - a lenne
De végül csak 2%-ban kellett a kódot módosítanotok. Ha bevezetnék a kötelező type hintet, akkor minden külső modul, amit használtok, meghalna.

A mi kódunkat egyáltalán nem kellett a PHP7 miatt módosítani - megéri egyszerű eszközökkel dolgozni.

egy évig maga a fejlődés nem állhat meg, az ügyfelek keresnének mást
Aha, persze. Ott van minden adatuk nálatok, és azért, mert látszólag nem fejlődik semmi, majd találnak egy alternatívát, ami kompatibilis a ti egyedi fejlesztésetekkel, oda egy gombnyomással beimportálják az adatokat, és folytatják a munkát, ahol elkezdték? Ébredj fel, Csipkerózsika!

És ezzel most nem azt akarom mondani, hogy álljatok át Go-ra, hanem arra célzok, hogy mintha sokszor előbb lőnél és utána kérdeznél.

Szerintem a PHP egy nagyon jó nyelv, de megvannak a korlátai, csodákat nem lehet tőle várni. A Go egy jó alternatíva, és a sebesség/memóriakritikus részeknél megéri megéri elgondolkodni a váltáson, ha a rendszer független modulokból áll.
19

Nalunk sem

janoszen · 2016. Dec. 20. (K), 11.16
A mi kódunkat egyáltalán nem kellett a PHP7 miatt módosítani - megéri egyszerű eszközökkel dolgozni.


+1, nalunk egyetlen egy projekten kellett nagyon kis mertekben modositani es abban regi szemethalmaz kod volt. A tobbi, mar altalunk gyartott projekt (kozotte ~3-5 eves kodbazissal) siman megy PHP 7-en. Igaz, nagyon odafigyeltunk, hogy ne hasznaljunk egzotikus PHP funkcionalitast.

A PHP-t azert nem lehet hanyagolni, mert gyakorlatilag de facto szabvany ha az ugyfel hordozhato weboldalt akar. Esetleg meg Node JS-el lehet kiserletezni, arra van kello mennyisegu tarhely szolgaltato, de a Java, Go kulon erolkodest igenyel uzemeltetesileg.

De ez off topic erosen. :)
20

Felhő

Poetro · 2016. Dec. 20. (K), 11.22
Mondjuk felhő szolgáltatóknál a Java vagy Go sem igényel túlzott erőlködést.
22

Szolgaltatasok

janoszen · 2016. Dec. 20. (K), 13.37
Persze, ha van aki foglalkozzon vele. De azert egy nagysagrenddel tobb NodeJS cloud szolgatato van mint mondjuk go, es a NodeJSnel egy nagysagrenddel tobb PHP host van.
23

Szerver

Hidvégi Gábor · 2016. Dec. 20. (K), 17.22
Aki csóró, az tárhelyet bérel, ott bőven elég a beépített PHP. De ha megy a biznisz, akkor már belefér egy virtuális vagy egy igazi szerver, ott pedig már lehet Go-zni.

A node.js-sel pedig a tavalyi menedzsment fiaskó meg az API instabilitása miatt komoly cég nem foglalkozik.
34

Virtgep

janoszen · 2016. Dec. 21. (Sze), 07.14
Azt ne felejtsd el, hogy nem csak a virtgep arat kell megfizetni, hanem az uzemeltetest is, az pedig sokszorosa a gep aranak. Ha egy technologiara nincs menedzselt uzemeltetesi szolgaltatas (azaz olyan ahol nem Te apt-get installalsz) az sok projektnek nem jarhato ut.
21

gyakorlat

Pepita · 2016. Dec. 20. (K), 12.12
Bocs Gábor, de a gyakorlatban az látszik nálunk, hogy lényegesen gyorsabban fut le ugyanaz a kód. Átlagosan majdnem 2x olyan gyors.

Nálunk is a módosítás nagy része a balról jobbra szabály és az örökített class fv overwrite paraméterek azonossága miatt volt.
-》 Ez mondjuk egy szükséges kód minőségi javulás is, egyáltalán nem baj.

Külső modulok: ha nem fejlesztik eléggé, keresünk mást vagy fejlesztjük mi.
de többnyire fejlesztik, nincs mindenki a fejlődés ellen. :)
24

PHP 5-ről PHP 7-re váltva a

Hidvégi Gábor · 2016. Dec. 20. (K), 17.46
PHP 5-ről PHP 7-re váltva a mi kódunk is 30-50%-kal gyorsabb.

A type hinting pedig így működik, idézet a dokumentációból:
Type declarations allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated
Kiemelés tőlem. Tehát annyit csinál, hogy ha a függvény paraméterének van típusa, akkor leellenőrzi azt, és hibát generál, ha nem stimmel; ha nincs típusa, akkor nem történik semmi.

Ez mondjuk egy szükséges kód minőségi javulás is, egyáltalán nem baj.
Remélem, a főnököd nem látja ezt az üzenetváltást közöttünk. A következőt írtad korábban:
Egy eléggé nagynak mondható rendszerrel már migráltunk 7 - re, nagy munka volt, de egyrészt megérte, másrészt a kód max 2% - a változott.
Tehát korábban használtatok mindenféle egzotikus PHP funkcionalitást, ami miatt át kellett nézni az egész kódot, ami nagy munka volt még szerinted is, és a teljes kód 2%-át át kellett írni. Ezzel szemben Janoszenéknél és nálunk, ahol a lehető legalapabb dolgokat használjuk, nulla vagy minimális melóval megoldható volt a váltás.

Ez egy csomó újabb kérdést felvet, például, hogy tulajdonképpen mit nyertetek ezekkel az egzotikus funkciókkal? Mert azt látjuk, hogy mit vesztettetek. Hogy lehet, hogy ezek nélkül is készíthetőek működő szolgáltatások? Valóban fejlődés ezeknek a használata? Mi lesz, ha a 8.0-ban hasonlóan sok meló lesz az egzotikumok átírása?

Ha a főnökötök lennék, én bizony feltenném a gárdának ezeket a kérdéseket.
27

látja :)

Pepita · 2016. Dec. 20. (K), 19.58
Mivel ő maga is fejleszt, valószínűleg látja. :)
Ha nem, akkor alkalmas időben meg fogom mutatni neki.

Egzotikumok:
Ahol sok fejlesztő és "fejlesztő" (<- idéző jel!) meg fordul, ott sokminden kerülhet a kódba.
És a példámnál maradva 5.x alatt semmi gondot nem okozott, ha volt egy parent function valami ($x) és egy child fv valami ($x, $y) .

Annyi, hogy 7.x ezt már nem preferálja. Vagyis terel a valódi OOP felé.

Nyugodtan szidd a rendszerünket, egyelőre regionálisan a legjobbak vagyunk, és ezt a pozíciót meg is tartjuk, 8.x alatt is. :)

Így utólag vissza nézek és azt látom, hogy a 7-re állás is leginkább azért volt nagy munka, mert még nem volt sok tapasztalatunk a verzióban. (Hozzá teszem, hogy bár "utólag könnyű okosnak lenni", le vonva az 5.x -》7.x tanulságait, a 8.x - re váltásban mindenképp nagy szerepet akarok vállalni.)

Maga az átállás hozta a szükséges tapasztalatot.

Tanulság: megijedni nem kell, helyette alapos (kézi is!) tesztelés kell élesítés előtt.

Nem bántásnak szánom: hála Istennek nem te vagy a főnököm. :)
Ne értsd félre: jórészt hasznosnak tartom itt a kérdéseid / aggodalmad, tanulok is belőle / miatta, annyi az egész, hogy van amikor gyors és csak "valamennyire" működő megoldás kell, és van amikor szigorúan tartani kell az elveket, és javítani, ami eltér tőlük.
Szerencsére a főnököm ezeket nagyon jól látja.
31

Nem értelek

Hidvégi Gábor · 2016. Dec. 20. (K), 23.04
Nem szidom a rendszereteket, az meg, hogy regionálisan elsők vagytok, nem a kódnak köszönhető : )

A lényegi kérdések megválaszolását látványosan kerülöd.
25

Példa

Hidvégi Gábor · 2016. Dec. 20. (K), 17.54
function hehe(int $haha) {
  print $haha;
}

hehe(12); //12
hehe('123'); //123
hehe('a123'); //Fatal error: Uncaught TypeError: Argument 1 passed to hehe() must be of the type integer, string given

function hehe2(int $haha) {
  $haha = 'asd';
  print $haha;
}

hehe2(123); //asd

Hogy ettől nem fog gyorsabban futni a kódotok, az száz százalék.
26

gyakorlati példa

solkprog · 2016. Dec. 20. (K), 19.52
Ha valaki beírja kikényszeríti a típust akkor valószínűleg nem véletlen.. akkor korábban ezt írta helyette:

function sum($number1, $number2) {
	if (!is_numeric($number1) || !is_numeric($number2)) {
		throw new Exception('....');
	}

	return $number1 + $number2;
}
Ennél meg _szerintem_ szebb a function sum(int $number1, int $number2)
(és tippre még gyorsabb is)
28

Helyes tipp

Pepita · 2016. Dec. 20. (K), 20.03
Azért gyorsabb, mert VAN típusa a bemeneti paramétereknek.
Erre próbáltam rá világítani fentebb is.
32

Nem értelek

Hidvégi Gábor · 2016. Dec. 20. (K), 23.06
Pedig még idéztem is a dokumentációból, ahol világosan leírják, hogyan működik a type hinting.
<?php
function tipusos(int $a, int $b) {
  return $a + $b;
}

function tipus_nelkuli($a, $b) {
  return $a + $b;
}

  $ido1 = microtime(true);

  for ($i = 0; $i < 1000000; $i++) {
    $eredmeny = tipusos(rand(), rand());
  }

  $ido2 = microtime(true);

  for ($i = 0; $i < 1000000; $i++) {
    $eredmeny = tipus_nelkuli(rand(), rand());
  }

  $ido3 = microtime(true);

  print "típusos: " . ($ido2 - $ido1) . "<br>";
  print "típus nélküli: " . ($ido3 - $ido2) . "<br>";
?>
Eredmény:
típusos: 0.81011414527893
típus nélküli: 0.75525093078613

Intel Atom 1,3GHz, Windows, PHP 7.0.2
33

nézz eggyel fentebb :)

Pepita · 2016. Dec. 21. (Sze), 04.28
Solkprog példája sokkal életszerűbb.

Látom, hogy nem foglak meg győzni, ha gondolod, használj PHP -8.x - et is tőlem, nyilván a régi a jobb, utáljuk és félünk a változástól. :)

Csak zárójelben: a rand () fv futásideje önmagában eléggé random, te pedig 2x hívod, míg a tesztelt fvt 1x...

De ez végül is mindegy, úgyis találsz másik "jó" példát; engem már meggyőzött a saját (éles) tapasztalatom: azok a class ok (és fv ei ) is gyorsabban futnak, amikhez nem is nyúltunk.
Ehhez képest bocsi, de nem eléggé meggyőző az, hogy te egyedül mást állítasz.
Egy 20 soros példa áll szemben sacra jóval több, mint 200 ezer sorral...

De egy irányba fel keltetted a figyelmem: én is fogom tesztelni kizárólag az átadott paramétert is. (rand nélkül)
Lehet, hogy jelenleg csak akkor hasznos, ha a visszaadott érték is típusos. (Mondjuk igazi értelme akkor van.)
37

Mikro

janoszen · 2016. Dec. 21. (Sze), 07.54
Nekem csak egy kerdesem van: tenyleg erdemes ilyen mikrooptimalizalasokkal jatszani? En azt latom hogy sokszor a folyamat javitasaval sokka nagyobb sebessegnovekedest lehet elerni.
38

Nem

Hidvégi Gábor · 2016. Dec. 21. (Sze), 10.08
Itt nem a mikrooptimalizáláson volt a hangsúly, hanem azon, hogy Pepita állított valamit (a type hinting használata gyorsít a kódon), amiről egy pár soros kóddal be lehet bizonyítani, hogy nem úgy van.
39

Hibakezeles

solkprog · 2016. Dec. 21. (Sze), 13.51
Ketszer felhivtuk ra figyelmed hogy hibas a logikad. Osszehasonlitasz ket fn de az egyikbe irtal hibakezelest a masikba nem. Ha a regibe is irsz (pl is_numeric el) akkor az lassabb lesz. Es meg hosszabb is lesz a kod
40

Nem értem

Hidvégi Gábor · 2016. Dec. 21. (Sze), 14.35
Én egyik függvénybe sem írtam hibakezelést.
41

Type hint

janoszen · 2016. Dec. 21. (Sze), 14.47
De a type hint egyfajta hibakezeles. Kezeled azt a hibat, hogy ha valami olyan jon ami nem konvertalhato stringre, vagy ha strict typinggal dolgozol, olyan ami nem string.

Azert csinalunk type hintet, hogy hibat kezeljunk es aktivan dokumentaljuk, hogy mit varunk.

Ez a ket megvalositas funkcionalitasat tekintve ekvivalens:

function test(string $bla) {
  //...
}

/** 
 * @param string $bla
 */
function test($bla) {
  if (
    is_int($bla) ||
    is_float($bla) ||
    is_bool($bla) ||
    (is_object($bla) && method_exists($bla, '__toString'))
  ) {
    $bla = (string)$bla;
  } else if (!is_string($bla)) {
    throw new TypeError();
  }
  //...
}
Vagy strict typing eseten:

declare(strict_types=1);

function test(string $bla) {
  //...
}

/** 
 * @param string $bla
 */
function test($bla) {
  if (!is_string($bla)) {
    throw new TypeError();
  }
  //...
}
42

Hibakezelés

Hidvégi Gábor · 2016. Dec. 22. (Cs), 11.10
Tehát van egy függvényünk, ami a példa kedvéért egy karakterláncot vár paraméterként.

Két eset lehetséges:

1, A teljes kontroll a te kezedben van, azaz a kódot te írtad, ekkor nincs miért aggódni. Ilyenkor akár az egészet megírhatod strict_types=1-gyel.

2, Ha a programkódod egy rutinkönyvtár része, akkor kívülről fogják meghívni, azaz nem tudod biztosan, mit fogsz kapni.

Ez utóbbi eset az érdekes, és itt is van válaszlehetőséged. A függvénynek mindenképp karakterlánccal kell dolgoznia, ezt garantálni kell, s erre két lehetőség van:

a, A hívóra bízod a konverziót, a függvény paraméterében type hintet használsz. Ekkor a függvényed minden meghívása előtt le kell futnia az ellenőrző és konverziós kódnak, amit a fenti négy példa közül a másodikban láthatunk. Ebben az esetben használhatsz type hintinget.

b, A szükséges ellenőrzést és konverziót magában a függvényben végzed el. Ilyenkor nincs "szóismétlés", és a programod csak akkor fog hibát dobni, ha a bejövő paraméter biztosan nem felel meg a követelményeknek.

---

Szólj, ha valamit félreértek vagy nem gondoltam át teljesen.

A helyzetet bonyolíthatja, hogy a strict_types csak a felhasználói függvényekre vonatkozik, a PHP beépített funkcióira nem, azaz a típusellenőrzéseket és konverziókat nem biztos, hogy megúszod.

Innentől kezdve számomra kérdéses a type hinting értelme és haszna, hisz ha a példafüggvényed meghívása előtt mindenképp kell ellenőrzést és opcionális konverziót végezni, akkor a type hinting egyrészt fölösleges, másrészt biztosan lassítja a futást.
43

Az 1-es pont - nem kell

BlaZe · 2016. Dec. 22. (Cs), 12.25
Az 1-es pont - nem kell törődni a contractokkal, amíg a kódot csak a cégen belül használjuk - a gányolás és a súlyos maintainability issuek előszobája.

A 2-esnél a b-t mitől gondolod opciónak? Az ellenőrzés, konverzió csak zaj a kódban, és minden hívásnál a te kódodnak kell csinálja. Olvashatóbb biztos nem lesz a kódod, és erősen kétlem, hogy hatékonyabb, mintha a futtatókörnyezet funkcionalitását használnád. És nem utolsósorban a bármit lemappelünk az elvárt típusra... Mégis hogy? :) Mi van, ha egy összetett típus jön? Azt mindig a hívónak kell garantálja, hogy a megfelelő típusú és tartalmú paramétert adja át, hisz nála van meg az a kontextuális információ, hogy mit jelent a nála lévő adat, és hogyan van reprezentálva. Jöhet hívás nem megbízható forrásból, ekkor lehet érdemes boundary checkeket csinálni, ami futás idejű hibát kell okozzon, ha nem megfelelő a paraméter.
44

Az 1-es pont - nem kell

Hidvégi Gábor · 2016. Dec. 22. (Cs), 13.00
Az 1-es pont - nem kell törődni a contractokkal
Én semmi ilyet nem írtam, sőt, pont az ellenkezőjét. Cégen belül a megfelelő szabályok felállításával és betartásával biztosítani tudod a típusok megfelelését.

A másik esetben azt írtam le, hogy nem tudod megspórolni az esetleges típusellenőrzést és konverziót, például azért, mert a PHP beépített függvényei is mind gyengén típusosak, legalábbis a PHP wikiben ezt írják. Innentől kezdve valakinek el kell végeznie az ellenőrzéseket, és az már ízlés kérdése, hogy szétszórva a kódban (2/a) vagy egy helyen (2/b) valósítod meg.
45

Cégen belül a megfelelő

BlaZe · 2016. Dec. 22. (Cs), 13.12
Cégen belül a megfelelő szabályok felállításával és betartásával biztosítani tudod a típusok megfelelését.
Milyen jobb módszert használtok a nyelvi elemeknél?

A másik esetben azt írtam le, hogy nem tudod megspórolni az esetleges típusellenőrzést és konverziót, például azért, mert a PHP beépített függvényei is mind gyengén típusosak, legalábbis a PHP wikiben ezt írják. Innentől kezdve valakinek el kell végeznie az ellenőrzéseket, és az már ízlés kérdése, hogy szétszórva a kódban (2/a) vagy egy helyen (2/b) valósítod meg.
Én meg hoztam egy példát, hogy miért hibás megközelítés a 2/a. Ha minden hívás előtt konvertálnod kell, akkor meg más baj is van a designnal.
46

Fajlonkent

janoszen · 2016. Dec. 22. (Cs), 14.40
Szerintem az alapveto felreertes itt abbol adodik, hogy Te azt mondod, hogy nem kell felkeszulni nem vart bemenetre.

Tegyuk fel, hogy en egy intet varok, de pl. stringet kapok. Mi fog tortenni?

1. Ha a string elejen van egy szam, akkor a tobbit a PHP eldobja az elso intre castolasnal, a szamot megtartja. Ez valtozatos es erdekes bugokhoz vezethet, ha pl. a tizedespont helyett tizedesvesszo jott a stringben, akkor a '123,456'-bol 123. Egyertelmuen hibas a bemenet, egyertelmuen hibas mukodeshez fog vezetni, de a kod megis tovabb fut.

2. Ha a a string elejen nem szam van, az int 0-ra konvertalodik. Meg rosszabb.

Vagyis a problema abbol adodik, hogy a programod nem vart es hibas bemenetre is latszolag helyes kimenetet ad, ami adott esetben adatveszteshez vezet es akar csak evekkel kesobb derul ki.

Lassuk be, ez 100%-ban a PHP hulyesege, mert egy nem tiszta szamot tartalmazo stringre csendben elvegezni a tipuskonverziot boduletes baromsag. Egy normalisan megcsinalt duct typing nyelvvel ez nem lenne AKKORA problem, mert legalabb hibat kapnal.

Viszont: en eleg fegyelmezett fejlesztonek gondolom magam, de ennek ellenere elofordul, hogy nem figyelek oda es a tesztek ellenere sikerul atadnom egy olyan adatot amit nem akartam. Ilyen esetekben a Hacklang compile-time typecheckere a nyakamba vagja hogy hulye vagyok. Es minden egyes esetben igaza van, nem ugy akartam osszekotni azokat a reszeket ahogy gondoltam. Minden. Egyes. Esetben. Sokkal jobb, ha mar a compiler ram tud szolni hogy hulye vagyok mint amikor runtime, sok teszteles aran veszem eszre hogy nem azt adtam at amit akartam. Vagy nem tesztelem elegge es production kornyezetben derul ki.

Raadasul egy normalis szerkezetu programban minimalis mennyisegu tipuskonverzio van, tobbnyire ott ahol mas rendszerekkel erintkezik, ott pedig ugyis le kell ellenorizni hogy megis mi a fenet kapsz.
35

strict

janoszen · 2016. Dec. 21. (Sze), 07.17
PHP strict mode:

declare(strict_types=1);

function hehe(int $haha) {
  print $haha;
}

hehe(12); //12
hehe('123'); //Fatal error: Uncaught TypeError: Argument 1 passed to hehe() must be of the type integer, string given
hehe('a123'); //Fatal error: Uncaught TypeError: Argument 1 passed to hehe() must be of the type integer, string given

function hehe2(int $haha) {
  $haha = 'asd';
  print $haha;
}

hehe2(123); //asd
Hacklang type checker:

test.php:3:9,20: Invalid lvalue (Parsing[1002])
7

Megmutatom akkor, hogy mire

visuall · 2016. Dec. 18. (V), 18.13
Megmutatom akkor, hogy mire is gondoltam:

<?php

define("DATABASE_EXPRESSION_WHERE_AND", 1);
define("DATABASE_EXPRESSION_WHERE_OR", 2);

interface Database extends DatabaseInteractions {
	public function __construct(database_connector $args, OPResult $result_object);
	public function Connect(): OPResult;
}

interface DatabaseInteractions {
	public function Add(): self;
	public function Get(): self;
	public function Set(): self;
	public function Delete(): self;
	
	public function Col(string ...$columns): self;
	public function Value(...$values): self;
	
	public function Limit(int $limit): self;
	public function Offset(int $offset): self;
	
	public function queryExpression(): DatabaseSelector_child;
	
	public function Execute(): DatabaseResult;
}

interface Database_wTransaction extends Database {
	public function isItemInTransactionList(): bool;
	public function installQueryAsTransaction();//instead of $db->Execute();
	public function executeTransaction();
}

interface DatabaseSelector_tree {
	public function setCondition($setting, $value=NULL): bool;
	public function createBlock($type=DATABASE_EXPRESSION_WHERE_AND): DatabaseSelector_child;
}

interface DatabaseSelector_child extends DatabaseSelector_tree {
	public function assignValue(string $column, $value): OPResult;
	public function assignMaxValue(string $column, int $value): OPResult;
	public function assignMinValue(string $column, int $value): OPResult;
	public function assignMultipleValues(string $column, ...$values): OPResult;
}

interface DatabaseResult extends OPResult {
	public function fetchNextRow($associative=false): array;
	public function fetchPreviousRow($associative=false): array;
}

?>
Képzeljünk el, hogy ez lenne a felület az adatbázis kódja fölött. Többszöri próbálkozás alapján erre a struktúrára lyukadtam ki.
Tetszőleges hibakezelő rutinokat beépítve az OPResult lenne a programunk logolásáért felelős alrendszer felülete, amelynek felületét csupán a belső mechanizmusoknak kellene ismernie.
Ti milyen szempontok alapján építenétek fel egy ilyen rendszert? A fentebb vázolt megoldás megfelelne az elvárásoknak?
9

Alahuzas

janoszen · 2016. Dec. 18. (V), 21.28
Az alahuzasokat szerintem keruld az osztalyok neveben az alahuzast, erdekes felreertesekhez vezethet mert regen azt hasznaltak nevterek elvalasztasara.

A define-okat szinten kerulnem, helyette osztalyok konstansait hasznalnam.
10

Aláhúzás helyett

visuall · 2016. Dec. 18. (V), 22.06
Az aláhúzás helyett milyen nevezéktant ajánlasz? Egyszerűen írjam egybe?
12

Pl camelCase

Pepita · 2016. Dec. 19. (H), 00.47
De talán szebb, ha az első betű is nagy: ClassName.
14

Meg egy dolog

janoszen · 2016. Dec. 19. (H), 14.52
Meg egy dolog, de ez inkabb az architekturahoz kapcsolodik. Azt tapasztalom, hogy eleg sok mindenki erolkodik a query builderekkel, de valahogy mindegyik latvanyosan rossz. Ezzel szemben SQL-re van normalis IDE tamogatas es lehet hogy egyszerubb szerkezettel is elered ugyanezt.

Irtam erre egy kiserletet, lehet hogy erdemes belole inspiraciot meriteni.
29

"mindegyik latvanyosan rossz. "

Pepita · 2016. Dec. 20. (K), 20.09
Nagy igazság, de vajon miért?

_szerintem_ azért, mert sokan esnek abba a hibába, hogy "ha már query builder, akkor tudjon már ... is" ...

Vagyis túlságosan el ragaszkodik az adott feladat scope jától.
(Mert hirtelen fel akarja találni a kereket.)
36

Mert folosleges

janoszen · 2016. Dec. 21. (Sze), 07.20
Talan azert, mert az SQL nyelvet probalja mappelni valami OOP-s mintara (ami folosleges, koszi szepen, tudunk SQL-t irni) es utana nekiall feature-okkel teletomkodni hogy legyen letjogosultsaga, ezaltal egy olyan korlatozast beleteni ami az SQL-ben nincs es sok esetben hasznalhatatlanna tenni.

Edit: az is lehet, hogy ezek az emberek buta szerkesztot hasznalnak ami nem kepes szolni ha hibas az SQL kod es igy a query buildertol remelik a hibamentes SQL kodot. Ha hasznalnanak tisztesseges IDE-t, ez mind nem lenne problema.
15

Kérdések

Hidvégi Gábor · 2016. Dec. 19. (H), 15.37
A bemásolt forráskód elég sok kérdést felvet:

1, A típusosságot igazából csak a Limitnél és az Offsetnél tudod kihasználni, de igazából ott sem értem, mire jó. Ugyanis mi van, ha ezeket az értékeket adatbázisból veszed, aminek a visszatérési típusa karakterlánc, azaz valahol a programban mindenképp kell típuskonverziót végezni. Ezt az opcionális átváltást miért nem ezekben a metódusokban végzed el?

2, Mi a célod ezzel a megvalósítással? A típusoknak akkor lenne értelme, ha adatbázismezőnként meg lehetne adni egy SELECT-ben, hogy ide egész számokat várok, ide dátumot, amoda meg karakterláncot. Ennek hiányában legfeljebb arra jó az egész, hogy össze tudod legózni a lekérdezéseket.

De ez újabb kérdéseket vet fel:

a, A témában n féle ilyen illesztőt írtak már, miért írsz sajátot? Gyakorolnál? Arra mondjuk épp jó.

b, Ezzel az eszközkészlettel csak rendkívül primitív lekérdezéseket tudsz összeszerelni – akkor tulajdonképpen mire jó az egész? Ráadásul jóval lassabb lesz, mintha te ragasztgatnád össze a lekérdezéseket vagy prepared statementeket használnál.

3, Miért OOP ez az egész? Mivel az általánosan használt MySQL-től mindegyik más adatbáziskezelő jelentősen eltér, nagyon nehéz olyan PHP kódot és SQL-t írni, ami mondjuk postgresql esetében is jól fog működni.

Ha ez így van, akkor nem látom értelmét ennek az absztrakciónak, bőven elég az, amit mondjuk a PDO nyújt.

A lekérdezések eredményeinél miért van szükség a visszafele léptetésre (fetchPreviousRow)? Miért nem kérsz le egyben minden sort, beteszed egy tömbbe, és kész, azon már lehet egy for ciklussal végigiterálni? A hibakezelés ettől még maradhat a lekérdezést végző függvényben, de ha már kaptál tőle visszatérési értéket, biztos lehetsz benne, hogy az hibátlan.

A Database és a DatabaseInteractions miért két külön interfész?
30

Csak 3.:

Pepita · 2016. Dec. 20. (K), 20.18
- Nem te lennél, ha nem kérdőjeleznéd meg az OOP -T. :)
- Ilyen "kis gagyi" CMS, mint a Drupal, többször is meg lépte, nem csak(!) az általad megadott 2 motorral. :)
- Mindent egy tömbbe: 100 000 000 rekord környékén már kissé meredek gondolat; vagy te mindig veszel nagyobb vasat, ha béna a kódod és lassú?

Egyébként - ha erre gondoltál - abban egyetértek, hogy nem lehet és nem kell olyan db interfészt írni, ami "mindenre jó".
16

Re

visuall · 2016. Dec. 19. (H), 17.32
Huh, Köszönöm a válaszokat!

Úgy látom, hogy ez ezen a terepen van még mit fejlődnöm..
47

Static

janoszen · 2017. Jan. 3. (K), 10.48
Na, reszben ezen tema nyoman elkezdtem osszerakni egy statikus kodelemzot ami elore szol ha nem megfelelo a kod statikus volta. Meg erosen prototipus allapotu, de lehet nezegetni es contributolni. :)