Namespaces en autoloading

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Mark Hogeveen

Mark Hogeveen

22/02/2014 16:25:21
Quote Anchor link
Hallo,
Ik ben al een hele tijd bezig om namespaces en autloading te laten werken.
PHP vindt op een of andere manier steeds niet de goede klasse.
Ik heb bijvoorbeeld deze code, als index.php in een private map.
Deze index.php doe ik includen op de index.php in de public map. (bootstrap manier)

/private/index.php
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
// private/index.php

use Routing\RouteCollection;
use Routing\Route;

echo "Index.php aangeroepen";

require_once("config.php");

include BASE_PATH . "/Library/Routing/RouteCollection.php";
function
__autoload($path) {
    
    $path = str_replace("\\", DIR_SEPERATOR, $path);
    
    // Debug
    echo "<br>base path: &nbsp;" . BASE_PATH;
    echo "<br>path: &nbsp;&nbsp;&nbsp;" . $path;
    echo "<br>absolute path: &nbsp;" . BASE_PATH . "/Library/" . $path . ".php";

    require_once(BASE_PATH . "/Library/" . $path . ".php");
}


$routes = new RouteCollection();

$routes->add(new Route("\/", ""));
$routes->add(new Route()); // nieuwe route maken, enz.

$rm = new RouteMatcher();
$rm->setCollection($routes);
$rm->match($_SERVER['REQUEST_URI']);

?>

De mapstructuur is als volgt:

private
- map: Library
-- map: Routing
--- RouteCollection.php
--- Route.php

- index.php

public
- index.php

RouteCollection.php heeft namespace: Routing\RouteCollection
Route.php heeft namespace: Routing\Route

Bij het autoloaden gaat het steeds mis, de klassen kunnen niet gevonden worden. Maar ik begrijp eigenlijk ook niet echt hoe namespaces werken. En al helemaal niet hoe je het use of use ... as keyword gebruikt.
Kan iemand me hierover wat uitleggen? Ik heb al veel op internet gelezen, maar het lukt nog steeds niet echt.

Hier zijn nog de errors die PHP gaf
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
[22-Feb-2014 10:16:50] PHP Fatal error:  Class 'Routing\RouteCollection' not found in /var/lib/stickshift/52e369455973ca150500011d/app-root/data/538262/private/index.php on line 22
[22-Feb-2014 10:16:50] PHP Stack trace:
[22-Feb-2014 10:16:50] PHP   1. {main}() /var/lib/stickshift/52e369455973ca150500011d/app-root/data/538262/private/index.php:0
[22-Feb-2014 10:17:00] PHP Fatal error:  Class 'Routing\RouteCollection' not found in /var/lib/stickshift/52e369455973ca150500011d/app-root/data/538262/private/index.php on line 22
[22-Feb-2014 10:17:00] PHP Stack trace:
[22-Feb-2014 10:17:00] PHP   1. {main}() /var/lib/stickshift/52e369455973ca150500011d/app-root/data/538262/private/index.php:0
 
PHP hulp

PHP hulp

28/03/2024 15:23:50
 
Ozzie PHP

Ozzie PHP

22/02/2014 16:51:19
Quote Anchor link
>> Maar ik begrijp eigenlijk ook niet echt hoe namespaces werken. En al helemaal niet hoe je het use of use ... as keyword gebruikt.

Zou je dat dan niet eerst eens gaan proberen te begrijpen? Als je gaat autorijden zonder rijbewijs schiet het ook niet echt op toch?

Sowieso vraag ik me af waarom je een router in de bootstrap plaatst, en waarom je niet eerst een kernel/core class gaat maken waarin je dat soort zaken afhandelt. De routing hoort niet thuis in de bootstrap.

Misschien moet je even uitleggen wat je bedoelt met "het lukt niet echt. Google staat vol met uitleg over namespaces: https://www.google.nl/?q=php+namespaces#q=php+namespaces
 
Wouter J

Wouter J

22/02/2014 17:19:17
Quote Anchor link
Quote:
Bij het autoloaden gaat het steeds mis, de klassen kunnen niet gevonden worden. Maar ik begrijp eigenlijk ook niet echt hoe namespaces werken. En al helemaal niet hoe je het use of use ... as keyword gebruikt.
Kan iemand me hierover wat uitleggen? Ik heb al veel op internet gelezen, maar het lukt nog steeds niet echt.

