I'm developing a Laravel 4 app that will make the same CRUD operations on my dataset available through a JSON REST API and a Web UI. It seems that to prevent breaking the DRY principle that my UI should consume my own API by routing all requests from the UI back to the API. I'm unsure though about the best approach to making this work. Presumably I would have separate UI and API controllers and somehow route the requests through. Or should I be looking at a different approach altogether?
Thanks.
NOTE: As vcardillo pointed out below, route filters are not called with these methods.
I am currently doing the same thing, and Jason's answer got me going in a great direction. Looking at the Symfony\Component\HttpFoundation\Request documentation, I figured out how to POST, as well as everything else I'd need to do. Assuming you're using a form, here is some code that could help you:
GET:
POST:
POST w/ cookies
POST w/ files
I hope this helps someone else. If you aren't using a form, or you are but not using Laravel's Input / Cookie facade, replace the Input / Cookie facades with your own content.
I'm actually tinkering with the same idea and it's pretty neat. With Laravel you do have the ability to make internal requests (some might refer to this as HMVC, but I won't). Here's the basics of an internal request.
$response
will now contain the returned response of the API. Typically this will be returned a JSON encoded string which is great for clients, but not that great for an internal API request. You'll have to extend a few things here but basically the idea is to return the actual object back through for the internal call, and for external requests return the formatted JSON response. You can make use of things like$response->getOriginalContent()
here for this kind of thing.What you should look at doing is constructing some sort of internal
Dispatcher
that allows you to dispatch API requests and return the original object. The dispatcher should also handle malformed requests or bad responses and throw exceptions to match.The idea itself is solid. But planning an API is hard work. I'd recommend you write up a good list of all your expected endpoints and draft a couple of API versions then select the best one.
You can use Optimus API consumer, the API is clean and simple, example making an internal request:
In it's core, it uses
Illuminate\Routing\Router
andIlluminate\Http\Request
to make the callTaylor Otwell suggested using
app()->handle()
rather thanRoute::dispatch()
to achieve a clean request.For
Route::dispatch($request)
I noticed if the endpoint of your non-GET request (parameters on the HTTP request body) uses a dependency injected\Illuminate\Http\Request
or\Illuminate\Foundation\Http\FormRequest
extending instance, state of the parameters, cookies, files, etc. are from the original HTTP request. i.e., for your application's controller action method.If parameter names and post method type for your app controller and API controller are the same, you won't notice the difference since the original parameter values are passed on. But when you're manually assembling the 3rd parameter of
Request::create()
,Route::dispatch()
will result in it being ignored.app()->handle()
fixes that context problem in the Laravel request lifecycle.Caveat:
app()->handle()
affectsIlluminate\Support\Facades\Request
, refreshing it with this new request instance. As a knock-on effect, calls likeRequest::isXmlHttpRequest()
orredirect()->back()
invoked afterapp()->handle()
will cause unpredictable behaviour. I'd suggest tracking the context of your original request and instead useredirect()->to(route('...'))
so you strictly control flow and state of your app.Given all these corner cases, it may be best to just do a manual curl using a Guzzle HTTP client.
If you are looking for using passport login api internally, then you need to add the parameters to original request:
If you're consuming your own API, use
app()->handle()
instead ofRoute::dispatch()
as Derek MacDonald has suggested.app()->handle()
creates a fresh request, whileRoute::dispatch()
runs the route within the stack, effectively ignoring parameters that are part of the request that you're sending.Edit: Just a heads-up. Taylor Otwell advises against using sub-requests to make internal API calls, as they mess the current route. You can an HTTP API client like
Guzzle
instead to make the API calls.