Retain http method on redirect - php

I wrote localisation helper in laravel which checks whether en, fr or another local is in the URI.
If no locale is supplied config("app.locale") should be prepended to the original URI and a redirect should be made to this new URI. I.e. /user should be redirected too /en/user.
I am currently trying to resolve this problem by using:
public function handle($request, Closure $next, $guard = null)
{
$langSegment = $request->segment(1);
// if first segment is language parameter then go on
if (strlen($langSegment) == 2 && ($langSegment == 'en' || $langSegment == 'fr')) {
App::setLocale($langSegment);
return $next($request);
} else {
$newURL=url(config("app.locale") . "/" . implode("/",$request->segments()));
return redirect($newURL);
}
}
This works fine for most request unless the method is POST and there is no $language set. When this is the case the user is redirect but the method is changed to a POST request.
I also tried changing my redirect to
return redirect()->route('routeName', $request->all(), 302, ['method','POST'])
But this also doesn't work.

So I did some testing with regards to the HTTP status code 307.
Let me first describe my test setup, I created the following routes:
Route::get("/help", 'HelpController#index');
Route::post("/post", 'HelpController#post');
Route::post("/redirected", 'HelpController#redirected');
The HelpController contained the following code:
<?php
namespace App\Http\Controllers;
class HelpController extends Controller
{
public function index(){
return view('help');
}
public function post(){
return redirect('/redirected', 307);
}
public function redirected(){
echo "Success";
}
}
and help.blade.php was a very basic form namely:
<form method="post" action="/post">
#csrf
<button>Go</button>
</form>
I am glad to report that a 307 return code does successfully keep the POST method.
I.e. when I went to the /help url and pressed the "Go" button I saw the "Success" message as expected.
What does this mean for me you might ask?
Well we can solve your problems with a very simple change:
return redirect($newURL);
becomes
return redirect($newURL, 307);
Wasn't that easy in the end?
Furthermore as you can see in my test setup this also keeps the crsf protection which is a definite plus from a security standpoint.

Related

Laravel route when where condition is false

I have the next code:
Route::get('/{lang}/user/sort-by-{class}', function ($lang,$class) {
return view('users.list',compact("lang","class"));
})->where('class', '[a-z]+');
Route::get('/{lang}/user/{user}', function ($lang,$user) {
return view('users.user',compact("lang","user"));
});
When condition in where is false, how can I send it directly to 404 when sort-by- is for example a number? The problem is that it goes to secondary route as an user.
For example:
/en/user/sort-by-name is ok
/en/user/sort-by-4446 must show 404 page
I know that i can do another route just between them with
Route::get('/{lang}/user/sort-by-{class}', function ($lang,$class) {
return \Response::view('errors.404',array(),404);
})->where('class', '.*');
but this seems ugly, i would like in same sentence
Basically, you may do this
Route::get('/{lang}/user/sort-by-{class}', function ($lang,$class) {
if (is_numeric($class)) {
abort(404, 'Your reason');
}
return view('heros.list',compact("lang","class"));
});
Though, using closures in routes is a bad practice because they cannot be serialized in production mode. That's why you should use a controller to return your view, and assign a middleware to this route which will check your class and abort the request if needed.

login page in two places. for each other redirect

I make an online store in which I have two login places. /checkout (in cart) and /login.
Can i do it in the existing method to make redirect look like this?
if i login in /checkout ->redirect('/checkout').
(for loggin in /login) it stays like it is /redirect('/')
I would solve that by using the redirectTo() method in the Login Controller and checking which route is sending the request through the path() method. You have to name the routes for it to work though. So in your login Controller you'll have this;
use Illuminate\Support\Facades\Route;
protected function redirectTo(){
if(Route::currentRouteName() == 'login'){
return '/';
}else if(Route::currentRouteName() == 'checkout'){
return '/checkout';
}
}
more info on how to get the route name here
and info on the redirectTo() function here
Try it out, tell me what happens..
only this solution works:
protected function redirectTo() {
if(strpos(URL::previous(), 'checkout')) {
return '/checkout';
} elseif(strpos(URL::previous(), 'login')) {
return '/';
}
}

Is using if else statement to load view based on parameters after controller and action part of url efficient or is there a better way of doing this

