2016-03-09 56 views
2

我創建在我的項目,在這個類得到一個報告類型爲字符串工廠類中工作。該字符串具有實現報表界面的具體類的名稱。對象創建不命名

我遇到的問題是,當我實例化這個類,我得到了Class not found錯誤。

這裏遵循的工廠代碼。

namespace App\Term\Reports; 

class Factory 
{ 
    public static function build($type) 
    { 
     $obj = new CableBySensor(); // Works! 

     // $type == 'CableBySensor' 
     $obj2 = new $type;   // Class not found :(

     // ... validates if the class exists ... 
     // ... and if it implements the Report Interface ... 
     // ... throw exception if class doesn't exist or doesn't implements interface 
     // ... then returns the corresponding object. 
    } 
} 

兩種方法實際上是相同的。

第一條:爲什麼我必須在字符串中指定類的全限定名以使其工作?類CableBySensorFactory駐留在相同的名稱空間中。

這開始給我找麻煩,因爲我也想驗證被實例化的類實現ReportsInterface

二:我如何克服呢?我是否應該像這樣打電話給工廠$myReport = Factory::build('App\Term\Reports\' . $className);或者我應該使用工廠類中的__NAMESPACE__常量,例如:$obj = new __NAMESPACE__ . '\' . $className

謝謝。

+0

讓我們退後一步,在這裏,你怎麼會在傳遞'$ type'作爲一個字符串?此外,你會認爲有'switch($ type){case「CableBySensor」:$ obj2 = new CableBySensort();打破;}'。 – Halcyon

+1

您是否試圖通過使用__NAMESPACE__看看它是否有效? –

+0

我建議您在線閱讀有關參數化工廠模式。我個人不會寫一個工廠類,然後像你一樣使用它。 – tomazahlin

回答

1

漠然的工廠方法是否是在這裏還是沒有用, 問題是,試圖從一個動態變量來實例化。

或者作爲akhoondi at php.net指出:

必須注意的是使用動態類名[...]「當前命名空間」時,[...]是全局命名空間。

有可能是3個解決方法:

  • 通過完全限定類名到你的工廠方法(arghh ...)

    $instance = Factory::build('Acme\CableBySensor'); 
    
  • 或者,做一次檢查你的構建方法並在必要時加上名稱空間的前綴(如建議here)(聲音對我來說不那麼簡單)

    public static function build($type) 
    { 
        if ($type[0] !== '\\') { 
         $type = '\\' . __NAMESPACE__ . '\\' . $type; 
        } 
        $obj = new $type; 
        ... 
    } 
    
  • 或者,如果您有PHP 5.5+爲什麼不使用class name resolution via ::class? 就個人而言,我會去一個儘可能:

    $instance = Factory::build(CableBySensor::class); 
    
+0

回答第一個問題。關於第二。我打算第二次,但稍作調整。就像我想用第三種選擇一樣,那時我只有一個名爲「cable_by_sensor」的字符串(這是用戶選擇的選項)。所以,我將'studly_case()'應用到'$ type'(然後我有實際的類名稱,作爲約定)。之後,我在前面添加'__NAMESPACE__',然後驗證類是否實現了我想要的接口,然後返回該對象的新實例或eles我拋出異常。 – TiagoRL