Laravel - How to Validate Grading System in Model and Controller - laravel

I am developing A web Application using Laravel-5.8 framework. I have a Model Class as shown below:
<?php
namespace App;
use App\Model;
class Gradesystem extends Model
{
protected $table = 'grade_systems';
}
Also my Controller is shown below:
public function store(Request $request){
$request->validate([
'grade_system_name' => 'required|string|max:255',
'point' => 'required',
'grade' => 'required',
'from_mark' => 'required',
'to_mark' => 'required',
]);
$gpa = new Gradesystem;
$gpa->grade_system_name = $request->grade_system_name;
$gpa->point = $request->point;
$gpa->grade = $request->grade;
$gpa->from_mark = $request->from_mark;
$gpa->to_mark = $request->to_mark;
$gpa->save();
}
How do I validate, probably from the Model or the Controller between from_mark and to_mark. Also, from_mark should not be greater that or equal to to_mark.
It must not allow a number that falls in the range of already existing value. For example if from_mark is 0 and to_mark is 49 are already in database. So, if a user enters from_mark or to_mark to be 30, it must not allow it.
How do I achieve this?
Thank you.

For custom Validations its better use Rule Objects, where you can implement the logic of your validation.
An Example:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return strtoupper($value) === $value;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}
You can see the info in the Laravel documentation
Hope this can help you

I did not understand entire validation you asked but this will help. With same way you can write any other validation on from_mark and to_mark.
$validator = Validator::make($request->all(), [
'grade_system_name' => 'required|string|max:255',
'point' => 'required',
'grade' => 'required',
'from_mark' => 'required',
'to_mark' => 'required',
]);
if ($validator->fails()) {
return redirect()->back()->withInput()->withErrors();
}
if ($request->get('from_mark') < $request->get('to_mark')) {
return redirect()->back()->withInput()->withErrors();
}

Related

Laravel JsonResource return specific key

<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
Sometimes I need to return some specific key instead whole resource.
How to return a specific array of key from JsonResource toArray()? like Request with only(['key1', 'key4']) function.
From your controller, when you pass data to your view or API, you simply specify the exact key you want to access.
For example, in your controller
public function store(Request $request){
//You other logic here
$post = new PostResource( $request->all() );
//Here, you return only the specific key you want to access
return response([
'title' => $post->title,
]);
}
All the best

Laravel Validation on storage path

As an example of Laravel validation:
$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
I want to add path exists or not in storage .
Storage::exists('/path/to/your/directory');
Based on this I want to do something like :
$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
'path' => ['storage_file_exists_or_not']
]);
How to achieve that. Thanks.
You can create a custom rule using
php artisan make:rule StorageFileExists
and specify your condition inside the passes function and write your message.
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Storage;
class StorageFileExists implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return (Storage::exists($value)) ? false : true;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'File is present.';
}
}
and write validation rule like this
$request->validate([
'path' => new StorageFileExists(), // your Rulename
]);

How to read URL parameters in laravel

I am begginer, and trying to create a referral system. following is sample url
http://dev.lea.com/register?ref=mh2HPLpVSn
I try to get referral string. how can i get separately? is there need of middleware for getting cookies? if yes then what will be code of middleware? and how can i get referral reference in RegisterController?
Here is my Register Controller.
<?php
namespace Lea\Http\Controllers\Auth;
use DB;
use Lea\User;
use Lea\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Cookie;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'fname' => 'required|string|max:255',
'lname' => 'required|string|max:255',
'referral' => 'string|max:255',
'username' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
// 'tracking_id' => 'required',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \Lea\User
*/
protected function create(array $data, Request $request)
{
// printing here referral Link
echo $request()->ref;
// $referred_by = Cookie::get();
// print_r($referred_by);
die;
return User::create([
'fname' => $data['fname'],
'lname' => $data['lname'],
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'affiliate_id' => str_random(10),
// 'referred_by' => $referred_by,
'identity' => $data['identity'],
'dob' => $data['dob'],
'board_id' => $data['board_id'],
'class_id' => $data['class_id'],
'subject_id' => $data['subject_id'],
'institute' => $data['institute'],
'address' => $data['address'],
'city' => $data['city'],
'std_mobile' => $data['std_mobile'],
'father_name' => $data['father_name'],
'father_mobile' => $data['father_mob'],
'ipadress' => \Request::ip(),
]);
}
}
When you have an URI such as /register?ref=mh2HPLpVSn you can retrieve ref like this:
$request()->ref
in your controller! I believe you can also use $request()->has('ref') to determine if it's present in the URI.
Hope this helps you!!
In laravel 6+ inside controller you can use like
$request->get('ResourcePath')
You can get your parameters using Request access.
Here one example for get your ref code:
public function register(Request $request)
{
$allParams = $request->all();
$refParam = $request->ref;
dd($allParams, $refParam);
...
}
public function showRegister(Request $request) {
var_dump(request->ref)
}
then you can do things like validation and so on, another possiblity is to change the template of your register form and add a hidden field with the refcode from the ref param and handle the whole request in your register method.

Customize Validation Messages in Laravel Requests

