konsulting / laravel-transformer
A simple way to transform data, with helpers for transforming data in Laravel applications.
Installs: 3 772
Dependents: 1
Suggesters: 1
Security: 0
Stars: 12
Watchers: 2
Forks: 0
Open Issues: 0
pkg:composer/konsulting/laravel-transformer
Requires
- php: ^8.0
- konsulting/laravel-extend-collections: ^0.2.0
Requires (Dev)
- illuminate/collections: ^11.0.0
- nesbot/carbon: ^2.0.0
- orchestra/testbench: ^9.0.0
- phpunit/phpunit: ^10.0.0
README
A simple way to transform data, with helpers for transforming data in Laravel applications.
Installation
- Install Transformer using composer:
composer require konsulting/laravel-transformer
Transformer in a Laravel application
- Transformer uses
Illuminate\Support\CollectionandIlluminate\Support\Arr, and requires a couple of extensions to these. The extensions are available in thekonsulting/laravel-extend-collectionspackage. - You'll need both the
CollectionsServiceProviderfrom that package, andTransformerServiceProviderin yourconfig/app.php.
If you are using Laravel 5.5, they will auto-register. However, if you have chosen not to auto-register,
or are using an earlier version, add the following to config/app.php
'providers' => [ // Other service providers... Konsulting\Laravel\CollectionsServiceProvider::class, Konsulting\Laravel\Transformer\TransformerServiceProvider::class, ],
- Optionally, add the Transformer Facade to
config/app.php
'aliases' => [ // Other aliases... 'Transformer' => Konsulting\Laravel\Transformer\TransformerFacade::class, ],
- Optionally publish the config file, and adjust the rule packs you want to use.
php artisan vendor:publish --provider=Konsulting\\Laravel\\Transformer\\TransformerServiceProvider --tag=config
Transformer outside a Laravel application
- Transformer uses
Illuminate\Support\CollectionandIlluminate\Support\Arr. Outside a Laravel application, it will usetighten/collect(an extraction of Collection && Arr from Laravel's Illuminate\Support) to get these dependencies. - Transform also requires a couple of extensions to these. The extensions are available in the
konsulting/laravel-extend-collectionspackage. You'll need to register the extensions manually. - You will need to build up your Transformer manually for use in your application.
// Basic example use Konsulting\Laravel\Transformer\Transformer; use Konsulting\Laravel\Transformer\RulePacks\CoreRulePack; use Konsulting\Laravel\Transformer\RulePacks\CarbonRulePack; require __DIR__ . '/../vendor/autoload.php'; // Extend Illuminate\Support\Arr and Illuminate\Support\Collection \Konsulting\Laravel\load_collection_extensions(); // Build up Transformer $transformer = new Transformer([CoreRulePack::class, CarbonRulePack::class]); // Transformer now available to use, see Usage
Usage
Transformer uses RulePacks to provide transformation functionality. RulePacks can be added to the Transformer during construction, or after with the addRulePack or addRulePacks methods.
A set of rules can be passed in during construction (useful when applying the same rules to different sets of data) or rules can be passed in at the point when performing transformation.
To transform data, the transform method is used. It accepts an array (or collection) of data to transform, and optionally rules to apply.
- Rules are presented in a similar manner to the Laravel Validator. They provide functionality to handle nested data, and follow the same string format.
- Arrays of rules are indexed by a field expression and provide a
|(pipe) delimited list of rules to apply. - Rules may be provided a set of parameters in CSV format. Field expressions may use
*as a wildcard to match elements at that depth and**as a special case to match everything. - Rule sequences are built up in the order they are provided.
// using the $transformer built up earlier $rules = [ '*' => 'drop_if_empty', 'name' => 'trim', 'contacts.*.name' => 'trim|uppercase' ]; $data = [ 0 => '', 'name' => ' Keoghan Litchfield ', 'contacts' => [ ['name' => 'Robin'], ['name' => 'Roger'], ['name' => ''], ], ]; $result = $transformer->transform($data, $rules); // Outputs [ // 'name' => 'Keoghan Litchfield', // 'contacts' => [ // ['name' => 'ROBIN'], // ['name' => 'ROGER'], // ], // ];
Transform helper
There is also a helper class Transform, which facilitates the easy transformation of a single value by one or more rules. Transform receives an instance of Transformer via its constructor, which provides the transformation logic and determines which rules are available.
Using the instance of Transformer built up previously:
use Konsulting\Laravel\Transformer\Transform; $transform = new Transform($transformer);
Rules may be called as methods on the Transform object, with the value to be transformed passed in as the first argument and any rule parameters as subsequent arguments.
$transform->trim(' Some string to be trimmed '); // Outputs 'Some string to be trimmed' $transform->regexReplace('testing', 'e', 'oa'); // Outputs 'toasting'
Alternatively, rules may be passed via the withRule() and withRules() methods (for singular and multiple rules respectively).
Rule parameters are passed either as separate arguments, or as an array.
// Single rule $transform->withRule(' test ', 'trim'); // Outputs 'test' // Single rule with parameters passed as separate arguments $transform->withRule('test', 'regex_replace', 'e', 'oa'); // Outputs 'toast' // Singe rule with parameters passed as an array $transform->withRule('test', 'regex_replace', ['e', 'oa']); // Outputs 'toast' as well // Multiple rules passed as a sequential array $transform->withRules(' test ', ['trim', 'uppercase']); // Outputs 'TEST' // Multiple rules and parameters passed as an assocative array: [$rule => [$param1, $param2], $rule2 => []...] $transform->withRules('--test--', [ // Outputs 'TOAST' 'trim' => ['-'], 'regex_replace' => ['e', 'oa'], 'uppercase' => [], ]);
Fluent API
Rules may also be called fluently: the input value is set with the input() method, and the result is obtained with get().
Any number of rule methods may be chained between these.
$transform->input(' hello ') ->trim() ->regexReplace('hello', 'world') ->uppercase() ->get(); // Outputs 'WORLD'
When the fluent API is used, the value is not passed as an argument to the rule methods (as it has already been set via input()).
As such, all arguments passed to rule methods are treated as rule parameters.
withRule() and withRules() may be used to fluently declare rules with or without parameters:
$transform->input($input) ->withRule('trim') ->uppercase() ->get(); $transform->input($input) ->lowercase() ->withRules(['trim', 'uppercase']) ->get();
Available Rules
We provide a couple of rule packs for use, it is easy to extend the rules available by creating your own Rule Pack. Rule Packs are loaded in the declared order, methods in later packs will override packs loaded earlier.
Parameter names are denoted by <param> and optional parameters by [<param>].
Core Rule Pack
Cleaning up
null_if_emptynull_if_empty_stringreturn_null_if_empty– equivalent tonull_if_empty|bail_if_null.return_null_if_empty_string– equivalent tonull_if_empty_string|bail_if_null.bail_if_nulldrop_if_nulldrop_if_emptydrop_if_empty_stringtrim:[<character(s)_to_trim>]– performs default PHP trim() if no characters supplied.
Casting
string- convert to string, an array is transformed to a CSV or returns ‘’ for items that cannot be represented as a string.booleanarraycollection- convert toIlluminate\Support\Collectionjsonfloatintegerdate_time:[timezone]date_time_immutable:[timezone]
String manipulation
uppercaselowercase
Regex and string replace
replace:<search_string>,<replace_string>regex_replace:<search_regex>,<replace_string>numericalphaalpha_dashalpha_numalpha_num_dash
Carbon Rule Pack
carbondate_format- parameter for the format required.
Related Fields Rule Pack
null_with:<key>drop_with:<key>bail_with:<key>null_without:<key>drop without:<key>bail_without:<key>
Number Rule Pack
clamp:<min>,<max>- constrain a number between two values
Note: key is a dot notation key for another field in the dataset
Laravel Helpers
We use Laravel frequently, so have a couple of extras added here.
Facade
Use the facade to gain easy access to the Transformer wherever you are.
\Transformer::transform($data, $rules);
Request Macro transform
The Service Provider adds the transform Macro to the Illuminate\Http\Request class. This makes it simple to invoke the transformation on a request at any point. The method passes the request object back to allow chaining.
// Example Controller namespace App\Http\Controllers; use App\ContactRequest; use Illuminate\Http\Request; class ContactRequestsController { // ... public function store(Request $request) { $request->transform([ 'name' => 'trim|uppercase', 'message' => 'trim', ]); $this->validate($request, [ 'name' => 'required', ]); return ContactRequest::create( $request->only('name', 'message') ); } }
TransformingRequest Trait
This trait makes the form request transform the data before validation occurs (which is upon it being resolved by the container).
Rules for transformation are provided in the transformRules method.
Using the TransformingRequest Trait
// Form Request namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; use Konsulting\Laravel\Transformer\TransformingRequest; class ContactFormRequest extends FormRequest { use TransformingRequest; // ... other methods including rules() public function transformRules() { return [ 'name' => 'trim|uppercase', 'message' => 'trim', ]; }
// Controller namespace App\Http\Controllers; use App\ContactRequest; use App\Http\Requests\ContactFormRequests; class ContactRequestsController { // ... public function store(ContactFormRequest $request) { return ContactRequest::create( $request->only('name', 'message') ); } }
Middleware
The TransformRequest middleware applies transformations to requests according to configured rules. These rules are specified in the middleware_rules key of the config file as detailed in Usage.
To register the middleware for use in your project, add the following line to your project's App/Http/Kernel.php:
'transform_data' => \Konsulting\Laravel\Transformer\Middleware\TransformRequest::class
The default middleware rules state that every field should be trimmed of whitespace and nulled if empty:
'middleware_rules' => [ '**' => 'trim|return_null_if_empty', ]
Rules need not be applied to all fields; specific fields may be targeted within the middleware if required:
'middleware_rules' => [ 'postcode' => 'uppercase', 'email' => 'lowercase', ]
With the above configuration, the postcode and email fields of every request sent through the middleware will be affected, but all other fields will be left unchanged.
Multiple transformer middlewares may be useful in a project: to achieve this, copy laravel-transformer/src/Middleware/TransformRequest.php to your project's App/Http/Middleware directory, and rename/edit as necessary. Each new middleware will have to be registered in the kernel.
Contributing
Contributions are welcome and will be fully credited. We will accept contributions by Pull Request.
Please:
- Use the PSR-2 Coding Standard.
- Add tests, if you’re not sure how, please ask.
- Document changes in behaviour, including readme.md.
Testing
We use PHPUnit and the excellent orchestral/testbench.
Run tests using PHPUnit: vendor/bin/phpunit