場景
在日常開發中,我們可能會遇到和第三方API互動的情況,一般API都返回json
格式的資料,我們會將json
轉化為array
,剩下的就是操作array
來完成自己的業務邏輯。但操作array
有時候是一件令人頭痛的事情,在程式設計的世界裡,操作object
可比操作array
更讓人能夠理解,而且IDE
的提示也更加友好。
實際場景
我們需要解析使用者的簡歷資訊,但OCR
不是我們的主要業務,所以我們買了第三方的OCR
解析,這個簡歷返回的資料是比較複雜的,而且我們要對一些欄位特殊處理。比如性別sex
,返回的是string
型別,但我們的資料庫是int
型別,不僅僅是資料型別不一樣,也可能欄位名稱
不一樣,這個時候我們就需要做資料轉化。可是這個返回資料太複雜,不僅僅是性別,還有學歷中的學校資訊等等。
Hydrate
為了解決上述的問題,可以通過反射Reflection
+註解Attribute
來實現一個強大的水合器Hydrate
。我們先來看程式碼使用,然後再分析是如何實現的。
程式碼
安裝
composer require kabunx/hydrate -vvv
定義Entity
新增對陣列entity的支援
<?php
declare(strict_types=1);
namespace App\Entities;
use Carbon\Carbon;
use Kabunx\Hydrate\ArrayEntity;
use Kabunx\Hydrate\Entity;
use Kabunx\Hydrate\Column;
/**
* 簡歷主體資訊
*/
class Resume extends Entity
{
protected string $sourceKeyFormat = 'studly';
public int $type = 0;
public string $resumeGrade = '';
// 在這裡欄位發生了變化
#[Column("Married")]
public bool $isMarried = false;
// 此處省略其他欄位(30多個)
// 英語等級證照,優先選擇大學最高證照
#[Column("GradeOfEnglish")]
public ?EnglishGrade $englishGrade;
/**
* 計算機(IT)技能
* @var array|It[]
*/
#[Column("ITSkills")]
#[ArrayEntity(It::class)]
public array $its = []
public function setIsMarried(?string $value): bool
{
return $value ? ($value == '是' ? true : false) : false;
}
// IT技能
// 如果定義了ArrayEntity,此方法可以直接忽略
public function setIts(?array $its): array
{
if (is_null($its)) {
return [];
}
$entities = [];
foreach ($its as $it) {
$entities[] = It::instance($it);
}
return $entities;
}
}
/**
* 英語成績
*/
class EnglishGrade extends Entity
{
protected string $sourceKeyFormat = 'studly';
public string $nameOfCertificate = '';
public string $score = '';
public ?Carbon $receivingDate;
}
/**
* IT技能情況
*/
class It extends Entity
{
protected string $sourceKeyFormat = 'studly';
// 技能類別
public string $skillType = '';
// 使用時間
#[Column(from: "TimeOfUse", to: "used_at")]
public string $usedTime = '';
// 掌握程度
public string $competencyLevel = '';
}
使用
<?php
use App\Entities\Resume;
// 此處模擬API的返回資料
$data = [
"Type" => 1,
"ResumeGrade" => '',
"Married" => '是',
"GradeOfEnglish" => [
"NameOfCertificate" => "",
"Score" => "優秀",
"ReceivingDate" => "2021-01-01"
],
"ITSkills" => [
[
"skillType" => "",
"TimeOfUse" => "",
"CompetencyLevel" => ""
]
]
];
// 如何轉化為entity
$entity = Resume::instance($data);
// 這裡可以操作entity了
// 如何轉化為我們要的資料吶
$enttiy->toArray();
// 將會根據你的註解來轉化,預設是snake格式
entity物件
轉為陣列
是不是很方便,在的實際工作中,我經常用。原來使用的註釋doctrine/annotations
被我替換為了原生的註解
。
在entity
中我們可以使用setProperty
來修改資料,這個和laravel
中的model
修改器是一樣的思路。
原始碼解析
具體的程式碼已經被我放到了GitHub
上,地址hydrate
大家可以先看,我後續會補充說明。
本作品採用《CC 協議》,轉載必須註明作者和本文連結