shabushabu / harness
Opinionated validation abstraction for a Laravel JSON:API that hopefully doesn't get in the way
Fund package maintenance!
boris-glumpler
paypal.me/BorisGlumpler
Requires
- php: ^7.4
- illuminate/database: ^7.0
- illuminate/http: ^7.0
- illuminate/pipeline: ^7.0
- illuminate/support: ^7.0
- illuminate/validation: ^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.16
- nunomaduro/collision: ^4.2
- orchestra/testbench: ^5.0
- phpunit/phpunit: ^9.0
- symfony/var-dumper: ^5.0
This package is auto-updated.
Last update: 2022-12-29 03:07:36 UTC
README
Harness
Opinionated validation abstraction for a Laravel JSON:API that hopefully doesn't get in the way
ToDo
- Make default messages configurable
- Do not require feedback method
- Live happily ever after
Installation
You can install the package via composer (‼️ at least once it has been published to Packagist...):
$ composer require shabushabu/harness
Class Constants
The Harness request expects two class constants, ROUTE_PARAM
and JSON_TYPE
, to be present on your models. It's what allows Harness to automatically handle the form request authorization as well as packaging the request data into proper JSON:API format.
class Page extends Model { public const JSON_TYPE = 'pages'; public const ROUTE_PARAM = 'page'; }
ShabuShabu Abseil actually uses those same class constants and is a great match for Harness, so do look into it!
Usage
Any requests for JSON:API enabled endpoints should extend ShabuShabu\Harness\Request
.
We can then write our form requests like so:
namespace App\Http\Requests; use ShabuShabu\Harness\Request; use function ShabuShabu\Harness\r; class PageRequest extends Request { public function ruleset(): array { return [ 'attributes' => [ 'title' => r()->required()->string(), 'content' => r()->required()->string(), ], 'relationships' => [ 'category' => [ 'type' => r()->string(), 'id' => r()->uuid(), ], ], ]; } public function feedback(): array { return [ 'attributes' => [ 'title' => [ 'required' => 'The title is required', 'string' => 'The title must be a string', ], 'content' => [ 'required' => 'The content field is required', 'string' => 'The content field must be a string', ], ], 'relationships' => [...] ]; } }
Any request extending ShabuShabu\Harness\Request
must implement the ruleset
and feedback
methods, rather than your usual rules
and messages
methods.
Under the hood Harness then uses the rules
and messages
methods to weave together a proper request.
Both ruleset
and feedback
should return nested arrays and will automatically wrap everything up into a proper JSON:API validation resource like below:
[ 'data.attributes.title' => 'required|string', 'data.attributes.content' => 'required|string', 'data.relationships.category.id' => 'uuid', 'data.relationships.category.type' => 'string', ];
Harness ships with all the validation methods you're used to.
Just camel-case the rule name, use it as a method and hand it any parameters.
Additionally, Harness also adds latitude
and longitude
rules.
Adding rules
In addition to the fluent methods used so far you can also add rules by passing them to the r
function:
return [ 'attributes' => [ 'title' => r('required', 'string', 'uuid'), ], ];
If you have any rules that are not covered by Laravel, then you can still add them via the push
method:
return [ 'attributes' => [ 'title' => r()->push($rule), ], ];
You can also add them conditionally:
return [ 'attributes' => [ 'title' => r()->push($rule, $condition === true), ], ];
There are times when you only want to add rules for a given attribute based on a condition. Harness solves this issue like so:
return [ 'attributes' => [ 'title' => r()->string()->when($condition === true), 'content' => r()->string()->unless($condition === true), ], ];
Removing rules
To make a request reusable for various operations, like POST or PUT, Harness allows you to remove single rules, like so:
return [ 'attributes' => [ 'password' => r()->sometimes()->removeRule('sometimes'), ], ];
Or only remove them for a given condition:
return [ 'attributes' => [ 'password_1' => r()->sometimes()->removeRuleIf('sometimes', $condition === true), 'password_2' => r()->sometimes()->removeRuleUnless('sometimes', $condition === true), ], ];
The above could also be written like so, using some black voodoo magic:
return [ 'attributes' => [ 'password_1' => r()->sometimes()->removeSometimes(), 'password_2' => r()->sometimes()->removeSometimesIf($condition === true), 'password_3' => r()->sometimes()->removeSometimesUnless($condition === true), ], ];
Testing
$ composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email boris@shabushabu.eu instead of using the issue tracker.
‼️ Caveats
Harness is still young and while it is tested, there will probs be bugs. I will try to iron them out as I find them, but until there's a v1 release, expect things to go 💥.
Credits
- All Contributors
- BTT, aka Boris Travelled Today, where Harness was extracted from
- Ivan Boyko [cc] for the harness icon
License
The MIT License (MIT). Please see License File for more information.