2010-12-22 75 views
4
//file foo.php 
<?php 
namespace foo; 
class foo{ 
    function __construct(){ 
     echo "hello"; 
    } 
} 
?> 

//file index.php 
<?php 
require_once("foo.php"); 
echo __NAMESPACE__; 
?> 

我的問題是,從我的index.php文件中,有可能知道foo.php的命名空間是什麼,而無需讀取文件內容並對其執行正則表達式?這似乎是一個很大的開銷。php獲取包含文件的名稱空間

///編輯

我真的很希望能夠到命名空間動態地添加到包含的文件。

<?php 
namespace dynamic; 
require_once("foo.php"); 
echo __NAMESPACE__; 
?> 

我想允許第三方插件,但php命名空間似乎很糟糕。我不想讓插件編輯器必須創建一個名稱空間。

+0

是否可以使用關鍵字「use」IE:「use foo」。對不起 - 不知道這是否會起作用 – cdnicoll 2010-12-22 18:43:12

回答

15

不可以,但你可以誘騙輪這樣:

//file foo.php 
<?php 
    namespace foo; 
    //... 
    return __NAMESPACE__; // must be last line 
?> 

以及讀取出來:

//file index.php 
<?php 
    $ns = require_once("foo.php"); 
+6

學到了新的東西。 – 2010-12-22 18:59:58

+4

n.b.從包含中返回的值可能被認爲是不好的做法,因爲它不是傳統的行爲。 – 2013-11-15 22:43:21

0

我制定了相當費力的手工方式做到這一點。

像在上面討論的過程本身很簡單:

  1. 讓你的每個文件的文件列表。現在,每一個文件:
  2. 創建一個隨機命名空間ID
  3. 裝飾文件並替換第一個開始標記
  4. 附加空間ID,並開始標籤到文件
  5. 寫入臨時文件
  6. 進口臨時文件
  7. 做任何反射需要然後清理

我在這裏有一個zend的例子....可能不是最有效的,但它的工作原理。

<?php 
//first setup zend 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__)."/../zend/library/"); 
require_once 'Zend/Loader/Autoloader.php'; 
$loader = Zend_Loader_Autoloader::getInstance(); 
$loader->registerNamespace(dirname(__FILE__)."/../zend/library/"); 

//include my extender class 
class Zend_Reflection_File_WithNamespace extends Zend_Reflection_File { 
    public function getFunctionsWithNamespace($namespace = '', $reflectionClass = 'Zend_Reflection_Function') 
    { 
     $functions = array(); 
     foreach ($this->_functions as $function) { 
      $newName = $namespace . "\\" . $function; 
      $instance = new $reflectionClass($newName); 
      if (!$instance instanceof Zend_Reflection_Function) { 
       require_once 'Zend/Reflection/Exception.php'; 
       throw new Zend_Reflection_Exception('Invalid reflection class provided; must extend Zend_Reflection_Function'); 
      } 
      $functions[] = $instance; 
     } 
     return $functions; 
    } 
} 

//find file(s) 
$startDir = 'hello/'; 
//$tempDir = 'php://temp/resource='; 
$tempDir = 'temp/'; 
$fileList = scandir($startDir); 

function ppPrintR($data) { 
    echo "<pre>"; 
    print_r($data); 
    echo "</pre>"; 
} 

//Now loop through each file, first writing to temp, including and then testing 
foreach ($fileList as $key => &$fileItem) { 
    if (is_file($startDir . $fileItem)) { 
     //Take file and convert it 
     $findDir = $startDir . $fileItem; 
     echo $startDir . $fileItem; 

     $inContents = file_get_contents($findDir); 
     $randIden = 'm' . preg_replace('/\.|\s/', '', microtime()); 

     //Replace the <?[php] at the start of the file with <? namespace xyz; 
     $inContents = trim($inContents); 
     $addString = 'namespace ' . $randIden . '; '; 

     $longTagPos = strpos($inContents,'<?php'); 
     $shortTagPos = strpos($inContents,'<?'); 

     if ($longTagPos !== false && $longTagPos < 10) { 
      $inContents = str_replace('<?php', '', $inContents); 
      $addString = '<?php ' . $addString; 
     } 
     else if ($shortTagPage !== false && $longTagPos < 10) { 
      $inContents = str_replace('<?', '', $inContents); 
      $addString = '<? ' . $addString; 
     } 
     $outContents = $addString . $inContents; 

     //Now write and require new temp file 
     $tempItem = $tempDir . $fileItem; 
     file_put_contents($tempItem, $outContents); 
     require($tempItem); 

     //Now do normal things 
     $reflectedFile = new Zend_Reflection_File_WithNamespace($tempItem); 
     echo 'Before<br/>'; 
     $functions = $reflectedFile->getFunctionsWithNamespace($randIden); 
     echo 'After<br/>'; 

     //Now foreach function, read params and consider execution 
     foreach($functions as &$functionItem) { 
      echo $functionItem->name . "<br/>"; 
      $functionParams = $functionItem->getParameters(); 
      ppPrintR($functionParams); 
     } 

     //FIXME should clean here 
    } 
} 
?> 
+1

雖然你的答案確實提供了一些有用的東西,但轉向Zend只是爲了做到這一點是矯枉過正的。只用PHP本身,有很多方法可以更快地處理這個問題。在轉向框架之前,請考慮您自己的知識和能力;) – Digitalis 2012-12-03 14:49:45

5

那麼,你可以掃描類命名空間。它包含命名空間。這是PHPUnit做事的方式。所以,即:

$namespaces = get_current_namespaces(); 

include 'plugin/main.php'; 

$newNamespaces = get_current_namespaces(); 
array_diff($namespaces, $newNamespaces) 

這裏是你如何實現get_current_namespaces()is it possible to get list of defined namespaces

2

如果你知道這個文件,你可以簡單地提取命名空間的形式,它:)。

function extract_namespace($file) { 
    $ns = NULL; 
    $handle = fopen($file, "r"); 
    if ($handle) { 
     while (($line = fgets($handle)) !== false) { 
      if (strpos($line, 'namespace') === 0) { 
       $parts = explode(' ', $line); 
       $ns = rtrim(trim($parts[1]), ';'); 
       break; 
      } 
     } 
     fclose($handle); 
    } 
    return $ns; 
} 

而且你不會限制在文件的末尾返回一些可以退出或返回指令的文件。