ugrás a tartalomhoz

Autoloading & namespaces: class not found [megoldott]

Dualon · 2014. Szep. 3. (Sze), 22.47
Névtér alapú autoloadingot próbálgatom tanulási céllal, amit pseudo-static osztályhívással kombinálnék (Osztaly::nemLetezoDinamikusMetodus()), á lá laravel, ám "class not found" hibát kapok. Mi lehet az oka?

Az elképzelés az, hogy egyedi autoloader regisztrálásával a névterek alapján csinálok autoloadingot, valamint a facade és inverse of control minták alapján osztály alias-ok szerint egy object containerből feloldom az objektumok nevét, hogy a kódban ilyen hívásokat tudjak csinálni:
Label::label("cimke")
Ugyanakkor pl. tesztelhetőség miatt ezt nem statikusan szeretném megoldani, hanem a kívánt osztályok betöltésével.

A könyvtárszerkezet:

/
index.php
Iharos/
  Kernel/
    Facade.php
    Iharos.php
  Label
    Label.php
    LabelModule.php
Az állományok tartalma:
- index.php: http://pastebin.com/Jz128edU
- Facade.php: http://pastebin.com/VUCRuNRk
- Iharos.php: http://pastebin.com/SYyR6PeY
- Label.php: http://pastebin.com/1mhEMmeJ
- LabelModule.php: http://pastebin.com/ereT9v7s

Az Iharos.php-ban lévő Iharos->autoLoader() valósítja meg a névtér alapú autoloadingot.
Konkrétan az index.php futásakor azt szeretném, hogy a Facade osztályt kiterjesztő Label osztály automatikus betöltése után a Facade::__callStatic() fusson le, ami az Iharos->manifest() alapján feloldja és szükség esetén példányosítja a kívánt modult (LabelModule), majd meghívja annak nem statikus label() metódusát. Azért használok külön Label és LabelModule osztályokat, hogy ne legyen "static call on non-static method" hiba.

A pseudo-static hívásokig nem jutok el, a kimenet ez:

app->registerAutoLoader()

app->autoLoader(Label)
autoLoader: /var/www/teszt/Iharos/Label/Label.php

app->autoLoader(Iharos\Kernel\Facade)
autoLoader: /var/www/teszt/Iharos/Kernel/Facade.php
Fatal error: Class 'Iharos\Kernel\Facade' not found in /var/www/teszt/Iharos/Label/Label.php on line 8


Mindenféle kombinációit kipróbáltam a névtereknek, elolvastam egy vagon autoloading és névtér cikket, kézikönyvet, laravel forráskódját is böngésztem, stack overflow is a barátom, de nem jövök rá a megoldásra.

1. Mi okozza a fenti hibát? (Névterek?)
2. Van bevett gyakorlat ilyen jellegű hibák felderítésében, tesztelésében?
3. Lehet a pseudo-static hívásokat egyszerűbben is modellezni?

Hálás lennék a segítségért, napok óta küzdök evvel. :)
 
2

Kicsit megnéztem a Iharos

spapp · 2014. Szep. 4. (Cs), 08.53
Kicsit megnéztem a Iharos class-t.

Szerintem légyszíves kezd a php dokumentációjával!
Már a constructor eleje problémás: return static::$instance;

De egyébként hemzseg a hibától!
- Ez helyet 'Iharos\Kernel\Iharos' lehet ezt 'Iharos\\Kernel\\Iharos'akartad írni.(?)

- error föggvény helyett -> throw new Exception('error message');

- getInstance
inkább ilyen legyen

    public static function getInstance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }
....
3

Re: Egyszerű hibakeresés PHP

Dualon · 2014. Szep. 4. (Cs), 09.52
Köszönöm a választ.

A debug_backtrace() hasznos, PSR-0, PSR-4 standardokat ismerem, de a lehető legegyszerűbb példában nem látom értelmét használni őket.

- Ez helyet 'Iharos\Kernel\Iharos' lehet ezt 'Iharos\\Kernel\\Iharos'akartad írni.(?)


Nem, mivel a backslash escape karakter.

- error föggvény helyett -> throw new Exception('error message');


Az error metódus célja csak annyi, hogy egy helyen kelljen csak módosítani, ahogy játszom a kóddal, plusz kivételt amúgyis macerás dobni autoloaderből, ami megint csak bonyolítaná a példát.
Mindenesetre ha bármi éles lesz ebből, abban tanácsod szerint kivételek lesznek.

getInstance...

Az Iharos szerintem singletonként viselkedik, emiatt a static vs self különbségnek nem szabadna megjelennie, de igazad van, a pontosság jegyében a self való ide.

Köszönöm a tanácsokat, megfogadom őket, sajnos azonban ezek egyike sem hoz megoldást. Bármi egyéb ötlet?
4

névterek

T.G · 2014. Szep. 4. (Cs), 18.06
Elég összevissza adtad meg a névtereket, ugyanazt add meg, mint a mappák nevei.
A névtér ne tartalmazza az adott osztály nevét.

Pl. Facade.php esetében: namespace Iharos\Kernel;
5

re:névterek

