Laravel saving post variable when there is validation error? - php

I am using laravel 4 , and I have a form with checkboxes and on sumbitting the form , it goes through the validation error process, if there is error how do I make it save the post values of these check boxes?
AdminRolesController:
public function postActions($action = NULL) {
// Allowed post actions..
$allowed = array('add', 'edit');
$action = in_array($action, $allowed) ? $action : NULL;
// check if action is not null
if(is_null($action))
return Redirect::to('admin/roles');
else
{
// POST ACTION
if($action == "add")
{
// put all your rules.
$rules = array(
'name'=>'required|regex:/^[a-zA-Z ]*$/|min:2',
'permission_ids' =>'required'
);
// run the validation rules on the inputs from the form
$validator = Validator::make(Input::all(), $rules);
// get all permissions or groups available
$perms = Permissions::all();
// share it to the view
// we have two parts of permissions ( 0 , 1)
// 0 : Admin Group Pages , 1: Front End Pages
View::share('perms', $perms);
if ($validator->passes())
{
// validation has passed, save user in DB
// create instance of our model..
// create a new role
$role = new Role;
$role->name = Input::get('name');
$permission_ids = Input::get('permission_ids');
// save info to db.
$role->save();
$msg = 'Role '.$role->name.' has been added';
}// end validation if
else
{
// validation has failed, display error messages
return Redirect::back()->with('message', 'The following errors occurred:')->withErrors($validator)->withInput();
}
}// end if add
}
}
I think part of the problem me redirecting with error messages , all the post values is lost , how could I still keep them?
Thanks

