In my Laravel 5.8 app I have many API routes which return paginated results. If I make a request to my API appending the following query string I can disable pagination.
http://api.test/users/?no_paginate=1
My question is... how can I disable no_paginate from being used on certain routes? I'd preferbly want some validation to go in the request class but I can't find anything in the docs for that.
You can do this using a Global Middleware.
Create a DisableNoPaginate Middleware:
php artisan make:middleware DisableNoPaginate
Then define what the middleware should do (DisableNoPaginate.php):
<?php
namespace App\Http\Middleware;
use Closure;
class DisableNoPaginate
{
public function handle($request, Closure $next)
{
//remove no_paginate param from request object
unset($request['no_paginate']);
return $next($request);
}
}
Arrange for the middleware to run on all routes (routes.php):
$app->middleware([
App\Http\Middleware\DisableNoPaginate::class
]);
Now the no_paginate query param should be stripped from all your incoming requests.
For the best approach to get users either paginate or get all listing by below code in UsersController
public function index($type = null, Request $request)
{
$builder = User::where(/*query*/);
if($type == "paginate") {
$items = $builder->paginate(10);
} else {
$items = $builder->get();
}
return view("users.index", ['users' => $items]);
}
Here is the route in web.php/api.php file
Route::get('/{type?}', ['as' => 'users.index', 'uses' => 'UsersController#index']);
Here url will be
http://api.test/users/paginate // get pagination response.
http://api.test/users // get response without pagination
I think this will help you.
Related
I'm using Woocommerce webhooks to listen out for every time an order is created/updated/deleted.
I've setup the webhook in Woocommerce as follows
In my Laravel routes file I have set up the route as follows:
use Illuminate\Http\Request;
// API routes...
Route::post('api/v1/orders/create', function (Request $request) {
Log::debug($request->all());
return $request->all();
});
However, when I view the logs as well as the return data in POSTMAN, all I get is an empty array.
Any HTTP method other than 'GET' throws a MethodNotAllowedException
I'm not sure of any other way in Laravel to consume data other than with Request $request.
According to my understanding of routing in Laravel, the input that you pass in to the function is meant to actually be variables for your route.
So if you had a route in your API:
api/v1/orders/{id}/create then in the route function you'd pass in id as the method argument. So this would be correct:
Route::post('api/v1/orders/{id}/create', function ($id) {
Log::debug($id);
return $id;
});
It's looking for request in your route definition.
Rather create a controller. Then in your routes.php use this:
Route::post('api/v1/orders/create', 'OrdersController#create')
That tells your routing to redirect all HTTP POST calls to api/v1/orders/create to the OrdersController.php and the create() method within that controller.
In your controller, you'll be able to use the $request variable as an input argument and it should work.
So in OrdersController.php:
class OrdersController extends Controller {
public function create(Request $request) {
Log::debug($request->all());
return $request->all();
}
}
Good Luck!
This worked for me. My route in api.php is as follow.
Route::post('/woocommerce/webhook/', 'Api\WoocommerceController#test');
And my controller action is as follow.
public function test()
{
$payload = #file_get_contents('php://input');
$payload = json_decode( $payload, true);
\Log::info(json_encode( $payload));
return response()->json([ 'data' => $payload, 'status' => \Symfony\Component\HttpFoundation\Response::HTTP_OK]);
}
I'm using Laravel 5.3 and want to return the user to a user-specified URL after login.
I am using a lot of JavaScript and want to return to a specific URL, that isn't the URL the user is trying to access, after they have logged in. The URL is different depending on user action.
For example:
/login?r=/come/here/after/login
I can pass this URL to the login screen, but I can't find a way to pass it through to the auth controller for redirection after login is successful.
In your case I would create a custom auth middleware just for the custom redirected routes:
class PostLoginRedirect
{
public function handle($request, Closure $next, $guard = null)
{
$response = $next($request);
if (\Auth::id() && isset($request->r)) {
// Return the new route redirect.
return redirect($request->r);
}
// Return the custom one in case r? don't exists.
return $response;
}
}
Declare your new middleware on app/Http/Kernel.php
protected $routeMiddleware = [
'login-redirect' => \YourNamespace\PostLoginRedirect::class
];
And add to your routes:
$this->post('login', ['middleware' => 'login-redirect', 'uses' => 'Auth\AuthController#login']);
Maybe you need to do a minor change but must work :)
I am trying to cache entire response using middleware
Steps i followed
Generated two middleware
AfterCacheMiddleware
BeforeCacheMiddleware
With in BeforeCacheMiddleware:
public function handle($request, Closure $next)
{
$key = $request->url();
if(Cache::has($key)) return Cache::get($key);
return $next($request);
}
With in AfterCacheMiddleware
public function handle ($request, Closure $next)
{
$response = $next($request);
$key = $request->url();
if (!Cache::has($key)) Cache::put($key, $response->getContent(), 60);
return $response;
}
Registered middleware in $routeMiddleware array of kernal.php
'cacheafter' => 'App\Http\Middleware\AfterCacheMiddleware',
'cachebefore' => 'App\Http\Middleware\BeforeCacheMiddleware',
With in routes.php i am calling this dummy routes like this
Route::get('middle', ['middleware' => 'cachebefore', 'cacheafter', function()
{
echo "From route";
}]);
Issue:
only cachebefore middleware is getting called. cacheafter is not getting called at all
Can anyone suggest what i am missing here ?
I found this question while I was looking for solution myself. I am aware that there is the Flatten package which does this caching, but I couldn't find nice examples on how to do this by myself. The solution attempt in this question contains ideas that were useful for my own solution, although I chose to go with a single middleware only.
Although the question is old and asker probably doesn't need the answer anymore, I will share my solution here as I feel that SO (and internet) lacks this caching sample for Laravel 5. I will try to explain as much as I can, but for most benefit you should be familiar with Routing, Caching and Middlewaring in Laravel 5. So here goes the solution:
Middleware
Create a middleware, those are usually placed in app/Http/Middleware folder and I will call the file CachePage.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Cache;
class CachePage
{
public function handle($request, Closure $next)
{
$key = $request->fullUrl(); //key for caching/retrieving the response value
if (Cache::has($key)) //If it's cached...
return response(Cache::get($key)); //... return the value from cache and we're done.
$response = $next($request); //If it wasn't cached, execute the request and grab the response
$cachingTime = 60; //Let's cache it for 60 minutes
Cache::put($key, $response->getContent(), $cachingTime); //Cache response
return $response;
}
}
Change $key according to your needs... You have all the $request with all the parameters... Change Cache::put($key, $value, $minutes) to Cache::forever($key, $value) if you will clear the cache manually and don't want it to ever expire.
Using the URL as key for storing cache is usable in most cases, but one might think of something more appropriate for a certain project.
Registering middleware
Register it in app/Http/Kernel.php by adding the middleware to $routeMiddleware array like this:
protected $routeMiddleware = [
/* ... */
/* Other middleware that you already have there */
/* ... */
'cachepage' => \App\Http\Middleware\CachePage::class,
];
Of course, you should change \App\Http\Middleware\CachePage if you placed it elsewhere or gave it another name. Also the key name cachepage is up to you - it will be used to invoke the middleware.
Usage
In your app/Http/routes.php use the middleware just like auth or other middlewares, for example, you might make a route group for all the pages that should be cached:
Route::group(['middleware' => 'cachepage'], function ()
{
Route::get('/', 'HomeController#home');
Route::get('/contacts', 'SectionController#contacts');
});
The list of middlewares has to be inside square brackets:
Route::get('middle', ['middleware' => ['cachebefore', 'cacheafter'], function()
{
echo "From route";
}]);
I've started learning Laravel 5.1 and so far I'm liking it! But there is one thing I don't get yet..
In my previous project I had 2 specific controllers (eg: "normal", "extended") which , after a successfull login, were called based on the Users user_group from the database.
If "Foo.Bar" enters his valid credentials and has the group normal he is redirected to NormalControler. Since I wasn't using any framework I restricted access to the other group by setting a $_SESSION with the group and checking it. So if another group tried to access that controller he got redirected.
How would this be achievable in Laravel 5? So far I have a controller which is callable without an Authentication and one restricted by this code in routes.php :
// All routes in the group are protected, only authed user are allowed to access them
Route::group(array('before' => 'auth'), function() {
// TO-DO : Seperate Controller access
});
And the login looks like this :
public function performLogin()
{
$logindata = array(
'username' => Input::get('user_name'),
'password' => Input::get('user_pass')
);
if( Auth::attempt( $logindata ) ){
// return \Redirect::to( check group and access this controller based on it);
}
else {
// TO-DO : Redirect back and show error message
dd('Login failed!');
}
}
----- EDIT -----
I've run the artisan command and made this middleware as you suggested :
namespace App\Http\Middleware;
use Closure;
use Request;
class GroupPermissions
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $group)
{
// Check User Group Permissions
if( $request->user()->group === $group ){
// Continue the request
return $next($request);
}
// Redirect
return redirect('restricted');
}
}
and edited this line into Kernel.php into $routeMiddleware :
'group.perm' => \App\Http\Middleware\GroupPermissions::class
I think this is done right so far, correct me if I'm wrong! Could I then do something like this to restrict the controllers?
Route::group(array('before' => 'auth'), function() {
Route::group( ['middleware' => 'group.perm', 'group' => 'normal'], function(){
Route::get('/normal/index', 'DummyNormalController#index');
});
Route::group( ['middleware' => 'group.perm', 'group' => 'extended'], function(){
Route::get('/extended/index', 'DummyExtendedController#index');
});
});
Ok, here is what you might do. Once user is logged in, you would check his credentials, get his user_group and decide what controller he should be redirected to.
if( Auth::attempt( $logindata ) ){
$user = Auth::user();
if ($user->inGroup('normal')) {
return redirect()->route('normal_controllers_named_route');
}
return redirect()->route('extended_controllers_named_route');
}
return redirect()->back()->withFlashMessage('don\'t get me wrong');
This will handle right routing after logging in.
The next portion where you need to protect you routes from unwanted user groups may be achieved with middlewares.
do an artisan command php artisan make:middleware ShouldBeInGroup
go to app/http/Kernel.php and add your new middleware to the routeMiddleware array. Key of the item might be anything you like. Let's call in inGroup. So: 'inGroup' => 'App\Http\Middleware\ShouldBeInGroup'
Now, in your controller, in constructor, you are able to call this middleware
$this->middleware('inGroup:extended'); //we also passing the name of the group
at lastly, work on the our middleware. Open newly created ShouldBeInGroup class and edit the handle method.
public function handle($request, Closure $next, $groupName)
{
if (Auth::check() && Auth::user()->inGroup($groupName)) {
return $next($request);
}
return redirect('/');
}
And finally you should work on inGroup method, that should return true of false. I assume that you have user_group field your users table. Then in your User eloquent model add the method
public function inGroup($groupName) {
return $this->user_group == $groupName;
}
Edit
if you want to use this middleware in your routes, you can do the following
Route::group(array('before' => 'auth'), function() {
Route::get('/normal/index', ['middleware' => 'group.perm:normal', 'uses' =>'DummyNormalController#index']);
}
But generally it's better to put all your middlewares into your Controller's constructor
public function __construct(){
$this->middleware('group.perm:normal'); // you can also pass in second argument to limit the methods this middleware is applied to : ['only' => ['store', 'update']];
}
And also on this note, Laravel provides built in auth middleware that you can use
public function __construct(){
$this->middleware('auth');
$this->middleware('group.perm:normal');
}
so then your routes would become much cleaner, just:
Route::get('normal/index', 'DummyNormalController#index');
I think the best way to do that is using middlewares. See the doc here
You can easily create a middleware using the following artisan command:
php artisan make:middleware ExtendedMiddleware
If you can't or don't want to use artisan, you need to create a class in The App/Http/Middleware folder.
In this class you'll need the following method to handle the request. In the method you can check for the user group.
public function handle($request, Closure $next)
{
// check user group
if( user_group_ok )
return $next($request); // Continue the request
return redirect('restricted'); // Redidrect
}
You can then use this middleware in your route.php file:
Route::group(['middleware' => 'auth'], function()
{
// Logged-in user with the extended group
Route::group(['middleware' => 'extended'], function()
{
// Restricted routes here
});
// Normal routes here
});
You can create a Middleware called : PermissionFilter
In PermissionFilter, you check if requesting user is in the group or not.
I can't provide a demo for now, but if you want I can make a demo later.
L5 middleware: http://laravel.com/docs/5.1/middleware
I have a problem with POST cURL request to my application.
Currently, I'm building RESTFUL registration function using laravel 5.
The routes for this is example is
localhost:8000/user/create
I pass value using cURL function on terminal
curl -d 'fname=randy&lname=tan&id_location=1&email=randy#randytan.me&password=randytan&remember_token=Y&created_at=2015-03-03' localhost:8000/auth/register/
And this is my routes.php
Route::post('user/create', 'UserController#create');
And this is my function to store the registration user
public function create()
{
//function to create user.
$userAccounts = new User;
$userAccounts->fname = Request::get('fname');
$userAccounts->lname = Request::get('lname');
$userAccounts->id_location = Request::get('id_location');
$userAccounts->email = Request::get('email');
$userAccounts->password = Hash::make(Request::get('password'));
$userAccounts->created_at = Request::get('created_at');
$userAccounts->save();
return Response::json(array(
'error' => false,
'user' => $userAccounts->fname . " " . $userAccounts->lname
), 200);
}
Executing the cURL syntax above, I'm getting this error TokenMismatchException
Do you have any ideas?
Because I'm implementing middleware only in my few urls, and this cURL registration url is not tight into any authentication mechanism.
Thanks before.
In Laravel 5 (latest version) you can specify routes you want to exclude in /app/Http/Middleware/VerifyCsrfToken.php
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'rest-api/*', # all routes to rest-api will be excluded.
];
}
Hope this helps.
Laravel 5 enforces CSFR token authentication in middleware by default.
you can disable CSFR on selected route Here is the link
or you can try some of these solutions. Hope so it will help.
changing your csfr token method /app/Http/Middleware/VerifyCsrfToken.php
public function handle ($request, Closure $next)
{
if ( !$request->is("api/*"))
{
return parent::handle($request, $next);
}
return $next($request);
}
In my case, i needed to add the route on api.php instead of web.php