cangelis/data-models

数据模型是处理结构化数据(如JSON和PHP数组)的优雅方式

2.0.0 2019-11-28 16:43 UTC

This package is auto-updated.

Last update: 2024-08-29 02:41:48 UTC


README

Build Status

数据模型是处理结构化数据(如JSON、XML和php数组)的优雅方式。它们基本上是对JSON和XML字符串或php数组的封装类。模型简化了JSON、XML或php数组的操作和处理工作流程。

优点

  • 开始简单(本页将向您介绍所有功能)
  • 设计上避免未定义索引
  • 动态访问模型属性,因此无需将类属性与JSON或XML属性映射
  • 使用 @property 文档块进行IDE自动补全,并使API使用默认情况下有文档记录
  • 模型之间存在多对一关系
  • 能够为属性分配默认值,因此可以可靠地处理未定义的属性
  • 能够在模型中的数据中添加逻辑
  • 将值转换为已知类型,如整数、字符串、浮点数、布尔值
  • 将值转换为Carbon对象,以便轻松处理日期属性
  • 能够实现自定义转换类型
  • 在对象模型上操作和工作,而不是在数组上操作,并将它们转换为数组或序列化为JSON

安装

composer require cangelis/data-models:^2.0

JSON用法

假设您有一个JSON数据,用于表示一篇博客文章,如下所示

$data = '{
    "id": 1,
    "author": "Can Gelis",
    "created_at": "2019-05-11 22:00:00",
    "comments": [
        {
            "id": 1,
            "text": "Hello World!"
        },
        {
            "id": 2,
            "text": "What a wonderful world!"
        }
    ],
    "settings": {"comments_enable": 1}
}';

您可以创建如下所示的模型

use CanGelis\DataModels\JsonModel;
use CanGelis\DataModels\Cast\BooleanCast;
use CanGelis\DataModels\Cast\DateTimeCast;

/**
 * Define docblock for ide auto-completion
 *
 * @property bool $comments_enable
 */
class Settings extends JsonModel {

    protected $casts = ['comments_enable' => BooleanCast::class];

    protected $defaults = ['comments_enable' => false];

}

/**
 * Define docblock for ide auto-completion
 *
 * @property integer $id
 * @property string $text
 */
class Comment extends JsonModel {}

/**
 * Define docblock for ide auto-completion
 *
 * @property integer $id
 * @property author $text
 * @property Carbon\Carbon $created_at
 * @property Settings $settings
 * @property CanGelis\DataModels\DataCollection $comments
 */
class Post extends JsonModel {

    protected $defaults = ['text' => 'No Text'];

    protected $casts = ['created_at' => DateTimeCast::class];

    protected $hasMany = ['comments' => Comment::class];

    protected $hasOne = ['settings' => Settings::class];

}

使用模型

$post = Post::fromString($data); // initialize from JSON String
$post = new Post(json_decode($data, true)); // or use arrays

$post->text // "No Text" in $defaults
$post->foo // returns null which doesn't have default value
$post->created_at // get Carbon object
$post->created_at->addDay(1) // Go to tomorrow
$post->created_at = Carbon::now() // update the creation time

$post->settings->comments_enable // returns true
$post->settings->comments_enable = false // manipulate the object
$post->settings->comments_enable // returns false
$post->settings->editable = false // introduce a new attribute

$post->comments->first() // returns the first comment
$post->comments[1] // get the second comment
foreach ($post->comments as $comment) {} // iterate on comments
$post->comments->add(new Comment(['id' => 3, 'text' => 'Not too bad'])) // add to the collection

$post->toArray() // see as array
$post->toJson() // serialize to json

/*
{"id":1,"author":"Can Gelis","created_at":"2019-11-14 16:09:32","comments":[{"id":1,"text":"Hello World!"},{"id":2,"text":"What a wonderful world!"},{"id":3,"text":"Not too bad"}],"settings":{"comments_enable":false,"editable":false}}
*/

