I've been trying to create a method in BaseController.php for validating requests in laravel for APIs. If I use the $this->validate($request, $rules) in API controller it doesn't return the required result. I used this code initially.
$validator = Validator::make($request->all(), [
'name' => 'required',
'email' => 'required|email|unique:users,email',
'phoneNo' => "required|max:15|min:11|unique:users,phoneNo",
'username' => 'required|unique:users,username',
'password' => 'required',
'c_password' => 'required|same:password'
]);
if ($validator->fails()) {
return $this->sendError('Validation Error.', $validator->errors());
}
But I don't want to do this for every method in every controller.
So, I thought that instead of writing this in every controller I should create a method in BaseController.php which I can use in every controller as all controllers are inherited from the BaseController.php.
So, I wrote this to achieve the functionality but this isn't working as it should.
class BaseController extends Controller
{
/**
* success response method.
*
* #return \Illuminate\Http\Response
*/
public function sendResponse($result, $message)
{
$response = [
'success' => true,
'data' => $result,
'message' => $message,
];
return response()->json($response, 200);
}
/**
* return error response.
*
* #return \Illuminate\Http\Response
*/
public function sendError($error, $errorMessages = [], $code = 404)
{
$response = [
'success' => false,
'message' => $error,
];
if (!empty($errorMessages)) {
$response['data'] = $errorMessages;
}
return response()->json($response, $code);
}
public function validateRequest($request, $rules)
{
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) return $this->sendError("Validation Error.", $validator->errors());
}
}
And in the register controller I use this
$this->validateRequest($request, [
'name' => 'required',
'email' => 'required|email|unique:users,email',
'phoneNo' => "required|max:15|min:11|unique:users,phoneNo",
'username' => 'required|unique:users,username',
'password' => 'required',
'c_password' => 'required|same:password',
]);
but it doesn't return an exception here. So, I have to add return to this statement in order for it to return an error. but it should stop the process itself and return the response to API here.
Any help would be appreciated.
Thank you
Update
I found the answer to it. I was a little wrong about this. I forgot to add Accept: "application/json" parameter in the header. We can simply use the same old validation method:
$request->validate([
'name' => 'required',
'email' => 'required|email|unique:users,email',
'phoneNo' => "required|max:15|min:11|unique:users,phoneNo",
'username' => 'required|unique:users,username',
'password' => 'required',
'c_password' => 'required|same:password',
]);
If you are working with API and you want to show a JSON response to this then, you can simply add this in your request headers and it will return a proper JSON response:
Accept: "application/json"
Related
public function register(Request $request) {
// $user = User::create([
// 'name' => $request->input('name'),
// 'email' => $request->input('email'),
// 'password' => Hash::make($request->input('password'))
// ]);
//
// return $user;
return "test";
}
Hi all,
basically, I'm trying to build a restful API with Laravel and my API is being hit by Postman, but when I send a JSON body my $request is an empty array.
It's the first time I'm touching Laravel so it's probably something obvious so thank you in advance !
Try this one
use Exception;
public function register(Request $request) {
try {
$user = User::create([
'name' => $request->input('name'),
'email' => $request->input('email'),
'password' => Hash::make($request->input('password'))
]);
return response()->json(['status' => true, 'message' => 'You have been register successfully', 'data' => $user]);
} catch (Exception $e) {
return response()->json(['status' => false, 'message' => $e->getMessage(), 'data' => []]);
}
}
I am creating a Laravel API for Authentication and DB management. In my AuthController, I have a login function that works well and a register function that does not work. Instead of returning the new user info and the 201 status, it returns a 200 and display the homepage of the API (the welcome.blade.php created Laravel).
My routes in api.php:
Route::post('login', 'AuthController#login');
Route::post('register', 'AuthController#register');
My AuthController:
class AuthController extends Controller
{
/**
* Register user
*/
public function register(Request $request)
{
$request->validate([
'firstname' => 'required|string',
'surname' => 'required|string',
'email' => 'required|email|unique:users',
'password' => 'required|string|confirmed'
]);
$user = new User([
'firstname' => $request->firstname,
'surname' => $request->surname,
'email' => $request->email,
'password' => bcrypt($request->password)
]);
$user->save();
$success['token'] = $user->createToken('MyApp')->accessToken;
$success['firstname'] = $user->firstname;
$success['surname'] = $user->surname;
$success['email'] = $user->email;
return response()->json(['success' => $success], 201);
}
/**
* Login user and create token
*
* #param [string] email
* #param [string] password
* #param [boolean] remember_me
* #return [string] access_token
* #return [string] token_type
* #return [string] expires_at
*/
public function login(Request $request)
{
$request->validate([
'email' => 'required|email|exists:users,email',
'password' => 'required|string',
// 'remember_me' => 'boolean'
]);
$credentials = request(['email', 'password']);
if(!Auth::attempt($credentials))
{
return response()->json([
'message' => 'Unauthorized',
'request'=> $credentials
], 401);
}
$user = Auth::user();
$tokenResult = $user->createToken('ApiPassToken');
$token = $tokenResult->token;
if ($request->remember_me)
{
$token->expires_at = Carbon::now()->addWeeks(1);
}
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
]);
}
What is wrong in the register function ?
i think this is for your validation. you have to return a json when your validation fails otherwise it returns last view. do your validation like this
$validator = Validator::make($request->all(), [
'firstname' => 'required|string',
'surname' => 'required|string',
'email' => 'required|email|unique:users',
'password' => 'required|string|confirmed'
]);
if ($validator->fails()) {
return response()->json(['message' => $validator->errors()->first(), 'status' => false], 500);
}
and remember use Validator class
use Illuminate\Support\Facades\Validator;
So let's say I've got a custom request called CreateReviewRequest.
In this request, I've got this method:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required_if(auth->logged)',
'comments' => 'required|max:255',
'stars' => 'required|min:1|max:5',
];
}
As you can see in the name key, I want from the client to be required to fill the name field if he's not logged in.
So my question is, how can I exactly require my client to fill the name when he's a guest?
You can use check() method:
public function rules()
{
return [
'name' => auth()->check() ? 'required' : '',
'comments' => 'required|max:255',
'stars' => 'required|min:1|max:5',
];
}
Can't you make a simple check?
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
if (auth()->check()) {
return [
'comments' => 'required|max:255',
'stars' => 'required|min:1|max:5',
];
}
return [
'name' => 'required',
'comments' => 'required|max:255',
'stars' => 'required|min:1|max:5',
];
}
Member only:
$validator = Validator::make($request->all(), [
'email' => auth()->check() ? '' : 'required|min:5|max:60|email',
]);
Guest only:
$validator = Validator::make($request->all(), [
'user_id' => auth()->check() ? 'required|integer|min:1' : '',
]);
Both:
$validator = Validator::make($request->all(), [
'message' => 'required|min:10|max:1000'
]);
Combined:
$validator = Validator::make($request->all(), [
'email' => auth()->check() ? '' : 'required|min:5|max:60|email',
'user_id' => auth()->check() ? 'required|integer|min:1' : '',
'message' => 'required|min:10|max:1000'
]);
I do have a feeling that I need to use Auth:: or something here to link to passes. Am I correct
Issue Line
if($validator->passes())
`
getLoginCredentials
protected function getLoginCredentials(Request $request)
{
$validator = $this->loginValidation($request);
if($validator->passes())
{
return[
'email' => Request::input('email'),
'password' => Request::input('password'),
'type' => 1
];
}else{
return redirect()->back()->withErrors();
}
}
loginValidation
protected function loginValidation($request)
{
$rules = array(
'email' => 'required|email',
'password' => 'required',
);
$this->validate( $request , $rules);
}
I think the actual problem is in the loginValidation method that should return an object. Please, see my code below. I've also changed getLoginCredentials a bit as Request shouldn't be called statically.
protected function getLoginCredentials(Request $request)
{
$validator = $this->loginValidation($request);
if ($validator->passes()) {
return [
'email' => $request->input('email'),
'password' => $request->input('password'),
'type' => 1
];
} else {
return redirect()->back()->withErrors();
}
}
loginValidation
protected function loginValidation(Request $request)
{
$rules = [
'email' => 'required|email',
'password' => 'required',
];
return Validator::make($request->all(), $rules);
}
I have a protected function that I want to use to check my login validation. However I am getting the error
Call to undefined method Illuminate\Database\Query\Builder::loginValidation
Do I have to write a model for my function?
Login Validation:
protected function loginValidation($data)
{
$rules = array(
'fname' => 'required|max:255',
'lname' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
);
return Validator::make($data, $rules);
}
getLoginCredentials
protected function getLoginCredentials(Request $request)
{
$validator = User::loginValidation(Request::all());
if($validator->passes())
{
return[
'email' => Request::input('email'),
'password' => Request::input('password'),
'type' => 1
];
return true;
}else{
return redirect()->back()->withErrors();
}
}
I guess the user model can not see your function. Do composer dump-autoload to see if the changes will reflect. if it does not try a new name and see if it will work.