surgiie/转换器

一个用于PHP的数据转换/格式化包。

v0.4.0 2024-05-27 17:08 UTC

This package is auto-updated.

Last update: 2024-09-27 18:01:54 UTC


README

转换器是一个PHP包,用于转换值或输入,由Laravel框架的验证组件提供支持。

Tests

安装

composer require surgiie/transformer

使用

要使用此包,请传递您的数据和应通过的数据的可调用函数数组

<?php

use Closure;
use Illuminate\Support\Stringable;

// Example functions available at runtime:
function to_carbon($value)
{
    return new Carbon\Carbon($value);
}

function only_numbers($value)
{
    return preg_replace("/[^0-9]/",'',$value);
}

$input = [
  'first_name'=>'    jim    ',
  'last_name'=>'   thompson',
  'address'  => '123 some street',
  'phone_number'=>'123-456-7890',
  'date_of_birth'=>"1991-05-01",
];

$transformers = [
    'first_name'=>'trim|ucfirst',
    'last_name'=>'trim|ucfirst',
    'phone_number'=>'only_numbers',
    // more on object values and method delegation below
    'address' => [Stringable::class, '->after:123 ', '->toString'],
    'date_of_birth'=>'to_carbon|->format:m/d/y',
];

$transformer = new DataTransformer($input, $transformers);

$newData = $transformer->transform();
// Returns:
// [
//     "first_name" => "Jim",
//     "last_name" => "Thompson",
//     "phone_number" => "1234567890",
//     "address"=> "some street",
//     "date_of_birth" => "05/01/91",
// ]

注意,语法类似于Laravel验证语法,因为此包由相同的组件提供支持。

传递参数

您可以使用 <function>:<comma-delimited-list> 语法为您的函数指定参数

<?php

$transformers = [
    'example'=>'your_function:arg1,arg2',
];

指定值参数顺序

默认情况下,传递给您的函数的第一个参数将是正在格式化的值,然后是按提供的顺序指定的参数。如果您的函数不接受值作为第一个参数,您可以使用 :value: 占位符来指定顺序。例如

<?php

$input = ['phone_number'=>'123-456-3235'];
$transformers = [
    'example'=>'preg_replace:/[^0-9]/,,:value:',
];
$transformer = new DataTransformer($input, $transformers);
$transformer->transform();

转换参数

您可能会发现,在将参数传递给转换函数时,由于基本类型参数的类型提示,可能会遇到运行时错误。由于此处参数被指定为字符串,您可能会遇到以下情况

<?php

function example_function(int $value){
    return $value + 1;
}

$input = ['example'=>"1"];

$transformers = [
    'example'=>'example_function:1',
];

上述代码会抛出错误,因为传递的 1 参数是一个字符串,而函数期望一个整数。在这些情况下,您可以使用以下约定将参数转换为目标原生类型,通过在值后附加 @<type> 来完成。例如,将 1 转换为整数

<?php

function example_function(int $value){
    return $value + 1;
}

$input = ['example'=>"1"];

$transformers = [
    'example'=>'example_function:1@int', // "1" will  be casted to an int.
];

可用的转换类型

以下是一些基本转换类型:

  • int
  • str
  • float
  • bool
  • array
  • object

注意 对于更复杂类型或转换需求,请使用以下文档中所述的闭包或 Surgiie\Transformer\Contracts\Transformable 类。

可选转换

如果您只想在值不为null或"空"时进行转换,您可以在函数链中使用 ? 字符来指定何时退出处理。这通常放在链的开始处

<?php

$input = ['first_name'=>null];
$transformers = [
    'example'=>'?|function_one|function_two',
];
$transformer = new DataTransformer($input, $transformers);
$transformer->transform();

注意:此包使用Laravel的 blank 助手确定空白/空值。如果您有更复杂的退出规则逻辑,可以使用闭包或 \Surgiie\Transformer\Contracts\Transformable 类,并调用第二个参数的退出回调。

闭包和Transformable类

您可以使用闭包来转换您的值

<?php

$input = ['first_name'=>' Bob'];
$transformers = [
    'first_name'=>['trim', function ($value) {
        // modify the value
        return $value;
    }],
];
$transformer = new DataTransformer($input, $transformers);
$transformer->transform();

或者,您可以实现 Surgiie\Transformer\Contracts\Transformable 协议,并使用类实例

<?php

use Surgiie\Transformer\DataTransformer;
use Surgiie\Transformer\Contracts\Transformable;

class TransformValue implements Transformable
{
    public function transform($value, Closure $exit)
    {
        // quit transforming value(s)
        if($someCondition){
            $exit();
        }

        // or modify the value
        $value = "Changed";

        return $value;
    }
}

