The packages under the BrightComponents namespace are basically a way for me to avoid copy/pasting simple functionality that I like in all of my projects. There's nothing groundbreaking here, just a little extra functionality for form requests, controllers, custom rules, services, etc.
-
Sanitization
Laravel provides limited sanitization options, via middleware, out-of-the-box. For example, the TrimStrings middleware is enabled by default. However, you'll be responsible for any other sanitization that needs to be performed on data from your users. waavi/sanitizer makes this a breeze. In form requests, it works similarly to validation. In the same way that the "rules" method returns an array of rules, the "filters" method should return an array of filters. This method has been added to your bright-components/valid FormRequest class by default . Here, just like with the 'rules' method, return an array of filters that you want to run on your data. See the available filters here, that you can use out-of-the-box. You can also create your own custom filters to use.
I often use custom rules in Laravel. From time to time, I want access to the current FormRequest and/or the current validator, from within the custom rule. Anything can be passed through the constructor of the custom rule, however, it can get ugly passing the FormRequest, Validator and other data like this. See below:
public function rules()
{
return [
'name' => ['required', 'size:2', new NotSpamRule($this, $this->getValidator())],
];
}
With this package, the following will accomplish the same:
public function rules()
{
return [
'name' => ['required', 'size:2', new NotSpamRule],
];
}
It may not seem like much of an improvement, but I prefer my rules to be as clean and readable as possible.
These custom rules can be used in your Form Requests or in a ValidationService class. See below.
In my day-to-day development, I utilize a pattern similar to Paul Jones' ADR pattern. Using this pattern, validating at the 'controller' level is discouraged. This is a function of the domain. It is recommended to perform any authorization as soon as possible (I prefer to authorize via middleware, using Laravel's built-in Gates/Policies). Data can then be retrieved from the request and passed to a service to be used for further data retrieval, manipulation, etc. This is part of the domain layer. Using a ValidationService, you can validate the data before the service starts working on it.
The ValidationService draws HEAVILY from Laravel's Form Requests and operates in a similar way, without the Authorization component. More is explained below in the 'Usage' section.
You can install the package via composer. From your project directory, in your terminal, enter:
composer require bright-components/valid
In Laravel > 5.6.0, the ServiceProvider will be automtically detected and registered. If you are using an older version of Laravel, add the package service provider to your config/app.php file, in the 'providers' array:
'providers' => [
//...
BrightComponents\Valid\ValidServiceProvider::class,
//...
];
Then, if you would like to change any of the configuration options, run:
php artisan vendor:publish
and choose the BrightComponents/Valid option.
This will copy the package configuration (valid.php) to your 'config' folder. Here, you can set the namespace and suffix for your FormRequests, ServiceValidation classes Custom Rules:
<?php
return [
'requests' => [
/*
|--------------------------------------------------------------------------
| Namespace
|--------------------------------------------------------------------------
|
| Set the namespace for the Custom Form Requests.
|
*/
'namespace' => 'Http\\Requests',
/*
|--------------------------------------------------------------------------
| Suffix
|--------------------------------------------------------------------------
|
| Set the suffix to be used when generating Custom Form Requests.
|
*/
'suffix' => 'Request',
/*
|--------------------------------------------------------------------------
| Duplicate Suffixes
|--------------------------------------------------------------------------
|
| If you have a Request suffix set and try to generate a Request that also includes the suffix,
| the package will recognize this duplication and rename the Request to remove the suffix.
| This is the default behavior. To override and allow the duplication, change to false.
|
*/
'override_duplicate_suffix' => true,
],
'rules' => [
/*
|--------------------------------------------------------------------------
| Namespace
|--------------------------------------------------------------------------
|
| Set the namespace for the custom rules.
|
*/
'namespace' => 'Rules',
/*
|--------------------------------------------------------------------------
| Suffix
|--------------------------------------------------------------------------
|
| Set the suffix to be used when generating custom rules.
|
*/
'suffix' => 'Rule',
/*
|--------------------------------------------------------------------------
| Duplicate Suffixes
|--------------------------------------------------------------------------
|
| If you have a Rule suffix set and try to generate a Rule that also includes the suffix,
| the package will recognize this duplication and rename the Rule to remove the suffix.
| This is the default behavior. To override and allow the duplication, change to false.
|
*/
'override_duplicate_suffix' => true,
],
'validation-services' => [
/*
|--------------------------------------------------------------------------
| Namespace
|--------------------------------------------------------------------------
|
| Set the namespace for the validation services.
|
*/
'namespace' => 'Services',
/*
|--------------------------------------------------------------------------
| Suffix
|--------------------------------------------------------------------------
|
| Set the suffix to be used when generating validation services.
|
*/
'suffix' => 'Validation',
/*
|--------------------------------------------------------------------------
| Duplicate Suffixes
|--------------------------------------------------------------------------
|
| If you have a Validation suffix set and try to generate a Validation that also includes the suffix,
| the package will recognize this duplication and rename the Validation to remove the suffix.
| This is the default behavior. To override and allow the duplication, change to false.
|
*/
'override_duplicate_suffix' => true,
],
];
To generate a FormRequest class, run the following command:
php artisan adr:request CreateComment
Using the default suffix option of "Request" and the default namespace option of "Http\Requests", this command will generate an "App\Http\Requests\CreateCommentRequest" class.
Note: If you have a suffix set in the config, for example: "Request", and you run the following command:
php artisan adr:request CreateCommentRequest
The suffix will NOT be duplicated. To turn off this suffix-duplication detection, change the "override_duplicate_suffix" option to false.
Below is an example Custom Form Request class:
<?php
namespace App\Http\Requests;
use BrightComponents\Valid\BaseRequest;
class CustomClass extends BaseRequest
{
/**
* 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 [
'name' => ['required'],
];
}
/**
* Get the sanitization filters that apply to the request.
*
* @return array
*/
public function filters()
{
return [
'name' => 'uppercase',
];
}
}
Note: For any pre-validation logic that is necessary, you can utilize the
beforeValidation()
method. There is also atransform()
method that can be used to manipulate the data before validation. Check out BrightComponents\Valid\BaseRequest for more details.
To generate a custom Rule, run the following command:
php artisan adr:rule CustomRule
Using the default suffix option of "Rule" and the default namespace option of "Rules", this command will generate an "App\Rules\CustomRule" class.
Note: If you have a suffix set in the config, for example: "Rule", and you run the following command:
php artisan adr:rule CustomRule
The suffix will NOT be duplicated. To turn off this suffix-duplication detection, change the "override_duplicate_suffix" option to false.
From time to time, you may need to access information from the current FormRequest and/or current validator inside your CustomRule classes. All custom rules come with the current FormRequest object and the current validator object attached. These can be referenced inside the CustomRule class via their properties. See below:
<?php
namespace App\Rules;
use BrightComponents\Valid\CustomRule;
class NotSpamRule extends CustomRule
{
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
// if needed, access the current Validator with $this->validator and the current FormRequest with $this->request
return true;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return 'The validation error message.';
}
}
If you are using Form Requests, it is not necessary to also use a Validation Service. Form Requests are designed to be used by your controllers, retrieving the data to be validated directly from the current request. A Validation Service is used to validate data from other classes within your domain.
To generate a validation service, run the following command:
php artisan adr:validation StoreCommentValidation
Using the default suffix option of "Validation" and the default namespace option of "Services", this command will generate an "App\Services\StoreCommentValidation" class.
Note: If you have a suffix set in the config, for example: "Validation", and you run the following command:
php artisan adr:validation StoreCommentValidation
The suffix will NOT be duplicated. To turn off this suffix-duplication detection, change the "override_duplicate_suffix" option to false.
Currently, the Validation Service must be resolved from the container. Then you call the validate()
method, passing in an array of data to be validated. Using any class in Laravel that automatically resolves classes from the container, you can use a Validation Service as outlined below. Here, I am using a Service class from BrightComponents\Services class, however, it will work within any of Laravel's components that auto-resolves classes, such as Events, Jobs, etc.:
<?php
namespace App\Services;
use App\Comment;
use BrightComponents\Services\Traits\SelfCallingService;
class StoreCommentService
{
use SelfCallingService;
protected $params;
/**
* Construct a new StoreCommentService.
*/
public function __construct(StoreCommentValidator $validator) // here, the validation service class is resolved from the container
{
$this->validator = $validator;
}
/**
* Handle the call to the service.
*
* @return mixed
*/
public function run($params)
{
$validated = $validator->validate($params); // we call the validate method, passing the array of parameters
return Comment::create([
'content' => $validated['content'], // the validated method returns the key/value pairs of data that was validaated
'user_id' => auth()->user()->id,
]);
}
}
Just as with Laravel's Form Requests, if the data, doesn't pass validation, you are redirected back to the form with the errors. The validation exception logic and redirect logic is customizable from within the ValidationService class, just like it is within Form Requests.
Below is a sample Validation Service class:
<?php
namespace App\Services;
use BrightComponents\Services\Validation\ValidationService;
class StoreCommentValidator extends ValidationService
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => ['required', new NotSpamRule()],
];
}
/**
* Get the filters to apply to the data.
*
* @return array
*/
public function filters()
{
return [
'name' => 'uppercase',
];
}
}
You can use our custom rules and the waavi/sanitizer filters within a ValidationService just like you can with the Custom FormRequests. Also, in the same way that CustomRules in FormRequests give you access to $request and $validator properties, the CustomRules used in the ValidationService has $validator and $service properties that give you access to the current Validator and the current ValidationService.
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
We plan to work on flexibility/configuration soon, as well as release a framework agnostic version of the package.
The MIT License (MIT). Please see License File for more information.