Een namespace is een nieuwe scope. Dus alles in 1 namespace hoort bij die namespace, variabelen, functies, classes, etc. In een andere namespace kun je niet zomaar bij deze namespace. Een namespace definieer je met het namespace keyword. Voorbeeldje:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php

namespace Acme\Routing\Loader;

class YamlRoutingLoader
{
    // ...
}
?>

Nu hebben we de PHP namespace Acme\Routing\Loader en de class YamlRoutingLoader in die namespace.

[side]
Merk op dat je hier dus ook meteen de aangerade structuur ziet van een namespace: VendorNaam\ComponentNaam(\SubComponentNaam)+


Normaal gesproken zit je in de globale namespace. Stel we zitten in de globale namespace en proberen nu deze class aan te maken, dan zal dat niet lukken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php

require_once 'path/to/YamlRoutingLoader.php'; // autoloader komt straks pas :)

$routingLoader = new YamlRoutingLoader(); //> CLASS NOT FOUND
?>

Dit komt omdat we, zoals je net geleerd hebt, niet zomaar elementen van een andere namespace kunt krijgen. Om dat te willen moet je de volledige namespace + classnaam gebruiken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php

require_once '...'; // nog steeds geen autoloader...

// beginnen met een slash om zeker te zijn dat we vanuit de globale namespace
// starten, een absolute namespace dus

$routingLoader = new \Acme\Routing\Loader\YamlRoutingLoader();
?>

Dit werkt! Maar stel dat we hem nu 2x willen aanmaken, dan moeten we dit 2x gaan herhalen. Dat betekend dat we dit niet makkelijk kunnen veranderen. Hiervoor hebben we het use statement uitgevonden, daarmee kun je een namespace (+ eventuele klasse) "aliasen". Als je geen specifieke alias naam opgeeft wordt de laatste element van een namespace gebruikt:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

require_once '...'; // autoloader, waar ben je?

// use statements zijn altijd absoluut, eerste slash mag niet meer

use Acme\Routing\Loader\YamlRoutingLoader;

$routingLoader = new YamlRoutingLoader();
// hé, dit is een alias voor Acme\Routing\Loader\YamlRoutingLoader en
// raad eens? Die bestaat!


// of

use Acme\Routing\Loader; // nu aliasen we net de klasse, maar een namespace

$routingLoader = new Loader\YamlRoutingLoader();
// hé, Loader is een alias voor Acme\Routing\Loader en dit wordt dus
// Acme\Routing\Loader\YamlRoutingLoader, die bestaat!

// of

use Acme\Routing\Loader as RoutingLoader; // een specifieke alias naam

$routingLoader = new RoutingLoader\YamlRoutingLoader();
// het moet niet gekker worden, RoutingLoader is een alias voor Acme\Routing\Loader
// en Acme\Routing\Loader\YamlRoutingLoader bestaat nog steeds!

?>


Ik hoop dat je dit principe een beetje snapt :)


Dan nu het autoloading verhaal, dit staat volledig los van het namespace verhaal. De enige overeenkomst is dat de autoloader de namespaces gebruikt om een klasse bestand te vinden, maar de namespaces zijn niet uitgevonden om de autoloader mogelijk te kunnen maken.

Nu kun je kiezen uit 2 heel bekende standaarden:
- PSR-0 - Dit betekend dat je bijv. instelt dat de Acme namespace gevonden kan worden in de /Library/Acme map en dat het elk afzonderlijk namespace element een map is. De klasse Acme\Routing\Loader\YamlRoutingLoader kan dan dus worden gevonden in /Library/Acme/Routing/Loader/YamlRoutingLoader.php
- PSR-4 - Dit is eigenlijk gelijk aan PSR-0, met 1 groot verschil: de namespace die je instelt wordt niet opgenomen in de mappenstructuur. Dus stel ik definieer dat Acme\Routing gevonden kan worden in de /Library/acme-routing map, dan moet Acme\Routing\Loader\YamlRoutingLoader zich dus in /Library/acme-routing/Loader/YamlRoutingLoader.php bevinden.

Deze autoloader kun je zelf maken, of je kunt hem van de PSR standaarden jatten, of je gebruikt een andere autoloader, bijv. die van Symfony2, Zend Framework of Composer.
Gewijzigd op 22/02/2014 17:19:45 door Wouter J
 
Mark Hogeveen

Mark Hogeveen

22/02/2014 17:43:16
Quote Anchor link
Bedankt voor de uitleg. Daar heb ik wat aan.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.