hello i got issue with access to few routes when they under restricted from middlewere
my route look like this
Route::group([
'middleware' => ['api','auth:sanctum'],
], function ($router) {
Route::prefix('users')->group(function ($usersRoute) {
Route::post('login', 'Api\Users\UserController#login');
Route::post('logout', 'Api\Users\UserController#logout');
Route::post('refresh', 'Api\Users\UserController#refresh');
Route::post('profile', 'Api\Users\UserController#profile');
});
Route::prefix('leads')->group(function ($leadRoute) {
// Route::get('look' , 'Api\Leads\LeadController#index');
// Route::get('look/{id}' , 'Api\Leads\LeadController#find');
// Route::post('look' , 'Api\Leads\LeadController#create');
// Route::put('look/{id}' , 'Api\Leads\LeadController#update');
// Route::delete('look/{id}' , 'Api\Leads\LeadController#archived');
// Route::put('look/{id}/view' , 'Api\Leads\LeadController#toggleView');
Route::prefix('assets')->group(function ($leadRoute) {
Route::get('/' , 'Api\Leads\AssetController#index');
Route::post('/' , 'Api\Leads\AssetController#create');
Route::get('/show/random' , 'Api\Leads\AssetController#showRandomAsset');
Route::delete('/{id}' , 'Api\Leads\AssetController#archived');
Route::delete('/autoclear' , 'Api\Leads\AssetController#autoClear');
Route::put('/{id}/show' , 'Api\Leads\AssetController#toggleShow');
});
});
});
now i have two controllers that the contractor look like this
class UserController extends BaseAPIController
{
/**
* Create a new AuthController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth:sanctum', ['except' => ['login']]);
}
when i check the route list
api,auth:sanctum |
| | POST | api/users/login | | App\Http\Controllers\Api\Users\UserController#login | api,auth:sanctum |
| | POST | api/users/logout | | App\Http\Controllers\Api\Users\UserController#logout | api,auth:sanctum |
| | POST | api/users/profile | | App\Http\Controllers\Api\Users\UserController#profile | api,auth:sanctum |
| | POST | api/users/refresh | | App\Http\Controllers\Api\Users\UserController#refresh | api,auth:sanctum
what i try is free login route free for all but i get
{
"message": "Unauthenticated."
}
i kinda lost please help
when I check the doc of laravel, I found that:
$this->middleware('subscribed')->except('store');
the second param for function middleware is using for options, so how about try:
$this->middleware('auth:sanctum')->except('login');
From your code, you're including the middleware twice and that's not right.
You should remove the group middleware in the routes file since you're already injecting the auth middleware in the constructor method.
Remove
Route::group([
'middleware' => ['api','auth:sanctum'],
], function ($router) {
After this your code should work as intended because auth:sanctum middleware would be called only once in your controller every time it is instantiated and will exclude the login route.
Related
I have a controller App/Controllers/Api/Orders.php
<?php
namespace App\Controllers\Api;
use CodeIgniter\RESTful\ResourceController;
class Orders extends ResourceController
{
protected $modelName = 'App\Models\Order';
protected $format = 'json';
public function getIndex()
{
return $this->respond($this->model->findAll());
}
public function delete($id = null)
{
return $this->respond(['test' => 123]);
}
}
When I'm trying to access /api/orders/ with GET request it works fine (so auto routing is working).
But when I'm trying to send a DELETE request: /api/orders/15 I get error 404. What am I doing wrong? The main source of confusion for me is that Codeigniter 4 RESTful documentation seems to talk about manual routes or legacy auto routing but not the improved version where you need to specify methodFunction (like getIndex).
Running php spark routes gives me the following:
+--------------+------------------+------+---------------------------------------+----------------+---------------+
| Method | Route | Name | Handler | Before Filters | After Filters |
+--------------+------------------+------+---------------------------------------+----------------+---------------+
| GET(auto) | api/orders | | \App\Controllers\Api\Orders::getIndex | | toolbar |
| DELETE(auto) | api/orders/[/..] | | \App\Controllers\Api\Orders::delete | <unknown> | <unknown> |
CodeIgniter version: 4.3.1
app/Config/Routes.php
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Auth');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->get('/', 'Home::index');
app/Config/Filters.php
public array $globals = [
'before' => [
// 'honeypot',
// 'csrf',
// 'invalidchars',
],
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
];
Solution:
Beyond prefixing the Controller method with an HTTP verb i.e delete, you need to provide a 'Controller method name' as the suffix. I.e: httpVerbMethodName.
Instead of: ❌
public function delete($id = null)
{
// ...
}
Use this: ✅
public function deleteOrder($id = null)
{
// ...
}
Route endpoint:
DELETE: http://localhost:4599/api/orders/order/15
| DELETE(auto) | api/orders/order[/..] | | \App\Controllers\Api\Orders::deleteOrder | | toolbar
Reference:
URI Segments
The segments in the URL, in following with the Model-View-Controller approach, usually represent:
example.com/class/method/ID
The first segment represents the controller class that should be invoked.
The second segment represents the class method that should be called.
The third, and any additional segments, represent the ID and any variables that will be passed to the controller.
Consider this URI:
example.com/index.php/helloworld/hello/1
In the above example, when you send a HTTP request with GET method, Auto Routing would attempt to find a controller named App\Controllers\Helloworld and executes getHello() method with passing '1' as the first argument.
Note
A controller method that will be executed by Auto Routing (Improved) needs HTTP verb (get, post, put, etc.) prefix like getIndex(), postCreate().
See Auto Routing in Controllers for more info.
I'm learning Laravel and I wanna group some routes using prefix and naming each route so I got something like this
Route::prefix('customers')->group(
function(){
Route::get('/', 'CustomerController#index')->name('customers.index');
Route::get('/create', 'CustomerController#create')->name('customers.create');
Route::post('/', 'CustomerController#store')->name('customers.store');
});
I want to avoid writing 'customers.' in every route name.
I have tried with group and name but it doesn't recognize the route name prefix 'customers.'
Route::group(['prefix' => 'customers', 'name' => 'customers.'],
function(){
Route::get('/', 'CustomerController#index')->name('index');
Route::get('/create', 'CustomerController#create')->name('create');
Route::post('/', 'CustomerController#store')->name('store');
});
The other way I found was with as and use but it seems to much code, and doesn't look kind of clean, actually the first one looks like a cleaner way.
Route::group([
'prefix' => 'customers',
'as' => 'customers.'
],
function(){
Route::get('/', ['as'=>'index', 'uses' => 'CustomerController#index']);
Route::get('/create', ['as'=>'create', 'uses' => 'CustomerController#create']);
Route::post('/', ['as'=>'store', 'uses' => 'CustomerController#store']);
});
Is there a better way to do it?
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
Taken from Laravel - Route::resource vs Route::controller
You can just use ->name(XYZ) when grouping:
Route::prefix('customers')
->name('customers.')
->group(function () {
Route::get('/', 'CustomerController#index')->name('index');
Route::get('/create', 'CustomerController#create')->name('create');
Route::post('/', 'CustomerController#store')->name('store');
});
Routes:
| | POST | customers | customers.store | App\Http\Controllers\CustomerController#store | web |
| | GET|HEAD | customers | customers.index | App\Http\Controllers\CustomerController#index | web |
| | GET|HEAD | customers/create | customers.create | App\Http\Controllers\CustomerController#create | web |
Why not use a resource?
You would simply do the following to get your desired result with one line:
Route::resource('customers', 'CustomerController')->only(['index', 'create', 'store']);
Routes:
+----------+-------------------------------+
| Method | URI |
+----------+-------------------------------+
| GET|HEAD | customers |
| POST | customers |
| GET|HEAD | customers/create |
+----------+-------------------------------+
I'm working on a Laravel project, and I made a simple CRUD system, but I have a small problem
to generate the URL system in my project, I made a Route::macro
and add it to AppServiceProvider:
Route::macro('crud', function () {
Route::group([
], function () {
// Route::resource('', 'CrudController');
Route::get('{model}', 'CrudController#index');
Route::get('{model}/create', 'CrudController#create');
Route::post('{model}', 'CrudController#store'); /** << post **/
Route::get('{model}/{id}', 'CrudController#show');
Route::get('{model}/{id}/edit', 'CrudController#edit');
Route::match(['PUT', 'PATCH'],'{model}/{id}', 'CrudController#update'); /** << post **/
Route::delete('{model}/{id}', 'CrudController#destroy'); /** << post **/
});
});
this works great so far, but the issue is I need to use ->name() with it, and adding the $model parameter to it!
example of what I'm trying to do:
Route::get('{model}', 'CrudController#index')->name('{model}.index');
is it possible?, Thanks in advance
You can get all models names and loop through them and add the model name to the route name prefix at runtime
loop (model in models)
Route::get("{model}","Atcion")->name("{model}.index")
endloop
I hope my answare helps you in your project
Here in this example you can loop over of some numbers and dynamically create some routes:
for ($i = 0; $i < 5; $i++) {
Route::get('test/' . $i, 'Controller#test_' . $i)->name('test.' . $i);
}
You can check that all added routes with "php artisan route:list".
I don't recommend you to do that, but for your case you can somewhere in routes.php define array like this, and loop over on that:
$models = ['user', 'owner', 'admin'];
foreach ($models as $model) {
Route::get($model, 'CrudController#index')->name($model . '.index');
}
Or you can define that array in configs (for example in "config/app.php") like:
'models' => ['user', 'owner', 'admin'];
And in routes.php you can just retrieve that with this (don't forget to run "php artisan config:cache" after changing app.php):
$models = config('app.models');
// foreach loop
You can prefix the name to a group of routes for the model
From the docs
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Route::macro('crud', function () {
Route::name('{model}.')->group(function () {
Route::get('{model}', 'CrudController#index')->name('index');
Route::get('{model}/create', 'CrudController#create')->name('create');
Route::post('{model}', 'CrudController#store')->name('store');
Route::get('{model}/{id}', 'CrudController#show')->name('show');
Route::get('{model}/{id}/edit', 'CrudController#edit')->name('edit');
Route::match(['PUT', 'PATCH'], '{model}/{id}', 'CrudController#update')->name('update');
Route::delete('{model}/{id}', 'CrudController#destroy')->name('destroy');
});
});
}
}
Result
+-----------+----------------------------+-----------------+------------------------------------------------------------+
| Method | URI | Name | Action |
+-----------+----------------------------+-----------------+------------------------------------------------------------+
| GET|HEAD | {model} | {model}.index | App\Http\Controllers\CrudController#index |
| POST | {model} | {model}.store | App\Http\Controllers\CrudController#store |
| GET|HEAD | {model}/create | {model}.create | App\Http\Controllers\CrudController#create |
| GET|HEAD | {model}/{id} | {model}.show | App\Http\Controllers\CrudController#show |
| PUT|PATCH | {model}/{id} | {model}.update | App\Http\Controllers\CrudController#update |
| DELETE | {model}/{id} | {model}.destroy | App\Http\Controllers\CrudController#destroy |
| GET|HEAD | {model}/{id}/edit | {model}.edit | App\Http\Controllers\CrudController#edit |
+-----------+----------------------------+-----------------+------------------------------------------------------------+
Now you can access example.com/user/create and example.com/product/create and they both take to the same controller method
I hope this helps
I am trying to route to a RESTful controller using the following in app/routes.php:
Route::controller('register', 'RegisterController');
Route::get('/', 'HomeController#showWelcome');
In my app/controllers/RegisterController.php file I have added the following:
<?php
class RegisterController extends BaseController
{
public function getRegister()
{
return View::make('registration');
}
public function postRegister()
{
$data = Input::all();
$rules = array(
'first_name' => array('alpha', 'min:3'),
'last_name' => array('alpha', 'min:3'),
'company_name' => array('alpha_num'),
'phone_number' => 'regex:[0-9()\-]'
);
$validator = Validator::make($data, $rules);
if ($validator->passes()) {
return 'Data was saved.';
}
return Redirect::to('register')->withErrors($validator);
}
}
I am getting the following error:
Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException
When I run php artisan routes in terminal I get:
+--------+--------------------------------------------------+------+----------------------------+----------------+---------------+
| Domain | URI | Name | Action | Before Filters | After Filters |
+--------+--------------------------------------------------+------+----------------------------+----------------+---------------+
| | GET /register/register/{v1}/{v2}/{v3}/{v4}/{v5} | | Register#getRegister | | |
| | POST /register/register/{v1}/{v2}/{v3}/{v4}/{v5} | | Register#postRegister | | |
| | GET /register/{_missing} | | Register#missingMethod | | |
| | GET / | | HomeController#showWelcome | | |
+--------+--------------------------------------------------+------+----------------------------+----------------+---------------+
I don't understand why register is showing twice in the URI and the second GET action is missing and why I am getting this error.
If you are using RESTful API, the best way is in your route,
Route::resource('register', 'RegisterController');
And change your public function getRegister() to public function index() and public function postRegister() to public function store()
Then the index() can be access using GET http://localhost/laravel/register and the store() using POST http://localhost/laravel/register
Chaneg the http://localhost/laravel/ with yours.
And the same way the update($id) is used for update and destroy($id) is used for delete
Route::controller('register', 'RegisterController');
This will also work if you change it
Route::controller('/', 'RegisterController');
THIS IS A QUESTION FOR LARAVEL 3
Given the following route
Route::get('groups/(:any)', array('as' => 'group', 'uses' => 'groups#show'));
And the URL I would like to use,
http://www.example.com/groups/1
I would like to be able to use the (:any) value in my controller.
My controller looks like
class Groups_Controller extends Base_Controller {
public $restful = true;
public function get_show($groupID) {
return 'I am group id ' . $groupID;
}
}
How is this possible to do? I have tried a few things including the following
Route::get('groups/(:any)', array('as' => 'group', 'uses' => 'groups#show((:1))'));
but it did not work.
UPDATE
Anytime I try to pass in the arguments as show above i get a 404 error.
Thanks for the help!
You don't need anything special for adding paramaters. Just like you had it.
Route::get('groups/(:any)', array('as' => 'group', 'uses' => 'groups#show'));
class Groups_Controller extends Base_Controller {
public $restful = true;
public function get_show($groupID) {
return 'I am group id ' . $groupID;
}
}
This is what you need in 1 line of code.
Route::get('/groups/{groupId}', 'GroupsController#getShow');
Suggestion: Use CamelCase as opposed to underscores, try & follow PSR-* guidelines.
Hope it helps.
You can add them like this
Route::get('company/{name}', 'PublicareaController#companydetails');
$ php artisan route:list
+--------+--------------------------------+----------------------------+-- -----------------+----------------------------------------------------+--------- ---+
| Domain | Method | URI | Name | Action | Middleware |
+--------+--------------------------------+----------------------------+-------------------+----------------------------------------------------+------------+
| | GET|HEAD | / |
| | GET | campaign/showtakeup/{id} | showtakeup | App\Http\Controllers\campaignController#showtakeup | auth | |
routes.php
Route::get('campaign/showtakeup/{id}', ['uses' =>'campaignController#showtakeup'])->name('showtakeup');
campaign.showtakeup.blade.php
#foreach($campaign as $campaigns)
//route parameters; you may pass them as the second argument to the method:
{{ $campaigns->name }}
#endforeach
Hope this solves your problem.
Thanks