数据传输对象
Testing Is Documentation
QueryPHP 提供了一个简单的数据传输对象组件。
Uses
php
<?php
use Leevel\Kernel\Utils\Api;
all 获取全部属性数据(下划线属性命名风格)
php
public function testAllUnCamelizeStyle(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => $dtoProp1 = new DtoProp1(),
'demoObject2Prop' => $dtoProp2 = new DtoProp2(),
'demoObject3Prop' => $dto2 = new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1->all();
self::assertSame('foo', $data['demo_string_prop']);
self::assertSame(1, $data['demo_int_prop']);
self::assertSame(1.5, $data['demo_float_prop']);
self::assertTrue($data['demo_true_prop']);
self::assertFalse($data['demo_false_prop']);
self::assertSame($dtoProp1, $data['demo_object_prop']);
self::assertSame($dtoProp2, $data['demo_object2_prop']);
self::assertSame($dto2, $data['demo_object3_prop']);
self::assertTrue($data['demo_mixed_prop']);
}
all 获取全部属性数据(驼峰属性命名风格)
php
public function testAllCamelizeStyle(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => $dtoProp1 = new DtoProp1(),
'demoObject2Prop' => $dtoProp2 = new DtoProp2(),
'demoObject3Prop' => $dto2 = new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1->all(false);
self::assertSame('foo', $data['demoStringProp']);
self::assertSame(1, $data['demoIntProp']);
self::assertSame(1.5, $data['demoFloatProp']);
self::assertTrue($data['demoTrueProp']);
self::assertFalse($data['demoFalseProp']);
self::assertSame($dtoProp1, $data['demoObjectProp']);
self::assertSame($dtoProp2, $data['demoObject2Prop']);
self::assertSame($dto2, $data['demoObject3Prop']);
self::assertTrue($data['demoMixedProp']);
}
默认忽略丢失的值
php
public function testDefaultIgnoreMissingValues(): void
{
$dto1 = new Dto1([
'demo_not_found' => 1,
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertSame('foo', $dto1->demo_string_prop);
}
strict 从数组或者数据传输对象创建不可变数据传输对象
php
public function testStrict(): void
{
$this->expectException(\UnexpectedValueException::class);
$this->expectExceptionMessage(
'Public properties `demo_not_found` of data transfer object `Tests\\Support\\Fixtures\\Dto1` was not defined.'
);
Dto1::strict([
'demo_not_found' => 1,
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
}
fromArray 从数组创建数据传输对象
php
public function testFromArray(): void
{
$dto1 = Dto1::fromArray([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1
->only(['demoIntProp', 'demoObject3Prop'])
->toArray()
;
self::assertSame([
'demo_int_prop' => 1,
'demo_object3_prop' => [
'demo_string_prop' => 'hello world',
],
], $data);
}
only 设置白名单属性
php
public function testOnly(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1
->only(['demoIntProp', 'demoObject3Prop'])
->toArray()
;
self::assertSame([
'demo_int_prop' => 1,
'demo_object3_prop' => [
'demo_string_prop' => 'hello world',
],
], $data);
}
only 设置白名单属性,合并默认白名单属性
php
public function testOnlyWithOnlyPropertys(): void
{
$dto1 = new DtoToArray([
'demoStringProp' => 'hello',
'demoIntProp' => 123456,
'demoIntOrStringProp' => 45,
]);
$data = $dto1->toArray();
self::assertSame([
'demo_int_prop' => 123456,
'demo_int_or_string_prop' => 45,
], $data);
$data = $dto1->only(['demoStringProp'])->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
'demo_int_prop' => 123456,
'demo_int_or_string_prop' => 45,
], $data);
}
only 设置白名单属性,覆盖默认白名单属性
php
public function testOnlyWithOnlyPropertysOverrideProperty(): void
{
$dto1 = new DtoToArray([
'demoStringProp' => 'hello',
'demoIntProp' => 123456,
'demoIntOrStringProp' => 45,
]);
$data = $dto1->toArray();
self::assertSame([
'demo_int_prop' => 123456,
'demo_int_or_string_prop' => 45,
], $data);
$data = $dto1->only(['demoStringProp'], true)->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
], $data);
}
except 设置黑名单属性
php
public function testExcept(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1
->except(
['demoIntProp', 'demoObject3Prop', 'demoObjectProp',
'demoObject3Prop', 'demo_false_prop', 'demo_object2_prop', ]
)
->toArray()
;
self::assertSame([
'demo_string_prop' => 'foo',
'demo_float_prop' => 1.5,
'demo_true_prop' => true,
'demo_mixed_prop' => true,
], $data);
}
except 设置黑名单属性,合并默认黑名单属性
php
public function testExceptWithExceptPropertys(): void
{
$dto1 = new DtoToArray2([
'demoStringProp' => 'hello',
'demoIntProp' => 123456,
'demoIntOrStringProp' => 45,
]);
$data = $dto1->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
], $data);
$data = $dto1->except(['demoStringProp'])->toArray();
self::assertSame([], $data);
}
except 设置黑名单属性,覆盖默认黑名单属性
php
public function testExceptWithExceptPropertysOverrideProperty(): void
{
$dto1 = new DtoToArray2([
'demoStringProp' => 'hello',
'demoIntProp' => 123456,
'demoIntOrStringProp' => 45,
]);
$data = $dto1->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
], $data);
$data = $dto1->except(['demo_int_prop'], true)->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
'demo_int_or_string_prop' => 45,
], $data);
}
withoutNull 设置转换数组时忽略 NULL 值
php
public function testWithoutNull(): void
{
$dto1 = new DtoToArray3([
'demoStringProp' => 'hello',
'demoIntProp' => 123456,
]);
$data = $dto1->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
'demo_int_prop' => 123456,
'demo_configal_int_prop' => null,
], $data);
$data = $dto1->withoutNull()->toArray();
self::assertSame([
'demo_string_prop' => 'hello',
'demo_int_prop' => 123456,
], $data);
}
toArray 对象转数组(下划线属性命名风格)
php
public function testToArrayUnCamelizeStyle(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => $dtoProp2 = new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1->toArray();
self::assertSame('foo', $data['demo_string_prop']);
self::assertSame(1, $data['demo_int_prop']);
self::assertSame(1.5, $data['demo_float_prop']);
self::assertTrue($data['demo_true_prop']);
self::assertFalse($data['demo_false_prop']);
self::assertSame(['demo1' => 'hello', 'demo2' => 'world'], $data['demo_object_prop']);
self::assertSame($dtoProp2, $data['demo_object2_prop']);
self::assertSame(['demo_string_prop' => 'hello world'], $data['demo_object3_prop']);
self::assertTrue($data['demo_mixed_prop']);
}
toArray.camelizeNamingStyle 对象转数组(驼峰属性命名风格)
php
public function testToArrayCamelizeStyle(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => $dtoProp2 = new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$data = $dto1->camelizeNamingStyle()->toArray();
self::assertSame('foo', $data['demoStringProp']);
self::assertSame(1, $data['demoIntProp']);
self::assertSame(1.5, $data['demoFloatProp']);
self::assertTrue($data['demoTrueProp']);
self::assertFalse($data['demoFalseProp']);
self::assertSame(['demo1' => 'hello', 'demo2' => 'world'], $data['demoObjectProp']);
self::assertSame($dtoProp2, $data['demoObject2Prop']);
self::assertSame(['demoStringProp' => 'hello world'], $data['demoObject3Prop']);
self::assertTrue($data['demoMixedProp']);
}
toArray 对象转数组带有白名单属性设置
php
public function testToArrayWithOnlyPropertys(): void
{
$dto1 = new DtoToArray([
'demoStringProp' => 'hello',
'demoIntProp' => 123456,
'demoIntOrStringProp' => 45,
]);
$data = $dto1->toArray();
self::assertSame([
'demo_int_prop' => 123456,
'demo_int_or_string_prop' => 45,
], $data);
}
数据传输对象属性数组访问 ArrayAccess.offsetExists 支持
php
public function testOffsetExists(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertTrue(isset($dto1['demo_string_prop']));
self::assertTrue(isset($dto1['demoStringProp']));
}
数据传输对象属性数组访问 ArrayAccess.offsetSet 支持
php
public function testOffsetSet(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$dto1['demo_string_prop'] = 'hello_world';
self::assertSame('hello_world', $dto1['demo_string_prop']);
self::assertSame('hello_world', $dto1['demoStringProp']);
$dto1['demo_string_prop'] = 'hello_world2';
self::assertSame('hello_world2', $dto1['demo_string_prop']);
self::assertSame('hello_world2', $dto1['demoStringProp']);
}
数据传输对象属性数组访问 ArrayAccess.offsetGet 支持
php
public function testOffsetGet(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertSame('foo', $dto1['demo_string_prop']);
self::assertSame('foo', $dto1['demoStringProp']);
}
数据传输对象属性数组访问 ArrayAccess.offsetUnset 支持
php
public function testOffsetUnset(): void
{
$this->expectException(\TypeError::class);
$this->expectExceptionMessage(
'Cannot assign null to property Tests\Support\Fixtures\Dto1::$demoStringProp of type string'
);
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertSame('foo', $dto1['demo_string_prop']);
self::assertSame('foo', $dto1['demoStringProp']);
unset($dto1['demo_string_prop']);
}
数据传输对象属性访问魔术方法 __isset 支持
php
public function testMagicIsset(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertTrue(isset($dto1->demo_string_prop));
self::assertTrue(isset($dto1->demo_int_prop));
}
数据传输对象属性访问魔术方法 __set 支持
php
public function testMagicSet(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertSame('foo', $dto1->demo_string_prop);
$dto1->demo_string_prop = 'hello';
self::assertSame('hello', $dto1->demo_string_prop);
}
数据传输对象属性访问魔术方法 __get 支持
php
public function testMagicGet(): void
{
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
self::assertSame('foo', $dto1->demo_string_prop);
}
实体属性访问魔术方法 __unset 支持
php
public function testMagicUnset(): void
{
$this->expectException(\TypeError::class);
$this->expectExceptionMessage(
'Cannot assign null to property Tests\Support\Fixtures\Dto1::$demoStringProp of type string'
);
$dto1 = new Dto1([
'demo_string_prop' => 'foo',
'demoIntProp' => 1,
'demoFloatProp' => 1.5,
'demoObjectProp' => new DtoProp1(),
'demoObject2Prop' => new DtoProp2(),
'demoObject3Prop' => new Dto2(['demoStringProp' => 'hello world']),
]);
$dto1->demo_string_prop = null;
}
初始化默认值填充方法
php
namespace Tests\Support\Fixtures;
use Leevel\Support\Dto;
class Dto3 extends Dto
{
public string $demoStringProp;
protected function demoStringPropDefaultValue(): string
{
return 'hello world';
}
}
php
public function test2(): void
{
$dto = new Dto3();
self::assertSame('hello world', $dto->demoStringProp);
}
初始化转换数据方法
php
namespace Tests\Support\Fixtures;
use Leevel\Support\Dto;
class Dto4 extends Dto
{
public string $demoStringProp;
protected function demoStringPropTransformValue(int $value): string
{
return (string) $value;
}
}
php
public function test3(): void
{
$dto = new Dto4(['demoStringProp' => 123456]);
self::assertSame('123456', $dto->demoStringProp);
}
初始化内置转换数据方法
php
namespace Tests\Support\Fixtures;
use Leevel\Support\Dto;
class Dto6 extends Dto
{
public int $int1 = 0;
public string $string2 = '';
public float $float3 = 0.0;
public bool $bool4 = true;
public array $array5 = [];
}
php
public function test5(): void
{
$dto = new Dto6([
'int1' => 'string',
'string2' => 123456,
'float3' => 'world',
'bool4' => 0,
'array5' => 'hello',
]);
self::assertSame(0, $dto->int1);
self::assertSame('123456', $dto->string2);
self::assertSame(0.0, $dto->float3);
self::assertFalse($dto->bool4);
self::assertSame(['hello'], $dto->array5);
}