beeyev/value-objects-php

PHP的不可变值对象,专为领域驱动设计(DDD)设计。通过具有表达性、可靠性和可维护性的代码来增强您的应用程序。

v2.0.1 2024-07-02 20:33 UTC

README

Latest Version on Packagist Supported PHP Versions

ℹ️ 简介

此包提供了一组不可变值对象,您可以在PHP应用程序中使用。

值对象是领域驱动设计(DDD)的一个关键概念。
它们是简单的对象,其等价性基于其值而不是其身份。
使用值对象可以帮助您编写更具有表达性、可靠性和可维护性的代码。

🧾 使用值对象的好处

  • 不可变性:确保对象在其生命周期内保持一致。
  • 表达性:自然表示领域概念。
  • 验证:封装验证逻辑,减少错误。
  • 可重用性:促进DRY原则。
  • 易于测试:自包含且易于测试。

📎 为什么使用值对象而不是原始数据类型

  • 验证:❗ 保证数据有效。
  • 自文档化代码:增强可读性。
  • 封装:包含与值相关的逻辑。
  • 一致性:确保数据处理的统一性。
  • 易于重构:集中更改逻辑或验证规则。

📦 安装

使用Composer安装此包。运行以下命令

composer require beeyev/value-objects-php

▶️ 使用

以下是使用此包提供的值对象的示例

电子邮件

use Beeyev\ValueObject\Email;

$email = new Email('abc@gmail.com');
echo $email->value;    // Output: 'abc@gmail.com'
echo $email->username; // Output: 'abc'
echo $email->domain;   // Output: 'gmail.com'

URL

use Beeyev\ValueObject\Url;

$url = new Url('https://example.com');
echo $url->value;   // Output: 'https://example.com'

// Every value object can be cast to a string
echo (string) $url; // Output: 'https://example.com'

UUID

use Beeyev\ValueObject\Uuid;

$uuid = new Uuid('550e8400-e29b-41d4-a716-446655440000');
echo $uuid->value; // Output: '550e8400-e29b-41d4-a716-446655440000'

IPv4地址

use Beeyev\ValueObject\IPv4;

$ip = new IPv4('172.20.13.13');
echo $ip->value; // Output: '172.20.13.13'

IPv6地址

use Beeyev\ValueObject\IPv6;

$ip = new IPv6('2606:4700:4700::1111');
echo $ip->value; // Output: '2606:4700:4700::1111'

坐标

表示地理坐标(纬度和经度)。

use Beeyev\ValueObject\Coordinate;

$coordinate = new Coordinate(37.7749, -122.4194);
echo $coordinate->latitude;  // Output: 37.7749
echo $coordinate->longitude; // Output: -122.4194
$coordinate->toArray();      // Array: [37.7749, -122.4194]

// Coordinate object can be created from a string
// Supported formats: '37.7749,-122.4194', '37.7749, -122.4194', '37.7749 122.4194', '37.7749/122.4194'
$coordinate = Coordinate::fromString('37.7749,-122.4194');

echo $coordinate->toString();  // Output: '37.7749, -122.4194'
// Or cast to a string
echo (string) $coordinate;     // Output: '37.7749, -122.4194'

JSON

表示JSON字符串。

use Beeyev\ValueObject\Json;

$json = new Json('{"name": "John", "age": 30}');
echo $json->value;      // Output: '{"name": "John", "age": 30}'
echo $json->toArray();  // Output: ['name' => 'John', 'age' => 30]

百分比

表示0到100的百分比整数值。

use Beeyev\ValueObject\Percentage;

$percentage = new Percentage(50);
echo $percentage->value; // Output: 50

RangeInteger

表示整数值范围。

use Beeyev\ValueObject\RangeInteger;

$range = new RangeInteger(-5, 10);
echo $range->start;   // Output: -5
echo $range->end;     // Output: 10
$range->toArray();    // Array: [-5, 10]
echo (string) $range; // Output: '-5 - 10'


// Range object can be created from a string
$range = RangeInteger::fromString('-5 - 10');

// If you try to create a range object with the start value greater than the end value, an exception will be thrown
try {
    $range = new RangeInteger(10, -5);
} catch (ValueObjectInvalidArgumentException $e) {
    echo $e->getMessage(); // Output: 'Start value cannot be greater than the end value.'
}

分辨率

表示分辨率(宽度和高度)。

use Beeyev\ValueObject\Resolution;

// Only positive integers are allowed
$resolution = new Resolution(1920, 1080);
echo $resolution->width;   // Output: 1920
echo $resolution->height;  // Output: 1080
$resolution->toArray();    // Array: [1920, 1080]
echo (string) $resolution; // Output: '1920x1080'

Semantic Version

表示语义版本号(SemVer)。

use Beeyev\ValueObject\SemVer;

$version = new SemVer('1.0.3');
echo $version->value; // Output: '1.0.3'
echo $version->major; // Output: 1
echo $version->minor; // Output: 0
echo $version->patch; // Output: 3

// Is supports semver with pre-release and build metadata
$version = new SemVer('1.0.3-beta+exp.sha.5114f85');
echo $version->value;          // Output: '1.0.3-beta+exp.sha.5114f85'
echo $version->releaseVersion; // Output: '1.0.3'
echo $version->build;          // Output: 'exp.sha.5114f85'
echo $version->preRelease;     // Output: 'beta'