Dualon · 2014. Szep. 10. (Sze), 12.47
Köszönöm neked is a választ!
A névtereket rendbetettem a tanácsod szerint, de továbbra is a kezdőbejegyzésben leírt hibát kapom.

Az osztályokat tartalmazó állományokat betölti az autoloader, így itt továbbra is valami névtér probléma lesz.

Az egyszerűség kedvéért feltettem a kódot githubra:
https://github.com/iharos/iharos

Bármi ötlet?
6

A Label.php betoltodesekor az

darevish · 2014. Szep. 10. (Sze), 21.21
A Label.php betoltodesekor az Iharos\Label\Label osztaly toltodik be, te pedig a Label-en hivod a static metodust.
use Iharos\Label\Label;
az index.php-ban? Vagy epp ezt akarod elkerulni?
9

Köszönöm, ez a megoldás :)

Dualon · 2014. Szep. 13. (Szo), 21.04
Köszönöm, ez a megoldás. :)

A röhej az, hogy éreztem, hogy valami triviális történik, ugyebár két sorral feljebb pontosan így példányosítottam az Iharos\Kernel\App-ot, de teljesen beakadt egy gondolatmenet... ezért jöttem a Weblaborra. :)
7

Az előttem lévő hozzászólást...

T.G · 2014. Szep. 10. (Sze), 21.52
Az előttem lévő hozzászólást azzal egészíteném ki, hogy az is megoldás, hogy a hatodik sort erre cseréled:
Iharos\Label\Label::label("Uzenet");
Ugye az egész névterezés arra jó, hogy az ugyanolyan nevű osztályaid ne akadjanak össze, ám valamilyen módon meg kell adni, hogy te melyik névtérben lévő Label-t hívnád meg.
10

Neked is köszönöm :)

Dualon · 2014. Szep. 13. (Szo), 21.04
Neked is köszönöm, pontosan itt volt a kutya elásva. :)
8

Köszi, hogy feltetted a

spapp · 2014. Szep. 11. (Cs), 09.20
Köszi, hogy feltetted a github-ra. Így könnyebb nézegetni.

Nekem nem világos, hogy az Iharos\Kernel\Iharos osztály pontosan mi célt szolgál? Olyan "svájci bicska" osztálynak tűnik:
  • szolgálna autoloader ként?
  • szolgálna factory ként?
  • singleton lenne?
  • vagy nem az? $app = new Iharos\Kernel\Iharos();


Ez szerintem nem jó. Egy osztály egy dolgot csináljon, de azt jól.
Aztán van benne egy-kettő olyan apró dolog ami most jó ötletnek tűnik, de később, mikor már a projekt megnő, igen bosszantó hibákat fog eredményezni.

Pl:

A php a __DIR__ állandóban a végén nem tárol path separátort,
te viszont a base_dir-ben igen. Ez szerintem nem konzisztens a php-val.

A "globális" (gondolom annak tervezted) osztály factory, manifest függvény, nagyon meg fogja nehezíteni a hibakeresést. Persze csak akkor ha működik ($module = $this->module_registry[$name];).

Én azt javaslom, hogy legyen egy autoloader osztályod. Az ne csináljon, ne tudjon semmi mást csak osztályokat betölteni. De azt tudja!
Néhány link amit érdemes ehhez átolvasnod:

12

A keveredő feladatokról...

Dualon · 2014. Szep. 13. (Szo), 21.23
Nekem nem világos, hogy az Iharos\Kernel\Iharos osztály pontosan mi célt szolgál?

Igen, jogos, keveredett az autoloader, a factory és facade feloldás. Szebb és praktikusabb a linux-szerű "egyet, de jól" megközelítés, még a bejegyzésed olvasása előtt a githubon lévő friss megoldásban csak az autoloadert és a facade feloldást tartottam meg.

Szerk.: A cél egyébként csak annyi volt, hogy megértsem a névtér alapú autoloadingot úgy, hogy mindezt kombinálom a pseudo-static hívással, vagyis tudjak úgy csinálni, mint a laravel. :))

A php a __DIR__ állandóban

Elegáns. :)

A "globális" (gondolom annak tervezted) osztály factory, manifest függvény, nagyon meg fogja nehezíteni a hibakeresést.

Pont ilyesmiket szeretnék megtanulni, tudnál erről bővebben írni? Ha arra gondolok, amire te, akkor valószínűleg a mostani verzióban szereplő App::resolve() is ugyanide vezet.

Köszönöm a linkeket!
11

Megoldás githubon forráskóddal

Dualon · 2014. Szep. 13. (Szo), 21.21
Kösz (még egyszer) mindenkinek a tanácsokat, a megoldás az index.php-ban a Label névterének megadása volt.

Egy átgondoltabb, kitisztított változatot feltettem githubra, ennek előnyei a korábbihoz képest (szerintem ^^):
- PSR-4 compliant autoloader
- nem szükséges a Label (vagy bármi hasonló) névterének megadása
- a Kernel\App (néhai Kernel\Iharos) nem kell, hogy singleton legyen
- a Kernel\App nem akar factory is lenni
- code cleanup