Buduję REST API korzystając laravel 5.laravel 5.0 Zastosowanie Struktura
Starając się zachować kontrolerów HTTP jest możliwie jak najmniejszy, więc używam warstwie usług (i repozytoriów), aby obsłużyć najbardziej logiki.
Ponieważ większość kontrolerów ma podobne metody (np. show
, index
, update
) Napisałem kilka cech, które obsługują każdy z nich. Ponieważ rozmawiają bezpośrednio z usługą, mogę je ponownie wykorzystać dla każdego kontrolera.
Na przykład:
<?php namespace API\Http\Controllers\Restful;
trait UpdateTrait
{
protected $updater;
public function update($itemID)
{
if (!$this->updater->authorize($itemID)) {
return response(null, 401);
}
if (!$this->updater->exists($itemID)) {
return response(null, 404);
}
$data = $this->request->all();
$validator = $this->updater->validator($data);
if ($validator->fails()) {
return response($validator->messages(), 422);
}
$this->updater->update($itemID, $data);
return response(null, 204);
}
}
Ponieważ wszystkie kontrolery posiadają te same cechy, wszystkie one mogą polegać na jednym interfejsie.
Na przykład:
<?php namespace API\Services\Interfaces;
interface UpdaterServiceInterface
{
public function validator(array $data);
public function exists($itemID);
public function update($itemID, array $data);
public function authorize($itemID);
}
Jednak to powoduje kilka problemów z automatycznego wstrzykiwania zależności.
1) muszę używać kontekst świadomy Oprawa:
$this->app->when("API\Http\Controllers\ThingController")
->needs("API\Services\Interfaces\UpdateServiceInterface")
->give("API\Services\Things\ThingUpdateServiceInterface")
To nie jest problematyczna w sobie - mimo że nie prowadzi do pewnego dość dużego kodu Service Provider, który nie jest idealny. Oznacza to jednak, że nie mogę użyć metody iniekcji, ponieważ automatyczna zależność wydaje się nie działać dla metod kontrolera podczas używania kontekstowego wiązania: Właśnie otrzymuję komunikat o błędzie.
Oznacza to, że konstruktor kontroler musi obsługiwać wszystkie wstrzykiwania zależności, który jest dość niechlujny:
class ThingsController extends Controller
{
use Restful\IndexTrait,
Restful\ShowTrait,
Restful\UpdateTrait,
Restful\PatchTrait,
Restful\StoreTrait,
Restful\DestroyTrait;
public function __construct(
Interfaces\CollectionServiceInterface $collection,
Interfaces\ItemServiceInterface $item,
Interfaces\CreatorServiceInterface $creator,
Interfaces\UpdaterServiceInterface $updater,
Interfaces\PatcherServiceInterface $patcher,
Interfaces\DestroyerServiceInterface $destroyer
) {
$this->collection = $collection;
$this->item = $item;
$this->creator = $creator;
$this->updater = $updater;
$this->patcher = $patcher;
$this->destroyer = $destroyer;
}
}
To nie jest dobry - to trudne do testowania i wszystkie te zależności mają dostać instancja, nawet gdy używa się tylko jednego z nich.
Ale nie mogę wymyślić ładniejszego sposobu obejścia tego.
Mogę użyć bardziej szczegółowego interfejsu, np. ThingUpdateServiceInterface
, (wtedy nie potrzebowałbym wiązania kontekstowego i mógłbym wstrzyknąć bezpośrednio w cechy), ale wtedy miałbym wiele interfejsów, które różnią się tylko nazwą. Co wydaje się głupie.
Inną alternatywą, o której myślałem, było użycie wielu mniejszych kontrolerów, więc Things\UpdateController
i Things\ShowController
- w ten sposób niepotrzebne zależności nie będą tworzone za każdym razem.
A może próba oderwania się od używania cech jest złym sposobem robienia rzeczy. Cechy czasami wydają się być potencjalnie anty-wzorem.
Każda rada byłaby doceniona.
Dzięki za miłe, szczegółowe pytanie. W jaki sposób utworzyć 'UpdateService' za pomocą kodu w UpdateTrait i wpisać-podpowiedź w swojej metodzie aktualizacji RESTful, np.' Public function update ($ ItemID, UpdateService) 'Nie testowałem tego ciasta, ale myślę, że to może nie być . Możesz mieć problem ze swoimi testami, jeśli będziesz kontynuował to, co masz do tej pory – Digitlimit
W L5 możesz zrobić to, co nazywa się Method Injection, patrz [tutaj] (https://mattstauffer.co/blog/laravel-5.0-method-injection) co więcej, chciałbym stworzyć middleware autoryzacji + "istniejące" oprogramowanie pośredniczące i używać klasy żądania w jak największym stopniu. Cechy są ładną abstrakcją kodu, ale później napotkasz problemy, które myślę po prostu dlatego, że do tej pory aplikacja nie jest "skomplikowana", czas mija, a aplikacja staje się coraz bardziej złożona, więc będziesz potrzebował "unikalnego" aktualizatora, patchera być może niszczyciel (powiedzmy, że robisz kilka relacji M: N). A co z tworzeniem RestfullController? I czy coś się przedłuża? – Kyslik
- Wstrzyknięcie metody nie działa, gdy używasz powiązania kontekstowego lub przynajmniej nie mogę go uzyskać. - Nie chcę tworzyć pojedynczego RestfulController i przedłużam, ponieważ sporo z nich nie będzie używać większości metod (np. Niektóre mają tylko 'index' i' show'). - Korzystam już z auth middleware, ale wydaje mi się, że mam je również w usługach (np. Jeśli korzystam z usługi dla konsoli zamiast HTTP) –