Невозможно десериализовать объекты массива при получении объекта - PullRequest
0 голосов
/ 11 апреля 2020

Мой массив объектов не десериализуется при загрузке сущности из базы данных.

У меня есть объект не-сущности с именем NetworkAddress. Затем в моей сущности Foo у меня есть массив этих сетевых адресов.

Сетевые адреса сохраняются как сериализованные PHP в базе данных, но когда я загружаю объект, данные для сети адреса не добавляются.

/**
 * @ORM\Entity(repositoryClass="App\Repository\FooRepository")
 */
class Foo implements \Serializable
{
    ...

    /**
     * @var NetworkAddress[]
     * @Groups({"main", "initialized"})
     * @ORM\Column(type="array")
     */
    private array $addresses;
    ...

Поэтому, когда я загружаю свой $foo объект, $foo->getAddresses() возвращает массив пустых NetworkAddresses, хотя необработанные значения базы данных таковы:

a : 1: {я: 0; C: 22: "App \ DTO \ NetworkAddress": 41: {а: 2: {я: 0; s: 9: "127.0.0.1"; я:;: 1 с 4: "5000";}}}

Я использую команду basi c ->findOneBy() в своем репо для извлечения объекта.

Сериализация, кажется, работает, но есть ли что-то особенное для десериализации объекта, хранящегося в виде массива?

Вот мой класс NetworkAddress, без методов получения / установки

class NetworkAddress implements \Serializable
{
    /**
     * @Groups({"main", "initialized"})
     * @Assert\Regex(
     *     pattern="/^[0-9A-z\.-]+$/",
     *     match=true,
     *     message="Invalid host format."
     * )
     */
    private string $host = 'localhost';

    /**
     * Intentionally left untyped so we can accept int or string for port number.
     *
     * @Groups({"main", "initialized"})
     * @Assert\NotBlank(message = "Port should not be empty.")
     * @Assert\Range(min="1", max="65535", invalidMessage="Invalid port.")
     */
    private $port;

1 Ответ

1 голос
/ 12 апреля 2020

Вы можете проверить следующее, связать с проблемой десериализации массива объектов и "безопасной php сериализацией", чтобы устранить проблему уязвимости при php сериализации.

class Foo implements \Serializable
{
    //...

    protected $addresses;
    //...

    public function __construct($addresses = null) {
        if (!is_null($addresses)) {
        {
            $this->addresses = $addresses;
        }
    }

    /* serialize network addresses */
    public function serialize(): string {

        /* sanitize for any recursion */
        if ($class = $this->checkRecursion()) {
            throw new \Exception("Recursion detected: '$class'");
        }
        return serialize($this->addresses);
    }

    /* deserialize network addresses */
    public function unserialize($serialized): void {
        $this->addresses = unserialize($serialized);

        /* sanitize for any recursion */
        if ($class = $this->checkRecursion()) {
            throw new \Exception("Recursion detected: '$class'");
        }
    }

    /* check recursion function */
    protected function checkRecursion() {
        $class = print_r($this, true);
        if (preg_match('/[^\=\>]+(?=\*RECURSION\*)/i', $class, $matches)) {
            return trim($matches[0]);
        }
        return false;
    }
}

Класс NetworkAddress:

class NetworkAddress implements \Serializable
{
    protected $netAddress ;

    public function __construct($netAddress = ['host' => '127.0.0.7', 'port' => 7007]) {
        if (!is_null($netAddress)) {
            $this->netAddress = $netAddress;
        }
    }

    /* get class property by name
        eg. $net->__get('netAddress');
     */
    public function __get($name) {
        return $this->$name;
    }

    /* set class property from name
        eg. $net->__set('netAddress', ['host' => 'localhost', 'port' => '8080']);
     */
    public function __set($name, $value) {
        $this->$name = $value;
    }

    /* safe serialize */
    public function serialize(): string {

        /* sanitize for any recursion */
        if ($class = $this->checkRecursion()) {
            throw new \Exception("Recursion detected: '$class'");
        }
        return serialize($this->netAddresses);
    }

    /* safe unserialize */
    public function unserialize($serialized): void {
        $this->netAddresses = unserialize($serialized);

        /* sanitize for any recursion */
        if ($class = $this->checkRecursion()) {
            throw new \Exception("Recursion detected: '$class'");
        }
    }

    /* check recursion function */
    protected function checkRecursion() {
        $class = print_r($this, true);
        if (preg_match('/[^\=\>]+(?=\*RECURSION\*)/i', $class, $matches)) {
            return trim($matches[0]);
        }
        return false;
    }
}

Пример звонков:

/* create new network adresses */
$addresses = [new NetworkAddress(['host' => 'localhost', 'port' => 8080]), new NetworkAddress(['host' => 'example.com', 'port' => 80])];

/* create new foo */
$foo1 = new Foo($addresses);

/* serialize foo object */
$serialized = serialize($foo1);

/* unserialized foo object */
$foo2 = unserialize($serialized);

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...