Использование моего собственного API Laravel


Я разрабатываю приложение Laravel 4, которое сделает те же операции CRUD с моим набором данных доступными через API REST JSON и веб-интерфейс. Похоже, что для предотвращения нарушения принципа DRY, согласно которому мой пользовательский интерфейс должен использовать мой собственный API, перенаправляя все запросы из пользовательского интерфейса обратно в API. Я не уверен, однако, в том, как лучше всего подойти к этой работе. Предположительно, у меня были бы отдельные контроллеры пользовательского интерфейса и API, и я каким-то образом перенаправлял бы запросы. Или мне следует рассмотреть другой подход в целом?

Спасибо.

Author: robjmills, 2013-05-13

7 answers

На самом деле я работаю над той же идеей, и это довольно аккуратно. С Laravel у вас есть возможность делать внутренние запросы (некоторые могут называть это HMVC, но я не буду). Вот основы внутреннего запроса.

$request = Request::create('/api/users/1', 'GET');

$response = Route::dispatch($request);

$response теперь будет содержать возвращенный ответ API. Обычно это будет возвращена строка в кодировке JSON, которая отлично подходит для клиентов, но не настолько хороша для внутреннего запроса API. Вам придется расширить здесь несколько вещей, но в основном идея заключается в том, чтобы вернуть фактический объект обратно для внутреннего вызова, а для внешних запросов вернуть отформатированный ответ JSON. Вы можете использовать такие вещи, как $response->getOriginalContent() здесь для такого рода вещей.

Что вам следует сделать, так это создать своего рода внутренний Dispatcher, который позволит вам отправлять запросы API и возвращать исходный объект. Диспетчер также должен обрабатывать неправильно сформированные запросы или неправильные ответы и создавать исключения для соответствия.

Сама идея основательна. Но планирование API - это тяжелая работа. Я бы рекомендовал вам составить хороший список всех ваших ожидаемых конечных точек и составить несколько версий API, а затем выбрать лучшую.

 40
Author: Jason Lewis, 2013-05-14 00:37:19

ПРИМЕЧАНИЕ: Как vcardillo указал ниже, фильтры маршрутов не вызываются с помощью этих методов.

В настоящее время я делаю то же самое, и ответ Джейсона заставил меня двигаться в правильном направлении. Посмотрев документацию Symfony\Component\HttpFoundation\Request, я понял, как ПУБЛИКОВАТЬ, а также все остальное, что мне нужно сделать. Предполагая, что вы используете форму, вот некоторый код, который может вам помочь:

ПОЛУЧИТЬ:

$request = Request::create('/api/users/1', 'GET');

$response = Route::dispatch($request);

СООБЩЕНИЕ:

$request = Request::create('/api/users/1', 'POST', Input::get());

$response = Route::dispatch($request);

СООБЩЕНИЕ w/ файлы cookie

$request = Request::create('/api/users/1', 'POST', Input::get(), Cookie::get('name'));

$response = Route::dispatch($request);

СООБЩЕНИЕ с файлами

$request = Request::create('/api/users/1', 'POST', Input::get(), null, Input::file('file'));

$response = Route::dispatch($request);

Я надеюсь, что это поможет кому-то еще. Если вы не используете форму или используете, но не используете фасад ввода/файлов cookie Laravel, замените фасады ввода/файлов cookie своим собственным контентом.

 21
Author: Domenic Fiore, 2015-06-04 00:24:57

Тейлор Отуэлл предложил использовать app()->handle() вместо Route::dispatch() для получения чистого запроса.

Для Route::dispatch($request) Я заметил, что если конечная точка вашего запроса без GET (параметры в теле HTTP-запроса) использует введенную зависимость \Illuminate\Http\Request или \Illuminate\Foundation\Http\FormRequest расширяющий экземпляр, состояние параметров, файлы cookie, файлы и т. Д. Взяты из исходного HTTP-запроса. т.Е. Для метода действия контроллера вашего приложения.

Если имена параметров и тип метода публикации для вашего приложения контроллер и контроллер API одинаковы, вы не заметите разницы, так как передаются исходные значения параметров. Но когда вы вручную собираете 3-й параметр Request::create(), Route::dispatch() приведет к тому, что он будет проигнорирован.

app()->handle() устраняет эту проблему контекста в жизненном цикле запроса Laravel.

Предостережение: app()->handle() влияет на Illuminate\Support\Facades\Request, обновляя его с помощью этого нового экземпляра запроса. В качестве побочного эффекта такие вызовы, как Request::isXmlHttpRequest() или redirect()->back(), вызываемые после app()->handle(), вызовут непредсказуемое поведение. Я бы предложил отслеживать контекст вашего первоначального запроса и вместо этого использовать redirect()->to(route('...')), чтобы вы строго контролировали поток и состояние вашего приложения.

Учитывая все эти угловые случаи, возможно, лучше всего просто выполнить ручную завивку с помощью HTTP-клиента Guzzle.

 11
Author: Derek MacDonald, 2015-12-11 20:52:16

Если вы используете свой собственный API, используйте app()->handle() вместо Route::dispatch(), как предложил Дерек Макдональд.

app()->handle() создает новый запрос, в то время как Route::dispatch() выполняет маршрут в стеке, эффективно игнорируя параметры, которые являются частью отправляемого вами запроса.

Редактировать: Просто предупреждение. Тейлор Отуэлл советует не использовать подзапросы для выполнения внутренних вызовов API, так как они портят текущий маршрут. Вы можете использовать клиент HTTP API, такой как Guzzle, вместо того, чтобы вызовы API.

 2
Author: jpcaparas, 2017-08-08 09:42:08

Вы можете использовать Потребитель API Optimus, API чистый и простой, пример выполнения внутреннего запроса:

$response = app()->make('apiconsumer')->post('/oauth/token', $data);

В своей основе он использует Illuminate\Routing\Router и Illuminate\Http\Request для выполнения вызова

// create the request
$this->request->create($uri, $method, $data, [], [], $server, $content);

// get the response
$response = $this->router->prepareResponse($request, $this->app->handle($request));
 1
Author: Walid Ammar, 2017-05-26 18:55:58

Если вы хотите использовать api входа в систему passport внутренне, вам нужно добавить параметры в исходный запрос:

    protected function manualLogin(Request $request)
    {
        $email = $request->input('email');
        $password = $request->input('password');

        $request->request->add([
        'username' => $email,
        'password' => $password,
        'grant_type' => 'password',
        'client_id' => $clientID,
        'client_secret' => $clientSecret,
        'scope' => '*']);

    $newRequest = Request::create('/oauth/token', 'post');

    return Route::dispatch($newRequest)->getContent();
}
 1
Author: Pankaj Garg, 2017-10-17 08:59:01

Если вы хотите использовать api входа в систему passport внутренне, вам нужно добавить параметры в исходный запрос:

protected function manualLogin(Request $request)
{
    $email = $request->input('email');
    $password = $request->input('password');

    $request->request->add([
        'username' => $email,
        'password' => $password,
        'grant_type' => 'password',
        'client_id' => $clientID,
        'client_secret' => $clientSecret,
        'scope' => '*']);

    $newRequest = Request::create('/oauth/token', 'post');

    return Route::dispatch($newRequest)->getContent();
}
 0
Author: Pankaj Garg, 2017-10-17 08:07:14