// SemVer value objects can be compared
$version1 = new SemVer('1.0.5');
$version2 = new SemVer('1.0.1-alpha+001');

$version1->greaterThan($version2); // true
$version1->lowerThan($version2);   // false

$version1->equalTo($version2);     // false
$version1->notEqualTo($version2);  // true

$version1->greaterThanOrEqualTo($version2); // true
$version1->lowerThanOrEqualTo($version2);   // false

时间戳

表示Unix时间戳。

use Beeyev\ValueObject\Timestamp;

$timestamp = new Timestamp(1631535600);
echo $timestamp->value;   // Output: 1631535600
echo $timestamp->dateTime // Returns DateTimeImmutable object

Class string

表示PHP类字符串。

use Beeyev\ValueObject\ClassString;

$classString = new ClassString('App\Models\User');
// Same as
$classString = new ClassString(User::class);

echo $classString->value; // Output: 'App\Models\User'

// Returns true if the class exists
$classString->isClassExist(); // true

// Returns true if the object is an instance of this class string.
$classString->isInstanceOf($user); // true

// It is possible to instantiate an object from the class string
$classString = new ClassString(\DateTimeImmutable::class);
$instance = $classString->instantiate();
assert($instance instanceof \DateTimeImmutable);

// It is possible to instantiate an object from the class string with arguments
$classString = new ClassString(\DateTimeImmutable::class);
$instance = $classString->instantiateWith('2021-01-01 00:00:00', new \DateTimeZone('UTC'));
assert($instance instanceof \DateTimeImmutable);
echo $instance->format('Y-m-d H:i:s'); // Output: '2021-01-01 00:00:00'

// It is possible to check if the interface exists
$classString = new ClassString(\DateTimeInterface::class);
$classString->isInterfaceExist(); // true

🐒 原始值对象

文本

表示非空文本字符串。

use Beeyev\ValueObject\Text;
use Beeyev\ValueObject\Exceptions\ValueObjectInvalidArgumentException;

$text = new Text('Hello, World!');
echo $text->value;    // Output: 'Hello, World!'
echo (string) $text;  // Output: 'Hello, World!'
echo $text->length(); // Output: 13

// If you try to create an empty text object, an exception will be thrown
try {
    $text = new Text('');
} catch (ValueObjectInvalidArgumentException $e) {
    echo $e->getMessage(); // Output: 'Text value cannot be empty.'
}

布尔值

use Beeyev\ValueObject\Boolean;

$boolean = new Boolean(true);
// It is also possible to create a boolean object from non-boolean values
// Supported values: 'true', 'false', '1', '0', 'yes', 'no', 'on', 'off'
// $boolean = new Boolean('on');

echo $boolean->value;      // Output: true
echo $boolean->toString(); // Output: 'true'
echo (string) $boolean;    // Output: 'true'

整数

use Beeyev\ValueObject\Integer;

$integer = new Integer(42);
// It is also possible to create an integer object from a string
// $integer = new Integer('42');

echo $integer->value; // Output: 42

正整数

表示大于零的正整数。对于存储必须始终为正的值很有用。例如,数据库行ID。

use Beeyev\ValueObject\PositiveInteger;
use Beeyev\ValueObject\Exceptions\ValueObjectInvalidArgumentException;

$positiveInteger = new PositiveInteger(42);
echo $positiveInteger->value; // Output: 42

// If you try to create a positive integer object from a negative value or equal to zero, an exception will be thrown
try {
    $positiveInteger = new PositiveInteger(0);
} catch (ValueObjectInvalidArgumentException $e) {
    echo $e->getMessage(); // Output: 'Provided number is not a positive integer. Given value: `0`.'
}

非负整数

表示大于或等于零的非负整数。

use Beeyev\ValueObject\NonNegativeInteger;
use Beeyev\ValueObject\Exceptions\ValueObjectInvalidArgumentException;

$positiveInteger = new NonNegativeInteger(96);
echo $positiveInteger->value; // Output: 96

双精度(浮点数)

表示双精度浮点数。

use Beeyev\ValueObject\Double;

$double = new Double(3.14);
// It is also possible to create a double object from a string
// $double = new Double('3.14');

echo $double->value;      // Output: 3.14
echo $double->toString(); // Output: '3.14'
echo (string) $double;    // Output: '3.14'

常见功能

每个值对象都具有以下功能

// Every value object can be cast to a string and supports \Stringable interface
$vo->toString(); // Returns the value of the object as a string
(string) $vo;    // Returns the value of the object as a string

// Value objects can be compared
$vo1->sameAs($vo2);    // Returns true if the values are equal
$vo1->notSameAs($vo2); // Returns true if the values are not equal

🏗 创建自己的值对象

可以通过扩展AbstractValueObject类来创建自己的值对象。

📚 扩展功能

您可以自由扩展值对象的功能,通过创建继承自提供的值对象的自定义类来实现。

🐛 贡献

如果您有改进建议或希望创建自己的自定义值对象作为内置功能,请提交Pull Request。
此外,可以通过GitHub问题跟踪器提交错误报告和功能请求。

© 许可证

MIT许可(MIT)。更多信息请参阅许可文件

如果您喜欢这个项目,请考虑给我一个⭐