siktec /

Quick Data Model 是创建项目数据模型的一种简单快捷的方式。

dev-main 2024-01-23 02:48 UTC

This package is auto-updated.

Last update: 2024-09-23 04:44:34 UTC


README

Build Status

QDM 是一个现代的 PHP 8 Quick Data Model。它通过 PHP 8 属性定义数据模型,是一种简单快捷的方式为 PHP 项目创建数据模型。其主要目的是将数据序列化和反序列化到 JSON 格式。也可以对数据模型进行验证,以及进行一些基本的数据操作。

快速入门

安装

composer require siktec/qdm

一瞥

<?php declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use QDM\Attr;

/**
 * A Car Data Model
 */
class Car extends QDM\DataModel implements \ArrayAccess
{
    use QDM\Traits\ArrayAccessTrait;

    public bool $is_valid = false;        // Not a DataPoint so for internal use only

    public function __construct(

        #[Attr\DataPoint(required: true)] // This is a required DataPoint can not be null
        public ?string $model = null,

        #[Attr\DataPoint]
        public ?int $year = null,         // A Public DataPoint that will be exported and imported

        #[Attr\DataPoint]
        protected ?string $code = null   // A Protected DataPoint that will imported but not exported
    ) { }
}

/**
 * A Car Collection
 */
#[Attr\Collect(models: Car::class)] // Can also be a "mixed" or an array of types
class CarLot extends QDM\Collection { } // Simple Collection class we can add cars to it

/**
 * A Car Dealership Data Model
 */
class Dealership extends QDM\DataModel implements \ArrayAccess
{
    use QDM\Traits\ArrayAccessTrait; // Bring some more functionality to the DataModel

    #[Attr\DataPoint]
    public ?CarLot $car_lot = null; // A Public DataPoint that will be exported and imported

    public function __construct(

        #[Attr\DataPoint(required: true)] // This is a required DataPoint can not be null
        public ?string $name = null,

        #[Attr\DataPoint(required: true)] // This is a required DataPoint can not be null
        public ?string $address = null,
    )
    {
        $this->car_lot = new CarLot(); //Initialize the CarLot Collection
    }
}

// Create a new Car Dealership
$dealership1 = new Dealership(
    name: "My Car Dealership",
    address: "123 Main St."
);

// Add a new Car to the Car Dealership
$dealership1->car_lot["car_one"] = new Car(
    model: "Ford Bronco",
    year: 2021,
    code: "1234"
);
// OR:
$dealership1->car_lot->add(new Car(
    model: "Ford Limo",
    year: 2021,
    code: "4321"
), "car_two");
// OR:
$dealership1->car_lot->extend([
    "car_three" => [
        "model" => "Ford F150",
        "year" => 2021,
        "code" => "5678"
    ]
]);

// AND MANY MORE WAYS TO PRAGMATICALLY INTERACT WITH THE DATA MODEL

// Export the Car Dealership to JSON (we could also export to an array)
$json1 = $dealership1->toJson(pretty : true); 
echo $json1;
/* 
{
    "name":"My Car Dealership",
    "address":"123 Main St.",
    "car_lot": {
        "car_one":{
            "model":"Ford Bronco",
            "year":2021
        },
        "car_two":{
            "model":"Ford Limo",
            "year":2021
        },
        "car_three":{
            "model":"Ford F150",
            "year":2021
        }
    }
}
*/

// Both ways work the same
$dealership2 = new Dealership();
$validation = [];
// Import the Car Dealership from JSON (we could also import from an array)
$success = $dealership2->from($json1, $validation);
if (!$success) {
    echo "Something went wrong";
    print_r($validation); // This will contain all the errors the basic validation are done by the DataModel class
    exit;
}
if ($json1 === $dealership2->toJson(pretty : true)) {
    echo "They are the same :)";
} else {
    echo "They are different";
}

