cangelis / data-models
数据模型是处理结构化数据(如JSON和PHP数组)的优雅方式
2.0.0
2019-11-28 16:43 UTC
Requires
- php: >=7.0
Requires (Dev)
- nesbot/carbon: ^1||^2
- phpunit/phpunit: ^7||^6||^5
Suggests
- ext-json: *
- ext-simplexml: *
This package is auto-updated.
Last update: 2024-08-29 02:41:48 UTC
README
数据模型是处理结构化数据(如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]
贡献
请随意贡献!