Replies: 2 comments 3 replies
-
Did you check https://symfony.com/doc/current/components/serializer.html ? In the past, I found it difficult to understand the Symfony component, and it was much faster to write my own version. My "dirty" solution that I created 2 years ago to create a DataView from the DB. Please don't judge too harshly; I wasn't too concerned about following best practices. Caution, my handwritten solutionClasses: final class CustomFetcher
{
/**
* @return CustomObjectInterface[]
* @throws Exception
*/
public function fetchCustomObjectArray(Result $statement, CustomObjectInterface $customObjectClass): array
{
$arr = [];
foreach ($statement->fetchAllAssociative() as $row) {
$arr[] = $customObjectClass::fromArray($row);
}
return $arr;
}
/**
* @throws Exception
*/
public function fetchCustomObject(Result $statement, CustomObjectInterface $customObjectClass): ?CustomObjectInterface
{
foreach ($statement->fetchAllAssociative() as $row) {
/** @var CustomObjectInterface $result */
$result = $customObjectClass::fromArray($row);
return $result;
}
return null;
}
} interface CustomObjectInterface
{
public static function fromArray(array $data = []): object;
} trait FromArrayTrait
{
public static function fromArray(array $data = []): self
{
foreach (get_object_vars($obj = new self) as $property => $default) {
if ($default === null) {
throw new \UnexpectedValueException('Oops in your class is a null property - ' . self::class);
}
$type = gettype($default);
$var = $data[$property] ?? $default;
if (!is_object($default) || is_object($var)) {
settype($var, $type);
$obj->$property = $var;
continue;
}
$class = $default::class;
if (enum_exists($class)) {
/** @var \UnitEnum $class https://www.php.net/manual/en/class.unitenum.php */
$obj->$property = $class::from($var);
continue;
}
//TODO: add check if exist a special static method for that, like ::create ?
$obj->$property = new $class($var);
}
return $obj;
}
} How to use: final class SomeDataView implements CustomObjectInterface
{
use FromArrayTrait;
public Id $id;
public string $name = '';
public string $someString = '';
public ItemEnum $itemEnum = ItemEnum::ITEM;
public function __construct() //because I have made that null is not acceptable we have to init all values :)
{
$this->id = new Id((new NilUlid())->toRfc4122());
}
} Inject $result = $this->customFetcher->fetchCustomObject($qb->executeQuery(), new SomeDataView); |
Beta Was this translation helpful? Give feedback.
-
You can use the Serializer component, specifically the PropertyNormalizer normalizer : <?php
require_once __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
class Instance {
public $guid;
public $storageZoneName;
public string $path;
private int $answer = 42;
}
$instance = new Instance();
$instance->path = 'yolo';
$reflectionNormalizer = new PropertyNormalizer();
// object to array :
$dump = $reflectionNormalizer->normalize($instance);
var_dump($dump);
// array to object :
$newObject = $reflectionNormalizer->denormalize($dump, Instance::class);
var_dump($newObject); It should dump :
More info on PropertyNormalizer on https://symfony.com/doc/current/components/serializer.html#built-in-normalizers Hope this helps |
Beta Was this translation helpful? Give feedback.
-
Many APIs return an array of hashed arrays. I keep thinking there must be a good way to work with those responses.
I often use PropertyAccessor to go through each key and see if I can set the value, but perhaps there's a Symfony way, given recent tools like MapQueryParameter.
I think I want to create a POP object
and then when I get my results back, somehow "cast" the results to the object.
My semi-solution:
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions