轻量级实用PHP值对象集合

v3.0.7 2024-05-22 15:57 UTC

README

PHP 8.1缺少数据类型。高度可扩展,已生产测试。

MIT license Latest release Downloads

Build Status Code coverage CodeClimate

永无止境的数据验证会让人筋疲力尽。要么你必须反复在每个使用它的函数中验证你的数据,要么你必须依赖它已经被其他地方验证过,并承担潜在问题的风险。

难闻,对吧?

Types取代验证地狱将使你的代码更易于阅读且更不容易出错。

Types将你的数据包裹在保证为有效和标准化;或者根本不存在的值对象中。它允许你使用特定类型提示而不是原始类型或数组。你的代码将坚不可摧,IDE也会喜欢它。

目录

安装

推荐安装方式是通过Composer

composer require smartemailing/types

它是如何工作的

这很简单。你只需用一行简单的代码初始化所需的值对象。从这一点开始,你就有干净、规范和有效的数据;或者处理 SmartEmailing\Types\InvalidTypeException

Types由以下部分组成

  • 可提取字符串的类型 - 验证过的字符串(电子邮件地址、域名、十六进制字符串等)
  • 可提取整数的类型 - 验证过的整数(端口)
  • 可提取浮点数的类型 - 验证过的浮点数(SigmoidValue、Part等)
  • 可提取枚举的类型 - 枚举(CountryCode、CurrencyCode、GDPR的法律依据等)
  • 复合(可提取数组)的类型 - 包含多个其他类型的结构(地址等)
  • 日期时间 - DateTime和DateTimeImmutable的提取
  • 原始类型提取器和唯一数组

不同类型提供与它们相关联的不同方法,但所有类型都共享这个提取API

包装原始值

<?php

declare(strict_types = 1);

use SmartEmailing\Types\Emailaddress;
use SmartEmailing\Types\InvalidTypeException;

// Valid input

$emailaddress = Emailaddress::from('hello@gmail.com'); // returns Emailaddress object
$emailaddress = Emailaddress::from($emailaddress); // returns original $emailaddress

// Invalid input

$emailaddress = Emailaddress::from('bla bla'); // throws InvalidTypeException
$emailaddress = Emailaddress::from(1); // throws InvalidTypeException
$emailaddress = Emailaddress::from(false); // throws InvalidTypeException
$emailaddress = Emailaddress::from(null); // throws InvalidTypeException
$emailaddress = Emailaddress::from([]); // throws InvalidTypeException
$emailaddress = Emailaddress::from(new \StdClass()); // throws InvalidTypeException

// Nullables

$emailaddress = Emailaddress::fromOrNull(null); // returns NULL
$emailaddress = Emailaddress::fromOrNull('bla bla'); // throws InvalidTypeException
$emailaddress = Emailaddress::fromOrNull('bla bla', true); // returns null instead of throwing

从数组中提取

这对于严格类型(验证)的多维数组非常有用,例如API请求、表单或数据库数据。

<?php

use SmartEmailing\Types\Emailaddress;
use SmartEmailing\Types\InvalidTypeException;

$input = [
	'emailaddress' => 'hello@gmail.com',
	'already_types_emailaddress' => Emailaddress::from('hello2@gmail.com'),
	'invalid_data' => 'bla bla',
];

// Valid input

$emailaddress = Emailaddress::extract($input, 'emailaddress'); // returns Emailaddress object
$emailaddress = Emailaddress::extract($input, 'already_types_emailaddress'); // returns original Emailaddress object

// Invalid input

$emailaddress = Emailaddress::extract($input, 'invalid_data'); // throws InvalidTypeException
$emailaddress = Emailaddress::extract($input, 'not_existing_key'); // throws InvalidTypeException

// Nullables 

$emailaddress = Emailaddress::extractOrNull($input, 'not_existing_key'); // returns null
$emailaddress = Emailaddress::extractOrNull($input, 'invalid_data'); //  throws InvalidTypeException
$emailaddress = Emailaddress::extractOrNull($input, 'invalid_data', true); // returns null instead of throwing

// Default values
$emailaddress 
	= Emailaddress::extractOrNull($input, 'not_existing_key') 
	?? Emailaddress::from('default@domain.com'); 
	// uses null coalescing operator to assign default value if key not present or null

