Heim  >  Artikel  >  PHP-Framework  >  Analysieren des Contracts-Vertrags unter dem Laravel-Framework

Analysieren des Contracts-Vertrags unter dem Laravel-Framework

藏色散人
藏色散人nach vorne
2020-01-31 20:08:142047Durchsuche

Analysieren des Contracts-Vertrags unter dem Laravel-Framework

Verträge

Der Vertrag von Laravel besteht aus einer Reihe von Schnittstellen, die die vom Framework bereitgestellten Kerndienste definieren Kapitel zur Einführung in die Benutzerauthentifizierung: Der Benutzerüberwachungsvertrag IllumninateContractsAuthGuard und der Benutzeranbietervertrag IlluminateContractsAuthUserProvider sowie der IlluminateContractsAuthAuthenticatable-Vertrag, der durch das AppUser-Modell implementiert wird, das mit dem Framework geliefert wird.

Warum Verträge verwenden?

Anhand der Quellcodedateien der oben genannten Verträge können wir erkennen, dass es sich bei dem von Laravel bereitgestellten Vertrag um eine Reihe von definierten Schnittstellen handelt das Kernmodul. Laravel stellt für jeden Vertrag entsprechende Implementierungsklassen bereit. In der folgenden Tabelle sind die von Laravel für die drei oben genannten Verträge bereitgestellten Implementierungsklassen aufgeführt.

Analysieren des Contracts-Vertrags unter dem Laravel-Framework

Wenn also in Ihrem eigenen Entwicklungsprojekt das von Laravel bereitgestellte Benutzerauthentifizierungssystem Ihre Anforderungen nicht erfüllen kann, können Sie die Implementierungsklassen des Watchers und des Benutzeranbieters entsprechend Ihren Anforderungen definieren Anforderungen wie: Das Projekt, an dem ich zuvor gearbeitet habe, bestand darin, dass die Benutzerauthentifizierung auf der API des Mitarbeiterverwaltungssystems des Unternehmens beruhte. Daher habe ich die Implementierungsklasse des Guard- und Benutzeranbietervertrags selbst geschrieben und Laravel die Benutzerauthentifizierung über den benutzerdefinierten Guard abschließen lassen und UserProvider. Wir haben die Methode zum Anpassen der Benutzerauthentifizierung im Kapitel zur Einführung in die Benutzerauthentifizierung vorgestellt. Leser können diesen Artikel lesen.

Der Zweck der Definition von Vertragsschnittstellen für alle Kernfunktionen durch Laravel besteht also darin, Entwicklern zu ermöglichen, ihre eigenen Implementierungsklassen entsprechend den Anforderungen ihrer eigenen Projekte zu definieren, und für Verbraucher dieser Schnittstellen (z. B. Controller oder Der Kernel stellt AuthManager usw. bereit.) Sie müssen sich nicht darum kümmern, wie die von der Schnittstelle bereitgestellten Methoden implementiert werden. Sie kümmern sich nur darum, welche Funktionen die Schnittstellenmethoden bereitstellen können, und können diese Funktionen dann ändern Schnittstelle bei Bedarf entsprechend den Anforderungen anpassen. Auf der Verbraucherseite sind keine Änderungen erforderlich.

Verträge definieren und verwenden

Was wir oben erwähnt haben, sind alle vom Laravel-Kernel bereitgestellten Verträge. Bei der Entwicklung großer Projekte können wir den Vertrag auch selbst im Projekt definieren Sie haben möglicherweise das Gefühl, dass die integrierten Controller- und Modellebenen ausreichen, um Code aus dem Nichts zu schreiben. Das Hinzufügen zusätzlicher Verträge und Implementierungsklassen macht die Entwicklung umständlich. Beginnen wir mit einem einfachen Beispiel und überlegen, was mit dem folgenden Code nicht stimmt:

class OrderController extends Controller
{
    public function getUserOrders()
    {
        $orders= Order::where('user_id', '=', \Auth::user()->id)->get();
        return View::make('order.index', compact('orders'));
    }
}

Dieser Code ist sehr einfach, aber wenn wir diesen Code testen möchten, müssen wir uns an die tatsächliche Datenbank wenden.

Mit anderen Worten, der ORM und dieser Controller sind eng miteinander verbunden. Wir haben keine Möglichkeit, diesen Code auszuführen oder zu testen, ohne das Eloquent ORM zu verwenden und eine Verbindung zu einer tatsächlichen Datenbank herzustellen. Dieser Code verstößt auch gegen das Software-Designprinzip der „Separation of Concerns“.

Um es einfach auszudrücken: Dieser Controller weiß zu viel.

