2016-09-01 75 views
3

我需要實現類調用系統是這樣的:Laravel動態類使用

想象還有一類Calendar.php處理數據庫查詢(或者,如果你喜歡的模型),它應該被默認使用。如果需要實現一些新行爲,我想實現一個類MaterialCalendar.php,它將擴展Calendar.php類,以便我可以在新創建的MaterialCalendar.php中使用Calendar.php中的所有方法如果需要的話覆蓋父方法。

的問題是如何實現這種行爲在代碼的任何地方使用,在一個視圖或控制器:

如果(子類存在){使用子類)其他(使用默認的父類}

上面僞代碼中的這種行爲應該是動態的,所以如果沒有MaterialCalendar.php,Calendar.php應該默認使用,如果存在MaterialCalendar.php那麼應該使用它。它需要是動態的,與本例中使用的類名無關。

+0

有實現這些類或靜態類的對象? –

+0

@MaciejSikora不,他們不是靜態 – user6784929

+0

如果不是靜態的,然後你可以用http://php.net/manual/en/internals2.opcodes.instanceof.php –

回答

1

定義接口,以保證你的代碼將的iCalendar的任何執行工作:

interface ICalendar { 
    public function method1(); 
    public function method2(); 
} 

創建實現:

class Calendar implements ICalendar { 
    public function method1() {} 
    public function method2() {} 

} 

class MaterialCalendar extends Calendar { 
    public function method1() {} 
    public function method2() {} 
} 

簡單的容器

class SimpleContainer { 
    private static $binds = []; 

    public static function bind($interface, $class) { 
     self::$binds[$interface] = $class; 
    } 

    public static function make($interface) { 
     if (array_key_exists($interface, self::$binds)) { 
      return new self::$binds[$interface]; 
     } 

     throw new \Exception("Interface is not binded"); 
    } 
} 

某處在引導你應該確定綁定到界面的類是:

SimpleContainer::bind(ICalendar::class, MaterialCalendar::class); 

使用下面的代碼在所有的地方,你需要得到日曆對象:

SimpleContainer::make(ICalendar::class); 
+0

大量使用設計模式和整體概念,但對於集裝箱Laravel的服務容器要靈活得多。 – samrap

+1

@samrap你是對的。我錯過了Laravel的使用或稍後更新的觀點。我的解決方案只是描述這個想法,但是在Laravel涉及的真實應用程序中,我推薦使用Laravel標準組件,其中容器就是其中之一。 –

0

安德烈是一個良好的開始,但也沒有必要設計一個容器,用於這一目的。 Laravel提供了一個功能強大的container,您可以在其中將實現綁定到接口。

使用的Andrej的接口和具體類,你可以創建一個service provider結合您希望類的ICalendar接口:

(在供應商的註冊方法):

$this->app->bind('App\Contracts\ICalendar', 'App\Models\MaterialCalendar'); 

當然,在這裏,您將有條件地決定將哪個類綁定到接口(請參閱功能class_exists)。

從這一點,你可以依賴Laravel的容器在需要的地方注入這種依賴。例如,在一個CalendarControllerstore方法,你可以簡單地type hint接口和Laravel會自動地給你,你綁定了具體類的一個實例:

use App\Contracts\ICalendar; 

class CalendarController extends Controller 
{ 
    ... 

    public function store(Request $request, ICalendar $calendar) 
    { 
     // Code... 
    } 
} 

我絕對推薦閱讀文檔在container以及providers。您感興趣的東西可能是Contextual Binding在其中您可以有條件地綁定實現來接口。