$emailaddress 
	= Emailaddress::extractOrNull($input, 'not_existing_key', true) 
	?? Emailaddress::from('default@domain.com'); 
	// uses null coalescing operator to assign default value if key not present or null or invalid

可字符串提取的类型

可提取字符串的类型基于验证过的字符串。所有值在验证之前都会被修剪。

它们可以通过字符串类型转换或调用 $type->getValue() 轻松转换回字符串。

电子邮件地址

SmartEmailing\Types\Emailaddress

小写和ASCII转换的电子邮件地址(hello@gmail.com

类型特定方法

  • getLocalPart() : string 返回电子邮件地址的本地部分(hello
  • getDomain() : \SmartEmailing\Types\Domain 返回域名部分(gmail.com,表示为Types\Domain

非空字符串

SmartEmailing\Types\NonEmptyString

去除空白的非空字符串。

域名

SmartEmailing\Types\Domain

小写域名(mx1.googlemx.google.com

类型特定方法

  • getSecondLevelDomain() : \SmartEmailing\Types\Domain 返回二级域名(google.com

十六进制32

SmartEmailing\Types\Hex32

32个字符长的小写十六进制字符串,用作MD5或UUID的容器,不带连字符。(741ecf779c9244358e6b85975bd13452)

十六进制颜色

SmartEmailing\Types\HexColor

7个字符长的大写字符串,用作颜色的容器。(#006EDB

GUID

SmartEmailing\Types\Guid

带连字符的小写Guid(741ecf77-9c92-4435-8e6b-85975bd13452

IP地址

SmartEmailing\Types\IpAddress

IP地址v4或v6。(127.0.0.1[2001:0db8:0a0b:12f0:0000:0000:0000:0001]2001:db8:a0b:12f0::1

类型特定方法

  • getVersion() : int 返回IP地址版本,46

URL

SmartEmailing\Types\UrlType

基于Nette\Http\Url的URL(https://www.google.com/search?q=all+work+and+no+play+makes+jack+a+dull+boy

  • 字符串中的所有空格都被url编码
  • 所有非ASCII字符都被url编码

类型特定方法

  • getAuthority() : string 返回授权(www.google.com
  • getHost() : string 返回主机(www.google.com
  • getQueryString() : string 返回查询字符串(q=all%20work%20and%20no%20play%20makes%20jack%20a%20dull%20boy
  • getPath() : string 返回URL路径(/search
  • getAbsoluteUrl() : string 完整URL作为string,为getValue()的别名
  • getQueryParameter(string $name, mixed $default = null): mixed 返回参数$name的值
  • getBaseUrl(): string 返回不带路径、查询字符串和哈希部分的URL(https://www.google.cz/
  • getScheme(): string 返回URL方案(https
  • hasParameters(string[] $names): bool 如果URL参数包含在$names数组中定义的所有参数,则返回true
  • getParameters(): array 返回所有URL参数作为字符串索引数组
  • withQueryParameter(string $name, mixed $value): UrlType 返回添加了查询参数的新实例

公司注册号

SmartEmailing\Types\CompanyRegistrationNumber

以下国家的空白免费公司注册号:CZSKCY

电话号码

SmartEmailing\Types\PhoneNumber

以下国家的空白国际格式电话号码:CZSKATBEFRHUGBDEUSPLITSESIMHNLCYIEDKFILUTR

类型特定方法

  • getCountry() : SmartEmailing\Types\CountryCode 原始国家(CZ

邮编

SmartEmailing\Types\ZipCode

以下国家的空白ZIP代码有效:CZSKUKUS

JSON

SmartEmailing\Types\JsonString

有效的JSON编码数据作为字符串

类型特定方法

  • static from(mixed $data) : SmartEmailing\Types\JsonString 接受字符串或数组。从有效的JSON字符串或原始数据(数组)创建JsonString
  • static encode(mixed $data) : SmartEmailing\Types\JsonString 从原始数据(数组)创建JsonString
  • getDecodedValue() : mixed 将JsonString解码回原始数据

Base 64

SmartEmailing\Types\Base64String

有效的Base 64编码数据作为字符串

类型特定方法

  • static encode(string $value) : SmartEmailing\Types\Base64String 从字符串创建Base64String
  • getDecodedValue() : string 将Base64String解码回原始字符串

Iban

SmartEmailing\Types\Iban

类型特定方法

  • getFormatted(string $type = SmartEmailing\Types\Iban::FORMAT_ELECTRONIC): string 返回格式化的Iban字符串。格式类型:FORMAT_ELECTRONICFORMAT_PRINT
  • getCountry(): SmartEmailing\Types\CountryCode
  • getChecksum(): int

SwiftBic

SmartEmailing\Types\SwiftBic

有效的Swift/Bic代码。

VatId

SmartEmailing\Types\VatId

类型特定方法

  • static isValid(string $vatId): bool 如果增值税ID有效则返回true,否则返回false
  • getCountry(): ?Country 返回主题应归属的国家,或null。
  • getPrefix(): ?string 返回增值税ID的前缀字符串,如从EL123456789中的EL,或null。
  • getVatNumber(): string 返回不带前缀的增值税号,如123456789
  • getValue(): string 返回整个增值税ID EL123456789

CurrencyCode

SmartEmailing\Types\CurrencyCode

有效的ISO 4217货币代码

CountryCode

SmartEmailing\Types\CountryCode

有效的ISO 3166-1 alpha-2国家代码

可提取整数的类型

可提取整数的类型基于已验证的整数。

它们可以通过int类型转换或调用$type->getValue()轻松地转换回int。

端口

SmartEmailing\Types\Port

端口号

整数区间,<0, 65535>

数量

SmartEmailing\Types\Quantity

物品数量

整数区间,<1, PHP_INT_MAX>

无符号整数

SmartEmailing\Types\UnsignedInt

无符号整数

整数区间,<0, PHP_INT_MAX>

可提取浮点数的类型

可提取浮点数的类型基于已验证的浮点数。

它们可以通过float类型转换或调用$type->getValue()轻松地转换回float。

部分

SmartEmailing\Types\Part

整体的部分

浮点数区间 <0.0, 1.0>

类型特定方法

  • static fromRatio(float $value, float $whole): Part 通过除以$value$whole创建新的实例。
  • getPercent(): float 返回(比率值) * 100以获取百分比表示

sigmoid函数值

SmartEmailing\Types\SigmoidValue

sigmoid函数的结果,当构建神经网络时非常有用。

浮点数区间 <-1.0, 1.0>.

整流线性单元函数值

SmartEmailing\Types\ReLUValue

ReLU函数的结果,当构建神经网络时非常有用。

浮点数区间 <0.0, Infinity).

无符号浮点数

SmartEmailing\Types\UnsignedFloat

无符号浮点数

浮点数区间,<0, PHP_FLOAT_MAX>

可提取数组的类型

可提取数组类型是封装一个或多个其他类型的复合类型。它们从关联数组创建。所有可提取数组类型都实现方法toArray() : array,该方法返回标准化数组或类型的原始数据。

DateTimeRange

SmartEmailing\Types\DateTimeRange

两个\DateTimeInterface之间的范围。对于超出Unix时间戳范围的日期时间,也是安全的。

可以从以下内容创建

DateTimeRange::from(
	[
		'from' => 'YYYY-MM-DD HH:MM:SS',
		'to' => 'YYYY-MM-DD HH:MM:SS',
	]
)

类型特定方法

  • getFrom(): \DateTimeImmutable 返回From日期和时间作为\DateTimeImmutable实例
  • getTo(): \DateTimeImmutable 返回To日期和时间作为\DateTimeImmutable实例
  • getDurationInSeconds(): int 返回FromTo日期之间的秒数
  • contains(\DateTimeInterface $dateTime): bool 如果提供的\DateTimeInterface位于FromTo日期之间,则返回true
  • getLengthInSeconds(): int 返回持续时间长度(以秒为单位)

持续时间

SmartEmailing\Types\Duration

人类可读的时间间隔。

可以从以下内容创建

Duration::from(
	[
		'value' => 1,
		'unit' => TimeUnit::HOURS,
	]
);

Duration::from(
	'1 hours'
);

类型特定方法

  • getDateTimeModify(): string 返回与\DateTime::modify()\DateTimeImmutable::modify()兼容的字符串
  • getUnit(): TimeUnit 返回TimeUnit枚举类型
  • getValue() int 返回单位数量
  • static fromDateTimeModify(string $dateTimeModify): self 从与\DateTime::modify()\DateTimeImmutable::modify()兼容的字符串创建新的实例

地址

SmartEmailing\Types\Address

地址位置包含街道和编号、镇、邮编和国家。

可以从以下内容创建

Address::from(
	[
		'street_and_number' => '29 Neibolt Street',
		'town' => 'Derry',
		'zip_code' => '03038',
		'country' => 'US',
	]
);

类型特定方法

  • getStreetAndNumber(): string 返回街道和编号
  • getTown(): string 返回镇
  • getZipCode(): ZipCode 返回ZipCode实例
  • getCountry(): CountryCode 返回CountryCode实例

价格

SmartEmailing\Types\Price

包含带税和不含税的货币单位数量以及货币的价格对象。

可以从以下内容创建

Price::from(
	[
		'with_vat' => 432.1,
		'without_vat' => 123.45,
		'currency' => CurrencyCode::EUR,
	]
);

类型特定方法

  • getWithoutVat(): float 返回不含增值税的价格
  • getWithVat(): float 返回含增值税的价格
  • getCurrency(): CurrencyCode 返回CurrencyCode实例

登录凭证

SmartEmailing\Types\LoginCredentials

包含登录和明文密码的值对象。您应在认证过程中仅将其存储在内存中,然后丢弃。

可以从以下内容创建

LoginCredentials::from(
	[
		'login' => 'admin',
		'password' => 'BLzW75kJxEa7YXuqF9Di',
	]
);

类型特定方法

  • getLogin(): string 返回登录名
  • getPassword(): string 返回密码

键值对

SmartEmailing\Types\KeyValue

包含字符串键和字符串值的值对象。

可以从以下内容创建

KeyValuePair::from(
	[
		'key' => 'overlook',
		'value' => 'all_work_and_no_play_makes_jack_a_dull_boy',
	]
);

类型特定方法

  • getKey(): string 返回键
  • getValue(): string 返回值

标量数组叶

SmartEmailing\Types\ScalarLeavesArray

包含单维或多维数组,其叶仅包含标量或NULL值的值对象。数组键保持不变。

可以从以下内容创建

ScalarLeavesArray::from(
	[
		[
			'a',
		],
		[
			1,
		],
		[
			'b',
			[
				true,
				[
					null,
				],
				[],
			],
		],
	]
);

针对数组类型特定的提取器

  • static extractOrEmpty(array $data, string $key): self 类似于标准 ::extract() 方法,但当 $data[$key]null 或未设置时,返回空的ScalarLeavesArray。

数组类型

Types 提供另一种类型的可提取数组:唯一的基本类型数组。它们的目的在于持有唯一的基本类型集合。它们实现 \Countable\IteratorAggregate,并原生支持集合操作。

所有数组类型共享以下功能

  • static empty() : self 创建所需数组类型的新空实例。
  • split(int $chunkSize): self[] 将当前实例分割成多个实例的数组,每个实例的数据集大小最大为 $chunkSize
  • merge(self $toBeMerged): self 返回一个新的实例,其中数据集由父实例和 $toBeMerged 实例的数据集组合而成。两个源实例保持不变。
  • deduct(self $toBeDeducted): self 返回一个新的实例,其中数据集包含所有在父实例中但不在 $toBeDeducted 中的项。两个源实例保持不变。
  • count(): int 返回数据集大小。
  • isEmpty(): bool 如果数据集为空,则返回 true,否则返回 false

针对数组类型特定的提取器

  • static extractOrEmpty(array $data, string $key): self 类似于标准 ::extract() 方法,但当 $data[$key]null 或未设置时,返回空集合。
  • static extractNotEmpty(array $data, string $key): self 类似于标准 ::extract() 方法,但当 $data[$key] 未设置、为 null 或为空数组时,抛出 InvalidTypeException

UniqueIntArray

SmartEmailing\Types\UniqueIntArray

UniqueIntArray 能够存储唯一的整数集合。

可以从以下内容创建

// duplicate values will be discarted
// keys are ignored

UniqueIntArray::from(
	[
		1, 2, 2, 3, 3, 3, 4 
	]
);

类型特定方法

  • getValues(): int[] 将唯一整数的集合作为数组返回。
  • toArray(): int[]getValues() 的别名。
  • add(int $id): bool 将另一个整数添加到数据集中。如果整数已经存在,则返回 false
  • remove(int $id): void 如果存在,则从数据集中删除整数。
  • contains(int $id): bool 如果 $id 包含在数据集中,则返回 true,否则返回 false

UniqueStringArray

SmartEmailing\Types\UniqueIntArray

UniqueStringArray 能够存储唯一的字符串集合。

可以从以下内容创建

// duplicate values will be discarted
// keys are ignored

UniqueStringArray::from(
	[
		'a', 
		'b', 
		'c', 
		'all work and no play makes jack a dull boy',
		'all work and no play makes jack a dull boy',
		'all work and no play makes jack a dull boy',
	]
);

类型特定方法

  • getValues(): string[] 将唯一字符串的集合作为数组返回。
  • toArray(): string[]getValues() 的别名。
  • add(string $id): bool 将另一个字符串添加到数据集中。如果字符串已经存在,则返回 false
  • remove(string $id): void 如果存在,则从数据集中删除字符串。
  • contains(string $id): bool 如果 $id 包含在集合中,则返回 true,否则返回 false

可提取枚举的类型

可枚举提取类型是可以包含定义集合中单个值的类型。它们基于 kkk

所有可枚举提取类型共享以下功能

  • getValue() : string 返回枚举值
  • equals(self $enum): bool 如果 $enum 包含与父相同的值,则返回 true
  • equalsValue(string $value): self 如果父包含与 $value 相同的值,则返回 true

枚举可以使用标准提取器或使用它们的常量来创建。

CurrencyCode::from(
	CurrencyCode::EUR
);
CurrencyCode::from(
	'EUR'
);

数据处理的法律依据

SmartEmailing\Types\LawfulBasisForProcessing

GDPR的处理法律依据

可用值

国家代码

SmartEmailing\Types\CountryCode

ISO-3166-1 Alpha 2国家代码

可用值

货币代码

SmartEmailing\Types\CurrencyCode

ISO-4217三位货币代码

可用值

适用领域

SmartEmailing\Types\FieldOfApplication

人类应用中最常见的领域。

可用值

时间单位

SmartEmailing\Types\TimeUnit

\DateTime::modify()参数格式兼容的时间单位

可用值

关系

SmartEmailing\Types\Relation

表示关系或门 - AND / OR

可用值

原始类型和数组

类型可以通过使用IntTypeIntArrayFloatTypeFloatArrayStringTypeStringArrayBoolTypeBoolArrayArray类来获取和提取原始类型。以下是一些示例

<?php

declare(strict_types = 1);

use SmartEmailing\Types\Arrays;
use SmartEmailing\Types\BoolArray;
use SmartEmailing\Types\BoolType;
use SmartEmailing\Types\FloatArray;
use SmartEmailing\Types\FloatType;
use SmartEmailing\Types\IntArray;
use SmartEmailing\Types\IntType;
use SmartEmailing\Types\StringArray;
use SmartEmailing\Types\StringType;
use SmartEmailing\Types\InvalidTypeException;

IntType::from(666); // 666
IntType::from('666'); // 666
IntType::from(666.1); // throws InvalidTypeException
IntType::from('abcd'); // throws InvalidTypeException
IntType::from('abcd'); // throws InvalidTypeException
IntType::fromOrNull(null); // null
IntType::fromOrNull(1); // 1
IntType::fromOrNull('abcd'); // throws InvalidTypeException
IntType::fromOrNull('abcd', true); // null

FloatType::from(1.1); // 1.1
FloatType::from('1.1'); // 1.1
FloatType::from(1); // 1.0
FloatType::from('1'); // 1.0
FloatType::from('xxx'); // throws InvalidTypeException
FloatType::fromOrNull(null); // null
FloatType::fromOrNull(1.0); // 1.0
FloatType::fromOrNull('abcd'); // throws InvalidTypeException
FloatType::fromOrNull('abcd', true); // null

StringType::from('xxx'); // 'xxx'
StringType::from(5); // '5'
StringType::from(5.0); // '5'
StringType::from(5.1); // '5.1'
StringType::fromOrNull(null); // null
StringType::fromOrNull('abcd'); // 'abcd'
StringType::fromOrNull([]); // throws InvalidTypeException
StringType::fromOrNull([], true); // null

BoolType::from(true); // true
BoolType::from(false); // false
BoolType::from(1); // true
BoolType::from(0); // false
BoolType::from('1'); // true
BoolType::from('0'); // false
BoolType::from('true'); // true
BoolType::from('false'); // false

Arrays::from([1, 2]); // [1, 2]
Arrays::from([1, 'abcd']); // [1, 'abcd']

IntArray::from([1, '2']); // [1, 2]
IntArray::fromOrNull([1, '2']); // returns int[]|null

FloatArray::from([1, '2']); // [1.0, 2.0]
FloatArray::fromOrNull([1, '2']); // returns float[]|null

StringArray::from([1, '2']); // ['1', '2']
StringArray::fromOrNull([1, '2']); // returns string[]|null

BoolArray::from([1, '1']); // [true, true]
BoolArray::fromOrNull([1, '1']); // returns bool[]|null

// All primitive types have their extract equivalent:

IntType::extract($data, 'key');
IntType::extractOrNull($data, 'key');
IntType::extractOrNull($data, 'key', true);

StringType::extract($data, 'key');
StringType::extractOrNull($data, 'key');
StringType::extractOrNull($data, 'key', true);

FloatType::extract($data, 'key');
FloatType::extractOrNull($data, 'key');
FloatType::extractOrNull($data, 'key', true);

Arrays::extract($data, 'key'); //returns mixed[]
Arrays::extractOrNull($data, 'key'); //returns mixed[]|null

IntArray::extract($data, 'key'); //returns int[]
IntArray::extractOrNull($data, 'key'); //returns int[]|null

FloatArray::extract($data, 'key'); //returns float[]
FloatArray::extractOrNull($data, 'key'); //returns float[]|null

StringArray::extract($data, 'key'); //returns string[]
StringArray::extractOrNull($data, 'key'); //returns string[]|null

BoolArray::extract($data, 'key'); //returns bool[]
BoolArray::extractOrNull($data, 'key'); //returns bool[]|null

DateTime和DateTimeImmutable

类型可以通过使用DateTimesDateTimesImmutable类来获取和提取\DateTime\DateTimeImmutable对象。支持的格式为Y-m-d H:s:i。API与其他类型相同,所以可用的方法是(以下为DateTimes

  • from(string $dateTime ) : \DateTime
  • extract(array $data, string $index) : \DateTime
  • extractOrNull(array $data, string $index, bool $getNullIfInvalid) : ?\DateTime

Date和DateImmutable

类型可以通过使用DatesDatesImmutable类来获取和提取\DateTime\DateTimeImmutable对象。日期是在00:00:00的时间设置上创建的。支持的格式为Y-m-d。API与其他类型相同,所以可用的方法是(以下为Dates

  • from(string $dateTime ) : \DateTime
  • extract(array $data, string $index) : \DateTime
  • extractOrNull(array $data, string $index, bool $getNullIfInvalid) : ?\DateTime

如何编写自己的类型

实现您自己的自定义类型很容易!首先,您必须决定您的新自定义类型应该是什么可提取类型,并在它的类中使用特定的可提取特征来增强它。接下来,您要做的唯一一件事是实现类构造函数,并在数据无效的情况下抛出InvalidTypeException。您可以在以下每个可提取类型中看到示例。

还有一个想法 - 如果您认为您的新类型对其他人有用,请,请做出贡献!

如何贡献

感谢您对改进类型的兴趣!️ ❤️ 🖖

在您打开pull request之前,请确保您没有忘记为您的代码编写测试

然后运行以下命令

  1. vendor/bin/tester tests 在本地运行测试。只需两秒钟即可完成 :-)

  2. bin/cbf 这将检查代码并自动修复一些代码样式问题,如缩进或换行符。

  3. bin/cs 这将运行另一个代码样式检查,将通知您有关必须手动解决的问题。请修复它们,然后重新运行命令。

  4. bin/stan PHP静态分析工具 - 这将检查代码是否存在一些应该重构的“脏”构造。请修复它们,然后重新运行命令。

  5. PR准备就绪!

我们在招聘

你喜欢我们的代码吗?如果你想成为SmartEmailing的一部分,我们正在招聘