it-roy-ru.com

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

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

Благодарю.

48
robjmills

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

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

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

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

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

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

44
Jason Lewis

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

В настоящее время я делаю то же самое, и ответ Джейсона заставил меня двигаться в отличном направлении. Просматривая Symfony\Component\HttpFoundation\Request документацию, я выяснил, как выполнить POST, а также все остальное, что мне нужно сделать. Предполагая, что вы используете форму, вот код, который может вам помочь:

ПОЛУЧИТЬ:

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

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

СООБЩЕНИЕ:

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

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

POST с печеньем

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

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

POST w/files

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

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

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

24
Domenic Fiore

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

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

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

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

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

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

13
Derek MacDonald

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

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

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

2
jpcaparas

Вы можете использовать Optimus API customer , 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
Walid Ammar

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

    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
Pankaj Garg

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

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
Pankaj Garg