Прошу подсказать по учебной задаче.
Требуется модифицировать класс Accessor таким образом, чтобы его объекты можно было сериализовать при помощи serialize() и восстановить при помощи unserialize(). По возможности организовать сериализацию таким образом, чтобы объект сохранялся в JSON-формате.
require_once 'include.php';
$obj = new Accessor();
print_r($obj->jsonSerialize());
Файл include.php:
class Accessor implements JsonSerializable
{
private $array = ['key1' =>'1','key2' =>'2','key7' =>'7'];
private $go = 123321;
public function __construct(array $array) {
$this->array = $array;
}
public function jsonSerialize() {
return $this->array;
}
}
Почему jsonSerialize() не отрабатывает?
Давайте внесем некоторую ясность ваш вопрос. Сначала вы пишите про функции стандартной сериализации в пхп - serialize()/unserialize()
. Они сохраняют переменную в строку в своем неком формате.
Пример:
class Accessor {
private $data = [
'key1' => 'value1',
'key2' => 2,
];
private $val = 100;
}
$a = new Accessor();
print serialize( $a );
на выходе получим строку следующего формата (она не совсем корректна, т.к. содержит непечатные символы, которые сюда не копируются)
O:8:"Accessor":2:{s:14:"O:8:"Accessor":2:{s:14:"Accessordata";a:2:{s:4:"key1";s:6:"value1";s:4:"key2";i:2;}s:13:"Accessorval";i:100;}
Данный метод сохранения весьма широко использовался лет так 10 назад, до начала массового использования JSON. Одно из его преимуществ относительно JSON в том, что он содержит информацию о типах. В самом начале идет строка O:8:"Accessor"
(O-объект, 8 - длина имени класса, далее название класса). Поэтому с помощью метода unserialize
вы получите экземпляр этого же класса.
Недостатком относительно JSON является тот факт, что этот формат не переносим между другими языками. Это внутренний формат для пхп.
А вот JSON напротив, является форматом обмена данных между разными системами но при этом сам по себе не содержит сведений о используемых типах данных.
Эти методы сериализации при вызовах используют "магические" методы объектов __sleep()
и __wakeup()
, при их наличии в классе объекта, либо если класс поддерживает интерфейс Serializable
.
Данный функционал позволяет получить данные объекта, которые следует сериализовать (чтобы не записывать объект целиком), а также выполнить действия по восстановлению состояния после того как объект десериализован.
Далее про кодирование в JSON. Для этих целей используются функции json_encode()/json_decode()
. private
поля класс не сериализуются. В случае приведенного выше класса, код
print json_encode( $a );
вернeт "пустой объект" - строку {}
. Если же поля будут объявлены как public
, то объект будет сериализован в следующую JSON-строку:
{"data":{"key1":"value1","key2":2},"val":100}
Теперь в вашем коде использован интерфейс JsonSerializable
. Как и в случаях с serialize()
и методами __sleep()
и Serializable::serialize
этот инетерфейс позволяет получить данные объекта, которые должны быть сохранены. Когда вы хотите сериализовать объект вы все так же вызываете json_encode($a)
, если объект не поддерживает указанный интерфейс, то происходит сериализация всех доступных полей. Если же переданный объект его поддерживает, то будет вызван метод jsonSerialize()
и сериализованы будут только те данные, которые он вернет.
Это позволяет во-первых сериализовать не все подряд, а только нужное, во-вторых - позволяет сериализовать любые поля, которые мы сочтем нужным, поскольку сами формируем массив значений (то есть вручную сохраняем, например, приватные поля).
Поэтому вернув в класс private
поля и добавив данный интерфейс:
class Accessor implements JsonSerializable {
private $data = [
'key1' => 'value1',
'key2' => 2,
];
private $val = 100;
public function jsonSerialize(){
return $this->data;
}
}
вызов json_encode($a)
вернет нам только значения массива data
:
{"key1":"value1","key2":2}
Если нам требуется сохранить значения и $data
и $val
, то мы определяем метод соответствующим образом:
public function jsonSerialize(){
return ['data' => $this->data, 'val' => $this->val];
}
В общем, тут надо понять, что сам метод jsonSerialize
ничего не кодирует, а просто предоставляет данные, которые должны быть закодированы.
И возвращаясь в вашему вопросу. Невозможно сказать, как следует модифицировать класс, который указан в задании, поскольку я так понимаю это не его первоначальный вид. Во вторых инструменты serialize()
и формат JSON
в принципе никак не связаны в пхп. Нельзя добиться, чтобы serialize
вдруг вернул json-строку,он возвращает свой формат. Но для этого можно использовать другие инструменты, такие как json_encode
.
В зависимости от того, что вы хотите сделать.
Если нужно, чтобы возвращался сериализованный массив из свойства array при вызове метода jsonSerialize()
, то пропишите в нем:
return json_encode($this->array);
То же самое сделайте для unserialize
, только json_decode
.
Если же вы хотите, чтобы все работало при вызове именно функции php serialize
, то так, увы, не получится, ввиду того, что метод встроенный и алгоритм его работы уже определен.
Есть способ переопределить этот метод через C в движке php. Но я не думаю, что в этом состоит задача.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Подскажите как правильно подправить условия? сейчас при заходе на страницу браузер выдает ошибку HTTP ERROR 500
Как получить путь к странице с которой сделан переход, типа $_SERVER['HTTP_REFERER'] только нужен именно путь без http://
Для того, чтобы пользоваться MediaPlayer, нужно использовать его в JavaFX потокеСамая простая программа для запуска JavaFX приложения выглядит примерно...