Your controller looks fine - all that's required to do to pass input back to the view is chaining ->withInput()
However, in your views, ensure you're populating the form using the old input values. You can do so, using Blade, by doing something like:
{{ Form::checkbox('permission_id', 'value', Input::old('permission_id)) }}

Related

Laravel checking submitted values with database before update

Ive been trying to check the fields that a user submitted from the form with the database fields to see if there was any change made
if it was let the save() query run, else send a message that no changes made
public function update(Request $request,$id)
{
$this->validate($request, [
'title' =>'required',
'notes' =>'required',
'description' =>'required'
]);
$editinc = Editted::find($id);
if($editinc > 0) {
dd($editinc);
}
$data = $request->all();
$post= Joborder::find($id);
//before this query runs i want to check my fields with db
//if no changes has been this should not be executes
$post->fill($request->input())->save();
return redirect('/thehood')->with('success','WE DID IT.');
}
Additional Info :
im a newbie in Laravel so take it easy on me.
if isDirty() is possible , how ? I checked lots of questions still have no clue how to use it.
if its not possible then is there a Laravel way? something that checks and if there are difference it will ONLY change their value NOT perform a full update on every field.
Edited :
this could be a way but I'm pretty sure there is Laravel way that I just don't know about it??!
$post= Joborder::find($id);
$data = $request->all();
foreach($data as $dat => $val) {
if($dat=="_token" || $dat=="_method") continue;
if($data[$dat] == $post->$dat) {
continue;
}else{
$post->$dat = $data[$dat];
$post->save();
$flag=1;
}
}
if($flag == 0 ) {
return redirect('/thehood')->with('success','NO EDIT HAS BEEN DoNE.');
}else{
return redirect('/thehood')->with('success','one or more Field has been edited .');
}
Here is what you can do, please enter all the fields you want to compare in the query as I am not entering all of them.
$exist = Joborder::where('title', $request->input('title'))->where('notes', $request->input('notes'))->first();
if($exist)
{
//Insert into database.
}

Passing Data to view in a Redirect request to prevent double submission

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'));
}

Input validation in laravel?

I have a Input validation to change user password, when i tried to submit the form i got always an error that the new password and confirm password are not matched even, this is my post action :
public function doChangePassword()
{
if(Auth::check())
{
$validator = Validator::make(Input::all(), User::$updatePasswordRules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('change-password')->with('message', 'The following errors occurred')->withErrors($validator)->withInput();
} else {
// store
$user = User::find(Auth::user()->id);
if(Auth::user()->password==Input::get('new_password')){
$user->password = Hash::make(Input::get('new_password'));
$user->save();
}
else{
return Redirect::to('change-password')->with('message', 'The password is not correct');
}
// redirect
Session::flash('message', 'Successfully updated password!');
return Redirect::to('login');
}
}
else{
return Redirect::to('login');
}
}
this is my rules :
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|confirmed',
'password_confirmation'=>'required|alpha_num|between:6,12'
);
so please if someone has an idea i will be very appreciative
It's because Laravel expects (for your specific case) confirmed field to be named new_password_confirmation
From doc "The field under validation must have a matching field of foo_confirmation. For example, if the field under validation is password, a matching password_confirmation field must be present in the input."
Thus rules should look like (also change input name in form):
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|confirmed',
'new_password_confirmation'=>'required|alpha_num|between:6,12'
);
Or you can do it with same validation rule (if don't want to update form inputs):
public static $updatePasswordRules = array(
'password'=>'required|alpha_num|between:6,12',
'new_password'=>'required|alpha_num|between:6,12|same:password_confirmation',
'password_confirmation'=>'required|alpha_num|between:6,12'
);

CakePHP Security - Prevent Form Injection

I currently have 1 table, Users which looks like this
|**id**|**username**|**password**|**role**|**email**|
I'm using CakePHP's form helper to automatically fill in editable form fields. I'm creating an edit page in which users can change there username/password/email, but should NOT be able to change their role. I'm currently checking to make sure the user hasn't injected a role POST field into the request and was wondering if there is any better way to do this? It's trivial in this scenario with such a small table, but I can see this becoming tiresome on fields/tables with a large amount of columns. My current edit action looks like this.
public function edit($id = null)
{
$this->User->id = $id;
if(!$this->User->exists())
{
throw new NotFoundException('Invalid user');
}
$userToEdit = $this->User->findById($id);
if(!$userToEdit)
{
throw new NotFoundException('Invalid user');
}
if($this->getUserRole() != 'admin' && $userToEdit['User']['owner'] != $this->Auth->user('id'))
{
throw new ForbiddenException("You do not have permission to edit this user");
}
if($this->request->is('post') || $this->request->is('put'))
{
//Do not reset password if empty
if(empty($this->request->data['User']['password']))
unset($this->request->data['User']['password']);
if(isset($this->request->data['User']['role']))
unset($this->request->data['User']['role']);
if($this->User->save($this->request->data))
{
$this->set('success', true);
}
else
$this->set('success', false);
}
else
{
$this->request->data = $this->User->read();
//Prevent formhelper from displaying hashed password.
unset($this->request->data['User']['password']);
}
}
The third parameter of save() method lets you to define the list of fields to save. Model::save() docs
$this->User->id = $this->Auth->user('id');
$this->User->save($this->request->data, true, array('username', 'email'))

Codeigniter form post and validation

I'm not a pro, but know my way around PHP, I'm new to Codeigniter.
Been going through these tutorials: http://net.tutsplus.com/articles/news/codeigniter-from-scratch-day-5-crud/
OK, so I have a page that lists users, clicking on users name will go to an edit page, the url of that page being: index.php/users/edit/1 (where 1 is the users id)
On edit page is a form, this form contains a few parts, each part is populated from different tables in the DB. So my Controller for edit is as follows:
function edit() {
//load model
$this->load->model('users_model');
//assign user data from DB
$data['data_user'] = $this->users_model->getUser($this->uri->segment(3));
//get users Password, using username from above
$data['data_user_password']= $this->users_model->getUserPassword($data['data_user'][0]->UserName);
$data['page_content'] = 'pages/users_edit';
$this->load->view('template/template', $data);
}
Notice:
$data['data_user'] contains users data like name, username, email
$data['data_user_password'] contains users password from a different table
I can then populate the form, on users_edit.php, this all works fine.
I'm accessing this data by doing the following:
if (is_array($data_user)) {
foreach($data_user as $user)
{
$userID = $user->id;
$userName = $user->Name;
$userUserName = $user->UserName;
$userMail = $user->Mail;
$userDepartment = $user->Department;
$userWorkPhone = $user->WorkPhone;
$userHomePhone = $user->HomePhone;
$userMobile = $user->Mobile;
}
}
//user password
if (is_array($data_user_password)) {
foreach($data_user_password as $user)
{
$userPassword = $user->value;
}
}
Name:
<?php echo form_input('name', set_value('name', $userName), 'id="name" class="inputLong"'); ?>
When I post, I'm sending data to: index.php/users/update
My controller for this page so far is:
function update() {
echo '<pre>';
print_r($_POST);
echo '</pre>';
//exit();
$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Name', 'trim|required');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('pages/users_edit');
}
else
{
$this->index();
}
}
For now, I'm just testing validation on users "name" where form input=name id=name
I think I'm not handling the if ($this->form_validation->run() == FALSE) part of it correctly, if the form contains data, it passes and redirects to index, if I leave name blank it either not handling the edit page correctly, or I dont know, something isnt right.. I think its because the page is being reloaded using the post array, and not passing the $data like I did in function edit().
Back to the form page, where it should be showing the validation_errors, its showing:
The Name field is required.
This is correct, however, for the rest of the fields that should be pre-populated, its showing PHP error:
A PHP Error was encountered
Severity: Notice
Message: Undefined variable: userUserName
Filename: pages/users_edit.php
Line Number: 50
You could do your validation inside your edit function instead of having an update function, that way, your data is still available for your view and if the validation has errors, codeigniter will take in charge to repopulate your fields. If the validation is ok, you do your next step
function edit() {
//load model
$this->load->model('users_model');
//assign user data from DB
$data['data_user'] = $this->users_model->getUser($this->uri->segment(3));
//get users Password, using username from above
$data['data_user_password']= $this->users_model->getUserPassword($data['data_user'][0]->UserName);
$data['page_content'] = 'pages/users_edit';
$this->load->view('template/template', $data);
//is the form submitted
if(form submit){
if ($this->form_validation->run() == TRUE)
{
$this->index();
}
else
{
$this->load->view('pages/users_edit', $data);
}
}
}
$this->load->view('pages/users_edit');
Inside your function update(), after your validation you load view but you don't PASS any data variables to it. So you don't have any variables which you can access at your view file..
You have to set your variables the same way as in your function edit():
$this->load->view('template/template', $data);
Currently there is not set variable $data_user so you can't loop it and use it..

Categories