Laravel - what is best practice about custom request? - laravel

I use 2 customs requests, one for the register, and one for the password change.
In both, there is the same password validation. How can I avoid duplicating this code and have it in only one request?
I don't know if it is possible, I would like to have your opinion.
Kylian

You can create your own CustomRequest class to validate your requests in Laravel.
Class CustomRequest extends Request
{
public function rules()
{
return [
'password' => 'required',
'username' => 'required'
];
}
public function messages()
{
return [];
}
}
use this above class in controller function.
public function functionName(CustomRequest $customRqt)
{
try {
dd($customRqt->all());
} catch (\Throwable $th) {
$thow $th;
}
}
this will help you to avoid duplicacy. I haven't run this code, but this will give you an idea.

Related

What should I do with error/successful messages in Laravel service classes

I'm writing an AuthService and I don't know how should I show the output. I decided to throw an exception for errors and a simple array for successful messages. I want to know if it's okay or there is a better way.
Let's say we have a function that check's if the email has already exist in DB or not:
public function checkEmailExist(string $email)
{
$user = $this->getUserByEmail($email);
if ($user) {
throw new EmailAlreadyExistException();
}
return [
'message' => 'Ok',
];
}
And the exception class defined like this to prevent messing the logs:
use Exception;
use Symfony\Component\HttpFoundation\Response;
class EmailAlreadyExistException extends Exception
{
public function render()
{
return response()->json([
'message' => __('errors.general'),
'errors' => [
'email' => [__('errors.user.email_already_exists')],
],
], RESPONSE::HTTP_CONFLICT);
}
public function report()
{
}
}
And the controller:
public function check(CheckRequest $request)
{
return $this->authService->checkEmailExist(
email: $request->email,
);
}
To find out if a user with the entered email address already exists, you can use the exists validation rule already present in the framework: https://laravel.com/docs/9.x/validation#rule-exists
A validation error will then be displayed instead of an exception which is absolutely not meaningful to a user.
Then, if you want to catch validation errors to return formatted responses according to your API specifications, you can modify the exception handler of Laravel: https://laravel.com/docs/9.x/errors#rendering-exceptions
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;
///
$this->renderable(function (ValidationException $e, $request) {
return response()->json([
'message' => 'validation_rule_failed',
'errors' => $e->errors(),
], Response::HTTP_UNPROCESSABLE_ENTITY);
});

Use 2 different FormRequests in a single controller

Is it possible to use 2 different FormRequest validations in a single Controller, one for store and the other for index, how?
I used method() to returns different validations from rules(), ex:
public function rules()
{
if($this->method() == 'GET')
{
return [
'customer' => 'required|numeric',
];
}
if($this->method() == 'POST')
{
return [
'author' => 'required|numeric',
];
}
}
but looks very uncomfortable
You can use 2 different Formrequest in one controller.
I do it as following
class PostController extends Controller
{
public function index(ManagePostRequest $request){
// your code goes here
}
public function create(CreatePostRequest $request){
// your code goes here
}
public function store(StorePostRequest $request){
// your code goes here
}
}
So according to the method you can have different rules in form request. Also you can use them for authorize the method.
Hope this is what you were asking as the question was a little unclear to me.

Validate specific rule - Laravel

I am using latest Laravel version.
I have requests/StoreUser.php:
public function rules() {
return [
'name' => 'required||max:255|min:2',
'email' => 'required|unique:users|email',
'password' => 'required|max:255|min:6|confirmed'
];
}
for creating a user.
Now I need and to update the user, but how can I execute only specific rules ?
For the example, if name is not provided, but only the email, how can I run the validation only for the email ?
This is easier than you thought. Make rules depend on the HTTP method. Here is my working example.
public function rules() {
// rules for updating record
if ($this->method() == 'PATCH') {
return [
'name' => 'nullable||max:255|min:2', // either nullable or remove this line is ok
'email' => 'required|unique:users|email',
];
} else {
// rules for creating record
return [
'name' => 'required||max:255|min:2',
'email' => 'required|unique:users|email',
'password' => 'required|max:255|min:6|confirmed'
];
}
}
You can separate your StoreUser request to CreateUserRequest and UpdateUserRequest to apply different validation rules. I think, this separation makes your code more readable and understandable.
Any HttpValidation request in laravel extends FormRequest that extends Request so you always have the ability to check request, auth, session, etc ...
So you can inside rules function check request type
class AnyRequest extends FormRequest
{
public function rules()
{
if ($this->method() == 'PUT'){
return [
]
}
if ($this->method() == 'PATH') {
return [
]
}
}
}
If things get complicated you can create a dedicated new HttpValidation request PostRequest PatchRequest
class UserController extends Controller
{
public function create(CreateRequest $request)
{
}
public function update(UpdateRequest $request)
{
}
}
See also the Laravel docs:
https://laravel.com/docs/5.8/validation
https://laravel.com/api/5.8/Illuminate/Foundation/Http/FormRequest.html

Laravel - return variable from Form Requests to Controller

How can I return a variable from Form Requests (App\Http\Requests) to Controller (App\Http\Controllers)?
I am saving a record on function persist() on Form Requests.
My goal is to pass the generated id so that I can redirect the page on edit mode for the user. For some reason, the Controller cannot receive the id from Form Requests.
App\Http\Requests\MyFormRequests.php:
function persist()
{
$business = Business::create([
'cart_name' => $this['cart_name'],
'product' => $this['product']
]);
return $myid = $business->id;
}
App\Http\Controllers\MyControllers.php:
public function store(MyFormRequests $request)
{
$request->persist();
return redirect()->route('mypage.edit.get', $request->persist()->$myid);
}
Important
I must add that this is not the recommended way. Your FormRequest should only be responsible for validating the request, while your Controller does the storing part. However, this will work:
App\Http\Requests\MyFormRequests.php:
function persist()
{
return Business::create([
'business_name' => $this['business_name'],
'nationality' => $this['nationality']
])->id;
}
App\Http\Controllers\MyControllers.php:
public function store(MyFormRequests $request)
{
$id = $request->persist();
return redirect()->route('register.edit.get', $id);
}
A guy name Snapey helped me:
public function store(MyFormRequests $request)
{
$business = $this->persist($request);
return redirect()->route('register.edit.get', $business->id);
}
private function persist($request)
{
....
return $business;
}
hope this could help someone in the future.

laravel 5 form request validation issue

in my laravel 5.1 app, I've got a Book model with a required "Title" field and several others non-required fields. To validate Book create/update, I use form request validation like this:
class StoreBookRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required',
'year' => 'numeric',
'pages' => 'numeric',
];
}
}
I then type-hint the request on the controller action and everytning works fine. Now I need to create a new controller action that updates only one of the non-required fields. To do so, I created another request like this:
class StoreReviewRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'vote' => 'numeric',
];
}
}
and I type-hint the request in the controller action:
public function updateReview(StoreReviewRequest $request, Book $book)
{
$input = array_except(Input::all(), '_method');
$book->update($input);
Session::flash('message', 'Review updated');
return redirect('/book');
}
The problem is that when I use the new controller action, the update form does not pass validation, but complains about missing "Title" field, even tough I'm not decalring that field as required in my StoreReviewRequest class. What am I doing wrong? Thanks!
As #Needpoule suggested, I was using the wrong action in my form.

Resources