RESTful API: данные из нескольких конечных точек в одном представлении - PullRequest
1 голос
/ 23 января 2020

Я начал создавать RESTful API (ну, я сделал все возможное, я стараюсь следовать шаблонам), и я наткнулся на сценарий, который я не совсем уверен, как справиться. Я объясню текущую структуру:

Мое приложение имеет 4 контроллера:

  • Клиенты
  • Платежи
  • Журнал

Взяв в качестве примера контроллер «Клиенты», я определил следующие действия:

  • GET / Customers: возвращает список клиентов
  • POST / Customers: создает нового клиента
  • GET / Customers / {id}: возвращает клиента с указанным идентификатором
  • PUT / Customers / {id}: обновляет клиента с указанным идентификатором
  • DELETE / Customers / {id}: уничтожает клиента

Полный код контроллера клиента:

namespace App\Http\Controllers;

use App\Customer;
use Illuminate\Http\Request;

class CustomerController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return Customer::all();
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $customer = Customer::create($request->all());
        return response()->json($customer, 201);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Customer  $customer
     * @return \Illuminate\Http\Response
     */
    public function show(Customer $customer)
    {
        return $customer;
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Customer  $customer
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Customer $customer)
    {
        $customer->update($request->all());
        return response()->json($customer, 200);

    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Customer  $customer
     * @return \Illuminate\Http\Response
     */
    public function destroy(Customer $customer)
    {
        $customer->delete();
        return response()->json(null, 204);
    }
}

Код очень похож на других контроллерах. Также важно отметить, что:

  • Клиент может иметь несколько платежей
  • Клиент может иметь несколько записей в журнале

Проблема начинается здесь :

Мне нужно отобразить на внешнем интерфейсе сводную страницу со всеми данными клиента (имя, адрес электронной почты, дата регистрации и т. Д. c), а также поле, отображающее количество совершенных платежей, и другое поле, отображающее количество записей в журнале.

Нужно ли делать 3 запроса? (Один для / клиентов / идентификатора, другой для клиентов / идентификатора / платежей и другой для клиентов / идентификатора / журналов)

Если я возвращаю все данные, относящиеся к клиенту, в вызове клиентов / идентификатора, я нарушаю RESTful конвенция

Ответы [ 2 ]

1 голос
/ 23 января 2020

Я использую apigility, но мой ответ все равно будет связан с вашим вопросом. Согласно терминологии REST (которую можно найти здесь https://apigility.org/documentation/intro/first-rest-service#terminology), вы говорите о сущности и коллекции.

/customers/id - entity,
/customers/id/payments - collection,
/customers/id/logs - collection. 

Это 3 разных запроса. Итак, да, вам нужно сделать 3 разных запроса.

Но, если честно, если вам не нужно разбивать на страницы над payments и logs, вы можете иметь только один запрос к / customer / id и в ответе вы можете иметь поля с массивом

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/status/3c10c391-f56c-4d04-a889-bd1bd8f746f0"
        }
    },
    "id": "3c10c391-f56c-4d04-a889-bd1bd8f746f0",
    ...
    _payments: [
        ...
    ],
    _logs: [
        ...
    ],
}

Upd (дублировать комментарий для будущих посетителей).

Также вам следует обратить внимание на DTO. Полагаю, эта ссылка будет интересной { ссылка }.

Upd2 .

В настоящий момент я отношусь к вашей коллекции /customers/id/payments следующим образом:

/payments?user_id=123

где user_id - поле фильтрации в таблице payments.

0 голосов
/ 24 января 2020

Думаю, ваша проблема в том, что вы путаете ваш REST API с вашей базой данных. Они не должны следовать той же структуре. Вы можете легко вернуть все вложенные JSON для GET /customers/{id}, если это то, что вам нужно из вашего REST API.

...