Der Verantwortliche muss nicht wissen, woher die Daten kommen, er muss nur wissen, wie er darauf zugreifen kann. Der Controller muss nicht wissen, woher die Daten von MySQL kommen, er muss lediglich wissen, dass die Daten aktuell verfügbar sind.

Trennung der Belange

Jede Klasse sollte eine einzige Verantwortung haben, und diese Verantwortung sollte vollständig von der Klasse übernommen werden.

Jede Klasse sollte nur eine einzige Verantwortung haben und alles in der Verantwortung sollte von dieser Klasse gekapselt werden

Als nächstes definieren wir eine Schnittstelle und implementieren dann die Schnittstelle

interface OrderRepositoryInterface 
{
    public function userOrders(User $user);
}
 
class OrderRepository implements OrderRepositoryInterface
{
    public function userOrders(User $user)
    {
        Order::where('user_id', '=', $user->id)->get();
    }
}

Binden Sie die Implementierung der Schnittstelle zum Service-Container von Laravel

App::singleton('OrderRepositoryInterface', 'OrderRespository');

Dann injizieren wir die Implementierung der Schnittstelle in unseren Controller

class UserController extends Controller
{
    public function __construct(OrderRepositoryInterface $orderRepository)
    {
        $this->orders = $orderRespository;
    }
   
    public function getUserOrders()
    {
        $orders = $this->orders->userOrders();
        return View::make('order.index', compact('orders'));
    }
}

Jetzt ist unser Controller völlig unabhängig von der Datenschicht. Dabei können unsere Daten von MySQL, MongoDB oder Redis stammen. Unser Controller kennt den Unterschied nicht und muss ihn auch nicht kennen. Auf diese Weise können wir die Webschicht unabhängig von der Datenschicht testen und es wird in Zukunft einfach sein, die Speicherimplementierung zu wechseln.

Schnittstellen- und Teamentwicklung

Wenn Ihr Team eine große Anwendung entwickelt, haben verschiedene Teile unterschiedliche Entwicklungsgeschwindigkeiten.

Zum Beispiel entwickelt ein Entwickler die Datenschicht und ein anderer Entwickler arbeitet an der Controller-Schicht.

Der Entwickler, der den Controller geschrieben hat, möchte seinen Controller testen, aber die Entwicklung der Datenschicht ist langsam und kann nicht gleichzeitig getestet werden. Wenn sich zwei Entwickler zunächst in Form einer Schnittstelle einigen können, folgen alle im Hintergrund entwickelten Klassen dieser Vereinbarung.

Sobald die Vereinbarung festgelegt ist, kann der Entwickler eine „gefälschte“ Implementierung für diese Schnittstelle schreiben, auch wenn die Vereinbarung noch nicht implementiert wurde.

class DummyOrderRepository implements OrderRepositoryInterface 
{
    public function userOrders(User $user)
    {
        return collect(['Order 1', 'Order 2', 'Order 3']);
    }
}

Sobald die gefälschte Implementierung geschrieben ist, kann er dies im IoC-Container an

App::singleton('OrderRepositoryInterface', 'DummyOrderRepository');

gebunden werden und dann kann die Ansicht dieser Anwendung mit gefälschten Daten gefüllt werden. Sobald der Backend-Entwickler beispielsweise mit dem Schreiben des eigentlichen Implementierungscodes fertig ist, wird dieser als RedisOrderRepository bezeichnet.

那么使用IoC容器切换接口实现,应用就可以轻易地切换到真正的实现上,整个应用就会使用从Redis读出来的数据了。

接口与测试

建立好接口约定后也更有利于我们在测试时进行Mock

public function testIndexActionBindsUsersFromRepository()
{    
    // Arrange...
    $repository = Mockery::mock('OrderRepositoryInterface');
    $repository->shouldReceive('userOrders')->once()->andReturn(['order1', 'order2]);
    App::instance('OrderRepositoryInterface', $repository);
    // Act...
    $response  = $this->action('GET', 'OrderController@getUserOrders');
         
    // Assert...
    $this->assertResponseOk();
    $this->assertViewHas('order', ['order1', 'order2']);
 }

总结

接口在程序设计阶段非常有用,在设计阶段与团队讨论完成功能需要制定哪些接口,然后设计出每个接口具体要实现的方法,方法的入参和返回值这些,每个人就可以按照接口的约定来开发自己的模块,遇到还没实现的接口完全可以先定义接口的假实现等到真正的实现开发完成后再进行切换,这样既降低了软件程序结构中上层对下层的耦合也能保证各部分的开发进度不会过度依赖其他部分的完成情况。

更多laravel框架相关技术文章,请访问laravel教程栏目!

Das obige ist der detaillierte Inhalt vonAnalysieren des Contracts-Vertrags unter dem Laravel-Framework. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen