update api not updating db in laravel - php

i tryed to make a update api in larvel in post man i am gettng 200 but the reponce of api is same as the old data and api does not update
what i have tryed is this
Route::patch('/update', function (\Illuminate\Http\Request $request) {
// Validate the incoming data
$data = $request->validate([
'name' => '|max:255',
'phone'=> 'max:255',
'email' => '|email|unique:users',
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
]);
// Retrieve the authenticated user
$user = auth()->user();
// Update the user's fields with the new data
$user->update($data);
// Return a JSON response with the updated user data
return new \Illuminate\Http\JsonResponse(['user' => $user] , 200);
})->middleware('auth:api');
as u can see in screen shot the data although it is 200 the responce is same old data and data is not updated in db

Route::patch('/update', function (\Illuminate\Http\Request $request) {
// Validate the incoming data
$data = $request->validate([
'name' => '|max:255',
'phone'=> 'max:255',
'email' => '|email|unique:users',
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
]);
// Retrieve the authenticated user
$user = auth()->user();
$data = $request->all();
$user->fill($data);
// Update the user's fields with the new data
$user->save();
// Return a JSON response with the updated user data
return new \Illuminate\Http\JsonResponse(['user' => $user] , 200);
})->middleware('auth:api');

Related

how to make a update api in laravel using autherntication token

