How to Session::flash with default AuthController in Laravel - php

After hour wasted on such a (as I thought) minor thing, I need Your help.
I've made a quickstart with Laravel using php artisan make:auth command. Then I redefined login method in AuthController. Now it looks like this:
protected function login(Request $request) {
if (Auth::attempt(["name" => $request->username, "password" => $request->password])) {
return Redirect::route("home")->with("message", "Zalogowano");
} else {
return Redirect::route("get.login")->with("message", "Nie zalogowano");
}
}
In my view I've got{{ Session::get("message") or "" }}
and my message doesn't show up.
I've also tried Session::flash("message", "message string"), same effect.
Any ideas what could I do to show a message after (un)successfull login?
PS. Should've mention logging in and out works just fine.

Are your routes defined within the 'web' middleware group (including the Auth routes)? The 'web' middleware group handles starting the session. More specifically the middleware \Illuminate\Session\Middleware\StartSession::class handles starting the session. No session, no messages. Your routes should be wrapped in the Route group like so:
Route::group(['middleware' => 'web'], function () {
// Define routes here
});
Take a look in app\Http\Kernel.php to see what Middleware classes are included in this Middleware group and dive into them.

Try {{ $message }} in your template.
When you use ->with("varnamehere", "value") to flash data on the end of your redirect, you can simply access the variable in your template with $varnamehere.
The variable simply exists, ready for use in your template.
There doesn't seem to be a section in the manual that clearly explains this.

In your view template try:
#if (session()->has('message') ? session()->get('message') : "") #endif
It will print the message if is set..
Hope it helps..

Related

Can U use the middleware the same way in the controller or route?

I'm trying to make sure that you can't just type /admin into the top bar. I made an extra column in the user table called admin and it's either 0 (normal user) or 1 (admin).
In the blade page, I'm checking:
#if (Auth::check())
#if (Auth::user()->admin == 1)
<p>Hello Admin</p>
#else
<p>Hello standard user</p>
#endif
#endif
I was asking if it's possible to either check in the route (something like this)
Route::get('/home', 'HomeController#index')->name('home')->middleware('auth')-where('admin' 1);
or in the controller (something like this)
public function __construct()
{
$this->middleware('auth')->where('admin' 1);
}
You can achieve this using a new middleware.
First create a new middleware by typing in your console:
php artisan make:middleware isAdmin
Name your middleware whatever you like, isAdmin is common here.
Next you must add the middleware to your Kernel.php located at app/Http/Kernel.php, edit the array named $routeMiddleware and add the following:
'isAdmin' => \App\Http\Middleware\IsAdmin::class,
Open your IsAdmin.php located in your middleware folder and modify the handle method like so:
{
if (Auth::user() && Auth::user()->admin == 1) {
return $next($request);
}
return redirect('/');
}
Note: the middleware will also check if a user is authenticated so could be used in place of auth for admin routes, remember to modify the return to suit your needs
Lastly, add the middleware to your route, there are a number of ways to do this.
if you are planning to use it instead of auth middleware, simple change auth to isAdmin in your routes file ->middleware('isAdmin')
Another option is to modify your routes file like so
Route::group(['middleware => 'auth'], function () {
Route::get('/home', 'HomeController#index')->name('home')->middleware('isAdmin');
}
So you don't need to apply the middlewares to each route, there are a bunch of possibilities for this here https://laravel.com/docs/7.x/middleware#assigning-middleware-to-routes

Declare same route twice but expect different behaviour according to a middleware

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.

Laravel 5.2 token mismatch and middleware error

I'm using Laravel 5.2 and doing all authentication manually. So, although everything works, but I get a token mismatch error and the reason is that I'm not passing my routes through the web middleware in my routes file:
Route::group(['middleware'=>['web']],function (){
Route::get('/', function () {
return view('welcome');
})->name('home');
});
Route::social();
where Route::social(); is
public function social() {
$this->post('/signup',['uses'=>'UserController#postSignUp','as'=>'signup']);
$this->post('/signin',['uses'=>'UserController#postSignIn','as'=>'signin']);
$this->get('/dashboard',function() {
return view('dashboard');
})->middleware('auth');
}
But if I move Route::social(); to the web middleware group, it doesn't count errors and so return empty errors even if there are. How do I get around with it? I want both things!
I've the token field in my form using {!! Form::token() !!}
You are probably manually adding an $error array to your view, the web middleware will do the same thing so this will be overwritten. The web middleware group includes \Illuminate\View\Middleware\ShareErrorsFromSession which creates an error variable in the views with validation errors.
There are two ways to fix this. One is to only include the \App\Http\Middleware\VerifyCsrfToken middleware for this route. The other, wich I would prefer, is to add the route to the web middleware group, but use another name for your array with errors.

Laravel 5.2.* redirect->back->with doesnt work

I want to write some data to my database, if the query fails I want to display an error.
I tried the following:
return redirect()->back()->with('data', ['Database Error!']);
The redirect works great, but I cant read out the response in $data
My Blade:
#if (session()->has('data'))
<div class="alert alert-danger" role="alert">...</div>
#endif
//Second try
<?php if(session('data')) echo $message; ?>
But both methods doesn't work, i read a lot of L5.2 Docs but nothing works.
Do i need to modify the session config?!?
Or what is the problem?
try
return back()->with('data', ['Database Error!']);
back() will take you to the previous page with a data variable that holds 'Database Error!'
This is a breaking problem with the 5.2 upgrade. What's happening is the middleware which is responsible for display the Session message in all your views is not being utilized because it was moved from the global middleware to the web middleware group.
There are two ways to fix this:
In your kernel.php file(app/Http/Kernel.php), you can move the middleware \Illuminate\View\Middleware\ShareErrorsFromSession::class back to the protected $middleware property.
Wrap all your web routes with a route group and apply the web middleware to them:
Route::group(['middleware' => 'web'], function() {
// Place all your web routes here...(Cut all `Route` which are define in `Route file`, paste here)
});

Laravel return back with flash data

I have a contact form. On submit the POST request goes to a controller that handles the contact form (checks the request and emails the data). At the bottom of the controller I have this:
return back()->with('flash-message', 'Message!');
In the view I try to echo the message with
{{ session('flash-message') }}
This doesn't seem to work. The message is not in the session.
What could be wrong?
Im using:
Laravel version 5.2.7
please take Session variables with this way..
return redirect()->back()->with('flash-message','message');
and in View..
{{Session::get('flash-message')}}
I figured it out. It has to do with the Laravel 5.2 update. The middleware which is responsible for making that flash data available to all your views is not being utilized in normal Routes anymore. It was moved from the global middleware to the web middleware group. This post explains the issue and how to fix it.
Laravel 5.2 $errors not appearing in Blade
This post explains 2 ways to fix it:
In your kernel.php file, you can move the middleware \Illuminate\View\Middleware\ShareErrorsFromSession::class back to the protected $middleware property.
You can wrap all your web routes in the web middleware group (see below). Also place the Routes that handle the form here:
Route::group(['middleware' => 'web'], function() {
// Place all your web routes here...
});
You can do this.In the controller:
Session::flash('message','Empty input not accepted');
return back();
And in the view file to use this Session you can do same as above mentioned:
{{ \Session::get($message) }}
Hope this helps you....

Categories