it-swarm.com.de

Meine eigenen konsumieren Laravel API

Ich entwickle eine Laravel 4-App, mit der dieselben CRUD-Vorgänge für mein Dataset über eine JSON REST-API und eine Web-Benutzeroberfläche verfügbar gemacht werden. Um einen Verstoß gegen das DRY -Prinzip zu verhindern, sollte meine Benutzeroberfläche meine eigene API verwenden, indem alle Anforderungen von der Benutzeroberfläche zurück an die API geleitet werden. Ich bin mir jedoch nicht sicher, wie ich das am besten erreichen kann. Vermutlich hätte ich getrennte UI- und API-Controller und leite die Anfragen irgendwie durch. Oder sollte ich einen anderen Ansatz wählen?

Vielen Dank.

48
robjmills

Ich bastele eigentlich an der gleichen Idee und es ist ziemlich ordentlich. Mit Laravel haben Sie die Möglichkeit, interne Anfragen zu stellen (einige können sich auf HMVC beziehen, aber ich werde es nicht tun). Hier sind die Grundlagen einer internen Anfrage.

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

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

$response enthält jetzt die zurückgegebene Antwort der API. Normalerweise wird eine JSON-codierte Zeichenfolge zurückgegeben, die für Clients geeignet ist, für interne API-Anforderungen jedoch nicht besonders gut geeignet ist. Sie müssen hier ein paar Dinge erweitern, aber im Grunde besteht die Idee darin, das eigentliche Objekt für den internen Aufruf zurückzugeben und für externe Anforderungen die formatierte JSON-Antwort zurückzugeben. Sie können hier Dinge wie $response->getOriginalContent() für diese Art von Dingen verwenden.

Was Sie dabei beachten sollten, ist das Erstellen einer Art interner Dispatcher, mit der Sie API-Anforderungen auslösen und das ursprüngliche Objekt zurückgeben können. Der Dispatcher sollte auch fehlerhafte Anfragen oder falsche Antworten verarbeiten und entsprechende Ausnahmen auslösen.

Die Idee selbst ist solide. Eine API zu planen ist jedoch harte Arbeit. Ich würde empfehlen, dass Sie eine gute Liste aller Ihrer erwarteten Endpunkte erstellen und ein paar API-Versionen entwerfen und dann die beste auswählen.

44
Jason Lewis

HINWEIS: Wie vcardillo weiter unten ausgeführt hat, werden mit diesen Methoden keine Routenfilter aufgerufen.

Ich mache gerade das Gleiche und Jasons Antwort brachte mich in eine gute Richtung. Wenn ich mir die Dokumentation zu Symfony\Component\HttpFoundation\Request anschaue, habe ich herausgefunden, wie man den POST abruft, und alles andere, was ich tun muss. Angenommen, Sie verwenden ein Formular, hier ist ein Code, der Ihnen helfen könnte:

ERHALTEN:

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

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

POST:

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

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

POST mit Cookies

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

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

POST mit Dateien

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

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

Ich hoffe das hilft jemand anderem. Wenn Sie kein Formular verwenden oder Laravel Input/Cookie facade verwenden, ersetzen Sie die Input/Cookie-Fassaden durch Ihren eigenen Inhalt.

24
Domenic Fiore

Taylor Otwell vorgeschlagen Verwenden von app()->handle() anstelle von Route::dispatch(), um eine saubere Anforderung zu erzielen.

Für Route::dispatch($request) ist mir aufgefallen, dass der Endpunkt Ihrer Nicht-GET-Anforderung (Parameter im HTTP-Anforderungshauptteil) eine abhängige Abhängigkeit von \Illuminate\Http\Request oder \Illuminate\Foundation\Http\FormRequest-Erweiterungsinstanz verwendet. Der Zustand der Parameter, Cookies, Dateien usw. stammt von original. HTTP-Anfrage für die Controller-Aktionsmethode Ihrer Anwendung.

Wenn Parameternamen und Post-Method-Typ für App-Controller und API-Controller identisch sind, werden Sie den Unterschied nicht bemerken, da die ursprünglichen Parameterwerte weitergegeben werden. Wenn Sie jedoch den dritten Parameter von Request::create() manuell zusammenstellen, führt Route::dispatch() dazu, dass er ignoriert wird.

app()->handle() behebt dieses Kontextproblem im Lebenszyklus von Laravel-Anforderungen.

Caveat:app()->handle() beeinflusst Illuminate\Support\Facades\Request und aktualisiert ihn mit dieser neuen Anforderungsinstanz. Anrufe wie Request::isXmlHttpRequest() oder redirect()->back(), die nach app()->handle() aufgerufen werden, verursachen als Folgeeffekt unvorhersehbares Verhalten. Ich würde vorschlagen, den Kontext Ihrer ursprünglichen Anfrage zu verfolgen und stattdessen redirect()->to(route('...')) zu verwenden, um den Fluss und den Status Ihrer App streng zu steuern.

In all diesen Eckfällen kann es am besten sein, ein manuelles Curl mit einem Guzzle HTTP-Client auszuführen.

13
Derek MacDonald

Wenn Sie Ihre eigene API verwenden, verwenden Sie app()->handle() anstelle von Route::dispatch(), wie Derek MacDonald vorgeschlagen hat.

app()->handle() erstellt eine neue Anforderung, während Route::dispatch() die Route innerhalb des Stapels ausführt und die Parameter ignoriert, die Teil der von Ihnen gesendeten Anforderung sind.

Edit: Nur ein Heads-Up. Taylor Otwell rät davon ab, Unteranfragen für interne API-Aufrufe zu verwenden, da diese die aktuelle Route durcheinanderbringen . Sie können stattdessen einen HTTP-API-Client wie Guzzle verwenden, um die API-Aufrufe auszuführen.

2
jpcaparas

Sie können Optimus-API-Consumer verwenden , die API ist sauber und einfach. Beispiel für eine interne Anforderung:

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

Im Kern verwendet es Illuminate\Routing\Router und Illuminate\Http\Request, um den Anruf durchzuführen

// 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

Wenn Sie intern nach Passport-Login-API suchen, müssen Sie die Parameter zur ursprünglichen Anfrage hinzufügen:

    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

Wenn Sie intern nach Passport-Login-API suchen, müssen Sie die Parameter zur ursprünglichen Anfrage hinzufügen:

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