how to make a update api in laravel using autherntication token - php

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) {
// ...

Related

update api not updating db in laravel

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

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 Registration Key with Validation

I'm currently trying to modify the base Laravel Authentication to include the use of a key created in the database, I've included another field named "key" which I've been able to get the registration to check via a model, the issue is that if the key is incorrectly input I haven't been able to let the user know the key is incorrect.
Current RegistrationController.php
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'key' => ['required'],
]);
}
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$d = Key::where('key', $request->only(['key'])['key'])->first();
if($d != null){
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
if ($response = $this->registered($request, $user)) {
return $response;
}
return $request->wantsJson()
? new Response('', 201)
: redirect($this->redirectPath());
}
else{
$this->validator($request->all())->validate();
return view('auth.register')->withErrors(['key', 'This key was not found']);
}
}
I've tried to modify the validate method to include same but when testing using same:12345 it looks for a variable called 12345 instead of checking if the key is the same as 12345, how do I change the validation to do what I've done in the register method to check the models instead.

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.

Categories