I'm using laravel 5.1, I'm trying to update locale in app file like this :
In Locale Middleware file :
...
public function handle($request, Closure $next)
{
if(Session::has('locale'))
{
$lang = Session::get('locale');
App::setLocale($lang);
}
return $next($request);
}
Any idea about this ??
Oooof finally after two hours ><' !!
It's the line place of locale class in middleware -.-' !!!
I set it in last line like this :
...
...
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\Locale::class,
];
and All is fine and working ! thanks for you all :))))
The only solution which I found was set locale in constructor method of middle ware, like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Request;
class Localization
{
protected $app;
public function __construct(Application $app, Request $request)
{
if($locale = $request->header('Content-Language')){
if(in_array($locale, ['en', 'fa'])){
$app->setLocale($locale);
}
}
}
/**
* Handle an incoming request.
*
* #param Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
With ♥♥♥ and over 2 hours trying!
Thanks,
:) I had the same problem and the solution was put the middleware in the file
App\Http\Kernel.php in the section of protected $middleware = []
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\myNewMiddleware::class,
];
I have solved my issue as follow:
1 Step. Created a middleware. php artisan make:middleware SetLocale
2 Step. Updated the middleware file. File: app/Http/Middleware/SetLocale.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLocale
{
private $locales = ['ar', 'en'];
// ...
public function handle($request, Closure $next, $locale)
{
if (array_search($locale, $this->locales) === false) {
return redirect('/');
}
App::setLocale($locale);
return $next($request);
}
}
3 Step. Appended my new middleware to app/Http/Kernel.php $routeMiddleware array.
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// ...
protected $routeMiddleware = [
// ...
'locale' => \App\Http\Middleware\SetLocale::class,
];
}
4 Step. I have used my the middleware in my routes/web.php file.
Route::group(['prefix' => 'ar', 'namespace' => 'Arabic', 'middleware' => 'locale:ar'], function() {
Route::get('/', 'PashtoHomeController#index')->name('arHome');
// ...
});
Route::group(['prefix' => 'en', 'namespace' => 'English', 'middleware' => 'locale:en'], function() {
Route::get('/', 'PashtoHomeController#index')->name('enHome');
// ...
});
Route::get('/', function() {
return redirect()->route('arHome');
});
Related
I am trying to add newrelic to my laravel site. I found this repo. But couldn't use it properly.
Where should I put this code?
App::after( function() {
Newrelic::setAppName( 'MyApp' );
} );
Or maybe other ways to add routes response time to newrelic...
App::after does not exists anymore.
You can register a middleware that is executed after the request to do what you need:
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
Newrelic::setAppName( 'MyApp' );
return $response;
}
}
and register it as usually in app/Http/Kernel.php:
protected $middleware = [
...,
\App\Http\Middleware\AfterMiddleware::class
];
I have read almost everything in web and documentation but i can't find solution for my Problem.
I have a variable stored in Session , then I want to put this variable in every url generated by route('some-route') .
In Session I have sub = "mysubid"
When I generate Route route('my-route') I want to pass this sub parameter in query string: http://domain.dom/my-route-parameter?sub=mysubid
Can you help me to solve This problem? Any helpful answer will be appreciated;
You can use the Default Values feature.
First create a new middleware php artisan make:middleware SetSubIdFromSession. Then do the following:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\URL;
class SetSubIdFromSession
{
public function handle($request, Closure $next)
{
URL::defaults(['sub' => \Session::get('sub')]);
return $next($request);
}
}
At the end register your new middleware in app/Http/Kernel.php by adding it to $routeMiddleware.
protected $routeMiddleware = [
// other Middlewares
'sessionDefaultValue' => App\Http\Middleware\SetSubIdFromSession::class,
];
Add {sub} and the middleware to your route definition:
Route::get('/{sub}/path', function () {
//
})
->name('my-route')
->middleware('sessionDefaultValue');
Since you want this on every web route you can also add the middleware to the web middleware group:
protected $middlewareGroups = [
'web' => [
// other Middlewares
'sessionDefaultValue',
],
'api' => [
//
]
];
Try this , You need to create middleware php artisan make:middleware SetSubSession
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\URL;
class SetSubsSession
{
public function handle($request, Closure $next)
{
if(session('sub')){
$url = url()->full();
return redirect($url.'?sub='.session('sub'));
}
return $next($request);
}
}
in app/http/Kernel.php
protected $routeMiddleware = [
........
'setsubsession' => \App\Http\Middleware\SetSubsSession::class,
]
in route.php add
Route::group(['middleware' => 'setsubsession'], function(){
//and define all the route you want to add sub parameter
});
using this you don't need to change all your routes.This will automatic add "sub" in the route define in that middleware.
Laravel version: 5.1.46
routes.php
Route::get('/rocha', 'RochaController#index');
Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'Age' => \App\Http\Middleware\AgeMiddleware::class,
'Role' => \App\Http\Middleware\RoleMiddleware::class,
];
RochaController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class RochaController extends Controller
{
public function __construct() {
$this->middleware('Role');
}
public function index() {
echo '<br>Hi I am index';
}
}
RochaMiddleware.php
namespace App\Http\Middleware;
use Closure;
class RoleMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
echo '<br>Hi I am middleware';
return $next($request);
}
public function terminate($request, $response) {
echo '<br>Shtting down...';
}
}
Result:
Hi I am middleware
Hi I am index
When I use middleware inside the controller via its constructor $this->middleware('Role') the terminate() function does not get called. When I switch the code taking out the constructor in the controller and change the route to the following the terminate() function gets called:
Route::get('/rocha', [
'middleware' => 'Role',
'uses' => 'RochaController#index'
]);
Result:
Hi I am middleware
Hi I am index
Shtting down...
Why does the constructor version ($this->middleware('Role')) prevent the terminate() function from being called?
Why does the route version work and the terminate() function is called as opposed to the above?
If you define a terminate method on your middleware, it will automatically be called after the response is ready to be sent to the browser.
from terminable-middleware
I think you misunderstand the usage of terminate method. Laravel actually call the terminate method, but the browser will not show the output of terminate. Because the response has been sent to browsers.
You can use this terminate method to test whether the call is successful.
public function terminate($request, $response)
{
file_put_contents(__DIR__ . '/1.txt', 'hello terminate');
}
By the way, I'm test your code, it always output:
Hi I am middleware
Hi I am index
I also wonder why you can get Shtting down...
I'm trying to do something but i cant even imagine how to do it.
To pass parameters to a middlware I'm doing this:
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
//
}]);
From the laravel documentation.
Then get the parameter in the handle function...
But laravel suggest to declare the middleware use in the __construct in the Controller, insted in the route.
So...
public function __construct() {
$this->middleware('auth');
}
But i dont know how to pass parameters to the Controller.
I would thank any help.
You can access url parameters into middleware shown as below:
routes.php
Route::get('/test/{id}', ['uses' => 'Test#test']);
Test Controller
<?php
namespace App\Http\Controllers;
class Test extends Controller
{
/**
* Test constructor.
*/
public function __construct()
{
$this->middleware('test');
}
public function test()
{
return 'sample';
}
Test Middleware
<?php namespace App\Http\Middleware;
use Closure;
class Test
{
public function handle($request, Closure $next)
{
dd($request->id);
return $next($request);
}
}
** dont forget update your Kernel.php to activate middleware
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'test' => \App\Http\Middleware\Test::class,
];
Don't put the middleware in the controller. Keep business logic out of the controller as often as possible.
Instead, make your middleware file.
php artisan make:middleware MyMiddlewareDoesThings
Now inside of your file, locate the $handle function.
public function handle($request, Closure $next)
Just add arguments after the request and closure
public function handle($request, Closure $next, $role)
Now $role will contain the value of role:value which from your example would be $editor
#muhammad-sumon-molla-selim answer is actually the best one according to the question, but it leaks into explanation.
With my knowledge I was able to follow his guideline so here is a full example plus a usecase where Route's middleware or Request parameters is not possible.
I have an abstract CRUDControllerBase, which is extended by many child controllers.
Each child controllers need a different permission to perform any action on the model excepts index/show.
So I was forced to dynamically pass the permission (string) from the controller to the Middleware, here is the base structure:
// App\Http\Controllers\CRUDControllerBase.php
abstract class CRUDControllerBase extends Controller
{
/**
* #var string The needed permission to call store or update
* If null, permission is granted to every users
*/
protected ?string $permission = null;
public function __construct()
{
// Here I need to pass to VerifyUserPermission the controller's permission
$this->middleware(VerifyUserPermission::class)
->except(['index', 'show']);
}
}
// App\Http\Controllers\DocumentController.php
class DocumentController extends CRUDControllerBase
{
protected ?string $permission = 'documents';
}
// App\Http\Controllers\EventController.php
class EventController extends CRUDControllerBase
{
protected ?string $permission = 'events';
}
And here is how I tackled this following the #muhammad-sumon-molla-selim answer:
// App\Http\Middleware\VerifyUserPermission.php
// Create the VerifyUserPermission middleware, which accepts the permission string
class VerifyUserPermission
{
public function handle(Request $request, Closure $next, ?string $permission): mixed
{
$user = $request->user();
// If a permission is needed but the user doesn't have it, abort
if ($permission && !$user->$permissionField) {
abort(401);
}
return $next($request);
}
}
// App\Http\Kernel.php
// Register the middleware
class Kernel extends HttpKernel
{
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
// [...]
'permission' => \App\Http\Middleware\VerifyUserPermission::class
];
}
// App\Http\Controllers\CRUDControllerBase.php
// Then just register the middleware into the CRUDControllerBase's constructor
abstract class CRUDControllerBase extends Controller
{
protected ?string $permission = null;
public function __construct()
{
// 'documents' permission will be needed for Documents' edition
// 'events' permission will be needed for Events' edition
// And so on for many others controllers
$this->middleware("permission:$this->permission")
->except(['index', 'show']);
}
}
If you want to get the parameters in the __construct of your controller you could do this:
class HomeController extends \BaseController
{
public function __construct()
{
$this->routeParamters = Route::current()->parameters();
}
}
Some service makes HTTP request to my site and passes some input. This input has a little bit wrong structure for me, so I'm trying to modify it.
I made a middleware and attached this middleware to my route. The handle method looks like this:
public function handle($request, Closure $next)
{
$input = $request->all();
// Input modification
$request->replace($input);
\Log::info($request->all()); // Shows modified request
return $next($request);
}
However in my controller I got old input. Also I'm a little bit confused since I also use FormRequest, and as I realize these two requests are different entities. Then how can I modify the input in the middleware?
I don't know what's the exact problem in your case but I'll show you what I did to make it work and it might solve your problem:
app/Http/Middleware/TestMiddleware.php
<?php namespace App\Http\Middleware;
use Closure;
class TestMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$input = $request->all();
if (isset($input['mod'])) {
list($input['int'], $input['text']) = explode('-', $input['mod']);
unset($input['mod']);
// Input modification
$request->replace($input);
\Log::info($request->all()); // Shows modified request
}
return $next($request);
}
}
app/Http/Kernel.php
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
Middleware\TestMiddleware::class, // this line added
];
app/Http/routes.php
Route::get('/test', ['uses' => 'TestController#index']);
app/Http/Requests/SampleRequest.php
<?php namespace App\Http\Requests;
class SampleRequest extends Request
{
public function rules()
{
return [
'int' =>
[
'required',
'integer'
],
'text' => [
'max: 5',
]
];
}
}
app/Http/Controllers/TestController.php
<?php namespace App\Http\Controllers;
use App\Http\Requests;
class TestController extends \Illuminate\Routing\Controller
{
public function index(Requests\SampleRequest $request)
{
dd($request->all());
}
}
In console I've run composer dump-autoload.
Now when I run the following url:
http://testproject.app/test?mod=23-tav
I'm getting in controller from dd:
array:2 [▼
"text" => "tav"
"int" => "23"
]
as expected and when I run for example http://testproject.app/test?mod=abc-tav I'm being redirected to mainpage in my case because data doesn't pass validation from SampleRequest (int is not integer)