namespaces
Pagina: « vorige 1 2 3 4 volgende »
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
namespace Parents;
use Our\Child\DosMoonen; // maak gebruik van ons kind DosMoonen
$dos = new DosMoonen;
?>
namespace Parents;
use Our\Child\DosMoonen; // maak gebruik van ons kind DosMoonen
$dos = new DosMoonen;
?>
Bovenstaande voorbeeld is logisch toch?
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
namespace Parents;
use Our\Child\DosMoonen as DosMoonen; // maak gebruik van ons kind DosMoonen... en noem ons kind "DosMoonen"
$dos = new DosMoonen;
?>
namespace Parents;
use Our\Child\DosMoonen as DosMoonen; // maak gebruik van ons kind DosMoonen... en noem ons kind "DosMoonen"
$dos = new DosMoonen;
?>
In het bovenstaande voorbeeld gaan we je hernoemen naar DosMoonen. Waarom zouden we dat doen? Je heet al DosMoonen dus waarom zouden we je dan nogmaals gaan hernoemen naar DosMoonen?
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
namespace Parents;
use Our\Child\DosMoonen as OurChild; // maak gebruik van ons kind DosMoonen en noem hem OurChild
$dos = new OurChild;
?>
namespace Parents;
use Our\Child\DosMoonen as OurChild; // maak gebruik van ons kind DosMoonen en noem hem OurChild
$dos = new OurChild;
?>
In het bovenstaande voorbeeld word jij door je ouders hernoemd naar "OnsKind". Nu heeft er dus een zinnige hernoeming plaatsgevonden.
Snap je wat ik bedoel? Het heeft geen zin om iets te hernoemen naar precies hetzelfde. Het is alsof je zegt rename "Ozzie PHP" naar "Ozzie PHP".
Merk overigens op dat ik bijna altijd aliases gebruik in mijn eigen projecten:
Code (php)
Dat zou niet meer werken, wat ik uit probeerde te leggen: http://www.phphulp.nl/php/forum/topic/namespaces/92491/2/#665664
En dan ben jij blijkbaar oneens met de volgende stelling:
use Organism\Animal\Mammal;' is de kortere versie van 'use Organism\Animal\Mammal as Mammal;'
Wat blijkbaar een onnodige discussie ter weeg bracht.
Gewijzigd op 13/11/2013 15:56:24 door Dos Moonen
>> Ozzie, en toch heeft dosMoonen gelijk. Eigenlijk zou je altijd use Ozzie\Core\Console\Application as Application moeten doen ipv use Ozzie\Core\Console\Application, maar PHP heeft zelf de shortcut erin gebouwd, zodat je wat minder typewerk hoeft te doen.
Ben ik het niet mee eens... vertaal letterlijk de tekst:
use Ozzie\Core\Console\Application // maak gebruik van de class Application (in de namespace...)
Tegenover:
use Ozzie\Core\Console\Application as Application // maak gebruik van de class Application (in de namespace...) en noem 'm Application. Dat is niet zinvol.
Hier is het natuurlijk prima:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
use Wj\TestParser\Extension\BBcode\Parser as BBcodeParser;
use Faker\Factory as FakerFactory;
use Twig_Engine as Templating;
// ...
?>
use Wj\TestParser\Extension\BBcode\Parser as BBcodeParser;
use Faker\Factory as FakerFactory;
use Twig_Engine as Templating;
// ...
?>
@Dos:
>> Wat blijkbaar een onnodige discussie ter weeg bracht.
We zitten in ieder geval weer op 1 lijn :)
Gewijzigd op 13/11/2013 15:59:31 door Ozzie PHP
Nee.
'use Ozzie\Core\Console\Application;' doet twee dingen:
- alias de class/interface 'Ozzie\Core\Console\Application' als 'Application' als deze bestaat.
- alias de namespace 'Ozzie\Core\Console\Application' als 'Application'
'use Dars\Core\Request\HTTP\Internal as InternalRequest;' doet twee dingen:
- alias de class/interface 'Dars\Core\Request\HTTP\Internal' als 'InternalRequest' als deze bestaat.
- alias de namespace 'Dars\Core\Request\HTTP\Internal' als 'InternalRequest'.
Zolang er bij geen '\' na 'InternalRequest' volgt heb je het over de geimporteerde class.
Wanneer er wel een '\' na 'InternalRequest' volgt heb je het over de geimporteerde namespace.
Dat is hoe ik het interpeteer. Wat het voor mij duidelijker maakt.
"PHP namespaces support three kinds of aliasing or importing: aliasing a class name, aliasing an interface name, and aliasing a namespace name. Note that importing a function or constant is not supported." - http://php.net/manual/en/language.namespaces.importing.php
Aangezien https://wiki.php.net/rfc/use_function geaccepteert is zullen functies en constanten nog bij dat lijstje komen. Al moet je 'use function ...' en 'use const' gebruiken.
Gewijzigd op 13/11/2013 16:37:04 door Dos Moonen
Dat is ook hoe ik het zie. Zo werkt het ook precies. Het ging er mij alleen even om dat je niet dit moet doen:
use Foo\Mailer as Mailer;
maar gewoon dit:
use Foo\Mailer;
Wel grappig dat je ook functions en constants kunt gebruiken. Kun je die constanten nu al gebruiken, of is dat pas vanaf een bepaalde php-versie?
Gewijzigd op 13/11/2013 17:11:50 door Wouter J
Hmmmm, da's jammer... dat gaat dus nog even duren.
Al met al weet ik nog steeds niet wat nu die ltrim in de autoload method doet. Iemand die daar uitsluitsel over kan geven? Volgens mij kan ik 'm er gewoon uitslopen?
Hoe groot is jouw korte termijn geheugen? http://www.phphulp.nl/php/forum/topic/namespaces/92491/2/#665655
Grappig Wouter, ware het niet dat ik toevallig met Dos ook in een privé-onderonsje zat waar het over dit onderwerp ging. Dos raadde mij aan om objecten te serializen en unserializen om te kijken wat er gebeurt, maar nog steeds krijg ik bij de class-naam geen slash aan het begin te zien. Vandaar mijn vraag of ik het eruit kan slopen.
Quote:
I discovered some oddities with how class_exists() and is_callable()
work when you use fully qualified names; basically, the leading NS
separator results in a false negative lookup (i.e., existing class is
_not_ found). I found that simply doing an ltrim() on the classname as
the first operation in the reference implementation fixes this. This
also means the strripos() operation no longer needs to worry about a
position of 0, either.
Bron: https://groups.google.com/d/msg/php-fig/zaIwMnMQ1_M/N7TXasJ5cyYJ
work when you use fully qualified names; basically, the leading NS
separator results in a false negative lookup (i.e., existing class is
_not_ found). I found that simply doing an ltrim() on the classname as
the first operation in the reference implementation fixes this. This
also means the strripos() operation no longer needs to worry about a
position of 0, either.
Bron: https://groups.google.com/d/msg/php-fig/zaIwMnMQ1_M/N7TXasJ5cyYJ
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class A {}
spl_autoload_register(function ($class) {
var_dump($class);
class_alias('A', $class);
});
var_dump(phpversion());
$class = new \B;
var_dump($class);
class_exists('\\Miauw');
?>
class A {}
spl_autoload_register(function ($class) {
var_dump($class);
class_alias('A', $class);
});
var_dump(phpversion());
$class = new \B;
var_dump($class);
class_exists('\\Miauw');
?>
Output onder PHP 5.5.5:
Output onder PHP 5.3.0
Zoals ik al eerder zei, vanwege backwards compatibility.
Als je nog wilt uitzoeken sinds welke versies het gefixed is kan je hier beginnen met je zoektocht:
https://github.com/php/php-src/blame/d86b5f01ac7089f46add60622260d6926c3977b8/Zend/zend_builtin_functions.c#L1245
Gewijzigd op 13/11/2013 18:20:25 door Dos Moonen
Wow, wat een eer... thanks :-)
Ik heb de test ook bij mij even gedraaid (versie 5.4.10)... en geen slash te bekennen. Ik kan ltrim er dus gewoon uitslopen :-)))
Toevoeging op 13/11/2013 20:42:53:
Nog 1 laatste vraag over PSR-0.
Is het altijd zo dat de "hoofd"-namespace wordt gebruikt voor het laden van classes? Dus stel je wil een prefix instellen die het pad van de library aangeeft, is het dan altijd zo:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
setPrefix('PDF' , '/pad/naar/pdf-library');
setPrefix('PostNL', '/pad/naar/PostNL-library');
// enz.
?>
setPrefix('PDF' , '/pad/naar/pdf-library');
setPrefix('PostNL', '/pad/naar/PostNL-library');
// enz.
?>
Of kan het ook zijn dat je een hoofd- en subnamespace moet kunnen instellen?
Code (php)
1
2
3
4
2
3
4
<?php
setPrefix('PDF\Exceptions' , '/pad/naar/pdf-library/exceptions');
setPrefix('PostNL\betaling', '/pad/naar/PostNL-library/betaling');
?>
setPrefix('PDF\Exceptions' , '/pad/naar/pdf-library/exceptions');
setPrefix('PostNL\betaling', '/pad/naar/PostNL-library/betaling');
?>
Of is dit laatste nooit aan de orde?
Gewijzigd op 13/11/2013 20:47:26 door Ozzie PHP
Met "hoofd"-namespace bedoel je de actieve namespace?
Of de Fully Qualified Name? (Hoe je de class/interface zou benaderen als je vanaf \ (de global namespace) zou beginnen)
http://www.php.net/manual/en/language.namespaces.rules.php
Daar kan je de regels lezen die PHP gebruikt om de FQN te bepalen.
Waarschijnlijk help dat je niet wat het is mij niet duidelijk wat je vraagt.
>> Ik heb de test ook bij mij even gedraaid (versie 5.4.10)... en geen slash te bekennen. Ik kan ltrim er dus gewoon uitslopen :-)))
Ach ja, waarom zou je je ook zorgen maken over servers die nog geen 5.4 draaien?
Zou het nu ooit zo kunnen zijn dat dit niet enkel gebeurt op basis van de "hoofd"-namespace (vendor?), maar bijv. op basis van hoofdnamespace + subnamespace? Dus dat je zoiets krijgt:
Code (php)
1
2
3
4
2
3
4
<?php
$autoloader->setPrefix('PDF\Exceptions' , '/pad/naar/pdf-library/exceptions');
$autoloader->setPrefix('PostNL\betaling', '/pad/naar/PostNL-library/betaling');
?>
$autoloader->setPrefix('PDF\Exceptions' , '/pad/naar/pdf-library/exceptions');
$autoloader->setPrefix('PostNL\betaling', '/pad/naar/PostNL-library/betaling');
?>
Ik denk het niet, maar ik vroeg het me dus af.
Toevoeging op 13/11/2013 23:29:24:
>> Ozzie, nee niet alleen beperken tot de hoofdnamespace. Jij bent alles veel te veel aan het beperken, niet doen dat is geen OO.
Oké... dus dit moet ook gewoon kunnen?
Code (php)
1
2
3
4
2
3
4
<?php
$autoloader->setPrefix('PDF\Exceptions' , '/pad/naar/pdf-library/exceptions');
$autoloader->setPrefix('PostNL\betaling', '/pad/naar/PostNL-library/betaling');
?>
$autoloader->setPrefix('PDF\Exceptions' , '/pad/naar/pdf-library/exceptions');
$autoloader->setPrefix('PostNL\betaling', '/pad/naar/PostNL-library/betaling');
?>
>> Ach ja, waarom zou je je ook zorgen maken over servers die nog geen 5.4 draaien?
Omdat ik op een eigen server draai misschien? :-s
Toevoeging op 13/11/2013 23:46:26:
@Wouter... er nog even verder over nadenkend... dat kan toch helemaal niet... dat je meer dan 1 namespace gebruikt? Stel je hebt dit:
Code (php)
1
2
3
2
3
<?php
$autoloader->setPrefix('PostNL\betaling\generator' , '/pad/naar/PostNL-library/betaling/generators');
?>
$autoloader->setPrefix('PostNL\betaling\generator' , '/pad/naar/PostNL-library/betaling/generators');
?>
En dan wil je bijv. een pakket_code genereren:
Dan zou de autoloader nu dus eerst moeten kijken of er een pad is gekoppeld aan de namespace "PostNL". Nee! Volgende controle... is er een pad gekoppeld aan de namespace "PostNL\betaling". Nee, ook niet! Nog een controle: is er een pad gekoppeld aan de namespace "PostNL\betaling\generator". Ja, na 3 pogingen hebben we beet.
Kan aan mij liggen, maar dit is toch niet efficiënt? Of zie ik nu iets over het hoofd?
Dan zou de autoloader dus per namespace
Ozzie PHP op 13/11/2013 23:24:31:
Kan aan mij liggen, maar dit is toch niet efficiënt? Of zie ik nu iets over het hoofd?
Ja, je ziet één ding over het hoofd: de autoloader zet de namespace-separator \ om in een directory-separator, bijvoorbeeld /, via de PHP-constante DIRECTORY_SEPARATOR. Het bruggetje is een directory- en bestandsstructuur die overeenkomt met de namespace-hiërarchie. Bijvoorbeeld Foo\Bar\Widget wordt gezocht in ../lib/Foo/Bar/Widget.php. Iets anders wil je meestal ook niet, want dan verlies je het overzicht.
Het hoeft niet. Misschien komt Library A met library B meegeleverd, deze gebruikt XYZ als top-level namespace. Vervolgens gebruik je naar library A ook nog lobrary D die ook XYZ als top-level namespace gebruikt. Dan zal je twee classloaders hebben die maar een deel van de XYZ namespace kunnen laden.
Omdat je niet met libraries wilt knoeien tenzij het echt moet. (Vanwege OCD is geen echte reden.) Laat je het zoals het is en heb je dus twee autoloaders die een top-level namespace delen.
Jij hoeft je in principe alleen zorgen te maken over jouw classes. Third party libraries zullen jouw classloader echt niet gebruiken.
Gewijzigd op 14/11/2013 08:11:41 door Dos Moonen
Dit principe begrijp ik. Maar ik heb m'n autoloader nu zo gemaakt dat ik kan zeggen: als de Vendor Name "Foo" is kijk dan in directory "x". En die directory "x" kan dan zijn wat ik zelf wil. Ik kan dus zeg maar dit doen:
of...
In de praktijk... stel ik zou dus iets met PostNL willen doen, heb ik er dan voldoende aan om de Vendor Name te koppelen aan een directory? Kan ik daar mee uit de voeten:
>> Het lieft heb je alles wat de zelfde 'top-level namespace ("Vendor Name")' gebruikt onder de zelfde map staan.
Het hoeft niet. Misschien komt Library A met library B meegeleverd, deze gebruikt XYZ als top-level namespace. Vervolgens gebruik je naar library A ook nog lobrary D die ook XYZ als top-level namespace gebruikt. Dan zal je twee classloaders hebben die maar een deel van de XYZ namespace kunnen laden.
Oke, maar is het dan voldoende als ik met mijn autoloader dit kan doen:
In het voorbeeld van de Symfony class loader zie ik namelijk ook dit:
Hier wordt dus een sub-namespace gebruikt. Heb je dat in de praktijk nodig vraag ik me af. Moet mijn eigen autoloader dat kunnen?
SplClassLoader kijken. Die doet namelijk hetzelfde:
De SplClassLoader heeft ook nog allerlei methoden aan boord om namespaces en packages een aparte behandeling te geven. Denk bijvoorbeeld aan packages die voor klassen de extensie .class of .class.php gebruiken in plaats van .php. Die komen "in het wild" vaker voor dan wij graag zien.
Dan zou ik eens naar de Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
// Example which loads classes for the Doctrine Common package in the
// Doctrine\Common namespace.
$classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
$classLoader->register();
?>
// Example which loads classes for the Doctrine Common package in the
// Doctrine\Common namespace.
$classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
$classLoader->register();
?>
De SplClassLoader heeft ook nog allerlei methoden aan boord om namespaces en packages een aparte behandeling te geven. Denk bijvoorbeeld aan packages die voor klassen de extensie .class of .class.php gebruiken in plaats van .php. Die komen "in het wild" vaker voor dan wij graag zien.