酵母 / 烤盘
从关联数组对象和配置中提取数据
Requires
- brick/varexporter: ^0.3.5
- jawira/case-converter: ^3.4
- nette/php-generator: ^3.6
- symfony/polyfill-php81: ^1.24
Requires (Dev)
- jetbrains/phpstorm-attributes: ^1.0
- justinrainbow/json-schema: ^5.2
- phpstan/phpstan: ^1.4
- phpunit/phpunit: 9.5.13
- ramsey/uuid: >=4
- vimeo/psalm: ^4.19
Suggests
- ramsey/uuid: Allows parsing of UUID's in units
README
A simple PHP 8 native object expansion (or hydration as some call it) framework
特性
- 仅关注数据的反序列化,因此非常适合配置
- 生成 JSON Schema(也适用于 yaml!)
- PHP 8 属性引导
- 简单的模板/泛型支持
- 简单的替代格式扩展器
- 自定义扩展器支持可以扩展出分支的对象
- 可读性代码生成,便于调试和加速
安装
composer require yeast/loafpan
非常快速的使用
$config = json_decode($json, true); $loafpan = new Loafpan($loafpanCacheDirectory); // Don't forget to annotate your class. $configClass = $loafpan->expand(MyConfig::class, $config);
用法
要开始使用 Loafpan,首先需要注释您的对象,在接下来的几个示例中,我们将创建一些伪类来解释细节
可扩展的对象被称为 "单元",单元必须用 Unit
注释或已注册自定义扩展器。但是,目前我们将介绍注释单元
在第一个示例中,Sandwich 是一个基于设置器的单元,将使用默认构造函数来实例化对象,然后手动设置属性。
Loafpan 是由 Field
属性引导的,这些属性表示哪些属性可以应用于对象。
// The first argument of `Unit` is the description of the object // This is used in the JSON Schema generation #[Unit("This is a very nice sandwich")] class Sandwich { // A custom field name can be given with the `name` parameter #[Field(name: "title")] public string $name = ""; // since PHP has no native support for generics or typed arrays (yet) // one can override the type, and use list<T> to define the actual type #[Field("The toppings of this sandwich", type: 'list<Yeast\Demo\Topping>')] public array $toppings = []; }
Topping 是基于扩展器的,并且只接受一个字符串,因为这是唯一的实例化方法。
扩展器函数是公共静态函数,具有 1 或 2 个参数(可选的第二个参数是 Loafpan 实例),第一个参数定义了可以用于从对象扩展输入的类型,例如 Topping 可以仅由字符串生成。
#[Unit("What goes on the bread stays on the bread")] class Topping { private function __construct(private bool $wet = false) {} #[Expander] public static function fromName(string $name) { return new static($name === 'water' ? true : false); } }
尽管 Topping 仅定义了 1 个扩展器,但您可以添加多个,请注意,当类型重叠时,结果可能是不可预测的。
使用我们刚才定义的 2 个类,Sandwich 的有效 JSON 对象将是
{ // because the "name" property has set it's name to "title", // the json object must use title "title": "Soggy sandwich", "toppings": [ "water", "2 pounds of lead" ] }
这将大致翻译为
$sandwich = new Sandwich(); $sandwich->name = "Soggy sandwich"; $sandwich->toppings = [ Topping::fromString("water"), Topping::fromString("2 pounds of lead") ];
最后,创建一个 Loafpan 实例,其中包含可以写入 PHP 文件的目录,然后使用您想要扩展的类(在我们的情况下是 Sandwich
)和用户输入调用 expand
。
以下示例展示了这种用法
$loafpan = new Loafpan($yourLoafpanCacheDirectory); /** @var Sandwich $sandwich */ $sandwich = $loafpan->expand(Sandwich::class, [ "title" => "Soggy sandwich", "toppings" => [ "water", "2 pounds of lead" ] ]); echo "I have a sandwich called " . $sandwich->name . " the topping:\n"; foreach ($sandwich->toppping as $topping) { echo " - " . ($topping->wet ? 'wet' : 'not wet') . "\n"; }
如果这里给出的选项不足以提供足够的灵活性,您始终可以实施自己的扩展器,通过在一个类上实现 UnitExpander
(\Yeast\Loafpan\UnitExpander
)并使用 Loafpan 实例上的 registerExpander
函数或设置 Unit
属性上的 expander
参数来将其注册到 loafpan 上。
有关自定义 UnitExpanders 的示例,请参阅 src/Expander
默认扩展器
list<T>
- 仅接受类型为 T 的数组列表map<T>
- 仅接受类型为 T 的关联数组DateTime
/DateTimeImmutable
- 仅接受 ISO-8601 格式的日期字符串Ramsey\Uuid\Uuid
/Ramsey\Uuid\UuidInterface
- 仅接受正确格式化的 UUID 字符串
待办事项
- 生成有关无效输入的详细错误