i am trying to make a update API that updates fileds using header auth token
I am new to larvel
this is what I have tried
Route::patch('/update', function (\Illuminate\Http\Request $request) {
$data = $request->validate([
'name' => '|max:255',
'phone'=> 'max:255',
'email' => '|email|unique:users',
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
])}) return new \Illuminate\Http\JsonResponse(['user' => $user] , 200);
})->middleware('auth:api');
Changes
Removed typo. 'name' => '|max:255' to 'name' => 'max:255' and 'email' => '|email|unique:users' to 'email' => 'email|unique:users'
Condition based unique() check added 'email|unique:users,email,' . $request->user()->id,. This will be used to Skip the Current record.
return should be placed inside the Route(), not outside.
Used $user = $request->user(); to update the record.
Route::patch('/update', function (\Illuminate\Http\Request $request) {
$user = $request->user();
$data = $request->validate([
'name' => 'max:255', # remove "|"
'phone'=> 'max:255',
'email' => 'email|unique:users,email,' . $request->user()->id, # remove "|"
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
]);
$user->update($data);
return new \Illuminate\Http\JsonResponse(['user' => $user] , 200);
})->middleware('auth:api');
Or for the in-detail update.(Without update())
$user = $request->user();
$user->name = $data['name'];
$user->phone = $data['phone'];
$user->email = $data['email'];
$user->period = $data['period'];
$user->babyname = $data['babyname'];
$user->baby_date = $data['baby_date'];
$user->save();
Few recommendations:
Use resource route instead of single routes -> https://laravel.com/docs/9.x/controllers#resource-controllers
Read more about validation rules -> https://laravel.com/docs/9.x/validation#available-validation-rules
You can customize the response status:
200 Success
404 Not Found (page or other resource doesn't exist)
401 Not authorized (not logged in)
403 Logged in but access to requested area is forbidden
400 Bad request (something wrong with URL or parameters)
422 Unprocessable Entity (validation failed)
500 General server error
API Route
//In the api route header
use App\Http\Controllers\UserController;
//The route method
Route::patch('/update/{user}', [UserController::class, 'update'])->middleware('auth:api');
UserController
/**
* Update the specified model.
*
* #param \Illuminate\Http\Request $request
* #param User $user
* #return \Illuminate\Http\Response
*/
public function update(Request $request, User $user)
{
//Please read: https://laravel.com/docs/9.x/validation#available-validation-rules
//For more information about validation rules and how they work.
$data = $request->validate([
'name' => '|max:255',
'phone'=> 'max:255',
'email' => '|email|unique:users',
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
]);
$user->update($data);
//You can pass a response status to handle it in your view/javascript as required
return response()->json([
'user' => $user->toArray(),
], 200);
}
Please let me know if you require further help or clarifications, always happy to help.
Fix your route; it is not found; you have to supply the ID inside the route to reach the controller:
Route::patch('/update/{id}', function (\Illuminate\Http\Request $request) {
// ...

How to access currently logged in user globally in Laravel, Auth::user() returning null

When a user is logged in, session('person_id') is set, but Auth::user() returns null.
This means I have to do this everywhere I need access to properties or methods of the user:
$person = Person::where('id', session('person_id'))->firstOrFail();
What is a better solution for this? Could I set $person in the BaseController then access the user via $this->user when I need it?
I don't want to do a DB query for every request on every page. Using Laravel 8 with PHP 8.
Here are my current login and signup functions:
/**
* Handles user login
*
* #param Request $request
* #return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials, request('remember'))) {
$request->session()->regenerate();
return redirect()->intended('/account')->with('status', 'Logged in');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
/**
* Saves a new unverified user, sends code to their email and redirects to verify page
*
* #param Request $request
*/
public function signUp(Request $request)
{
// #todo Move to SignUpRequest file
$request->validate([
'email' => 'required|email|unique:people',
'password' => 'required',
]);
$person = new Person;
$person->email = $request->email;
$person->password = Hash::make($request->password);
if (!$person->save()) {
return back()->with('status', 'Failed to save the person to the database');
}
$request->session()->put('person_id', $person->id);
$verification = new Verification;
$verification->person_id = $person->id;
$verification->code = rand(111111, 999999);
$verification->valid_from = Carbon::now();
$verification->expires_at = Carbon::now()->addDay();
if (!$verification->save()) {
return back()->with('status', 'Failed to save the verification to the database');
}
// email stuff
return redirect('/verify')->with('status', 'Successfully created account, please verify to continue');
}
It seems your fighting with framework default authentication you're using another model instead of User
I recommend reading the official documentation
You can take a look at laravel breeze to see how they implemented authentication
if you check the laravel breeze you'll see you missed the Auth::login($user)
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(RouteServiceProvider::HOME);
}
Laravel ships with a the global helper auth() and you can access the logged user with auth()->user()

Laravel - Validator::make fails my unique rule

I'm trying to use a validation on 'name' as unique, but to be ignored if the objected that has that same name is the same object being updated.
The Validation keeps failing, can you help me figuring out why?
Validator Function - I'm using same validator function to both create and update and only need to apply the rule on the update.
protected function validator(array $data, Wharehouse $wharehouse = null)
{
//different validations for create and edit
if($wharehouse != null){
return Validator::make($data, [
'name' => ['required', 'string', 'max:255', Rule::unique('wharehouses')->ignore($wharehouse)],
'espacoTotal' => ['required', 'numeric', 'max:60000']
]);
}else{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255', Rule::unique('wharehouses')],
'espacoTotal' => ['required', 'numeric', 'max:60000']
]);
}
}
Validation Call
protected function editById(Request $request)
{
$wharehouse = Wharehouse::find($request->wharehouse_id);
$validation = $this->validator($request->all(),$wharehouse);
if ($validation->fails()) {
return Redirect::to('/wharehouses')->withInput()->withErrors($validation);
} else {
$wharehouse->name = $request->input('name');
$wharehouse->espacoTotal = $request->input('espaco');
$wharehouse->save();
return back()->with('create.success','Armazem actualizado com sucesso.');
}
}
Append the id of the instance currently being updated to the validator.
Pass the id of your instance to ignore the unique validator.
In the validator, use a parameter to detect if you are updating or
creating the resource.
If updating, force the unique rule to ignore a given id: unique:table,column,except,idColumn
//rules
'name' => ['required', 'string', 'max:255', 'unique:users,name,' . $userId],

Validation issue in laravel update function

