Redirect Loop in Laravel 5 - php

I'm doin the backend of a website while learning Laravel. I have these router below:
Route::get('/update/survivor/flag', 'SurvivorsController#flagSurvivor');
Route::get('/submit/log/flag', 'LogsController#submitFlag');
And in the flagSurvivor function i have:
public function flagSurvivor(Request $request){
$this->validate($request,[
'idFlagged' => 'required',
'idFlagger' => 'required'
]);
//Get the ids
$id = $request->input('idFlagged');
$flaggerid = $request->input('idFlagger');
//Get the flagger name
$survivors = Survivor::all();;
$flaggerSurvivor = $survivors->find($flaggerid);
//Flag a survivor
$survivors = Survivor::all();;
$flaggedSurvivor = $survivors->find($id);
$flaggedSurvivor->flags = $flaggedSurvivor->flags+1;
//Save updates
$flaggedSurvivor->save();
//Redirect
return redirect('submit/log/flag')
->with('nameFlagged', $flaggedSurvivor->name)
->with('idFlagged', $id)
->with('nameFlagger', $flaggerSurvivor->name)
->with('idFlagger' , $flaggerid);
}
which works perfectly except for the redirect part. After inserting the change into the DB it should send data to the submitFlag function, except that it doesn't. It just keeps looping with itself until it crashes from too many redirects. The log submit page also works just fine:
public function submitFlag(Request $request){
$this->validate($request,[
'nameFlagged' => 'required',
'nameFlagger' => 'required',
'idFlagger' => 'required',
'idFlagged' => 'required'
]);
$flaggerid = $request->input('idFlagger');
$flaggedid = $request->input('idFlagged');
$flaggername = $request->input('nameFlagger');
$flaggedname = $request->input('nameFlagged');
//Create a new log
$flag = new Log;
$flag->log = "The survivor $flaggername($flaggerid) reported that the survivor $flaggedname($flaggedid) is contaminated";
//Save log
$flag->save();
echo "Success";
}
if i go to
localhost/submit/log/flag?idFlagger=1&idFlagged=2&nameFlagger=Matheus&nameFlagged=Tauan
It echoes "Success" and inserts the log into the DB. But i just don't get it why it doesn't work by sending the parameters in the flagSurvivor function. I assume I'm doing the withs in the redirects wrong, or maybe something in the routes I have no idea. Any help is appreciated!
Turns out that using
return redirect('submit/log/flag?nameFlagged='.$flaggedSurvivor->name.'&idFlagged='.$id.'&nameFlagger='.$flaggerSurvivor->name.'&idFlagger='.$flaggerid);
Instead of the 'with's that I was using works properly.

Change your redirect to an action and the with's to an associative array:
//Redirect
return redirect()->action('LogsController#submitFlag', [
'nameFlagged' => $flaggedSurvivor->name,
'idFlagged' => $id,
'nameFlagger' => $flaggerSurvivor->name,
'idFlagger' => $flaggerid
]);
Redirecting to a controller action

Related

How to validate data, protect routes, authorize routes/actions in Laravel 8