How do i customize my Validation Messages in My REQUESTS FILE?
how do i add messages next to the rules?
What i want is to put customized messages just like the common validation. Is it possible? to do just the normal way of validation in the Requests?
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ArticleRequest extends Request
{
/**
* 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 [
'title' => 'required|min:5',
'content' =>'required',
'user_id' => 'required|numeric',
'category_id' => 'required|numeric',
'published_at' => 'required|date'
];
}
}
You can define a messages() method with validation rules for that form request only:
class StoreArticleRequest extends Request
{
//
public function messages()
{
return [
'title.required' => 'The title is required.',
'category_id.numeric' => 'Invalid category value.',
];
}
}
It takes the form of the field name and the rule name, with a dot in between, i.e. field.rule.
You may customize the error messages used by the form request by
overriding the messages method. This method should return an array of
attribute / rule pairs and their corresponding error messages:
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
https://laravel.com/docs/5.3/validation#customizing-the-error-messages
I use this solution to translate the field labels:
...
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|min:5',
'content' =>'required',
'user_id' => 'required|numeric',
'category_id' => 'required|numeric',
'published_at' => 'required|date'
];
}
/**
* Get the validation attributes that apply to the request.
*
* #return array
*/
public function attributes()
{
return [
'title' => __('app.title'),
'content' => __('app.content'),
'user_id' => __('app.user'),
'category_id' => __('app.category'),
'published_at' => __('app.published_at')
];
}

Laravel 5 __construct() argument passing error

So I am trying to group all my validation rules into its respective files in folders for easy maintenance. Below is how my folder structures look:
Project
--app
--config
--(more folders)
--domains
----App
--------Entities
--------Repositories
--------Services
--------Validators
----Core
--------Validators
So what I wanted to achieve is under Core\Validators I created a LaravelValidator.php which look like this
<?php namespace Core\Validators;
use Validator;
abstract class LaravelValidator {
/**
* Validator
*
* #var \Illuminate\Validation\Factory
*/
protected $validator;
/**
* Validation data key => value array
*
* #var Array
*/
protected $data = array();
/**
* Validation errors
*
* #var Array
*/
protected $errors = array();
/**
* Validation rules
*
* #var Array
*/
protected $rules = array();
/**
* Custom validation messages
*
* #var Array
*/
protected $messages = array();
public function __construct(Validator $validator)
{
$this->validator = $validator;
}
/**
* Set data to validate
*
* #return \Services\Validations\AbstractLaravelValidator
*/
public function with(array $data)
{
$this->data = $data;
return $this;
}
/**
* Validation passes or fails
*
* #return Boolean
*/
public function passes()
{
$validator = Validator::make(
$this->data,
$this->rules,
$this->messages
);
if ($validator->fails())
{
$this->errors = $validator->messages();
return false;
}
return true;
}
/**
* Return errors, if any
*
* #return array
*/
public function errors()
{
return $this->errors;
}
}
Then in my App\Validators I created a file name RegistrationFormValidator.php which look like this
<?php namespace App\Validators\Profile;
class RegistrationFormValidator extends \Core\Validators\LaravelValidator
{
protected $rules = array(
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
);
}
so usually in laravel 4.2, to validate something all i do is construct the validation rules and then call it in services which look like this
<?php namespace App\Services\Profile;
/*
|-----------------------------------------------------------
| This section injects the repositories being used
| in this service.
|-----------------------------------------------------------
*/
use App\Repositories\Profile\ProfileRepository;
use Core\ValidationFailedException;
use App\Validators\Profile\RegistrationFormValidator;
use Validator;
class ProfileService implements ProfileServiceInterface
{
protected $_profile;
protected $v;
/*
|-----------------------------------------------------------
| All construsted models variables must carry
| the '_' sign to identify it as a model variable
|-----------------------------------------------------------
*/
public function __construct(ProfileRepository $_profile, RegistrationFormValidator $v)
{
$this->_profile = $_profile;
$this->v = $v;
}
/*
|-----------------------------------------------------------
| 1. All try and catch error handling must be done
| in the respective controllers.
|
| 2. All data formattings must be done in this section
| then pass to repository for storing.
|
| 3. No controller actions allown in this section
|-----------------------------------------------------------
*/
public function createProfile($array)
{
if($this->v->passes())
{
//save into db
}
else
{
throw new ValidationFailedException(
'Validation Fail',
null,
$this->v->errors()
);
}
}
}
But the problem is once i upgraded into laravel 5 i did the same thing and when i try to execute the code it returns me with this error
ErrorException in ProfileService.php line 26:
Argument 2 passed to App\Services\Profile\ProfileService::__construct() must be an instance of App\Validators\Profile\RegistrationFormValidator, none given
My code works absolutely fine in L4.2 but once i upgraded it wont work anymore. I also know that i can do validation like such
public function createProfile($array)
{
$v = Validator::make($array, [
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
]);
if($v->passes())
{
}
else
{
throw new ValidationFailedException(
'Validation Fail',
null,
$v->errors()
);
}
}
But the problem is if i would have more validation rules or scenario it will flood the whole service file.
Any suggestions or solutions that will guide me? thanks in advance!
In Laravel 5 you have something similar, which handles better the validation and makes validation clean and easy. It is called Form Request Validation. The idea there is the same - to have different classes that handle validation in different scenarios.
So whenever you need a validation you can create new FormRequest, like this:
php artisan make:request RegisterFormRequest
A new class will be generated under app/Http/Requests. There you can see it has two methods authorize and rules. In the first one you can make a check if given user is allwed to make this request. In the second method you can define your rules, just like in the validator.
public functions rules() {
return array(
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
);
}
Then you can change your controller method like this:
public function postCreateProfile(RegisterFormRequest $request) {
// your code here
}
The are a few cool things here. First one - the class will be automatically constructed in injected in your controller method by the IoC container, you don't need to do something special. The second cool thing is that the validation check is done before the Request object is passed to the controller, so if any validation error occurs you will be redirected back with all errors according to your rules set. This means that writing your code in the postCreateProfile method you can assume if this code get executed the validation is passed at this position and no additional check are needed by you.
I suggest you to migrate your code to use Laravel 5 Form Requests, because what you need is already implemented in the framework, and yes basically this is the point of the migration of one version to another. You can also check the documentation for more examples.

Resources