How to show custom messages in laravel 5.8? - laravel

I am using laravel 5.8 version, i have one api which is responsible for registering ,i create one Request file which contains rules() and messages() function to display error messages but it's not throwing any error messages if any validation fails ,why this is happening can somebody explain ?
UserController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}
userRequest.php
<?php
namespace App\Http\Requests;
use App\Rules\CustomRule;
use Illuminate\Foundation\Http\FormRequest;
class userRequest extends FormRequest
{
public function messages()
{
return [
'first_name.required' => 'A title is required',
];
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'string|required|max:25',
'phone_number' => 'required|integer'
];
}
}
The error i am facing when i hit the route without first_name key it's showing 404 not found error

you might have missed headers part for taking the form-data
Accept = application/json

As laravel docs
If validation fails, a redirect response will be generated to send the
user back to their previous location. The errors will also be flashed
to the session so they are available for display. If the request was
an AJAX request, a HTTP response with a 422 status code will be
returned to the user including a JSON representation of the validation
errors.
So you need to specify the response type you expect, if you use postman for testing your api end point you have to add in request header Accept:application/json
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}

Related

Missing required parameter for [Route: verification.verify]

On a project I have I am using Fortify as my BE. I need a multilingual app, therefore I added the
'prefix' => {locale}' to config/fortify.php.
Login, registering, and 2FA, are working ok, but the problem arrives with the email verification process.
If I try to click on the link received by email, it goes to the /email/verify and returns a forbidden page error.
Then if I request to get another verification email it returns the error displayed on the title of the question.
Probably it has something to be with the locale parameter because when I run route::list, the verification.verify route is displayed with the endpoint of {locale}/email/verify/{id}/{hash}, so I assume that the link on the request another mail is causing the error since it is referenced as /email/verify/{id}/{hash}.
So does anyone know how to change it?
Or has anyone faced a similar problem regarding Fortify and these localization routes?
What I had to do was to customize some of the default Fortify functions, extending some classes in order to add the locale parameter to them.
When a new user is registered (event) it sends the verification email (listener), so I had to configure the files involved in this flow.
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Registered;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendEmailVerificationNotification implements ShouldQueue
{
use Queueable;
public function handle(Registered $event)
{
if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) {
$event->user->sendCustomVerificationEmailNotification();
}
}
}
And create the function sendCustomVerificationEmailNotification on the user's model and the notification CustomVerificationNotification that will be sent.
public function sendCustomVerificationEmailNotification()
{
$this->notify(new CustomVerificationNotification);
}
<?php
namespace App\Notifications;
use Carbon\Carbon;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\URL;
class CustomVerificationNotification extends VerifyEmail
{
protected function verificationUrl($notifiable)
{
if (static::$createUrlCallback) {
return call_user_func(static::$createUrlCallback, $notifiable);
}
return URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'locale' => app()->getLocale(),
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
]
);
}
}
Then in case, the user wants an additional verification email notification, this is handled through a function on the EmailVerificationNotificationController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\Http\Controllers\EmailVerificationNotificationController;
class CustomEmailVerificationController extends EmailVerificationNotificationController
{
/**
* Send a new email verification notification.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
if ($request->user()->hasVerifiedEmail()) {
return $request->wantsJson()
? new JsonResponse('', 204)
: redirect()->intended(Fortify::redirects('email-verification'));
}
$request->user()->sendEmail();
return $request->wantsJson()
? new JsonResponse('', 202)
: back()->with('status', 'verification-link-sent');
}
}

Cannot get requested data from route

Laravel 8, PHP 7.4.3 Trying to get request ID from the route. In this case I want to get 52 from the routeBeing a basic problem, still creating issue for me. My Route   http://127.0.0.1:8000/user/expense/52/edit My Code
ExpenseController.php
// namespace App\Http\Controllers;
public function edit(Request $request, Expense $expense)
{
//I tried running each dd individually.
dd( $request->get('id') ); //returns null
dd( $request->id ); //returns null
dd( $request['id'] ); // returns null
}
For reference to this controller, check this
Please note that the route is generated by Route::resource function in web.php file. I want to know how to get the ID from the route. I also tried to use Custom Form Request but again that fails as the id is null,IDRequest.php
//namespace App\Http\Requests;
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'id' => 'required'
];
}
This approach also fails me. Please tell me what is it that I am missing. Link for IDRequest
Every help and hint is appreciated.
// namespace App\Http\Controllers;
public function edit(Request $request, Expense $expense)
{
}
$request->get('id') looks for the id param in your form data or params.
Expense $expense will load the resource with primary key id 52 as per route value. You can fetch the id from $expense variable.

Trigger JSON response via Trait in Controller Larael

I'm using Laravel 8 to build an API, I have a route which for the purposes of the question is... /api/fact which GETs a random fact. I have a FactsController.php file and two traits, one for constructing a JSON response, the other for getting a fact. For some reason when calling the trait's function from within my controller (which made the request) I'm not getting any returned JSON back in Postman...
Traits/GetFact.php
<?php
namespace App\Traits;
use App\Traits\ApiResponse;
trait GetFact {
use ApiResponse;
/**
* Get random fact
*
* get random fact
*/
public function getRandomFact () {
$this->getFact();
$this->apiResponse([
'msg' => "Fact..."
], 200, true);
}
}
Traits/ApiResponse.php
<?php
namespace App\Traits;
trait ApiResponse {
/**
* API Response
*
* Return a JSON response for our API with params
*/
public function apiResponse ($data, $code, $success = false) {
return response()->json(array_merge(['success' => $success], $data), $code);
}
}
Controllers/FactController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Traits\GetFact;
class FactsController extends Controller
{
use GetFact;
/**
* Fact
*
* #param Request $request
*/
public function fact()
{
$this->getRandomFact()
}
}
When I make my request to /api/fact I should be getting the returned JSON listed where I'm calling $this->apiResponse() with the msg, but I'm not? It's like the return doesn't seem to return JSON because it's scoped to the trait and not the controller and that there isn't a return in there? How can I achieve the listed.
You are not "returning" anything from your Controller method. You have to return something for their to be a response with content. Also, fact and getRandomFact do not return anything so calling those isn't doing anything for you. You are also calling a getFact method and not assigning the return to anything (if it even returns anything).

