2016-12-04 5 views
0

Я собираюсь создать с нуля PHP-клиент для REST API. Я рассматриваю использование Guzzle library.Что такое хорошая архитектура для клиента API?

Я думаю, что пользователь не должен иметь дело с транспортными вещами, такими как объекты запроса (даже из пользовательских классов xxxRequest) и должен иметь дело только с бизнес-объектами/классами обслуживания. Но может быть, я ошибаюсь ...

Вот несколько примеров возможных архитектур. Какая уважительная практика и почему?
Не стесняйтесь улучшать их или предлагать лучший способ.


Пример 1:

class ApiClient { 
    function createBooking (BookingEntity $booking, CustomerEntity $customer) { 
     //... 
    } 
} 

Этот пример позволяет пользователю использовать только бизнес-объект, но класс ApiClient может начать быть загрязнен, если API нужно много методов ... Кроме того ApiClient необходимо изменить, если мы хотим добавить функции.


Пример 2:

class ApiClient { 
    function execute(CreateBookingRequest $createBookingRequest) { 
     //... 
    } 
} 

class CreateBookingRequest { 
    private BookingEntity $booking; 
    private CustomerEntity $customer; 
    private $queryParams; 

    public createQueryParams() { 
     // to create the query params (from the attibutes) for the http client 
    } 
} 

Вот если новая функция необходима в ApiClient не должен быть изменен, только новый класс должен быть создан. Однако пользователь должен иметь дело с классами с именем суффикса Request. ИМО он ничего не знает о запросе или технических вещах.


Пример 3:

class BookingService { 
    function createBooking (BookingEntity $booking, CustomerEntity $customer) { 
    //... 
    } 
} 

В этом примере добавить один слой.


Во всех случаях, где должно быть жрать HTTPClient атрибут в классе ApiClient/Service? Или класс ApiClient расширяет класс Guzzle Client?

ответ

1

Ну, нет никаких реальных стандартов для этого, но это определенно горячая тема, и я бы даже сказал, что это не конкретизация Guzzle.

Короткий ответ: Я выбрал бы вариант 1 и 3 в зависимости от сложности API.

Более длинный ответ: если есть определенные ресурсы (например, резервирование для получения, создания, удаления и еще несколько), то я бы пошел с опцией 3. Если есть только несколько вызовов API, я бы по-прежнему пошел с опцией три, поскольку это лучшее представление с точки зрения API (ваш клиент API на самом деле является просто ОСУЩЕСТВЛЕНИЕМ API, поэтому он должен следовать соглашениям API, терминологии ... по крайней мере теоретически), но вариант 1 может быть быстрее и легче понять сначала. Техническое обслуживание может усложниться, если API становится более сложным, поэтому даже тогда вам придется переписать его на вариант 3.

Конфигурированный экземпляр Guzzle отправляется к конструктору вашего класса.

У вас все еще может быть клиентский класс API, если у вас есть классы ресурсов/сервисов, которые в этом случае не будут больше точки входа конфигурации и фабрики для ваших классов ресурсов.

Если вы планируете повторно использовать этот клиент в нескольких проектах, вы можете захотеть использовать абстракцию HTTP-клиента (например, вместо Guzzle, так как вы не сможете установить Guzzle 6 во всех них (конфликт зависимости и т. Д.).)

Последнее, но не менее вы можете проверить this аут, который собирается стать основой API/начальной загрузки для именно этих случаев (но это еще не закончена, так что используйте его на свой страх и риск)

+0

Очень Интересно, что бы вы предложили, если есть много входных параметров? Пример 2 позволяет помещать их как атрибуты в классы xxxRequest. Поскольку лучше использовать объект, а не много p араметры, как мы можем воспроизвести это в примере 1 и 3? Если мы добавим класс, что было бы хорошим соглашением об именах? Предположим, что xxxParam на данный момент, где должны быть функции адаптера для преобразования всех атрибутов xxxParam в параметры запроса для http-клиента (в данном случае тела json)? – Kwadz

+0

Все зависит от вашего домена. Множество параметров обычно означает какую-то структуру данных, а не совсем безразличные параметры. В таком случае я бы поместил их в классы моделей. Я могу снова указать на то, что клиент на самом деле является реализацией интерфейса, и, скорее всего, API также предоставляет модель данных, которую вы можете использовать как есть. Сериализация происходит внутри самого клиента, который знает, как сериализовать модель. При желании вы можете иметь отдельный уровень сериализации, но он все равно будет вызываться клиентом. –

+0

Хорошо, но если в методе createBooking есть много объектов модели в качестве входных параметров, я думаю, что это хорошая практика, чтобы обернуть их в один объект, не так ли? Например, допустим, что у нас есть параметры: http://pastebin.com/dBKJnk4S Я думаю, что 9 аргументов в методе createBooking не приемлемы, поэтому мы должны их обернуть, нет? Что это хороший способ сделать это? Что может быть хорошим суффиксом для этих классов, чтобы это было ясно? Где должен быть код для перевода его в json body? – Kwadz

Смежные вопросы