Laravel checking submitted values with database before update - php

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.
}

Related

Laravel Custom Validation Method

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.

Yii2; code running in "else" block first, and then running code before "if" block?

I'm completely lost as to why this is happening, and it happens about 50% of the time.
I have a check to see if a user exists by email and last name, and if they do, run some code. If the user doesn't exist, then create the user, and then run some code.
I've done various testing with dummy data, and even if a user doesn't exist, it first creates them, but then runs the code in the "if" block.
Here's what I have.
if (User::existsByEmailAndLastName($params->email, $params->lastName)) {
var_dump('user already exists');
} else {
User::createNew($params);
var_dump("Creating a new user...");
}
And here are the respective methods:
public static function existsByEmailAndLastName($email, $lastName) {
return User::find()->where([
'email' => $email,
])->andWhere([
'last_name' => $lastName
])->one();
}
public static function createNew($params) {
$user = new User;
$user->first_name = $params->firstName;
$user->last_name = $params->lastName;
$user->email = $params->email;
$user->address = $params->address;
$user->address_2 = $params->address_2;
$user->city = $params->city;
$user->province = $params->province;
$user->country = $params->country;
$user->phone = $params->phone;
$user->postal_code = $params->postal_code;
return $user->insert();
}
I've tried flushing the cache. I've tried it with raw SQL queries using Yii::$app->db->createCommand(), but nothing seems to be working. I'm totally stumped.
Does anyone know why it would first create the user, and then do the check in the if statement?
Editing with controller code:
public function actionComplete()
{
if (Yii::$app->basket->isEmpty()) {
return $this->redirect('basket', 302);
}
$guest = Yii::$app->request->get('guest');
$params = new CompletePaymentForm;
$post = Yii::$app->request->post();
if ($this->userInfo || $guest) {
if ($params->load($post) && $params->validate()) {
if (!User::isEmailValid($params->email)) {
throw new UserException('Please provide a valid email.');
}
if (!User::existsByEmailAndLastName($params->email, $params->lastName)) {
User::createNew($params);
echo "creating new user";
} else {
echo "user already exists";
}
}
return $this->render('complete', [
'model' => $completeDonationForm
]);
}
return $this->render('complete-login-or-guest');
}
Here's the answer after multiple tries:
Passing an 'ajaxParam' parameters with the ActiveForm widget to define the name of the GET parameter that will be sent if the request is an ajax request. I named my parameter "ajax".
Here's what the beginning of the ActiveForm looks like:
$form = ActiveForm::begin([
'id' => 'complete-form',
'ajaxParam' => 'ajax'
])
And then I added this check in my controller:
if (Yii::$app->request->get('ajax') || Yii::$app->request->isAjax) {
return false;
}
It was an ajax issue, so thanks a bunch to Yupik for pointing me towards it (accepting his answer since it lead me here).
You can put validation like below in your model:
public function rules() { return [ [['email'], 'functionName'], [['lastname'], 'functionforlastName'], ];}
public function functionName($attribute, $params) {
$usercheck=User::find()->where(['email' => $email])->one();
if($usercheck)
{
$this->addError($attribute, 'Email already exists!');
}
}
and create/apply same function for lastname.
put in form fields email and lastname => ['enableAjaxValidation' => true]
In Create function in controller
use yii\web\Response;
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
else if ($model->load(Yii::$app->request->post()))
{
//place your code here
}
Add 'enableAjaxValidation' => false to your ActiveForm params in view. It happens because yii sends request to your action to validate this model, but it's not handled before your if statement.

Checking Username Availability in Laravel

Is there a way to check if a username is already taken in laravel? I mean I want to check if a username is taken already without submitting the form that means checking the availability of the username while the user is typing. If there is what language should I use? And please cite examples. Thank you!
$count = User::where('userName', 'like', '%Lyka%')->count();
if($count > 0)
{
//username exists
}
else
{
//username doesn't exist
}
or you can validate in laravel validation itself
$rules = array('username' => 'required|unique:user');
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails())
{
$messages = $validator->messages()->first();
Session::put('msg',$messages);
return Redirect::back();
} else {
// username not exist
}
unique:user => unique from the table called user
username => is the column of the table user
A better approach would be to use laravel validation. Use ajax to send the input to laravel backend. And then somewhere in your controller.
$validator = Validator::make($request->all(), [
'username' => 'unique:users',
]);
And check if it fails
if ($validator->fails()) {
//do whatever you want to do at fail
//possible return appropriate json with error
}
Is there a way to check if a username is already taken in laravel?
Yes, try some PHP like the following:
$count = User::where('userName', '=', 'Lyka')->count();
if($count > 0)
{
//username exists
}
else
{
//username doesn't exist
}
If you want to check asynchronously you would have to write some Javascript and use AJAX to check while the user is filling out the form.
If there is what language should I use?
PHP obviously and Javascript.
Good luck.

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

Laravel saving post variable when there is validation error?

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

Categories