I'm trying to develop a PHP game with Laravel, and so far a user - with enough gold and not part of a guild - can create a guild using a simple form with one text field. The issue is that currently I'm using Laravel's dd() function in order to show that they failed to have the gold or were already in a guild.
As such, I went looking for a way to give it a more baked-in feel by seeing if I could put this behavior into a custom rule/validator, but I'm unsure as to how to go about this. Examples would be preferred... here's my current function.
public function store(Request $request)
{
$request->validate([
'name' => 'required|min:4|alpha_dash|unique:guilds'
]);
$char = Auth::user()->character;
$cost = config('game.create-guild-cost');
$guild = new Guild;
if($char->gold < $cost) {
dd('Not enough money');
}
if($char->guild != null) {
dd('You cannot already be in a guild.');
}
$guild->name = request('name');
$guild->leader_id = $char->id;
$guild->save();
$char->gold = $char->gold - $cost;
$char->guild_id = $guild->id;
$char->save();
return redirect()->route('guilds.show', ['guild' => $guild]);
}
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|min:4|alpha_dash|unique:guilds'
]);
if ($validator->fails()) {
return redirect()
->back() //please double check this but you got the idea
->withErrors($validator)
->withInput();
}
// Do your stuff here....
}
So basically Laravel provides you to put your error messages in session behind the scene and then go to your desired page get the errors from the session and show them nicely in your view files.
Related
I'm building a small validator for my form with laravel 7 and i needed a custom logic to be added after the standard validation so I used the after validation hook as in doc. My issue is not with the logic of the controller but the fact that after the validation occur and I add the custom error message i don't get redirected to the original form. What I'm missing?
public function store(Request $request)
{
//
$data = $request->all();
$newSpn = new Sponsorization;
$userId = Auth::id();
$paymentPlanId = $data["payment_plan_id"];
$apartmentId = $data["apartment_id"];
$payPlanInfo = PaymentPlan::find($paymentPlanId)->hours_duration;
$alreadyActive = $this->alreadyActive($apartmentId);
$userApartment = DB::table('apartments')
->where('user_id', $userId)
->pluck('id');
$validator = Validator::make($request->all(),[
'payment_plan_id' => "required",
'appartment_id' => [
'required',
Rule::in($userApartment)
]
]);
$validator->after(function ($validator) use ($alreadyActive){
if ($alreadyActive) {
$validator->errors()->add('apartment_promo', 'A promo is already active on this apartment!');
}
});
if ($validator->fails()) {
//
}
$newSpn->apartment_id = $apartmentId;
$newSpn->payment_plan_id = $paymentPlanId;
$newSpn->start_date = date("Y-m-d H:m:s");
$newSpn->end_date = date("Y-m-d H:m:s",strtotime("+{$payPlanInfo} hours"));
$newSpn->save();
}
You can redirect back to the page where you come from like this
if ($validator->fails()) {
return redirect()->route('name.of.route.where.you.come.from')
->withErrors($validator)
->withInput();
}
As you want to be redirect to the orignal form you must define that behaviour when the validation failed so you can pass the validation errors and old input values calling the method withErrors and withInput
my delete function like this:
help me guys before I added this line return Redirect::route('attribute.index');
I had no error but after I have this error
405 Method Not Allowed
public function update($id)
{
$input = Input::all();
$validator = Validator::make($input, CapacityModel::rules());
// process the save
if ($validator->fails()) {
Session::flash('message', trans('messages.error_save'));
} else {
// store
$this->capacity->update($input['capid'], $input);
// redirect
Session::flash('message', trans('messages.success_save'));
return Redirect::route('attribute.index');
}
}
my route like this:
Route::resource('/reference/attribute','nez\attribute\SeiAttributeController',['names'=>'attribute']);
my controller's index like this:
public function index()
{
return View::make($this->view_path.'.index');
}
This looks questionable:
$this->capacity->update($input['capid'], $input);
Where does $this->capacity get resolved? Are you certain the attribute is always set at this point in the method?
The update method typically takes a single parameter, which is an array of keys with their new values.
If you have correctly resolved $this->capacity to the record you want to update, then you would be best off with something along these lines:
$this->capacity->update([
'field_1' => Arr::get($input, 'field_1'),
'field_2' => Arr::get($input, 'field_2'),
//...etc
]);
I'm working on a laravel 5.7 project and I want to have my own authentication scenario.
Well, I'll give a mobile from my user and send her a one time pass to her phone and then check if she is giving me the correct code.
So, I do not use laravel authentication system at this point at all.
My Controller is something like this :
/*
* Show Login Form
*/
public function showLoginForm()
{
return view('auth.custom.login');
}
/*
* Login
*/
public function login(Request $request)
{
$mobile = $request->mobile;
$this->validate($request, [
'mobile' => 'iran_mobile|required'
]);
$check = User::where('mobile', $mobile)->first();
if( $check === null )
{
Session::flash('toasterr', 'is not registered yet');
Session::put('mobile', $mobile);
return redirect(route('register'));
}
else
{
$singleTimePass = Str::random(4);
sendSms($mobile, 'your code:' . PHP_EOL . $singleTimePass . PHP_EOL . 'Insert that bla bla');
Session::put('singleTimePass', $singleTimePass);
Session::put('mobile', $mobile);
return redirect(route('check_pass'));
}
dd($check);
}
/*
* Show Check Pass page
*/
public function showCheckPass()
{
return view('auth.custom.pass');
}
/*
* Check Pass For Login
*/
public function checkPassForLogin(Request $request)
{
$this->validate($request, [
'pass' => 'required|regex:/^[\w-]*$/'
]);
if( $request->pass == Session::get('singleTimePass'))
{
$user = User::where('mobile', Session::get('mobile'))->first();
// dd($user->id);
Auth::login($user->id);
return redirect(route('game'));
}
else
{
Session::flash('toasterr', 'pass is wrong');
return redirect(route('check_pass'));
}
}
/*
* Show Register Form
*/
public function showRegisterForm()
{
return view('auth.custom.register');
}
/*
* Register
*/
public function register(Request $request)
{
$this->validate($request, [
'name' => 'persian_alpha|required',
'family' => 'persian_alpha|required',
'username' => 'required|min:4|max:255|string',
'mobile' => 'iran_mobile|required',
]);
return $request->all();
}
Ok! Every thing seems to be good but now, I expect laravel that give me abilities like Auth::check() or Auth::user() and...
So I know that I have an error at this line: Auth::login($user->id); and I want to know how can I do something like this manually for mentioned goal.
May be it is because of my poor knowledge about laravel authentication architecture but it would be appreciate if you let me know how do that because googled this for a while and there's not direct answer to this question-or I did not searched enough-.
Based on the documentation the login method expects a User object to log you in. So you can either try
Auth::login($user);
// or
Auth::loginUsingId($user->id);
I've a problem with Laravel 5.1 Redirect With Input. I can't seem to get old values from submitted input.
I've been research for any post in stack overflow and still stuck in this problem.
This is my request controller
public function create() {
$this->data["pageDescription"] = "Add new page.";
$this->data["pageSubtitle"] = $this->data["pageTitle"] . " Add New";
$this->data["formAction"] = adminRoute("page");
return view("admin.page.form")->with("data", $this->data)->withInput(Input::old());
}
and this is my submitted controller
public function store(Request $request) {
Input::flash();
$validator = Validator::make($request->all(), [
"title" => "required|max:100",
"url_title" => "required|max:100",
"meta_description" => "required|max:50",
"content_title" => "required|max:100",
"content_description_id" => "required",
"status" => "required|in:pending,published",
"add_more_content" => "required|in:true,false"
]);
if($validator->fails()) {
return redirect()->back()
->with("data", $this->data)
->withErrors($validator)
->withInput();
} else {
return redirect()->back()->withInput();
}
}
It's kinda weird because when I dump Session::all() before I redirect()->back() the _old_input is exists
But when I dump Session::all() on my function create() the _old_input is empty.
Even when I skip the validation, and use
redirect()->back()->withInput();
I still got the same problem, the old values input empty
This is my form view
Anybody know what I am doing it wrong?
Thank youu
Did you get validation error? I'm not 100% sure, but I think redirect()->back() calls to the GET method of your form.
I am trying to prevent double submission through the back button in a simple voting application
I was doing this before. After voting it returns this view
return View::make('votes.votesresults')->with('candidates',$candidates)->with('count',$count);
This passes two variables to votesresult view but unfortunately if someone clicks the back button they can resubmit their votes. I looked around and came across the PRG pattern. Am supposed to use a redirect to prevent this. So i tried this
return Redirect::route('votes.votesresults')->with('candidates',$candidates)->with('count',$count);
Here are my controllers
public function votesuccess()
{
$rules = array(
'name' => 'required'
);
$validator = Validator::make(Input::all(),$rules);
if ($validator->fails()) {
return Redirect::to('votes/index')
->withErrors($validator)
->withInput(Input::except('password'));
} else {
// store
$vote = new Vote;
$candidates = Candidate::all();
$candidate_id =Input::get('name');
$candidate = Candidate::find($candidate_id);
$vote = $candidate->votes()->save($vote);
//$count = DB::table('votes')->where('candidate_id','=','$candidate_id')->count();
$count = DB::table('votes')->count();
// redirect
Session::flash('message', 'Successfully Cast your vote!');
//return View::make('votes.voteresults')->with('candidates', $candidates)->with('count',$count);
return Redirect::route('voteresults')->with('candidates', $candidates)->with('count',$count);
}
}
public function voteresult()
{
$candidates = Candidate::all();
return View::make('votes.voteresults');
}
My routes are like this
Route::post('votesuccess', array('as' => 'votesuccess', 'uses'=>'VoteController#votesuccess'));
Route::get('voteresults', array('as' => 'voteresults', 'uses'=>'VoteController#voteresult'));
This does not work because it returns undefined variable: candidates. My results view requires these variables. So how do I implement the PRG pattern correctly such that I prevent double submission while being able to pass data to my view
You are redirecting to the route named voteresults, which is handled by the voteresult function and not the votesuccess function.
In your votesuccess function, you should load the view and include the candidates variable in that view. You can access the candidates variable stored in the session by using Session::get('candidates').
It would help to see you voter results view to see what's going on there, and where/how you've put in logic to avoid duplicate submission. Are you concerned about accidental re-submissions, or just multiple submissions from the same user? If the latter, then you would need to build in some logic that limits a user to only 1 vote. You could do this by check if the user has a related vote.
if ( ! $candidate->votes() ) {
// no votes exist, proceed with storing vote
}
Below is you controller refactored a bit:
public function votesuccess()
{
$rules = array(
'name' => 'required'
);
$validator = Validator::make(Input::all(),$rules);
if ($validator->fails()) {
return Redirect::back('votes/index')
->withErrors($validator)
->withInput(Input::except('password'));
} else {
// store
$candidate = Candidate::find(Input::get('name'));
$vote = $candidate->votes()->save(new Vote);
// redirect
Session::flash('message', 'Successfully Cast your vote!');
return Redirect::route('voteresults');
}
}
public function voteresult()
{
$candidates = Candidate::all();
$count = DB::table('votes')->count();
return View::make('votes.voteresults', compact('candidates', 'count'));
}