Rest API - struktura, wiele repozytoriów

0

Lepiej zrobić kilka endpointów, z których każdy zwraca model powiązany z repozytorium (getById, getByName, etc.).
Następnie pobierałbym dane z każdego z tych endpointów po stronie frontendu.
Nie podoba mi się takie rozwiązanie - jest to pomieszanie logiki backendowej z tym co się dzieje na froncie:

Backend:

class TestRepository implements TestRepositoryInterface
{
 public function getById(int $id): TestInterface
    {
    }

 public function getByName(string $name): TestInterface
    {
    }

 public function getByStatus(string $status): TestInterface
    {
    }
}

Frontend:

$.ajax({
    type: "get",
    url: `/rest/V1/module/test?id=${id}`,
    contentType: 'application/json',
    cache: true
}).done($.proxy(function(response) {
    if (response.status === 1) {
        $.ajax({
            type: "get",
            url: `/rest/V1/module/test?name=${response.name}`,
            contentType: 'application/json',
            cache: true
        }).done($.proxy(function(response) {
            this.onDone(JSON.parse(response));
        }, this))
    } else {
        $.ajax({
            type: "get",
            url: `/rest/V1/module/test?name=${response.status}`,
            contentType: 'application/json',
            cache: true
        }).done($.proxy(function(response) {
            this.onDone(JSON.parse(response));
        }, this))
    }
}, this)).fail($.proxy(function(response, status, error) {
    this.onFail(response, status, error);
}, this))

Wolałbym całą logikę zrobić po stronie php.
Czyli coś na wzór:

Backend:

class TestRepository implements TestRepositoryInterface
{
 public function getByFilterData(int $id, string $name, string $status): TestInterface
    {
        $test = $this->getById($id);

        if($test->getStatus() === 1){
            return $this->getByName($name);
        } else {
            return $this->getByStatus($status);
        }
    }
}

Frontend:

$.ajax({
    type: "get",
    url: `/rest/V1/module/test?id=${id}&name=${name}&status=${status}`,
    contentType: 'application/json',
    cache: true
}).done($.proxy(function(response) {
    this.onDone(JSON.parse(response));
}, this)).fail($.proxy(function(response, status, error) {
    this.onFail(response, status, error);
}, this))

Ostatnie pytanie:

Czy w danym repozytorium, które jest powiązane z rest api mogę wstrzykiwać inne repozytoria?
Jeżeli nie - jak w takim wypadku obejść konieczność pobierania danych z innych repozytoriów?

1

jak w takim wypadku obejść konieczność pobierania danych z innych repozytoriów?

Jeśli doszło do takiej sytuacji, to znaczy, że źle wyznaczyłeś bounded context i powinieneś przeprojektować aplikację.

Jeżeli w ogóle nie wyznaczałeś bounded contextów, to znaczy, że nie robisz DDD i nie masz żadnych repozytoriów, a zwyczajne DAO (data access object) / TDG (table data gateway) - w takim wypadku możesz robić co chcesz.

(w temacie: http://commitandrun.pl/2016/0[...]potrzebny_wzorzec_projektowy/)

TestInterface

Robisz interfejsy do encji / DTO?

3

To całkiem proste, wystarczy wstawić warstwę pomiędzy kontrolerami a repozytoriami, w której zagregujesz wyniki z wielu zapytań. Czy to rozwiązuje problem wstrzykiwania repo w repo?

0

@Patryk27:

To Magento2, stosuje tutaj service contracts.
Tak robię interfejsy do DTO.
Wzoruje się na praktykach z bardziej znanych wtyczek (Amasty/Mirasvit).

@Charles_Ray, @Patryk27:

Utworzenie serwisu/helpera, w którym to korzystam z kilku repozytoriów a następnie wstrzyknięcie go do danego repozytorium, po to żeby użyć go w moim endpoincie będzie złą praktyką (widziałem takie rozwiązanie w jednym z modułów od DPD)?

0

Jak robisz endpoint na listę to nie robisz stosu endpointów tylko jeden z różnymi parametrami. Jak chcesz pobrać konkretny to też może być jeden gdzie brany jest pod uwagę który parametr został przesłany.

4

Prościej byłoby mieć zamiast zestawu "repozytoriów" i helperów po prostu klasę, która z bazy wyciągnie odpowiednie dane i zwróci jako DTO w potrzebnym nam kształcie.
Dzięki temu można zoptymalizować zapytanie, pobrać tylko te dane, które są potrzebne, jest spora szansa na uniknięcie N+1, nie będzie overengineeringu, nie będzie "repozytoriów", no i ogólnie można uniknąć sporo wtfów rzuconych przez następne pokolenia.

3

To co chcesz osiągnąć najlepiej zrobić za pomocą materialized view ale pociąga to za sobą pewne wyzwania architektoniczne- np. jak utworzyć taki widok na podstawie tego co dzieje się w różnych częściach systemu.

Samo budowanie widoku przez frontend poprzez wyciąganie danych z różnych endpointów nie jest jednak niczym niezwykłym więc niekoniecznie jest złym rozwiązaniem. Z logiką biznesową również nie ma nic wspólnego..

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0