2016-09-01 5 views
3

Ich brauche ein System für die Klasse Berufung wie folgt zu implementieren:Laravel dynamische Klasse Verwendung

Stellen gibt es eine Klasse calendar.php Umgang mit Datenbankabfragen (oder ein Modell, wenn Sie möchten), die standardmäßig verwendet werden soll. Wenn es notwendig ist, ein neues Verhalten zu implementieren, möchte ich eine Klasse MaterialCalendar.php implementieren, die die Calendar.php Klasse erweitert, so dass ich alle Methoden aus der Calendar.php in der neu erstellten MaterialCalendar.php verwenden kann Überschreiben Sie gegebenenfalls die übergeordneten Methoden.

Die Frage ist, wie diese Art von Verhalten im Code verwendete überall zu implementieren, in einer Ansicht oder in einem Controller:

if (Kindklasse existiert) {use Kindklasse} else {use Standardelternklasse}

Dieses Verhalten oben in Pseudocode sollte dynamisch sein, wenn also keine MaterialCalendar.php Calendar.php sollte standardmäßig verwendet werden, wenn MaterialCalendar.php vorhanden ist, dann sollte das verwendet werden. Es muss dynamisch sein, unabhängig von den in diesem Beispiel verwendeten Klassennamen.

+0

Es gibt Objekte, die diese Klassen oder statische Klassen implementieren? –

+0

@MaciejSikora nein sie sind nicht statisch – user6784929

+0

Wenn nicht statisch Dann können Sie variable Klasse überprüfen, indem Sie http://php.net/manual/en/internals2.opcodes.instanceof.php –

Antwort

1

Schnittstelle definieren zu gewährleisten, dass der Code bei jeder Implementierung von ICalendar arbeiten:

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

erstellen Implementierungen:

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

} 

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

Einfache Behälter

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"); 
    } 
} 

Sie Irgendwo in Bootstrap sollte Identifizieren Sie, welche Klasse an die Schnittstelle gebunden werden soll:

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

den folgenden Code in allen Orten, an denen Sie Kalenderobjekt erhalten müssen:

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

Große Verwendung von Designmustern und Gesamtkonzept, aber für Container Laravels Service Container ist viel flexibler. – samrap

+1

@samrap Sie haben Recht. Ich habe den Punkt verpasst, dass Laravel verwendet wird oder vielleicht wurde es später aktualisiert. Meine Lösungen beschreiben nur die Idee, aber in der echten App, in die Laravel involviert war, empfehle ich die Verwendung von Laravel-Standardkomponenten, bei denen der Container einer davon ist. –

0

Andrej ist für einen guten Start, aber es gibt keine Notwendigkeit, einen Behälter für diesen Zweck zu entwerfen. Laravel wird mit einem mehr als fähigen container geliefert, in dem Sie Implementierungen an Schnittstellen binden können.

Mit Andrej Schnittstelle und konkreten Klassen, könnten Sie eine service provider erstellen, die die Klasse bindet Sie an die ICalendar Schnittstelle wollen:

(innerhalb des Registers Methode des Anbieters):

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

Natürlich ist es ist hier, dass Sie bedingt entscheiden werden, welche Klasse an die Schnittstelle binden soll (siehe Funktion class_exists).

Von diesem Punkt an können Sie sich darauf verlassen, dass der Laravel-Container diese Abhängigkeit injiziert, wo immer Sie sie brauchen. Zum Beispiel in einem CalendarController ‚s store Methode, man konnte einfach type hint die Schnittstelle und Laravel werden Sie automatisch eine Instanz der konkreten Klasse geben, die Sie an ihn gebunden:

use App\Contracts\ICalendar; 

class CalendarController extends Controller 
{ 
    ... 

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

ich die Dokumentation auf jeden Fall empfehlen das Lesen auf der container sowie providers.Etwas von Interesse für Sie könnte Contextual Binding sein, in dem Sie Implementierungen an Schnittstellen bedingt binden können.