I have a question that might sound silly to you so please forgive me.
I am not sure when do I use the routes/api.php file.
If I want to delete a record from a datatable with ajax, do I need to create a separate controller and put the route in api.php or can I use the same controller I use for everything else and put the route in web.php?
I'm not sure if you read the Laravel documentation or how much familiar you are with Laravel, but in Laravel 5.3 you have web routes and api routes in separate files.
You use api routes only for registering your api (ie if you are building a rest api service), and all routes placed there will be prefixed by default with /api. So ie if you define a route /user inside the api file, it will be automatically prefixed with /api, so your end point would be www.yourapplication.com/api/user.
If you are not building a rest api service or anything similar dont use this file at all, use the web file for defining all of your application routes.
Also consider visiting Laracast website, as they have a nice introduction to new changes in Laravel 5.3 including web and api routes. Hope this helps you.
All that routes placed in api.php will be prefixed by /api, which was also mentioned by bernadd, there are other differences:
in this link(https://mattstauffer.co/blog/routing-changes-in-laravel-5-3) you can find the difference between api and web in laravel code:
in App\Providers\RouteServiceProvider:
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
//
}
protected function mapApiRoutes()
{
Route::group([
'middleware' => ['api', 'auth:api'],
'namespace' => $this->namespace,
'prefix' => 'api',
], function ($router) {
require base_path('routes/api.php');
});
}
protected function mapWebRoutes()
{
Route::group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require base_path('routes/web.php');
});
}
in App\Http\Kernel.php in "protected $middlewareGroups" you can see this:
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
And:
in config\auth.php : In this file's Comments you can clearly find out the difference between default "auth"('guard' => 'web') vs "auth:api"
Related
Laravel 8 with Sanctum.
I plan to use the same API routes for SPA and external users. The problem is that Sanctum requires the EnsureFrontendRequestsAreStateful middleware to be added to the "api" middleware group which makes my API "stateful". It's fine for a SPA, but I'd like to keep it "stateless" for external calls with token authentication.
The simplest solution would be to separate SPA and external routes, with different middleware groups. Not so elegant! Please advise something better :)
UPD: Decided to split routes
routes/api.php
Route::middleware('auth:sanctum')->as('api.')->group(function () {
require 'resources.php';
});
routes/spa.php
Route::middleware('auth:sanctum')->as('spa.')->group(function () {
require 'resources.php';
});
routes/resources.php
Route::apiResources([
'products' => 'Api\ProductController',
]);
App\Providers\RouteServiceProvider
public function boot()
{
$this->routes(function () {
....
Route::prefix('spa')
->middleware('spa')
->namespace($this->namespace)
->group(base_path('routes/spa.php'));
});
}
App\Http\Kernel
protected $middlewareGroups = [
....
// Stateless, external calls
'api' => [
'throttle:api',
SubstituteBindings::class,
],
// SPA, stateful, internal use
'spa' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:api',
'SubstituteBindings::class,
],
];
I have situation about returning users from DB. In my controller I am trying it like below:
UPDATED:
NOTE: for clear misunderstanding. Actually I am logged in as a user. No problem with that part. But it looks like auth:: doesn't understand that and when I try to retrieve users. it's redirecting me to login's endpoint...
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Auth;
class UsersController extends Controller
{
public function getUser(){
$users = Auth::user();
dd($users);
}
}
And about the api route:
Route::group(['middleware' => 'auth:api'], function() {
Route::post("logout", "Api\AuthController#logout");
/* User */
Route::get('/user', 'Api\UsersController#getUser');
});
Route::group(["prefix" => "v1"], function(){
/* Auth */
Route::post("login", "Api\AuthController#login")->name("login");
Route::post("register", "Api\AuthController#register");
});
Here is the thing. If I use my UserController route outside the middleware:api then endpoint is returns null. And if use it inside the middleware it redirects me to my login's endpoint. Because of the "->name('login')"
In the end I can't return the users. Additionally this is what config/auth looks like.
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
By the way before asked. I tried to change guard's web to api but nothing is changed.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Is there anyone have better understanding on this situation. How can I return users with using passport? Do I missing something here?
Apparently, the problem is with the request header. Only a logged in user can call /api/user endpoint with an access_token in the request header.
Request header will have this pair
Authorization: Bearer eyJ0eXAiOiJKV1..........
Nothing to do in laravel part, as it's working as expected.
If you are using Laravel Passport. Let's read and make your step same in document: https://laravel.com/docs/5.8/passport
From your API request, need to pass the access_token to backend.
Hoping you can resolve that issue!
I have a ajax function which call a controller listed on api.php (route).
Inside this controller, I'm trying to make a user's log. So, I need to store the id user in a log table. But, when I try to access any method of Auth::user(), even being logged in, I get the exception "Unauthenticated".
I think It's a miss of sending some header information on ajax function.
Someone could help me, please?
If I am correct, api.php routes in laravel are set to uses tokens rather than the session. This means each call will require a token (specified on the user model/record) to be passed.
Using Auth::user() within web.php will work as that uses user sessions to authenticate.
You can try this one,
In your Kernel.php file add your own name like 'sessions' to the $middlewareGroups. It should contain \Illuminate\Session\Middleware\StartSession::class
Assign 'sessions' to those routes you want.
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
],
'sessions' => [
\Illuminate\Session\Middleware\StartSession::class,
]
];
routes/api.php
Route::group(['middleware' => ['sessions']], function () {
Route::resource(...);
});
I think it must work for you
<?php echo Auth::user() ?>
or {{Auth::user()->(id)}}
I have a middleware which works fine when defined as a global middleware in Kernel.php. However, I want it to be applied only to specific routes, so I do this:
Route::group(['prefix' => 'myapi/', 'middleware' => 'api'], function(){
});
Calling php artisan route:list shows that the middleware is detected correctly. However, it does not get executed (I know this because even purposely placing an error in the file does not do anything).
...
protected $middlewareGroups = [
...
'api' => [
'throttle:60,1',
\App\Http\Middleware\CORSMiddleware::class,
],
];
When the middleware is set as global, it does not get listed by route:list. Also, purposely specifying a wrong middleware name in routes.php does not throw any error.
EDIT:
Logging shows that the middleware is executed for all GET ressource routes, but not for POST/PUT/DELETE.
I believe middleware has to be placed inside an array when adding it to a group - that will cause it to trigger and give you the expected result:
Route::group(['prefix' => 'myapi/', 'middleware' => ['api']], function(){
});
Is it possible to add middleware to all or some items of a resourceful route?
For example...
<?php
Route::resource('quotes', 'QuotesController');
Furthermore, if possible, I wanted to make all routes aside from index and show use the auth middleware. Or would this be something that needs to be done within the controller?
In QuotesController constructor you can then use:
$this->middleware('auth', ['except' => ['index','show']]);
Reference: Controller middleware in Laravel 5
You could use Route Group coupled with Middleware concept:
http://laravel.com/docs/master/routing
Route::group(['middleware' => 'auth'], function()
{
Route::resource('todo', 'TodoController', ['only' => ['index']]);
});
In Laravel with PHP 7, it didn't work for me with multi-method exclude until wrote
Route::group(['middleware' => 'auth:api'], function() {
Route::resource('categories', 'CategoryController', ['except' => 'show,index']);
});
maybe that helps someone.
UPDATE FOR LARAVEL 8.x
web.php:
Route::resource('quotes', 'QuotesController');
in your controller:
public function __construct()
{
$this->middleware('auth')->except(['index','show']);
// OR
$this->middleware('auth')->only(['store','update','edit','create']);
}
Reference: Controller Middleware
Been looking for a better solution for Laravel 5.8+.
Here's what i did:
Apply middleware to resource, except those who you do not want the middleware to be applied. (Here index and show)
Route::resource('resource', 'Controller', [
'except' => [
'index',
'show'
]
])
->middleware(['auth']);
Then, create the resource routes that were except in the first one. So index and show.
Route::resource('resource', 'Controller', [
'only' => [
'index',
'show'
]
]);