$input = ['first_name' => ' Bob'];
$transformers = [
    'first_name' => ['trim', new TransformValue],
];
$transformer = new DataTransformer($input, $transformers);
$transformer->transform();

数组输入

您还可以使用点表示法格式化嵌套数组数据

<?php

$input = [
    'contact_info'=>[
        'first_name'=>'    jim    ',
        'last_name'=>'   thompson',
        'phone_number'=>'123-456-7890',
        'address'=>'123 some lane.'
    ]
];
$transformers = [
    'contact_info.first_name'=>'trim|ucwords',
    'contact_info.last_name'=>'trim|ucwords',
    'contact_info.phone_number'=>'preg_replace:/[^0-9]/,,:value:',
    'contact_info.address'=>[function ($address) {
        return 'Address Is: '.$address;
    }],
];
$transformer = new DataTransformer($input, $transformers);
$transformer->transform();

通配符

您还可以在键上使用通配符来应用匹配通配符模式的转换器

<?php

$input = [
    'first_name'=>'    jim    ',
    'last_name'=>'   thompson',
    'ignored'=>' i-will-be-the-same'
];
$transformers = [
    // apply to all keys that contain "name"
    '*name*'=>'trim|ucwords',
];
$transformer = new DataTransformer($input, $transformers);
$transformer->transform();

对象值/方法委派

如果值已转换为实例,则可以将函数调用委派给对象。使用 -><methodName>:args 语法,您可以在该实例上指定方法链

<?php

use Closure;

class Example
{

    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function concat($string)
    {
        return $this->value . $string;
    }

}

function example($value)
{
    return new Example($value);
}


$input = [
  'string'=>"Foo",
];
$transformers = [
    'string'=>'example|->concat:Bar',
];

您还可以使用接受单个值作为构造函数参数的类常量,例如

<?php

$input = [
    'string'=>"Foo",
];
$transformers = [
    'string'=>[Example::class, '->concat:Bar'],
];

执行前保护层

默认情况下,所有在运行时可以调用的函数都将被执行。但是,如果您想添加一个保护或安全层,以阻止某些方法被调用,您可以通过返回 true 来添加一个守卫回调,检查方法是否应该被调用。

<?php

use Surgiie\Transformer\DataTransformer;
use Surgiie\Transformer\Transformer;

// accepts the function name being executed and the key/name of the input being processed:
Transformer::guard(function($method, $key){
    // only "trim" is allowed to be executed
    return in_array($method, ['trim']);
});

$input = [
    'first_name'=>'    jim    ',
];
$transformers = [
    'first_name'=>'trim|ucwords',
];

$transformer = new DataTransformer($input, $transformers);

// throws a Surgiie\Transformer\Exceptions\ExecutionNotAllowedException once it gets to ucwords due to the guard method.
$transformer->transform();

手动转换值/单个值

要格式化单个值,请使用 Transformer 类。

<?php

use Surgiie\Transformer\Transformer;

$transformer = new Transformer("   uncle bob   ", ['trim', 'ucwords']);

$transformer->transform(); // returns "Uncle Bob"

使用特性

要在类中即时转换数据和值,请使用 \Surgiie\Transformer\Concerns\UsesTransformer 特性。

<?php

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Surgiie\Transformer\Concerns\UsesTransformer;

class ExampleController extends Controller
{
    use UsesTransfomer;

    public function store(Request $request)
    {
        //...

        // transform a single value
        $newValue = $this->transform(" example  ", ['trim|ucwords']);
        // or transform an array of data
        $newData = $this->transformData(['example'=> 'data    '], ["example"=>'trim|ucwords']);
    }
}

使用请求宏

要在 Illuminate\Http\Request 对象实例上使用宏转换数据,请在请求上调用 transform() 方法,该方法返回转换后的数据。

public function store(Request $request)
{
    // Using data from the request object (i.e. `$request->all()`)
    $transformedData = $request->transform([
        'first_name' => ['strtoupper'],
    ]);

    // $transformedData['first_name'] will be all uppercase
    // all other data will be included from the request

    // You can also customize the input that is transformed,
    // in this case $transformedData will only have the `first_name` key.
    $transformedData = $request->transform($request->only(['first_name']), [
        'first_name' => ['strtoupper'],
    ]);
}

在调用 FormRequest 对象时,它使用 validated() 函数来检索输入数据。请注意,这要求您要针对的数据在表单请求的规则函数中定义为验证规则,否则数据将不会进行转换。

包发现/不发现

Laravel 会自动注册包服务提供者,但如果您不希望这样做,您可以通过在 composer.json 中包含以下内容来忽略服务提供者的包发现:

"extra": {
    "laravel": {
        "dont-discover": [
            "surgiie/transformer"
        ]
    }
}

贡献

以下方式始终欢迎贡献:

  • 讨论
  • 问题跟踪器
  • 拉取请求