XML用法

这很简单,与JSON模型非常相似。

假设有一个XML数据

$data = '<Team Color="#ffffff">
    <Players>
        <Player><Name>Beckham</Name><BirthDate>1975-05-02</BirthDate></Player>
        <Player><Name>Zidane</Name><BirthDate>1972-06-23</BirthDate></Player>
    </Players>
    <TeamLocation>
       <City>Istanbul</City>
       <Country>Turkey</Country>     
    </TeamLocation>
</Team>';

您可以设置如下所示的关系

use CanGelis\DataModels\XmlModel;
use CanGelis\DataModels\Cast\DateCast;

class Player extends XmlModel {

    // root tag name <Player></Player>
    protected $root = 'Player';

    protected $casts = ['BirthDate' => DateCast::class];

}

class Address extends Xmlmodel {

    protected $root = 'Address';

}

class Team extends XmlModel {
    
    protected $root = 'Team';

    protected $hasMany = [
        'Players' => Player::class
    ];
    
    protected $hasOne = [
        'TeamLocation' => Address::class
    ];
    
    // the attributes in this array will be
    // behave as XML attributes see the example
    protected $attributes = ['Color'];

}

一旦您设置了关系和数据,您就可以开始使用数据。

$team = Team::fromString($data);

echo $team->TeamLocation->City; // returns Istanbul
$team->TeamLocation->City = 'Madrid'; // update the city

echo $team->Players->count(); // number of players
echo $team->Players[0]->Name; // gets first player's name

echo $team->Color; // gets the Color XML attribute
$team->Color = '#000000'; // update the XML Attribute

echo get_class($team->Players[0]->BirthDate); // returns Carbon\Carbon
$team->Players->add(Player::fromArray(['Name' => 'Ronaldinho'])); // add a new player

echo (string) $team; // make an xml string

生成的XML将是;

<Team Color="#000000">
	<TeamLocation>
		<Country>Turkey</Country>
		<City>Madrid</City>
	</TeamLocation>
	<Players>
		<Player><Name>Beckham</Name><BirthDate>1975-05-02</BirthDate></Player>
		<Player><Name>Zidane</Name><BirthDate>1972-06-23</BirthDate></Player>
		<Player><Name>Ronaldinho</Name></Player>
	</Players>
</Team>

可用的转换

以下是可用的转换。

    CanGelis\DataModels\Cast\BooleanCast
    CanGelis\DataModels\Cast\FloatCast
    CanGelis\DataModels\Cast\IntegerCast
    CanGelis\DataModels\Cast\StringCast
    // these require nesbot/carbon package to work
    CanGelis\DataModels\Cast\DateCast
    CanGelis\DataModels\Cast\DateTimeCast
    CanGelis\DataModels\Cast\Iso8601Cast
    

自定义转换

如果您更喜欢实现更复杂的价值转换逻辑,数据模型允许您实现自定义的。

假设您使用Laravel Eloquent并想将一个JSON属性转换。

// data = {"id": 1, "user": 1}

class EloquentUserCast extends AbstractCast {

    /**
     * The value is casted when it is accessed
     * So this is a good place to convert the value in the
     * JSON into what we'd like to see
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function cast($value)
    {
        if (!$value instanceof User) {
            return User::find($value);        
        }
        return $value;
    }

    /**
     * This method is called when the object is serialized back to
     * array or JSON
     * So this is good place to make the values
     * json compatible such as integer, string or bool
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function uncast($value)
    {
        if ($value instanceof User) {
            return $value->id;
        }
        return $value;
    }
}

class Post {
    
    protected $casts = ['user' => EloquentUserCast::class];
    
}

$post->user = User::find(2); // set the Eloquent model directly
$post->user = 2; // set only the id instead
$post->user // returns instance of User
$post->toArray()

['id' => 1, 'user' => 2]

贡献

请随意贡献!