Controller Method not called with custom Form Request Method

For form validation I made a Request class via php artisan make:request UpdatePlanRequest.
However after using the UpdatePlanRequest class in store the method isn't called anymore.
The UpdatePlanRequest:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdatePlanRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{ //TODO: CHECK IF THE PROTOTYPE IDS ARE OWNED BY THE USER (https://stackoverflow.com/questions/42662579/validate-an-array-of-integers/42693970)
return [
'start_date' => 'required|date',
'end_date' => 'required|date|after:start_date',
'name' => 'required|string'
];
}
}
The controller method:
use App\Http\Requests\UpdatePlanRequest;
public function store(UpdatePlanRequest $request)
{
//
dd('hello');
}
If the function header is store(Request $request) hello is shown, in that example it isn't.
The custom Request class is necessary to call $request->validated(); later for validation purposes according to the docs.
Is there a reason you have your Request class as being abstract? The default class that is created when running php artisan make:request <name> doesn't define the class as being abstract. This seems to work for me, but not when declaring it as abstract.
$request->validated(); is used to retrieve the validated inputs, so just by calling the UpdatePlanRequest it should validate the request
//Try This
use App\Http\Requests\UpdatePlanRequest;
public function store(UpdatePlanRequest $request)
{
$validatedData = $request->validated();
dd('$validatedData');
$profile = new Profile([
'user_id' => $request->get('user_id'),
]);
$profile->save();
echo $request->session()->flash('alert-success', 'Profile details Succefully Added!');
return redirect('create')->with('success', 'Data saved!');
}
Your route will be.
Route::get('profile','ProfileController#store');
Route::post('profile/create','ProfileController#store')->name('create');
Well this works right!
When the method is called, it checks the request class (UpdatePlanRequest). If there is an error, it does not enter the method anymore and you can not see the output of dd() function.
If the data is correct after checking the rules, then dd() will be displayed.
You must manage errors

Laravel 5 - sanitize certain inputs on validation

Is it possible to sanitize certain inputs on (or before validation)?
I have this rules for now (as example):
public function rules()
{
return [
'name' => 'required|min:3|max:255|string',
'description' => 'string',
'hours.*' => ['required', new Hours],
];
}
I want to sanitize name and description, but I don't to sanitize hours. Is this possible to do on validation, or I have to sanitize after validation and before insert?
I don't recommend to do sanitization after validation.
Suppose we have a blog system and guests/users can comment on posts, and the minimum characters in a comment is 10
If someone comments with thank you (there's a trailing space), it will be passed at the validation level because it's a 10 chars comment, but when we sanitize the comment, say we trim it, it will be left with 9 chars. This is a silly example but can be something very important in your business logic somewhere.
Sanitize then validate.
To do request inputs sanitization, this article has a good pattern to do it https://medium.com/#melihovv/how-to-sanitize-input-data-in-declarative-manner-in-laravel-e4486068f751
To cannot do this before validation as the original value will still be there in request. It can be easily dealt with mutators.
You can use Eloquent's Mutators to format attribute values in Eloquent Model before insert or update.
To define mutator, add set prefix and attribute suffix with the attribute's name. Like following
// Name mutator
public function setNameAttribute($name)
{
$this->attributes['name'] = strtolower($name); // used strtolower just to show the mutation
}
// Description mutator
public function setDescriptinAttribute($description)
{
$this->attributes['description'] = strtolower($description); // used strtolower just to show the mutation
}
Check documentation for more info https://laravel.com/docs/5.6/eloquent-mutators#defining-a-mutator
The only way I could think of validating the input like that would be validating it on the client side. So basically using Javascript to validate it. If the user for some reason disables Javascript your server site validation would work. What you could try as well would be to post the data asynchronous using Ajax for instance and immidietly return an error message if the validation fails, this approach would be server side.
test this :
web.php
Route::get('test/', 'TestController#test');
TestController class :
<?php
namespace App\Http\Controllers;
use App\Http\Requests\PostRequest;
use App\Post;
class PostController extends Controller
{
public function test(PostRequest $request)
{
dd($request->get('name'));
}
}
PostRequest class :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$this->sanitize();
return [
'name'=>'required',
'description'=>'required',
'description'=>'required',
];
}
public function sanitize()
{
$input = $this->all();
$input['name'] = $input['name'].'some change';
$input['description'] = $input['description'].'another change';
$this->replace($input);
}
}
As you can see, I defined a method called sanitize in PostRequest
Now when I set the value of the name to the ‍‍ali in URL, but the ali some change value will be printed.
You can also use the daylerees / sanitizer package.

Resources