I can have the following urls
www.example.com/accounts/
www.example.com/accounts/signup
www.example.com/accounts/signup/validate
www.example.com/accounts/login
for each case, accounts becomes my controller, and index, signup, signup and login becomes my actions (or methods) respectively. I have to render different views based on what my actions are. Here is an example of what my code looks like
index
$url_segments = explode('/', $url);
$controller = !empty($url_segments[0]) ? $url_segments[0] : 'home';
array_shift($url_segments); // removes the controller name from array
$action = isset($url_segments[0]) && !empty($url_segments[0]) ? $url_segments[0] : 'index';
array_shift($url_segments); // removes the action name from array
$controller = ucfirst($controller);
$controller = new $controller($url_segments);
$controller->$action();
controller class
class Accounts{
private $url_segments;
public function __construct() {
$this->url_segments = $url_segments;
}
public function index() {
// index code here
}
public function login() {
// login code here
}
public function signup() {
if (!isset($this->url_segments[0])) {
// url entered was: example.com/signup
} else if (isset($this->url_segments[0]) && $this->url_segments[0] == 'validate') {
// url entered was: example.com/signup/validate
}
}
}
from how my code appeared above, it can be seen that as parameters keep adding after the controller and action part of the url I'll need to keep using conditional statements to run the proper code as in the case of /signup/ and signup/validate. Is this method of using conditional statement to load view based on parameters efficient or is there a better way of doing this.
I would recommend you to make use of a routing system like Symfony Routing. There you could add a new Route for every url and redirect them to your specific controller.
Example Route:
$routes = new RouteCollection();
$routes->add('/accounts_signup', route('POST', "/accounts/signup", 'App\Controller\AccountController:signup'));
return $routes;
This route would call the signup method in the AccountController calss when www.example.com/accounts/signup get called with a post request.
I recommend you to use something like this. Even if this might be a bit complicated for the beginning, after reading (and understanding) the docs this will safe you a lot of time and it will make your code more readable as well.

How to redirect different page from same controller function in laravel 5.2

I want to redirect 2 different page from this controller function along with value.Here is my code. It works but both of time url become same.what shuld I do?
//in routes.php
Route::post('/','mycontroller#check');
// in controller.php
public function check(Request $request)
{
$c_email = $request->email;
$c_pass=$request->pass;
$c_type=$request->select;
$var=DB::select("SELECT * FROM reg where email = '$c_email' and Password = '$c_pass' and type = '$c_type'");
if ($var) {
return view('farmer')->with('user',$var);
// return redirect('farmer')->with('user',$var);
}
else {
$msg="Invalid login";
return view('index')->with('show',$msg);
}
}
If you want to actually redirect u can use the redirect() helper as statet in the official docs https://laravel.com/docs/5.3/redirects
You can also pass data
redirect('/my-route')->with(['user' => $var]);
The passed data can then be accesses through the session helper
$var = session('user')
HOWEVER, it seems like you have major issues in your code. Your password does not seem to be encrypted. Also there's no reason to use plain sql instead of eloquent here.
The route that is shown in the browser is defined in your
Route::post('/','mycontroller#check');
If you just return different views, the route does not change. You need to redirect to other views.
If you redirect to other routes you will ofcourse need to add / define them.
Route::get('/my-route', function() {}); // or post etc.

Input or Request are always empty in controllers

I need some help on a topic that is making me crazy on Laravel 5.2
I have the following routes.php, which I have reduced to the minimum :
use Illuminate\Http\Request;
/**
* Category Page
*/
Route::get('/category/test/', function()
{
dd("I'm in !");
dd(Input::all());
$page = Input::get('page');
if(isset($page)){
dd($page);
}
}
When I call the following url : http://192.168.99.100/category/test?page=55, I would expect to get the parameter page in Input or Request but however it is always empty. The following code just displays "I'm in !" but nothing else.
Can you help me understanding what is wrong in here ? I previously used controllers and Request parameters but it was also empty, thus this simple test. Note that post requests are working fine.
Thanks !
I finally found it out !
That was a problem in my nginx configuration, that prevented php variable QUERY_STRING to be correctly set up and Laravel is basing on this variable to retrieve the data.
For more information, see https://serverfault.com/questions/231578/nginx-php-fpm-where-are-my-get-params/362924#362924
Thaks for your answers anyway !
You can use both , actually there is no error in your code except if you missed the use statement for Input facade.
use Illuminate\Http\Request;
/**
* Category Page
*/
Route::get('/category/test/', function()
{
dd(Input::all());
dd("I'm in !");
$page = Input::get('page');
if(isset($page)){
dd($page);
}
}
So question is why you are getting nothing! because the route is GET request so if you post/update/patch anything to it you will get methodNotAllowed exception. Now just goto your browser and type http://whateverdomain/category/test/?page=atiq&have=fun and yes now there is something.........
Route::get('/category/test/', function(Request $request)
{
$input=$request->All();
dd($input);
$page = request->get('page');
if(isset($page)){
dd($page, request->get('have'));
}
}
because you didn't told function to expect request
it shall be
Route::get('/category/test/', function(Request $Request)
{
$input=$Request->All();
dd($input);
// usage $input['query'];
$page = Input::get('page');
if(isset($page)){
dd($page);
}
}

Categories