I'm having a admin dashboard in my laravel application
From the dashboard Admin can edit the user profile contents.
Here is my current usercontroller (only the update function included)
public function update(Request $request, $id)
{
$this->validate($request, [
'name' => ['required', 'alpha','min:2', 'max:255'],
'last_name' => ['required', 'alpha','min:2', 'max:255'],
'email' => ['required','email', 'max:255', 'unique:users,email,'.$id],
'password' => ['same:confirm-password','regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{12,}$/'],
'mobile'=>['required', 'regex:/^\+[0-9]?()[0-9](\s|\S)(\d[0-9]{9})$/','numeric','min:9'],
'username'=>['required', 'string', 'min:4', 'max:10', 'unique:users,username,'.$id],
'roles'=>['required'],
//'user_roles'=>['required'],
]);
$input = $request->all();
if(!empty($input['password'])){
$input['password'] = Hash::make($input['password']);
}else{
$input = array_except($input,array('password'));
}
$user = User::find($id);
$user->update($input);
DB::table('model_has_roles')->where('model_id',$id)->delete();
$user->assignRole($request->input('roles'));
if($input['roles']=='customer'){
return redirect()->route('customers.index')
->with('success','Customer has been updated successfully');
}
else{
return redirect()->route('users.index')
->with('success','User has been updated successfully');
}
}
Now my problem is,
When ever admin updates an user without changing the password fields, the password fields get validated and throw me a regex error related to the password...
How can I avoid that issue and validate password field only if they are being changed.
With your current validation rules password field will always be checked with the regex. Adding nullable rule in first position of your password validation rules could help you solving the issue.

Send a email only if a users updates profile with new data. Laravel

My application gives employees of a company the ability to edit their data(example: address). Once they change any of it, a manager gets an e-mail with their new information. The problem is that an email is sent every time a employee clicks update. I need the application to compare the info in the database and only send an email if there's new information. What is good way to achieve this? I am sorry I forgot to mention, the email needs to contain only the new iformation. So isDirty() would not work for me.
public function editcredentials_action(Request $request)
{
$user = Auth::user();
$address = $user->address;
$this->validate($request, [
'password' => 'max:255',
'language' => 'integer',
'facebook_profile' => 'max:255',
'twitter_profile' => 'max:255',
'street' => 'max:255',
'house_number' => 'max:255',
'city' => 'max:255',
'zip_code' => 'max:255',
'country' => 'max:255',
]);
if (!empty($request->get('password')) && $request->get('password')) {
$user->password = bcrypt($request->get('password'));
}
$user->facebook_profile = $request->get('facebook_profile');
$user->twitter_profile = $request->get('twitter_profile');
$user->language_id = $request->get('language');
$user->save();
if (!$address) {
$address = new UserAddress();
$address->user_id = $user->id;
}
$address->street = $request->street;
$address->house_number = $request->house_number;
$address->city = $request->city;
$address->zip_code = $request->zip_code;
$address->country = $request->country;
$address->save();
$data = [
'email' => $user->email,
'facebook' => $user->facebook_profile,
'twitter' => $user->twitter_profile,
'name' => $user->name . ' ' . $user->lastname,
'address' => $address,
];
Mail::send('emails.user-update', $data, function ($message) use ($data) {
$message->from('no-reply#example.com', 'Profile change');
$message->to('profilechange#example.com');
$message->subject('Profile change: ' . $data['name']);
});
Session::flash('message', trans('app.global.saved'));
return back();
//return redirect()->route('profile.edit-credentials');
}
I don't think isDirty() will work here, but you can save user data in the beginning:
$params = ['language', 'facebook_profile', 'twitter_profile', 'name'];
$oldUserData = auth()->user()->only($paramsToCOmpare);
Then compare the data after using save() method:
if (count(array_diff($oldUserData, $user->only($paramsToCompare))) > 0) {
// Data was changed.
}
You can do the same for UserAddress model. For password just check if it was filled in the form (since you're not displaying it anyway):
if (!empty($request->password))

Categories