// Obviously we can also do this:
$dealership3 = new Dealership();
$dealership3->from([ // Import the Car Dealership from an array
    "name" => "My Car Dealership",
    "address" => "123 Main St.",
    "car_lot" => [
        "car_one" => [
            "model" => "Ford Bronco",
            "year" => 2021,
            "code" => "1234"
        ],
        "car_two" => [
            "model" => "Ford Limo",
            "year" => 2021,
            "code" => "4321"
        ],
        "car_three" => [
            "model" => "Ford F150",
            "year" => 2021,
            "code" => "5678"
        ]
    ]
]);

/*
 There a lot more to this library :)
 filters, setters, getters, collections, custom methods for validation, etc.
 Many moreways to interact with the data model such as array access, iterators, etc.
 Many more ways to export and import data from and to the data model.
 SO CHECK OUT THE DOCUMENTATION AND EXAMPLES
*/

待办事项

  • 添加一个 DataModel 类来处理数据模型
  • DataModel 类嵌套数据模型支持
  • 安全数据模型使用 $errors 数组来存储所有错误,而不是抛出异常
  • 支持数据点属性,可以根据数据类型和可见性覆盖默认行为
  • 为 DataModel 类实现 ArrayAccess 接口
  • 为 DataModel 类实现 Iterator 接口
  • 添加更多测试 (进行中)
  • DataModel 类的通用接口,以便人类可以扩展它并创建他们自己的 DataModel 类
  • 为 DataModel 类添加 revert 方法,以将数据模型还原到其原始状态(默认值)
  • 添加手动初始化数据模型默认状态的能力。基本上,构造函数不是强制性的,所有事情都应该在调用父构造函数之前工作。
  • 添加一个 Collection 类来处理数据模型对象的集合
  • 集合也可以包含在 DataModel 中,并且可以包含任何 IDataModel 类型的项
  • 集合类应实现 ArrayAccess、Iterator 和 Countable 接口。
  • 集合应检查添加到其中的项的类型,并且可以配置为允许或不允许类型。
  • 添加更多控制集合如何处理键的方法。特别是在向集合添加项目或从集合中删除项目时。
  • 为 DataModel 类添加 Filter 属性,在设置值之前规范化数据点值。
  • 从数据点引用 Filter 组。这样,我们可以避免为多个数据点重复相同的过滤器序列。
  • 添加一些基本的过滤器,默认情况下可供开发者使用。 使用新的过滤器选项,这不再需要,因为我们可以调用任何函数
  • 添加一个类似于过滤器的 Check,它应该返回一个布尔值,以及可选的错误消息。这对于实现高级验证很有用。
  • 为 DataModel 类添加 validate() 方法,该方法将运行所有的 Check 过滤器,并返回一个错误数组。尽管在设置数据点的值之前始终调用 Check,但此方法可以在初始化数据模型之后以及用户可能对其进行修改后使用。
  • 添加一个类似于过滤器的 Set,这是设置值之前发生的最后一件事情,因此用户可以为数据点定义自定义设置方法,可能对实现高级验证或数据库交互很有用。
  • 添加一个 Get,这是返回值之前发生的最后一件事情,这适用于从 i.e. toArray, toJson, get() 方法导出的任何数据。
  • 所有功能(Filter、Check、Set、Get)都可以应用于整个数据模型或特定的数据点。
  • 添加一个 describe() 方法,它将返回带有所有属性及其值的解析后的数据模型。这对于调试特别有用,尤其是在使用嵌套数据模型和引用时。
  • 改进错误|异常处理 + 测试
  • 文档(进行中)
  • 示例(进行中)
  • 蜜罐(额外标志) - 一个特殊的数据点,将存储在数据模型中未定义为键值对的任何多余数据。
  • 发布版本 v1.0.0
  • 添加一个可选的Trait,使DataModel类能够使用更高级的toArrayFilter方法,这将允许用户为DataModel定义自定义的toArrayFilter方法。
  • 添加一个可选的Trait,使DataModel类能够使用更高级的fromArrayFilter方法,这将允许用户为DataModel定义自定义的fromArrayFilter方法。
  • 当从集合导出到数组时,应针对集合中的每个项目调用toArrayFilter方法。