This will be a bit long question, I'm finishing my application, but there are few left things to be done before ending.
At first: I did few POST forms/functions. They works well, but in case I would not pass one of the $request data, it comes with SQL bug, I read that to manage that I need validation, so I made Request model with validation rules, but I dont know how to implement it into my Controller class.
This is how looks like my request model and create class inside of controller:
public function create(Request $request)
{
$id = Auth::id();
$event = new Event;
$event->name = $request->name;
$event->description = $request->description;
$event->address = $request->address;
$event->date_of_event = $request->date_of_event;
$event->displayed = 0;
$event->photo_patch = $request->photo_patch->store('images','public');
$event->club_id = $request->club_id;
$event->user_id = $id;
$event->save();
return redirect('events');
}
------------Request---------------------------
return [
'name' => 'required|max:50',
'description' => 'required|max:100',
'address' => 'required|max:63',
'date_of_event' =>'required',
'photo_patch' =>'required',
'club_id' =>'required',
];
Second thing to protect is to split views for admin and for user, Since I did authorization via Gate(admin-level) with column in db admin(boolean)
I'm thinking about doing validation like this:
public function index()
{
$id = Auth::id();
if (Gate::authorize('admin-level')){
$events = Event::get();
}
else{
$events = Event::where('user_id',$id)->get();
}
return view('backend/event/index', ['events' => $events]);
}
but then, comes error:
Non static method 'authorize' should not be called statically.
Is there any way to bypass that? Or, is there any better/easier way to authorize?
My third problem is to protect users from making changes by other users.
What do I mean by that.
Every user got acces only to his own club/events BUT if someone would put url for example other ID, he can edit every single club/event he want. How can I prevent it?
And my final question
I'm protecting my routes with middleware auth is there any better way to do it?
Route::middleware(['auth'])->group(function() {
Thank you in advance for anwsers.
Your gate should be called on the facade, which i do not believe you are doing. Please use the following gate class.
use Illuminate\Support\Facades\Gate;
Validation can be implemented by calling validate() on your request object. This will also automatically throw exceptions if failed.
$validated = $request->validate([
'name' => 'required|max:50',
'description' => 'required|max:100',
'address' => 'required|max:63',
'date_of_event' =>'required',
'photo_patch' =>'required',
'club_id' =>'required',
]);
Disallowing users from editing clubs. In general you control the access to objects, either with policies or with queries. This is an example with a policy.
public function find(Club $club) {
$this->authorize('view', $club);
}
class ClubPolicy {
public function view(User $user, Club $club)
{
return $club->user_id === $user->id;
}
}

Assigning a value to an instance of a model outside of Model::create in a controller

I am using laravel to make a website. In this website I have made a file upload system which works inside of the create function in the controller. In this function I am saving the image and at the same time assigning the fileName to the model. However, this value disappears after the redirect. I have die dumped it right before the redirect and there it is assigned.
My question is why is the fileName disappearing?
My create function that makes an instance of my model:
Edit: the beers.store should be beers.index
public function store(Request $request) {
$b = Beer::create($request->validate([
'name' => ['required', 'min:3', 'max:20'],
'nameOfFile',
'brewery' => ['required', 'min:5', 'max:25'],
'ABV' => ['required']
]));
if ($request->hasFile('image')) {
$name = $requiest->file('image')->getClientOriginalName();
$b->nameOfFile = $name;
$request->file('image')->storeAs('public/images', $b->id . ' ' . $name);
}
return redirect(route('beers.store', ['beer' => $b]));
}
The problem seemed to be that I was not calling $b->save();
Another way I could have fixed the problem is by doing Beer::find($b->id)->update(['nameOfFile' => $name]); but this adds unnecessary queries to the code, making it less optimized.

Laravel 5.1 - Return to edit page

i'm writing a resource controller, and i have a problem with edit method.
i inserted a validator form, and if there is a error return to edit page with messages, but RETURN doesnt work good!
public function update(Request $request, $id)
{
$rules = [
'title' => 'required',
'content' => 'required',
'image' => 'required',
];
$messages = [
'title.required' => 'Campo titolo richiesto',
'content.required' => 'Contenuto richiesto',
'image.required' => 'Campo immagine richiesto',
];
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()){
return redirect('admin/article/edit' , $id)->withErrors($validator);
}else {
$s = new Article;
$visible = (isset($_POST['visible']) == '1' ? '1' : '0');
$data = array(
'title' => $request->get('title'),
'slug' => $request->get('title'),
'content' => $request->get('content'),
'image' => $request->get('image'),
'user_id' => $request->get('user_id'),
'category_id' => $request->get('category_id'),
'visible' => $visible,
);
$s->where('id', '=', $id)->update($data);
return redirect('admin/article')->with('message', 'Articolo aggiornato con successo!');
}
}
It return to:
admin/article/edit/5
NOT to
admin/article/5/edit
How can i fix this issue? thank you for your help!
PS: $id work well, return my id edited
Here is the redirect helper. As you can see below, it takes status as its' second parameter.
function redirect($to = null, $status = 302, $headers = [], $secure = null)
What you do with passing the $id as the second parameter is actually setting the $status.
You need to pass the $to parameter as the full path like below.
return redirect('admin/article/' . $id . '/edit')->withErrors($validator);
I guess that you want to generate the url with route, which can be implemented like below.
return redirect(route('admin.article.edit', compact($id)))->withErrors($validator);
So you're saying the redirect on failure doesn't redirect to the right URL? Have you tried doing return redirect('admin/article/' . $id . '/edit')->withErrors($validator);?
I haven't tested this approach, but perhaps return redirect()->back()->withErrors($validator); could also work.
One way to do this, as others have suggested, is like following:
return redirect("admin/article/{$id}/edit")->withErrors($validator);
Or if you've a "Route Name" defined, like this..
return redirect()->route('route.name',[$id])->withErrors($validator);
it all depends on how you prefer, I prefer the later one, looks clean to me.
Easiest solution:
Laravel 5.1 has a back() helper, that returns to the previous page:
return back()->withErrors($validator);
More thorough explanation:
If you want to be more verbose, a generally more robust way to redirect to a route is to first define it as a named route in your routes.php:
Route::get('admin/article/{article_id}/edit', ['as' => 'articles.edit', 'uses' => 'ArticlesController#edit']);
Route::bind('article_id', function($id, $route) {
return App\Article::whereId($id)->findOrFail();
}
If you are using Route::resource instead, then this is already done automatically for you. To find the name of the route, run the command-line php artisan route:list. Then, in your controller method, you call it like this:
return redirect()->route('articles.edit', ['article_id' => $id])->withErrors($validator);
Using that kind of call, Laravel will automatically build the correct URL for you. This is more robust because if you ever want to change that URL to something else or change what controller method it calls, you only need to change it in one place, the routes.php, and not everywhere in your code (as long as every reference to that route in your code is referring to it by name).
Here you have
return redirect('admin/article/edit' , $id)->withErrors($validator);
means the link/route is admin/article/edit/$id(5 or 2 or ...)
better check
return redirect('admin/article/' . $id . '/edit')->withErrors($validator);
The redirect go to the passed url:
return redirect('admin/article/' . $id . '/edit'); #admin/article/id/edit
return redirect('admin/article/edit', $id); #admin/article/edit/5
And you can use methods to get this url:
return redirect(action('Controller#update', compact($id)));

How to solve Method App\JenisSurat::__toString() must return a string value on Laravel 5?

I want to input data to database. I am using Laravel 5. When I clicked the submit button. I got an error like the image below. Here is controller:`
public function tambahjenissurat(Request $request)
{ $this->validate($request, [
'jenis_surat' => 'required'
]);
$jenis_surat = $request['jenis_surat'];
$jenis_surat = new JenisSurat();
$jenis_surat->jenis_surat = $jenis_surat;
$jenis_surat->save();
return redirect()->route('jenissurat');
}`
Your code is expecting a string but you are passing an object. that could be the problem. try to give different names for object and variable. Something like this should fix the problem. See the lines below EDIT sections
public function tambahjenissurat(Request $request)
{ $this->validate($request, [
'jenis_surat' => 'required'
]);
**EDIT**
$jenis_surat_var = $request['jenis_surat'];
$jenis_surat = new JenisSurat();
**EDIT**
$jenis_surat->jenis_surat = $jenis_surat_var;
$jenis_surat->save();
return redirect()->route('jenissurat');
}

Laravel 4: Unique(database) not validating

I am creating a basic CMS to teach myself the fundamentals of Laravel and PHP.
I have a 'pages' table and I am storing a url_title. I want this URL title to be unique for obvious reasons. However, whatever I do to validate it, fails. It just saves anyway. I'm sure it is something simple. Can you spot what is wrong with this code?
I am also using Former in the view, that doesn't validate either. I have tried hard-coding a value as the last option in the unique method and it fails also.
http://anahkiasen.github.io/former/
http://laravel.com/docs/validation#rule-unique
States: unique:table,column,except,idColumn
Here is my Controller:
public function store()
{
$validation = Pages::validate(Input::all());
if($validation->fails()) {
Former::withErrors($validation);
return View::make('myview');
} else {
Pages::create(array(
'title' => Input::get('title'),
'url_title' => Input::get('url_title'),
'status' => Input::get('status'),
'body' => Input::get('body'),
'seo_title' => Input::get('seo_title'),
'seo_description' => Input::get('seo_description')
));
//check which submit was clicked on
if(Input::get('save')) {
return Redirect::route('admin_pages')->with('message', 'Woo-hoo! page was created successfully!')->with('message_status', 'success');
}
elseif(Input::get('continue')) {
$id = $page->id;
return Redirect::route('admin_pages_edit', $id)->with('message', 'Woo-hoo! page was created successfully!')->with('message_status', 'success');
}
}
}
Here is my model:
class Pages extends Eloquent {
protected $guarded = array('id');
public static $rules = array(
'id' => 'unique:pages,url_title,{{$id}}'
);
public static function validate($data) {
return Validator::make($data, static::$rules);
}
}
I have tried the following:
public static $rules = array(
// 'id'=> 'unique:pages,url_title,{{$id}}'
// 'id'=> 'unique:pages,url_title,$id'
// 'id'=> 'unique:pages,url_title,:id'
// 'id'=> 'unique:pages,url_title,'. {{$id}}
// 'id'=> 'unique:pages,url_title,'. $id
);
Any ideas? I spoke to the guy who created Former. He can't make head nor tail about it either. He suggested tracking it back to find our what query Laravel uses to check the uniqueness and try running that directly in my DB to see what happens. I can't find the query to do this. Does anyone know where to track it down?
Many thanks
Your rule should be:
public static $rules = array(
'url_title' => 'unique:pages,url_title,{{$id}}'
);
As I guessed from your code Input::get('url_title')
You have to use the field name used in the form.
Thanks peeps. I have been using the Laravel unique solutions and it hasn't been working well. I found this package which solves the issue brilliantly.
https://github.com/cviebrock/eloquent-sluggable#eloquent
Definitely worth a look.
Thanks for your feedback.

Categories