Salut,
Je me demandais s'il existe un moyen dans php 5.3+ d'obtenir une liste d'espaces de noms définis dans une application. alors
si file 1 has namespace FOO
et file 2 has namespace BAR
Maintenant, si j'inclus le fichier 1 et le fichier 2 dans le fichier 3, j'aimerais savoir avec une sorte d'appel de fonction que l'espace de noms FOO et BAR sont chargés.
Je veux y parvenir pour être sûr qu'un module dans mon application est chargé avant de vérifier si la classe existe (avec is_callable).
Si ce n'est pas possible, j'aimerais savoir s'il existe une fonction pour vérifier si un espace de noms spécifique est défini, quelque chose comme is_namespace ().
J'espère que vous avez l'idée. et ce que j'essaye d'accomplir
Premièrement, pour voir si une classe existe, utilisé class_exists
.
Deuxièmement, vous pouvez obtenir une liste de classes avec namespace en utilisant get_declared_classes
.
Dans le cas le plus simple, vous pouvez utiliser ceci pour trouver un espace de noms correspondant à partir de tous les noms de classe déclarés:
function namespaceExists($namespace) {
$namespace .= "\\";
foreach(get_declared_classes() as $name)
if(strpos($name, $namespace) === 0) return true;
return false;
}
Autre exemple, le script suivant produit une structure de tableau hiérarchique d'espaces de noms déclarés:
<?php
namespace FirstNamespace;
class Bar {}
namespace SecondNamespace;
class Bar {}
namespace ThirdNamespace\FirstSubNamespace;
class Bar {}
namespace ThirdNamespace\SecondSubNamespace;
class Bar {}
namespace SecondNamespace\FirstSubNamespace;
class Bar {}
$namespaces=array();
foreach(get_declared_classes() as $name) {
if(preg_match_all("@[^\\\]+(?=\\\)@iU", $name, $matches)) {
$matches = $matches[0];
$parent =&$namespaces;
while(count($matches)) {
$match = array_shift($matches);
if(!isset($parent[$match]) && count($matches))
$parent[$match] = array();
$parent =&$parent[$match];
}
}
}
print_r($namespaces);
Donne:
Array
(
[FirstNamespace] =>
[SecondNamespace] => Array
(
[FirstSubNamespace] =>
)
[ThirdNamespace] => Array
(
[FirstSubNamespace] =>
[SecondSubNamespace] =>
)
)
Je sais que cette question a déjà une réponse, mais je voulais apporter une solution plus réaliste à ce que je pense être votre problème. Si j'avais eu plus de temps hier quand j'ai fait mon commentaire, j'aurais publié ceci. Désolé de ne pas l'avoir fait.
On dirait qu'OP a un système de modules dont il a besoin pour savoir si un module particulier est chargé avant d'autoriser un appel.
Tout d'abord, j'aimerais dire que l'utilisation d'espaces de noms simplement pour déclarer des modules actifs est, IMO, abuser de leur utilité. Si vous suivez le but de l'espacement des noms à la lettre, votre structure pourrait ressembler davantage à ceci:
L'ensemble de votre système doit être dans son propre espace de noms. Appelons cet espace de noms System
. Ensuite, les modules seraient probablement sous le System\Module
espace de noms. Ensuite, en fonction de la complexité, il serait possible que chaque module ait un espace de noms sous System\Module
. Prenant vos exemples, System\Module\FOO
et System\Module\BAR
.
Maintenant, passons à la création d'un système de modules qui s'enregistre en charge.
Tout d'abord, nous avons besoin d'un endroit pour nous inscrire. Appelons ça System\Module\Registry
et, comme il y aura probablement beaucoup de registres différents, il implémentera le System\iRegistry
. Par souci de concision, je ne publie que System\Module\Registry
. Selon toute vraisemblance, il implémentera également une sorte de modèle de cohérence globale, comme un singleton, mais je ne le montre pas non plus. C'est ici:
<?php
namespace System\Module
{
class Registry extends System\Registry
{
protected $registered = array();
public function register( $name=null )
{
$this->registered[] = $name;
}
public function isRegistered( $module )
{
// Code to find module
}
public function getModule( $module )
{
// Code to find module
// OR, if you can't find it...
throw new ModuleNotRegisteredException("Module named \"{$module}\" could not be found in the registry.");
}
}
}
?>
Maintenant, dans chaque module, vous devez appeler cette fonction de registre lorsque le fichier est chargé. Il y a plusieurs façons de faire ça. La première consiste à avoir du code dans l'espace de noms de votre module qui s'exécute à la charge similaire au code procédural typique:
namespace System\Module\FOO
{
// Load this module
$system->module->register("FOO");
}
Ce qui précède signifierait cependant une duplication de code. Vous pouvez également utiliser le chargement automatique pour cela à la place, de cette façon le code "d'enregistrement" est en un seul endroit. Voici un concept très basique pour faire cela:
spl_autoload_register(
function ($className)
{
// Code to load files.
// Once loaded register our modules.
if( $namespace = "System\\Module" )
{
$system->module->register( $classname );
}
}
);
Une autre façon possible de faire cela serait de définir une interface pour les modules avec une fonction spécifique pour l'enregistrement lorsque le module est initialisé. Cependant, cela signifie que le module doit être chargé en premier et peut causer ses propres problèmes en fonction de vos besoins.
Après avoir fait ceci: