Brief:
Actually, I'm little bit confused while using Laravel api route file.
Question:
If I need to access the data of my web site in other platform (like android app) that is made using laravel, then should I create a different route in api.php file?
If yes then I will be declaring two routes and controllers for each request, first in web.php and second in api.php. Is it correct?
Basically, I want to ask that how I can make an api, so that I can access the data in website as well as in other platforms?
I was searching for a good tutorial for this, but I didn't got a good one.
Ideally the API routes and Web routes should be completely different but if you want it to be same then instead of defining routes in different file you can add routes only in web.php and add a special parameter from your client and in controller if you are getting the parameter then return the JSON Object or else return the view.
Eg.
web.php
Route::get('getUsers','UserController#getUsers');
UserController.php
...
public function getUsers(Request $request)
{
...
if ($request->has('api')) {
return $users; //API Route (Laravel will by Default return the JSON Response no need to do json_encode)
}
return view('pages.user_list'); //Normal Routes hence returning View
}
...
Requests
Normal Request
<Yourdomain>/getUsers
API Request
<Yourdomain>/getUsers?api=true
I hope that helped...
Write your api routes in api.php and web routes in web.php.
The Api routes always have the name api in the routes thus you can differentiate the routes., I mentioned here because as #Akshay Khale mentioned an example with query parameter.
if you want to use the same controller for both API and Web, Api Requests always have the Header Content-Type : Json and "Accept":"application/json" so in your controller you can do it as below.
public function getUsers(Request $request)
{
...
if ($request->wantsJson()) {
return response()->json($users, 200); //here why we are extending response object because using json() method you can send the status code with the response.
}
return view('pages.user_list'); //Normal Routes hence returning View
}
for the laravel 5.6 and above the above answers won't work for me , so here is my 2 cents.
I have put the routes in web.php and api.php and normal no any magic tricks .
public function getUsers(Request $request)
{
....
if( $request->is('api/*')){
...
return response()->json($user_data, 200);
}
...
return view('users', ['users_data'=>$user_data]);
}
It will return json output for
127.0.0.1:8000/api/users
and normal view in html for
127.0.0.1:8000/users
Related
I started creating a REST API using the lumen framework and wanted to set up a particular behaviour for my GET /user route. Behaviour is the following:
If the request come from an authenticated user (using auth middleware), the method getAllFields from UserController is called and return all the data from the user
If it's not the case, the method get from UserController is called and return some of the data from the user
It seems logic to me to just write it like that in my web.php using a simple middleware:
<?php
$router->group(['middleware' => 'auth'], function () use ($router) {
$router->get('/user/{id}', [
'uses' => 'UserController#getAllFields'
]);
});
$router->get('/user/{id}', [
'uses' => 'UserController#get'
]);
But for some reason, even if the middleware is correct, I always get the response of the second route declaration (that call get()). I precise that if I remove the second route declaration, the one in the middleware work as expected.
Have someone an idea how I can achieve something similar that work?
Router will check if your request matches to any declared route. Middleware will run AFTER that match, so You cannot just return to router and try to find another match.
To fallow Laravel and Routes pattern - You should have single route that will point to method inside controller. Then inside that You can check if user is logged or not and execute getAllFields() from that controller. It will be not much to rewrite since You are currently using UserController in both routes anyway.
web.php
$router->get('/user/{id}', 'UserController#get');
UserController.php
public function get()
{
return auth()->check() ? YourMethodForLogged() : YourMethodForNotLogged();
}
Or if there is not much logic You can keep this in single method.
Also it is good idea to fallow Laravels REST standards (so use show instead of get, "users" instead of "user" etc - read more https://laravel.com/docs/7.x/controllers)
web.php
$router->get('/users/{user}', 'UserController#show');
UserController.php
public function show(User $user)
{
if (auth()->check()) {
//
} else {
//
}
}
To summary - for your needs use Auth inside controller instead of middleware.
To check if user is logged You can use Facade Auth::check() or helper auth()->check(), or opposite Auth::guest() or auth()->guest().
If you are actually using Lumen instead of full Laravel then there is not auth helper by default (You can make own or use package like lumen-helpers) or just keep it simple and use just Facades instead (if You have then enabled in Lumen).
Read more https://laravel.com/docs/7.x/authentication and https://lumen.laravel.com/docs/7.x/authentication
This pattern is against the idea of Laravel's routing. Each route should be defined once.
You can define your route without auth middleware enabled and then define your logic in the controller.
My api.php route is
Route::get('/allposts','PostController#index');
Controller function is and working with web.php Route file
public function index()
{
$posts= Post::all();
return PostResource::collection($posts);
}
my Resource is toArray function is
public function toArray($request)
{
return parent::toArray($request);
}
Postman link using GET are
"queuetest.com/api/allposts"
"http://queuetest.com/api/allposts"
both are not working
and getting Result in both Post man and browser: Sorry the page your looking for could not be found
Do you get something other than the Sorry the page you're looking for could not be found message when you do var_dump('test');die(); in your index method as the first line.
Edit: try to remove then / before /allPosts
Another edit: check in your RouteServiceProvider if the mapApiRoutes prefix is set to 'api'
If you are using the default route configuration that comes out of the box, you should place your route in routes/api.php if you want to access it in the /api namespace. Right now, the route should be accessible from http://queuetest.com/allposts.
This behavior can be configured in App\Providers\RouteServiceProviders.php. If you have a modified route configuration, there are numerous things that could cause this behaviour, and it is impossible to locate the problem without seeing more code.
I got this error-->'NotFoundHttpException in RouteCollection.php line 161'..When i try to call my additional controller in laravel 5.2..Already I did php artisan serve to activate localhost:8000..can you please explain the basic layout of routing with controller in laravel?
NotFoundHttpException occurs when no given route is matched to your given request to a certain endpoint/url.
Make sure you are sending the request to the correct url which is correctly defined in your routes.php (web.php for laravel 5.3+) with it's correct verb, (GET, POST, PATCH, etc).
Basic flow goes like this:
In your routes.php, you'd define a route like:
Route::get("/users", "UsersController#show");
then in your Http folder define that given controller with it's name which you referred in above call and anything proceeding # symbol is a callback function which gets called automatically.
So in your http/UsersController.php, you'd have:
public function show(Request $request) {
//Do something with your request.
return "Something"; //could be an array or string or
//whatever since laravel automatically casts it into JSON,
//but it's strongly recommended to use transformers and compact method.
}
For more information try looking at laravel docs, they provide an amazing way to get started tutorial. Laravel Docs
Im building an API in Laravel 5.3. In my routes/api.php file I have 3 endpoints:
Route::post('/notify/v1/notifications', 'Api\Notify\v1\NotifyApiController#notificationsPost');
Route::post('/notify/v1/alerts', 'Api\Notify\v1\NotifyApiController#alertsPost');
Route::post('/notify/v1/incidents', 'Api\Notify\v1\NotifyApiController#incidentsPost');
Several services will call these routes directly, however, when a request comes in from some services, the input data needs to be processed before it can hit these endpoints.
For example, if a request comes in from JIRA, I need to process the input before it hits these endpoints.
Im thinking that the simplest way to do this would be to have a 4th endpoint like the below:
Route::post('/notify/v1/jira', 'Api\Notify\v1\JiraFormatter#formatJiraPost');
The idea being to hit the /notify/v1/jira endpoint, have the formatJiraPost method process the input and then forward the request to /notify/v1/notifications (/alerts, /incidents) as required.
How can I have the /notify/v1/jira endpoint forward the request to the /notify/v1/notifications endpoint?
Do you see a better way to do this?
Depending how your app will work, you could always have your services pointing to /notify/v1/jira and then do the processing like you suggested.
Another alternative is have the JIRA service pointing at the same routes as all the other services but to use a Before middleware group to pre-process your data. Something like
Route::group(['middleware' => ['verifyService']], function () {
Route::post('/notify/v1/notifications', 'Api\Notify\v1\NotifyApiController#notificationsPost');
Route::post('/notify/v1/alerts', 'Api\Notify\v1\NotifyApiController#alertsPost');
Route::post('/notify/v1/incidents', 'Api\Notify\v1\NotifyApiController#incidentsPost');
});
You could check in your middleware your service.
<?php
namespace App\Http\Middleware;
use Closure;
class verifyService
{
public function handle($request, Closure $next)
{
//You could use switch/break case structure
if (isJIRA($request)) {
//Do some processing, it could be outsourced to another class
//$JiraPost = new formatJiraPost($request);
//Keep the requesting going to the routes with processed data
return $next($request);
}
//You could add extra logic to check for more services.
return $next($request);
}
protected function isJIRA(Request $request){
//Logic to check if it is JIRA.
}
}
I'm building a little Lumen application with a simple API & Authentication.
I want to redirect the user to the intended URL and if he visits /auth/login by himself I want him to redirect to /foo.
In the Laravel Docs there is this function: return redirect()->intended('/foo');
When I use this in my route I get an error in the server log which says this:
[30-Apr-2015 08:39:47 UTC] PHP Fatal error: Call to undefined method Laravel\Lumen\Http\Redirector::intended() in ~/Sites/lumen-test/app/Http/routes.php on line 16
I think this is because Lumen is a smaller version of Laravel and maybe this function isn't implemented (yet).
I solved this problem by adjusting my Middleware a little bit as well as storing the Request::path() in the session.
This is how my Middleware looks:
class AuthMiddleware {
public function handle($request, Closure $next) {
if(Auth::check()){
return $next($request);
} else {
session(['path' => Request::path()]);
return redirect('/auth/login');
}
}
}
And in my routes.php I have this route (which I will outsource to a controller asap):
$app->post('/auth/login', function(Request $request) {
if (Auth::attempt($request->only('username', 'password'))){
if($path = session('path')){
return redirect($path);
} else {
return redirect('/messages');
}
} else {
return redirect()->back()->with("error", "Login failed!");
}
});
Thanks to IDIR FETT for suggesting the Request::path() method.
Hopefully this will help a few people that are new to
Lumen, which is a great framework by the way. :)
Indeed looking at the source code of Lumen it is not implemented:
https://github.com/laravel/lumen-framework/blob/5.0/src/Http/Redirector.php
Your options are:
Check Laravel's (Symfony's?) implementation and put it into your own code
Write completely your own implementation – one super simple way of doing it would be store the request URL in a session, redirect to the login page and when the user successfully logs in retrieve the URL from the session and redirect him
i think you have to specify a route name in the intended method, not a URI:
return redirect()->intended('foo');
assuming you have already named the route, i think this still works as well:
return Redirect::intended('/foo');
UPDATE:
try this:
retrieve the requested URI :
$uri = Request::path(); // Implemented in Lumen
then redirect to the requested URI :
return redirect($uri);
this could work !!