Namespaces en dynamische classname
De sitatuatie is dat ik een factory class heb in de namespace 'API'. In de namespace 'API\Flickr' heb ik een class met de naam Datamapper (volledig dus \API\Flickr\Datamapper). Nu heb ik de volgende situaties geprobeerd en het verbaasde me dat de de tweede niet werkt:
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
<?php
//code dus in de factory \API\Factory die \API\Flickr\Datamapper moet aanmaken
//direct aanmaken, werkt
$obj = new Flickr\Datamapper()
//met een dynamische naam, werkt niet
$classname = 'Flickr\\Datamapper';
$obj = new $classname();
//dynamische naam met volledige namespace, werkt wel
$classname = '\\API\\Flickr\\Datamapper';
$obj = new $classname();
?>
//code dus in de factory \API\Factory die \API\Flickr\Datamapper moet aanmaken
//direct aanmaken, werkt
$obj = new Flickr\Datamapper()
//met een dynamische naam, werkt niet
$classname = 'Flickr\\Datamapper';
$obj = new $classname();
//dynamische naam met volledige namespace, werkt wel
$classname = '\\API\\Flickr\\Datamapper';
$obj = new $classname();
?>
Kan iemand mij uitleggen waarom de tweede optie met relatieve namespace niet werkt, terwijl het wel werkt als de classname niet dynamisch is?
We missen hier wat context, aangezien de eerste onder normale omstandigheden in een "Fatal error: Class 'Flickr\Datamapper' not found" zou moeten stranden.
Mijn namespace kennis is nog vrij pril, dus wellicht dat ik nog gewoon wat kennis mis. Maar als ik het goed begrijp is de classname Flickr\Datamapper een relatieve namespace tov de factory waarin die wordt aangemaakt en is de absolute namespace dan \API\Flickr. Mijn autoloader krijgt dus als naam door \API\Flickr\Datamapper en vertaalt dat naar een pad waarin het bestand gevonden kan worden met de Datamapper class. Tot zover werkt het in elk geval en mijn veronderstelling was dat dat ook zou moeten werken met een dynamische classname.
Nope. Dan krijg ik dus de foutmelding: "Fatal error: Class 'Flickr\Datamapper' not found"
Dat is inderdaad raar: waarom vindt je autoloader de eerste wel maar de (gelijknamige) tweede niet?
Daar zeg je me wat, even de autoloader de classnames laten printen die hij doorkrijgt. Bij de eerste optie krijgt hij door '\API\Flickr\Datamapper', dus inclusief volledige namespace. Bij de tweede optie krijgt hij door 'Flickr\Datamapper', dus dan wordt de namespace blijkbaar niet aangevuld.
Oftewel de huidige namespace en eventuele uses worden genegeerd.
Het lijkt er inderdaad op dat de huidige namespace in zo'n situatie niet meegenomen wordt. Vraag blijft bij mij wel staan waarom.
Oplossing is er op zich wel, zoals gemeld in de eerst post, door gewoon de volledige namespace op te geven. Nog ietsje mooier wat mij betreft kwam ik net achter, ik kan de huidige namespace er ook voorzetten via de __NAMESPACE__ constante. Dus dan krijg ik dit:
Dit werkt ook en vind ik op het moment de best werkbare oplossing.