How to convert an array into an object by Reflection + Attribute

scene

In daily development, we may encounter situations where we interact with third-party APIs. General APIs return data in json format, we convert json to array, and all that remains is to manipulate arrays to complete our business logic. However, manipulating arrays can sometimes be a headache. In the programming world, manipulating object s is more understandable than manipulating arrays, and IDE Tips are also more friendly.

Actual Scene

We need to parse the user's resume information, but OCR is not our main business, so we bought a third-party OCR parsing. The resume returns complex data, and we have to deal with some fields specially. For example, gender,The returned data is string type, but our database is int type, not only the data type is different, but also the field name may be different, so we need to do data conversion at this time. But the returned data is too complex, not only gender, but also school information in academic qualifications and so on.

Hydrate

To solve these problems, a powerful Hydrate can be implemented by reflecting Reflection+Annotation Attribute. Let's look at code usage before analyzing how it is implemented.

Code

install

composer require kabunx/hydrate -vvv

Define Entity

<?php
declare(strict_types=1);
namespace App\Entities;

use Carbon\Carbon;
use Kabunx\Hydrate\Entity;
use Kabunx\Hydrate\Source;

/**
 * Resume Subject Information
  */
class Resume extends Entity
{
    protected string $sourceKeyFormat = 'studly';

    public int $type = 0;

    public string $resumeGrade = '';

    // The field has changed here
    #[Source("Married")]
    public bool $isMarried = false;

    // Omit other fields here (more than 30)

    // English Level Certificate, Highest College Certificate Preferred
    #[Source("GradeOfEnglish")]
    public ?EnglishGrade $englishGrade;
    /**
     * Computer (IT) Skills
     * @var array|It[]
     */
    #[Source("ITSkills")]
    public array $its = []

    public function setIsMarried(?string $value): bool
    {
        return $value ? ($value == 'yes' ? true : false) : false;
    }

    // IT Skills
    public function setIts(?array $its): array
    {
        if (is_null($its)) {
            return [];
        }
        $entities = [];
        foreach ($its as $it) {
            $entities[] = It::instance($it);
        }
        return $entities;
    }
}

/**
 * English Achievement
 */
class EnglishGrade extends Entity
{
  protected string $sourceKeyFormat = 'studly';
  public string $nameOfCertificate = '';

  public string $score = '';

  public ?Carbon $receivingDate;
}

/**
 * IT Skills
 */
class It extends Entity
{
  protected string $sourceKeyFormat = 'studly';
  // Skill categories
  public string $skillType = '';

  // Usage Time
  #[Source("TimeOfUse", "used_at")]
  public string $usedTime = '';

  // Mastery Level
  public string $competencyLevel = '';
}

Use

<?php
use App\Entities\Resume;
// Here simulates the API's return data
$data = [
    "Type" => 1,
    "ResumeGrade" => '',
    "Married" => 'yes',
    "GradeOfEnglish" => [
        "NameOfCertificate" => "",
        "Score" => "excellent",
        "ReceivingDate" => "2021-01-01"
    ],
    "ITSkills" => [
        [
            "skillType" => "",
            "TimeOfUse" => "",
            "CompetencyLevel" => ""
        ]
    ]
];

// How to convert to entity
$entity = Resume::instance($data);
// entity is now operational

// How to convert to the data we want
$enttiy->toArray();
// Will be converted according to your comment, default is snake format

Whether it's convenient or not, I often use it in my actual work. I replaced the original doctrine/annotations with the original annotations.
In entity, we can use setProperty to modify data, which is the same idea as the model modifier in laravel.

Source Parsing

Specific code has been put on GitHub by me, address hydrate
You can look at it first, and I'll add notes later.

Tags: Laravel

Posted on Mon, 20 Sep 2021 09:45:26 -0400 by champoi