Laravel 5 __construct() argument passing error - laravel

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.

Related

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 do I show custom error messages with Laravel form requests?

I am new to Laravel, and have made a UserRequest class that handles validating incoming sign up requests. This is what I have inside it:
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'firstname' => 'required|string',
'lastname' => 'required|string',
'email' => 'required|email',
'password' => 'required|string|min:6',
];
}
/**
* Custom message for validation
*
* #return array
*/
public function messages()
{
return [
'firstname.required' => 'First name is required!',
'lastname.required' => 'Last name is required!',
'email.required' => 'Email is required!',
'password.required' => 'Password is required!'
];
}
My question is do these error messages automatically show if the user doesn't enter a field, or is there anything else I need to do, ie in my controller?
Thanks!
you must include the UserRequest in your controller e.g.
use App\Http\Requests\UserRequest;
And make sure you define your incoming request as a UserRequest (and not a regular Laravel Request) e.g.
public function update(UserRequest $request)
The validation should then be performed automatically.

Laravel - How to Validate Grading System in Model and Controller

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();
}

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.

Laravel, registration and login on same page. Errors on both forms

I'm working on a website with Laravel and I have the registration and login forms on the same page. The only problem is that if I type the wrong password on the login form the error will show on both forms below the password input.
I've googled this and I have seen some other people with this problem but they are all working on a version below 5.4 and all those solutions are different in version 5.4. Does anyone know what exactly I need to change to make this work?
So far I've changed the names in the forms to 'login_password' and 'register_password', but this only gives me errors.
If you're going to go down the route of changing the input names you'll need to update your LoginController and RegisterController.
Login Controller
You will need to add the following:
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'login_password' => 'required',
]);
}
protected function credentials(Request $request)
{
return [
$this->username() => $request->input($this->username()),
'password' => $request->input('login_password'),
];
}
RegisterController (these methods should already exist in the controller, you'll just need to update password to register_password where applicable)
/**
* 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, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'register_password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['register_password']),
]);
}
You will also need to include the Request by putting the following at the top of the file with the other use statements:
use Illuminate\Http\Request;
Hope this helps!

Resources