drbonzo/metassione

此软件包已被废弃,不再维护。未建议替代软件包。

POPO 到 stdClass 和 POPO 填充器

0.7.0 2016-06-30 13:37 UTC

README

  • 允许将 POPO (POPO = 纯旧 PHP 对象) 转换为 stdClass
    • 为什么?json_encode() 不处理私有属性。
    • 因此,您需要将所有属性设置为公共的或使用 metassione
  • 以及 stdClass 到 POPO
    • 将您的 JSON 转换为具有类型检查和类型转换等的 PHP 对象

POPO 到 stdClass

这允许将复杂对象转换为 stdClass,然后转换为 JSON(使用 json_encode())。

示例

构建对象层次结构

$post = new \Blog\Post();
$post->setTitle('il titolo');
$post->setContents('Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Ut posuere risus eu commodo fermentum. Nullam nec dignissim est.
Curabitur adipiscing massa sit amet velit vehicula aliquam.');

{
	$comment_1 = new \Blog\Comment();
	$comment_1->setAuthorName("l'autore 1");
	$comment_1->setContents("Lorem ipsum");

	$comment_2 = new \Blog\Comment();
	$comment_2->setAuthorName("l'autore 2");
	$comment_2->setContents("dolor sit amet");

	$comments = [$comment_1, $comment_2];
	$post->setComments($comments);
}

转换为 stdClass

$metassione = new \NorthslopePL\Metassione\Metassione();
$rawData = $metassione->convertToStdClass($post);
print_r($rawData);

给出

stdClass Object
(
    [title] => il titolo
    [contents] => Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Ut posuere risus eu commodo fermentum. Nullam nec dignissim est.
Curabitur adipiscing massa sit amet velit vehicula aliquam.
    [comments] => Array
        (
            [0] => stdClass Object
                (
                    [authorName] => l'autore 1
                    [contents] => Lorem ipsum
                )

            [1] => stdClass Object
                (
                    [authorName] => l'autore 2
                    [contents] => dolor sit amet
                )

        )

)

然后我们可以将其转换为 JSON(JSON_PRETTY_PRINT = php 5.4+): $json = json_encode($rawData, JSON_PRETTY_PRINT); print($json);

这给出

{
    "title": "il titolo",
    "contents": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nUt posuere risus eu commodo fermentum. Nullam nec dignissim est.\nCurabitur adipiscing massa sit amet velit vehicula aliquam.",
    "comments": [
        {
            "authorName": "l'autore 1",
            "contents": "Lorem ipsum"
        },
        {
            "authorName": "l'autore 2",
            "contents": "dolor sit amet"
        }
    ]
}

stdClass 到 POPO

这允许将 JSON 中的数据转换为 POPO。而不是从未指定的对象和数组中读取数据 - 您可以使用自己的类、类型提示等。

使用您的 POPO

$comments = $post->getComments();
echo $comments[0]->getAuthor();
echo $comments[0]->getContents();

与数组和 stdClasses(没有类型/方法提示)进行比较

echo $post->comments[0]->author;
echo $post->comments[0]->contents;

示例

我们使用上面的示例中的 $rawData,来构建相同的 \Blog\Post 对象

$otherPost = new \Blog\Post();
$metassione->fillObjectWithRawData($otherPost, $rawData);

print_r($otherPost);

这给出

Blog\Post Object
(
    [title:Blog\Post:private] => il titolo
    [contents:Blog\Post:private] => Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Ut posuere risus eu commodo fermentum. Nullam nec dignissim est.
Curabitur adipiscing massa sit amet velit vehicula aliquam.
    [comments:Blog\Post:private] => Array
        (
            [0] => Blog\Comment Object
                (
                    [authorName:Blog\Comment:private] => l'autore 1
                    [contents:Blog\Comment:private] => Lorem ipsum
                )

            [1] => Blog\Comment Object
                (
                    [authorName:Blog\Comment:private] => l'autore 2
                    [contents:Blog\Comment:private] => dolor sit amet
                )

        )

)

这与我们的起始 $post 对象相等。

为什么是 'metassione'

  1. METASSIONE
  2. METAdati e di rifleSSIONE
  3. metadati e di riflessione
  4. 翻译成英文:metadata and reflection

构建 POPO

为了使 Metassione 的工作,您需要在您的类中添加类型提示和 phpdocs。

示例

<?php
namespace NorthslopePL\Metassione\Tests\Examples;

class PropertyWithoutFullClassname
{
	/**
	 * Fully qualified class name - same namespace
	 *
	 * @var \NorthslopePL\Metassione\Tests\Examples\ChildKlass
	 */
	private $firstChild;

	/**
	 * Class from the same namespace as current file.
	 * This is the same as '\NorthslopePL\Metassione\Tests\Examples\ChildKlass'
	 *
	 * @var ChildKlass
	 */
	private $secondChild;

	/**
	 * Fully qualified class name - other namespace
	 *
	 * @var \Other\Lib\ChildKlass
	 */
	private $thirdChild;
	
	/**
	 * Not fully qualified class name - from global namespace
	 * @var SomeClassWithoutNamespace
	 */
	private $fourthChild;
}
?>

可用的属性类型

  • 基本类型
    • int | integer
    • string
    • float | double
    • bool | boolean
  • 基本类型的数组
    • int[] | integer[]
    • string[]
    • float[] | double[]
    • bool[] | boolean[]
    • FirstClass
    • OtherClass
    • \Foo\Bar\AnotherClass
  • 类数组(arrayarray|Foobar[] 中被忽略)
    • FirstClass[]
    • OtherClass[]
    • \Foo\Bar\AnotherClass[]

变更日志

0.6.1 更新测试到 phpunit 5.4

0.6.0 完全重写

  • Metassione::fillObjectWithRawData($targetObject, stdClass $rawData) 返回 $targetObject
    • 这允许您编写:$myObject = $metassione->fillObjectWithRawData(new MyKlass(), $rawData);
    • 而无需在临时变量中存储 new MyKlass()
  • 将类元数据检索与填充对象分开(CachingClassDefinitionBuilder
    • 添加了缓存类元数据(仅在内存中)
  • 性能:比 JsonMapper 慢约 20%,而 Metassione 0.4 慢 100% 以上
  • 属性处理改进
    • 支持可以为空的属性(integer|nullFooBar|null
    • 属性缺少或值为空
      • 属性值设置为零值 - 对于非可空属性
        • 整数 -> 0
        • 浮点数 -> 0.0
        • string -> ''
        • 布尔类型转换为false
        • SomeKlass类型转换为new SomeKlass()
        • 任何数组转换为[]
      • 对于可为空的属性,属性值设置为null
        • 整数类型转换为null
        • 浮点数类型转换为null
        • 字符串类型转换为null
        • 布尔类型转换为null
        • SomeKlass类型转换为null
        • 任何数组转换为[]警告:数组类型的属性总是设置为空数组,而不是null。这是设计上的要求
  • 将值转换为正确的类型
    • 示例:属性类型为整数,传递了12.95浮点数。最终对象将包含12作为其属性值
  • 识别未定义的属性 - 它们将被填充为null。当指定属性的类型无效时,它被视为未定义,并且总是填充为null值。
  • 仍然不支持从其他命名空间导入类(使用use ACME\Foo\Bar然后/* @var Bar */

从0.4.0升级到0.6.0

Metassione 0.6.0在处理属性值时更加严格。

  • 如果您允许属性为null(例如integer|null),请警告metassione将在属性没有有效值时将这些值设置为null
  • 处理目标类的所有属性。如果没有找到此类属性的值,则将其设置为零值null
  • 在0.4.0中,您可以设置对象为整数属性,但现在这是不可能的。属性将获得0.0(或null)的值。

0.4.0

可以使用不带完全类名的属性。

示例

<?php
namespace NorthslopePL\Metassione\Tests\Examples;

class PropertyWithoutFullClassname
{
	/**
	 * @var \NorthslopePL\Metassione\Tests\Examples\ChildKlass
	 */
	private $firstChild;

	/**
	 * @var ChildKlass
	 */
	private $secondChild;

	/**
	 * @var \Other\Lib\ChildKlass
	 */
	private $thirdChild;
}
?>
  • $firstChild - 指定了完整的类名。将使用该类名
  • $secondChild
    • 仅指定了ChildKlass。将尝试加载NorthslopePL\Metassione\Tests\Examples\ChildKlass
    • 如果找到\ChildKlass,则使用它
    • 如果没有找到,则如果找到NorthslopePL\Metassione\Tests\Examples\ChildKlass,则使用它
    • 否则抛出异常
  • $thirdChild - 指定了完整的类名。将使用该类名。

此功能不适用于以下情况:

  • 使用useuse \Foo\Bar; ... @var Bar
  • 命名空间别名