[composer]autoloading psr-4
Ik probeer eigen classes d.m.v. composer te autoloaden. Hiervoor heb ik een directory genaamd app/custom/myclass.php in de class heb ik de volgende namespace
Nu heb ik in de composer.json het volgende
wanneer ik een composer.update uitvoer krijg ik helaas de melding dat de class niet bestaat. Wat doe ik hier fout?
app/ moet zijn app/custom ??
manual kom ik er ook niet helemaal uit.. de custom is in dit geval volgens de handleiding al de directory waarnaar gezocht moet worden en deze bevind zich in app/ als ik het goed begrepen heb.
@Ozzie nee helaas werkt dat ook niet. Volgens de composer Probeer eens het hardcoded path in te geven vanaf de root, dus "path/to/app". En als dat niet werkt, kijk dan even in je error log. Als he goed is zou je daaruit moeten kunnen afleiden welk path er gebruikt wordt en dan kun je waarschijnlijk zien waar het misgaat.
De app/ zit al in de root dir. verder zit er niets anders in app/ dan die custom directory. Verder wordt ik ook van de error log niks wijzer.. daar krijg ik namelijk exact dezelfde error..
en die luidt?
Daar wordt dus aangeroepen..
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$app['JsonFetcher'] = $app->share(function($app) {
return new app\custom\JsonFetcher($app);
});
?>
$app['JsonFetcher'] = $app->share(function($app) {
return new app\custom\JsonFetcher($app);
});
?>
en daarna moet je
uitvoeren, update is voor je packages bij te werken.
Ik zie nu dat je
gebruikt, maar je definieerd je namespace als "custom" en niet "app\custom".
daarom moet je "app" weglaten uit je namespace, of toevoegen in je autoload statement in je composer file.
Gewijzigd op 26/06/2014 14:45:44 door Tim S
@Tim bedankt het werkt nu :) de edit kwam ik zelf ook al achter tijdens het veranderen.
Wouter dat had ik dus, maar dat werkte niet.. Hoe ziet mijn namespace etc er dan uit in dat geval?
return new app\custom\JsonFetcher($app);
het begin "app\" weghalen.
Maar let wel, de class JsonFetcher moet dan dus direct in de map app worden geplaatst:
app/JsonFetcher.php
dus stel dit is je mappen-structuur:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
`-- app
| `-- controller
| |-- views
|-- CustomPackage
| `-- src
| | `-- JsonFetcher.php
| |-- tests
| | `-- JsonFetcherTest.php
| `-- controller
| |-- views
|-- CustomPackage
| `-- src
| | `-- JsonFetcher.php
| |-- tests
| | `-- JsonFetcherTest.php
En dit je classes:
dan zou je die zo kunnen autoloaden met psr-4:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
"autoload": {
"psr-4": {
"Reshad\CustomPackage\\": "Custompackage/src",
"Reshad\CustomPackage\\": "Custompackage/tests"
}
}
"psr-4": {
"Reshad\CustomPackage\\": "Custompackage/src",
"Reshad\CustomPackage\\": "Custompackage/tests"
}
}
Gewijzigd op 27/06/2014 00:37:16 door Tim S
Toevoeging op 27/06/2014 00:37:12:
@Tim stel ik zet de JSonFetcher dus direct in de app folder wat wordt daar dan de namespace? en de autoloader?
Wat bedoel je met "ordenen"?
Tim S op 27/06/2014 00:34:07:
Lijkt me niet echt efficiënt om dezelfde namespace naar 2 verschillende mappen te laten verwijzen eerlijk gezegd.
Toevoeging op 27/06/2014 00:40:59:
Reshad, ik zou eerst een directorystructuur maken, die jij zelf prettig en overzichtelijk vindt. Daarna zou ik me gaan bezighouden met het autoloaden. Je bent vrij om het te doen zoals je het zelf fijn vindt.
Ozzie PHP op 27/06/2014 00:39:39:
Lijkt me niet echt efficiënt om dezelfde namespace naar 2 verschillende mappen te laten verwijzen eerlijk gezegd.
Dit is juist de kracht van psr-4, zodat je je mappen kan indelen zoals je wilt.
Zonder dat je je hoeft te houden aan een bepaalde mappen stuctuur.
Anders kun je net zo goed psr-0 gebruiken.
---------
Ik ga er even vanuit dat je het zo wilt dan:
Het maakt eigenlijk niet uit wat je namespace is, als je het ook maar goed in je JsonFetcher.php declareert.
Je zou nu dit kunnen hebben:
met:
maar je kan ook bijvoorbeeld:
met:
je bepaald dus eigenlijk gewoon welke namespace prefix gekoppeld moet worden aan welke map.
Gewijzigd op 27/06/2014 09:26:57 door Tim S
Maar hoe zit dat dan wanneer ik meerdere subfolders heb? bepaal ik zelf tot waar de normale directory gaat en tot waar de subdirectory?
Zonder dat je je hoeft te houden aan een bepaalde mappen stuctuur.
Dat kan toch nog steeds? Het lijkt me handiger om dan een Test namespace te maken. Je koppelt nu 1 namespace aan 2 folders. Stel dat de classes 50/50 verdeeld zijn dan betekent het dat je in 50% van de gevallen een onnodige controle uitvoert.
Je kunt dan beter een aparte Reshad\Test namespace aanmaken die naar de test-map verwijst.
Toevoeging op 27/06/2014 00:54:24:
Reshad, je hebt verschillende type autoloaders die op een bepaalde manier autoloaden. PSR-0 en PSR-4 zijn de bekendste. Maar je kunt ook zelf een autloader maken.
Het principe is dat als een class nog niet geladen is (via require) de naam van die class naar de autoloader wordt gestuurd. Op basis van die naam, en op basis van de namespaces die jij hebt ingesteld, wordt de class geladen.
Heel simpel... even de basis-gedachte. Je hebt een class Foo(). Die zet jij in het mapje "Reshad". Vervolgens zeg je tegen de autoloader: stel de namespace Reshad in op het pad "Reshad".
Vervolgens doe jij:
$foo = new Reshad\Foo();
De autoloader ziet nu de namespace "Reshad". Aha! Bij deze namespace hoort de map "Reshad". Blijkbaar moet ik dus het bestand "Reshad/Foo.php" requiren.
Dat is de basis-gedachte van autoloading.
Reshad F op 27/06/2014 00:47:38:
Ah oke dus de 'key' als het ware staat gelijk aan de namespace? en de value gelijk aan de directory?
Maar hoe zit dat dan wanneer ik meerdere subfolders heb? bepaal ik zelf tot waar de normale directory gaat en tot waar de subdirectory?
Maar hoe zit dat dan wanneer ik meerdere subfolders heb? bepaal ik zelf tot waar de normale directory gaat en tot waar de subdirectory?
Je kan je mappen nu gewoon verder uitbreiden, zolang je die classes die je wilt autoloaden correct blijft namespacen iig.
Bijv:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
`--app
| `-- Sub
| `-- MeerSub
| `-- BesteClassOoit.php
"autoload": {
"psr-4": {
"Custom\\": "app",
}
}
<?php namespace Custom\Sub\MeerSub;
class BesteClassOoit {} ?>
| `-- Sub
| `-- MeerSub
| `-- BesteClassOoit.php
"autoload": {
"psr-4": {
"Custom\\": "app",
}
}
<?php namespace Custom\Sub\MeerSub;
class BesteClassOoit {} ?>
Toevoeging op 27/06/2014 02:23:30:
Ozzie PHP op 27/06/2014 00:49:28:
Dat kan toch nog steeds? Het lijkt me handiger om dan een Test namespace te maken. Je koppelt nu 1 namespace aan 2 folders. Stel dat de classes 50/50 verdeeld zijn dan betekent het dat je in 50% van de gevallen een onnodige controle uitvoert.
Je kunt dan beter een aparte Reshad\Test namespace aanmaken die naar de test-map verwijst.
Je kunt dan beter een aparte Reshad\Test namespace aanmaken die naar de test-map verwijst.
Ik bewaar liever mijn unit tests in een aparte map indien mogelijk.
En qua performance maakt het niks uit, zolang je maar
uitvoerd.
Overigens zou ik op deze manier in een production omgeving mijn tests nu makkelijk uit de autoloader kunnen halen. Wat weer een performance winst is ten opzichte van jouw manier.
Gewijzigd op 27/06/2014 02:25:15 door Tim S
Tim S op 27/06/2014 00:43:40:
Was dat maar waar. PSR-4 schrijft juist heel expliciet een directorystructuur voor. Met de highlights in vet:Dit is juist de kracht van psr-4, zodat je je mappen kan indelen zoals je wilt.
[...] This PSR also describes where to place files that will be autoloaded according to the specification.
3. When loading a file that corresponds to a fully qualified class name ...
i. A contiguous series of one or more leading namespace and sub-namespace names, not including the leading namespace separator, in the fully qualified class name (a "namespace prefix") corresponds to at least one "base directory".
ii. The contiguous sub-namespace names after the "namespace prefix" correspond to a subdirectory within a "base directory", in which the namespace separators represent directory separators. The subdirectory name MUST match the case of the sub-namespace names.
iii. The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
Met andere woorden: basisdirectory, subdirectory én bestandsnaam liggen in PSR-4 alle drie vast.