Решение типовых проблем с json_encode (PHP)

Это краткая статья о наиболее вероятных проблемах с json_encode и их решениях. Иногда при кодировании данных в json, с помощью json_encode в php, мы получаем не тот результат который ожидаем. Я выделил три наиболее частые проблемы с которыми сталкиваются программисты:


  • доступ к полям
  • кодировка текстовых значений
  • цифровые значения

Доступ к полям


Проблема заключается в том что json_encode имеет доступ только к публичным полям объекта. Например если у вас есть класс


class Example {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }
}

то результатом выполнения следующего кода будет:


$obj = new Example("some", "value", "here"); 
echo json_encode($obj);

// {"publicProperty":"some"}

как видно в результирующий json были включены только публичные поля.
Что же делать если нужны все поля?


Решение


Для php < 5.4:
нам необходимо будет реализовать в классе метод который будет возвращать готовый json. Т.к. внутри класса есть доступ ко всем полям можно сформировать правильное представление объекта для  json_encode


class Example {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }

    public function toJson()
    {
        return json_encode([
            'publicProperty' => $this->publicProperty,
            'protectedProperty' => $this->protectedProperty,
            'privateProperty' => $this->privateProperty,
        ]);
    }
}

Для получение json-a c объекта теперь нужно пользоваться методом toJson, а не прямым применением json_encode к объекту


$obj = new Example("some", "value", "here"); 
echo $obj->toJson();

Для php >= 5.4:
достаточно будет реализовать интерфейс JsonSerializable для нашего класса, что подразумевает добавление метода jsonSerialize который будет возвращать структуру представляющую объект для json_encode


class Example implements JsonSerializable
{
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }

    public function jsonSerialize() 
    {
        return [
            'publicProperty' => $this->publicProperty,
            'protectedProperty' => $this->protectedProperty,
            'privateProperty' => $this->privateProperty,
        ];
    }
}

Теперь мы можем использовать json_encode как и раньше


$obj = new Example("some", "value", "here"); 
echo json_encode($obj);

// {"publicProperty":"some","protectedProperty":"value","privateProperty":"here"}

Почему не стоит использовать подход с toJson методом?


Многие наверно заметили что подход с созданием метода возвращающего json может быть использован и в версиях php >= 5.4. Так почему же не воспользоваться им? Все дело в том что ваш класс может быть использован как часть иной структуры данных


echo json_encode([
    'status' => true,
    'message' => 'some message',
    'data' => new Example("some", "value", "here"),
]);

и результат уже будет совсем другой.
Также класс может использоваться другими программистами, для которых такой тип получение json-а с объекта может быть не совсем очевиден.



Что если у меня очень много полей в класcе?


В таком случае можно воспользоваться функцией get_object_vars


class Example implements JsonSerializable
{
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;
    protected $someProp1;
...
    protected $someProp100500;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }

    public function jsonSerialize() 
    {
        $fields = get_object_vars($this);
        // что-то делаем ...
        return $fields;
    }
}

А если нужно private-поля, из класса, который нет возможности редактировать?


Может получиться ситуация когда нужно получить private поля (именно private, т.к. доступ к protected полям можно получить через наследование) в json-е. В таком случае необходимо будет воспользоваться рефлексией:


class Example
{
    public $publicProperty = "someValue";
    protected $protectedProperty;
    private $privateProperty1;
    private $privateProperty2;
    private $privateProperty3;

    public function __construct($privateProperty1, $privateProperty2, $privateProperty3, $protectedProperty)
    {
        $this->protectedProperty = $protectedProperty;
        $this->privateProperty1 = $privateProperty1;
        $this->privateProperty2 = $privateProperty2;
        $this->privateProperty3 = $privateProperty3;
    }
}

$obj = new Example("value1", 12, "21E021", false);
$reflection = new ReflectionClass($obj);

$public = [];

foreach ($reflection->getProperties() as $property) {
    $property->setAccessible(true);
    $public[$property->getName()] = $property->getValue($obj);
}

echo json_encode($public);

//{"publicProperty":"someValue","protectedProperty":false,"privateProperty1":"value1","privateProperty2":12,"privateProperty3":"21E021"}

Кодировка текстовых значений


Кириллица и другие знаки в UTF8


Второй тип распространённых проблем с json_encode это проблемы с кодировкой. Часто текстовые значения которые нужно кодировать в json имеют в себе символы в UTF8 (в том числе кириллица) в результате эти символы будут представлены в виде кодов:


echo json_encode("кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $");

// "\u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430 or \u20b3 \u0192 \u5143 \ufdfc \u20a8 \u0bf9 \uffe5 \u20b4 \uffe1 \u0e3f \uff04"

Отображение таких символов лечится очень просто — добавлением флага JSON_UNESCAPED_UNICODE вторым аргументом к функции json_encode:


echo json_encode("кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $", JSON_UNESCAPED_UNICODE);
// "кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $"

Символы в других кодировках


Функция json_encode воспринимает строковые значения как строки в UTF8, что может вызвать ошибку, если кодировка другая. Рассмотрим маленький кусочек кода (данный пример кода максимально упрощен для демонстрации проблемной ситуации)


echo json_encode(["p" => $_GET['p']]);

На первый взгляд ничего не предвещает проблем, да и что здесь может пойти не так? Я тоже так думал. В подавляющем большинстве случаев все будет работать, и по этой причине поиск проблемы занял у меня несколько больше времени, когда я впервые столкнулся с тем что результатом json_encode было false.


Для воссоздания такой ситуации предположим что p=%EF%F2%E8%F6%E0 (на пример: localhost?=%EF%F2%E8%F6%E0 ).
*Переменные в суперглобальных массивах $_GET и $_REQUEST уже декодированы.


$decoded = urldecode("%EF%F2%E8%F6%E0");

var_dump(json_encode($decoded));
// bool(false)

var_dump(json_last_error_msg());
// string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

Как можно увидеть из ошибки: проблема с кодировкой переданной строки (это не UTF8). Решение проблемы очевидное — привести значение в UTF8


$decoded = urldecode("%EF%F2%E8%F6%E0");
$utf8 = utf8_encode($decoded);

echo json_encode($utf8);
// "ïòèöà"

Цифровые значения


Последняя типовая ошибка связана с кодированием числовых значений.


Например:


echo json_encode(["string_float" => "3.0"]);
// {"string_float":"3.0"}

Как известно php не строго типизированный язык и позволяет использовать числа в виде строки, в большинстве случаев это не приводит к ошибкам внутри php приложения. Но так как json очень часто используется для передачи сообщений между приложениями, такой формат записи числа может вызвать проблемы в другом приложении. Желательно использовать флаг JSON_NUMERIC_CHECK:


echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK);
// {"string_float":3}

Уже лучше. Но как видим «3.0» превратилось в 3, что в большинстве случаев будет интерпретировано как int. Используем еще один флаг JSON_PRESERVE_ZERO_FRACTION для корректного преобразования в float:


echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK | JSON_PRESERVE_ZERO_FRACTION);
// {"string_float":3.0}

Прошу также обратить внимание на следующий фрагмент кода, что иллюстрирует ряд возможных проблем с json_encode и числовыми значениями:


$data = [
    "0000021", // нули слева
    6.12345678910111213, // много знаков после точки (будет округленно)
    "+81011321515", // телефон
    "21E021", // экспоненциальная запись
];

echo json_encode($data, JSON_NUMERIC_CHECK);
//[
//    21,
//    6.1234567891011,
//    81011321515,
//    2.1e+22
// ]

Спасибо за прочтение.


Буду рад увидеть в комментариях описание проблем, с которыми вы сталкивались, что не были упомянуты в статье

 

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 55

    –1

    Хороший материал. Добро пожаловать!

      0

      угу, хороший


      "лечиться, кодеровка"

      +3
      Извините, но статья рассчитана на тех, кто не смог осилить документацию?
      www.php.net/manual/ru/function.json-encode.php
      www.php.net/manual/ru/json.constants.php
        +8

        А еще:
        https://www.php.net/manual/en/reflectionmethod.setaccessible.php
        https://www.php.net/manual/en/function.utf8-encode
        https://www.php.net/manual/en/function.urldecode
        https://www.php.net/manual/en/function.get-object-vars
        https://www.php.net/manual/en/class.jsonserializable


        Да что там мелочиться. Можно, в принципе, поставить вот так:
        https://www.php.net/manual
        И будет норм. Это не сарказм. Я вполне серьезно считаю, что надо прочитать всю доку хотя бы раз (возможно, пропуская специфичные разделы экзотических расширений).


        Но фишка в том, что некоторые темы размазаны по доке. Не от плохого дизайна структуры доки, а от того, что иначе и не получится написать систематизированную документацию. Кто хоть раз писал тех.маны — прекрасно поймет о чем речь. И бывает хочется скомпилировать полученные знания в небольшой шпаргалке.


        Хотя никакого оригинального исследования данный пост в себе не содержит, субъективно считаю вполне уместным делать такие заметки.

          0
          Не от плохого дизайна структуры доки

          На самом деле она не очень. Но, к сожалению, она настолько монструозная сейчас, что как-то рефакторить вообще не вариант.

            0

            Я и не говорил, что она "очень". Я сказал, что проблема размазанности не от этого )

          +2
          Раньше я думал что это валидное требование. Теперь я полностью не согласен.

          Ну не читают мануалы. И на это есть причина, которую уже никто не сможет исправить. Технологий слишком много. Ты приходишь на проект и у тебя всегда минимум 20 новых (для тебя) технологий которые надо за месяц начать использовать.

          Я уже молчу про случаи — когда ты приходишь на проект, а там новый (для тебя) язык. Там количество вещей «прочитай документацию» легко переваливает за сотню.

          Хуже того, в современном мире нельзя себя лочить на технологию. Пока ты 10 лет оттачиваешь свое знание выбранной технологии — индустрия может сменить технологии для решения той-же задачи три раза.
          0

          Выглядит так словно json_encode очень плохо спроектирован. Почему так?

            +1
            В подавляющем большинстве случаев никаких проблем с json_encode нет. Это скорей напоминание об особенностях
              +2

              Функция нормально сделана.
              Просто она не подходит под такие задачи, в итоге получается подобное натягивание совы на глобус.


              Советую смотреть в сторону
              https://symfony.com/doc/current/components/serializer.html

              +3
              Вы отдельно рассматриваете случай PHP < 5.4 для классов, но почему-то забываете о том, что не только JsonSerializable, но и JSON_UNESCAPED_UNICODE в этих версиях PHP не существует. И для нормального представления символов вне диапазона ASCII придётся писать дополнительную обёртку. В комментариях к моей давней статье на эту тему Mithgol предложил забавный трюк для преобразования \u043a\u0438 в нормальный вид:
              echo preg_replace_callback('#\\\u[\da-f]{4}+#', function ($val) {
              		return json_decode('"' . $val[0] . '"', true);
              	}, json_encode('кирилица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $'));
                +4

                Зачем вообще рассматривать случай PHP < 5.4 в 2020 году?


                PHP 5.3 Support End-of-Life: June 3, 2019

                Давайте еще вспомним PHP4 и Services_JSON из PEAR, почему нет? :-)

                  +1
                  Зачем вообще рассматривать случай PHP < 5.4 в 2020 году?
                  PHP 5.3 Support End-of-Life: June 3, 2019
                  Потому что legacy которых еще до фига в продакшене. Года еще не прошло с момента окончания суппорта.
                  И если не знать отличий и не считать нужным их знание, то вместо решения задачи за 5 минут будет полчаса писаться гневный репорт сеньёру что мол «это не я идиот что не могу пофиксить проблему, это все вокруг отсталые что у них пхп 5.3 где-то используется. Поэтому надо просто отрефакторить 500кб кода, а потом я приступлю к решению задачи»©
                  Тут правда тоже есть нюанс, для рефакторинга когда с 5.3 неплохо бы знать особенности 5.3 :)

                  p.s.: Из мануала тоже предложите выкинуть инфу об отличиях версий?
                    0

                    Из мануала выкидывать не надо. Кому понадобится, там и прочитает. А в статье в 2020 году неуместно.

                      0
                      Это "статья о наиболее вероятных проблемах с json_encode и их решениях.
                      Отсылка к разным версиям тут не только не лишняя, она необходима.
                      2020 год звучит конечно гордо, но по факту ему всего 10 дней исполнилось. Поддержка 5.3 пхп закончилась чуть больше полугода назад, рано еще забывать старые версии.
                        0

                        Полноценная поддержка закончилась аж в 2014 году. До середины 2019 выпускались критические исправления, связанные с безопасностью. На переход на более свежую версию было больше пяти лет. Сейчас использовать в продакшене 5.3 — это сидеть на пороховой бочке.

                          0
                          На переход на более свежую версию было больше пяти лет.
                          Бизнес переходит на новые версии когда в этом есть смысл, а не когда они только выходят.

                          Сейчас использовать в продакшене 5.3 — это сидеть на пороховой бочке.
                          Это не так.

                          «У вас в продакшене PHP 5.3? Спасибо, неинтересно».
                          GreedyIvan Стартапная в целом логика недолгоживущих проектов.
                          Любой достаточно большой и долгий проект будет иметь в своем загашнике достаточное количество легаси. Есть и постарее стэки технологий, чем php окончанию поддержки которого и года не исполнилось.
                          windows XP уже 5 лет как окончена поддержка, в скольких банках, бухгалтериях и банкоматах она используется? В ядерном щите сша как давно от дискет отказались?
                            0
                            Я говорю, что IT в таких компаниях — не приоритет.

                            Обычная менеджерская задачка. Есть проект, который нужно развивать. Есть спецы, которые его развивают. При этом проект должен соответствовать современным реалиям, а те, кто его делают — это само собой разумеющееся. «Бизнесу нет выгоды в регулярном обновлении стека». И если вначале, когда проект начинался, были набраны специалисты совренного на тот момент уровня владения технологиями, то через пять лет остались только те, кому всё равно на собственное развитие. Потому что компания кладёт на развитие тех, кто развивает её продукт.

                            Придёт такой специалист собеседоваться. 15 лет опыта, последние 10 лет поддерживал и развивал проект на PHP 5.3. О современных технологиях только слышал или чуть-чуть щупал на пет-проектах. Опыт использования современных фреймфорков — увы, мимо. И целый набор эксклюзивных архитектурных идей и практик, принятых на его прошлом месте работы, которые никак не соотносятся с текущими бест-практиками. Хочет сеньером. Но увы, ничего кроме позиции джуниора ему не предложить. И то, сомнительный кандидат, так как где-то несколько лет назад окончательно положил на саморазвитие. Студент без опыта поинтереснее будет. Это такой крайний вариант.

                            То же самое и с менеджерами проектов. Есть те, кому команда неинтересна. Вкладываться в то, чтобы она росла вместе с проектом, — нет, не слышал, выхлопа для бинеса в этом нет. Мы их выучим, а они уйдут ещё. Получаем через 3-4 года неинтересный рынку соискателей стек технологий (сложность найти за рыночную цену), огромную текучку, и пару старожилов, потеря которых равносильна смерти проекта.

                            Но если IT — не приоритет, то и так сойдёт. Проекты живут в стадии операционной поддержки, баг фикса, и по фиче раз в пол года. Идеальное место для «пенсии». Главное, продать себя в такую компанию подороже.
                              0
                              Я говорю, что IT в таких компаниях — не приоритет.
                              ИТ ни в каких компаниях ни приоритет. ИТ ради ИТ не существует, ИТ всегда прикладно к какому-нибудь бизнесу.
                              Даже если это ИТ студия пилящая проекты на заказ — у нее все равно будут проекты с легаси кодом от заказчика, хотя бы для рефакторинга, но рефакторить легаси без знаний легаси невозможно.

                              Придёт такой специалист собеседоваться. 15 лет опыта, последние 10 лет поддерживал и развивал проект на PHP 5.3. О современных технологиях только слышал или чуть-чуть щупал на пет-проектах.
                              Нигде в дискуссии не утверждалось, что не надо использовать современные технологии. Так что «только слышал и чуть щупал» это чисто домысел непонятно зачем. Речь шла о том, что надо знать старые, особенно когда на этих старых вертиться еще полинтернета и они всего как полгода формально списаны.

                              Если хотите аналогию, ситуация скорее такая.
                              Весь такой «современный» спец приходит в крупную ИТ компанию, в которой (т.к. она ведет крупные проекты и не первый год) есть достаточное количество легаси кода.
                              Его спрашивают «а ты питон 2 понимаешь, у нас легаси код есть, надо его рефакторить иногда, соединять с новым кодом, ну и вообще понимать что происходит».
                              А он такой «ахаха, Вы лузеры, у Вас в продакшене питон 2, спасибо не интересно, сейчас уже 2020 год, питон 2.7 снимается с поддержки в этом году, пхп 5.3 с поддержки снят еще летом 2019, кому Вы нужны отсталые динозавры».
                              Что характерно, такой спец будучи нанят на какой-то стартап (а легаси нет только в стартапах, да и то не всегда, вспомним питон2 у которого куча либ отсутствующих в питон3), через несколько лет после выхода пхп 8 будет считать свои знания 7-ки огромным преимуществом, хотя до этого считал что знать 5-ку недостойно его квалификации.

                              p.s.: Даже в зендовской сертификации на 7-ку есть вопросы из 4-ки и 5-ки и их отличий от 7-ки. Так что этот «современный» специалист даже зендовский сертификат по пхп не получит со своим ЧСВ по поводу легаси кода.
                                0
                                Так что этот «современный» специалист даже зендовский сертификат по пхп не получит со своим ЧСВ по поводу легаси кода.

                                И что? Я не получу — мне от этого в старье углубляться?
                                Даже если принять со всей серьезностью легаси и его необходимость — мне лезть в это старье ради сертификата? Бред. И необходимость сертификата — отдельный бред.

                                через несколько лет после выхода пхп 8 будет считать свои знания 7-ки огромным преимуществом, хотя до этого считал что знать 5-ку недостойно его квалификации

                                И породится еще одно «поколение с 15 летним опытом, бизнесу нужно», вместо того, чтобы всем дружно следовать одному курсу роста квалификации.
                                Не нужно устаревание навыков и остановку роста бояться называть старостью и остановкой. Это имеет причины и имеет последствия. Сейчас легаси реально есть на 7 версиях.
                                  0

                                  Немного не так.


                                  Я говорю, что есть бизнес, который кладет на развитие своих сотрудников. И такой бизнес, если что-то пойдет не так, в первую очередь поменяет команду исполнителей. Ты пилишь систему четвертый год и постоянно жалуешься, что под текущие нагрузки она не проектировалась. А потом наблюдаешь, как твой проект постепенно загибается, а рядом набрали новую команду с современными компетенция… И правильно сделали, потому что у твоей команды есть понимание, что старое не тянет, но опыта с новым нет. И за эти четыре года у вас не было времени его получать.


                                  Специалист, работающий с современными технология, по опыту, довольно быстро адаптируется в легаси-проекте. Но если надо идти заниматься исключительно легаси проектом, то надо просить конский оверпрайс. Чтобы хоть как-то компенсировать потерю своей привлекательности на рынке за время, проведенное в таком проекте.

                                    0
                                    мне от этого в старье углубляться? Не нужно устаревание навыков и остановку роста бояться называть старостью и остановкой.
                                    Maksclub
                                    Не нужно наклеивать ярлык старье только потому, что у Вас нет желания уделить хоть немного времени легаси.
                                    По факту 5-ка пхп и 2-ка питона это легаси, которое пока что надо знать, если Вы хотите считать себя серьезным разработчиком. А не ковбоем врывающимся в любой серьезный проект с криком «тут все старье, надо выкинуть и написать все с нуля, потому что я понятия не имею как оно работает и разбираться не буду»©

                                    Немного не так.

                                    Я говорю, что есть бизнес, который кладет на развитие своих сотрудников
                                    Почему Вы говорите что бизнес кладет на развитие своих сотрудников? Нигде в дискуссии не утверждалось, что не надо использовать современные технологии.

                                    Ты пилишь систему четвертый год и постоянно жалуешься, что под текущие нагрузки она не проектировалась.
                                    Так перепроектируйте его на современные рельсы. И вот сюрприз — прогеры незнакомые с легаси не смогут перепроектировать легаси код на современные рельсы, они придут — заявят что «это все старье и г-но код и надо писать все заново». И будут 4 года пилить все заново, а тем временем питон 3-шка станет легаси кодом и нужна будет новая команда, потому что «нельзя же работать со старьем».

                                    Специалист, работающий с современными технология, по опыту, довольно быстро адаптируется в легаси-проекте.
                                    Скорее наоборот. Специалист с бакграундом в легаси быстро адаптируется к современности. Потому что он будет понимать откуда ноги растут.

                                    если надо идти заниматься исключительно легаси проектом, то надо просить конский оверпрайс
                                    Вы так говорите, как будто изучить легаси 5-ки пхп это нечто сравнимое с изучением явы после бейсика.
                                      0
                                      Так перепроектируйте его на современные рельсы

                                      Дать возможность перепроектировать на новые рельсы команде, которая с ними не знакома, — это авантюра подороже будет, чем нанять новую команду, знакомую с этими рельсами.

                                      Если же в компании налажена система по техническому росту своих сотрудников, то тогда вопрос: а как там оказался легаси проект, который не находится в процессе миграции на новый стек?

                                      Потому что он будет понимать откуда ноги растут.

                                      Есть ровно противоположный опыт. Бест-практики возрастом более 10 лет, которые уже рассматриваются как анти-паттерны. И очень интересные нестандартные архитектурные решения (зарекомендовавшие себя костыли с предыдущего места работы).

                                      Любая отсебятина сотрудника в проекте уменьшает автобусный фактор. И требует инициализации процесса по шерингу знаний об этой отсебятине.

                                      Вы так говорите, как будто изучить легаси 5-ки пхп это нечто сравнимое с изучением явы после бейсика.

                                      Я говорю об обратной ситуации. Что если вам будет суждено провести следующие лет 5 в легаси проекте, то цена ваших технических навыков по завершению этого проекта будет рынком проигнорирована.
                                        0
                                        Дать возможность перепроектировать на новые рельсы команде, которая с ними не знакома
                                        Опять Вы с этой мантрой о том, что «тот кто знает питон 2, тот не может знать питон 3». Неужели так трудно представить себе команду знакомую с легаси, которая знакома и с новыми рельсами?

                                        Я говорю об обратной ситуации. Что если вам будет суждено провести следующие лет 5 в легаси проекте
                                        Есть разница между «проектом в котором есть легаси» и «проектом который будут делать на легаси». Топик если что о первом варианте, Вы же упорно сворачиваете на второй.

                                        Есть разница между «у нас пара сервисов/проектов (из нескольких десятков) в фазе поддержки крутятся на php 5.3 иногда — надо фиксить что-то» и «заниматься исключительно легаси проектом». Если в первом случае твое знание старых версий — твое конкурентное преимущество перед другими кандидатами «при прочих равных»,
                                        VolCh Абсолютно так.
                                        0
                                        Вы так говорите, как будто изучить легаси 5-ки пхп это нечто сравнимое с изучением явы после бейсика.

                                        Есть разница между "у нас пара сервисов/проектов (из нескольких десятков) в фазе поддержки крутятся на php 5.3 иногда — надо фиксить что-то" и "заниматься исключительно легаси проектом". Если в первом случае твое знание старых версий — твое конкурентное преимущество перед другими кандидатами "при прочих равных", то во втором случае это большой конкурентный минус работодателя/заказчика и этот минус должен им оплачиваться, если хочет получать адекватных специалистов.

                          0

                          Опытным путем показано, что в компаниях, в которых используются древние технологии, IT стоит далеко не на первом месте. И те, кто хочет развиваться в IT, в таких компания не задерживаются, да и не идут туда.


                          "У вас в продакшене PHP 5.3? Спасибо, неинтересно".


                          Кроме зарплаты заметно выше рынка (в реальности не больше средней по рынку), такие конторы ничего IT-специалисту предложить не могут. Но огромный минус в остановке в развитии на время работы в такой компании, не стоит даже тех бонусов, которые могут там предложить.

                            0

                            Ещё они могут предложить специалисту осуществить или возглавить перевод легаси на новые рельсы, предложив больше среднего по рынку за знание и нового, и старого и за готовность в старом копаться.

                            +2
                            Так это проблемы тех, у кого legacy в проде до сих пор.

                            Информация об особенностях php 5.x не повышает моей ценности как специалиста в долгосрочной перспективе. Выбирая между вариантами — потратить время на изучение тонкостей новой версии tensorflow/keras (сюда можно подставить что угодно из новых технологий) и изучить особенность сильно устаревшей версии php, я конечно же выберу первый вариант. Потому что именно он принесет мне пользу, позволит в будущем оставаться востребованным специалистом и зарабатывать много денег. А вариант №2 ведет меня в болото поддержки древнего говна, профессиональной деградации, невостребованности на рынке через 3-5 лет и зависимости от одного работодателя.

                            Когда я начинал карьеру разработчика у многих на проде был еще php 4, и разумеется я даже сейчас помню многие особенности ветки 4.x, вот только это одно из наиболее бесполезных знаний в моей голове, с радостью бы забыл.
                              0

                              Ну вот отсылки к четвёрке, например, из мануала почти везде уже вырезали.

                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Спасибо, исправил
                            +4
                            Получать значение private полей ивне класса — зачем? Эти поля для того и нужны, чтобы к ним доступ был только изнутри.
                            JSON_NUMERIC_CHECK в большинстве случаев избыточен. Достаточно написать (int)$a, либо $a === null? null: (int)$a. Плюс в PHP 7 (особенно 7.4) более-менее присутствует строгая типизация.
                            Дело в том, что данный атрибут преобразует в число вообще все строки — которые нужно и которые не нужно. Если у вас поле должно быть строго строкой, но пользователь ввел в него цифры…
                              0
                              Получать значение private полей ивне класса — зачем?

                              Чтобы можно было сериализовать, а потом десериализовать, и получить что было.


                              [Де]сериализацию я имею ввиду в широком смысле — от банального serialize() до Data Mapper ORM.

                              –3
                              Спасибо! Узнал для себя новое! Сохранил на память!)
                                +5
                                echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK); // {"string_float":3}

                                Я убежден, что правильнее будет следить за типами своих данных и не полагаться на неявное преобразование типов. Тогда к моменту, когда мы хотим сериализовать число, оно у нас будет уже числом, а не строкой


                                echo json_encode(["real_float" => 3.0]); // {"real_float":3}
                                  +4

                                  Докину в копилку проблему, с которой сталкивался сам.


                                  Сериализуем какой-то словарь данных:


                                  json_encode(["key1" => "value1"]) // {"key1": "value1"}

                                  В один прекрасный день у нас словарь на входе оказался пустым. Ну, всякое бывает, рабочая ситуация.


                                  json_encode([]) // [] - Упс - нарушили контракт, вернули массив вместо объекта!

                                  Лечится флагом JSON_FORCE_OBJECT (тоже, конечно же, прекрасно описанном в документации)

                                    0

                                    JSON_FORCE_OBJECT как и JSON_NUMERIC_CHECK может приводить к проблемам когда форсится не то что надо. Если в вашем словаре бывают массивы, то больно иным способом.


                                    Если конкретный массив должен стать в любом случае объектом в JSON, лучше собирать данные в stdClass или, что семантичнее, в ArrayObject

                                      0

                                      Спасибо, ценное замечание.
                                      Действительно, в моем случае JSON_FORCE_OBJECT работал, потому что вложенных массивов не было.

                                    +2

                                    Извиняюсь за именование флага JSON_UNESCAPED_UNICODE, молод был :) Хотя и сейчас с трудом придумал бы как ее лаконично назвать.

                                      0
                                      Нормальное название) лучше чем какой нибудь JSON_UNSC_UNCD
                                      +3

                                      На всякий случай хочу дополнить, что флаг JSON_THROW_ON_ERROR нынче обязателен для любых операций при работе с JSON.

                                        0
                                        Ну если в статье 5.4 как граница указана, то про этот флаг будем читать через пару лет :)
                                          0

                                          Ну я вообще не понимаю зачем учитывать такое старьё. Уже 7ка как бы депрекейтед, даже 7.1. А тут 5.4 10ти летней давности.

                                            0
                                            Потому что согласно статистике w3techs.com/technologies/details/pl-php
                                            php 5 используется на 53.7% веб-сайтов
                                            php 7 используется на 45.9% веб-сайтов
                                              +1
                                              В каком году написана эта страница?
                                              Там последние страницы 2018 года, а данная страница — не известно какого года.

                                              Я не видел ни одной работы в Москве с 5 версией на борту. А в Москве большая часть крупных проектов в РФ и видел я много. Не будем брать в расчет хостинги и блоги на них (коих может быть большее число), но там и нет инженеров, которые бы ПРАВИЛЬНО с json работали бы.

                                                0
                                                В каком году написана эта страница?
                                                В 2020. Там же написано в Technologies Overview как это собирается и что оно обновляется ежедневно.
                                                  0
                                                  На вид там все зачахло.
                                                  Кроме того ниже привел ссылки — статистика за первое полугодие 2017 напоминает картину по вашей ссылке. Потому склонен верить в правдоподобность, но просто потерявшую актуальность. Виджеты работают динамически с датой, потому тут все ясно-понятно.

                                                  Вы серьезно будете утверждать про актуальность? Честно? :)
                                                  w3techs.com/technologies/history_overview/programming_language
                                                    0
                                                    Скорее всего зачахло, но если Вы посмотрите по годам — то разница между январем 2019 и январем 2020 есть. Если бы там просто все умерло — данные были бы одними и теми же.
                                                0
                                                вот статистика за вторую половину 2019
                                                blog.packagist.com/php-versions-stats-2019-1-edition

                                                Там есть ссылки за разные годы (вверху статьи) и за первую половину 2017 статистика схожа с вашей:
                                                seld.be/notes/php-versions-stats-2017-1-edition
                                                  0
                                                  вот статистика
                                                  Там статистика не об использовании версий php вебсайтами, а об использовании версий php композером. Понятно, что 7-ка будет пользоваться композеров в разы чаще, просто потому, что сайты на 5-ке на порядок реже используют композер.
                                                  В современном композере, кстати, знаете что сказано? «Composer requires PHP 5.3.2+ to run»©

                                                  При этом обратите внимание, если посмотреть требования пакетов на той же странице — то больше 50% репозитариев требует 5-ку.
                                                    0
                                                    Ок, в этом и есть погрешность, тк ваша статья писалась примерно в 2018 году, а сошлась со статистикой 2017 начала…

                                                    Но даже WP, кладезь старых версий сайтов — 44% на старых версиях,
                                                    wordpress.org/about/stats

                                                    Понятное дело большие проекты так или иначе обновились, тк это ни разу не сложно и выгодно.

                                                    Сюда добавлю довод, который уже писал — никогда на собеседованиях не видел проектов с 5 на борту, а я много прошел их. Один раз вроде говорили про Woman.ru, но они вроде обновляли на тот момент (могу соврать), все, везде 7.1 минимум, как правило 7.2
                                                      0
                                                      в этом и есть погрешность
                                                      Это не погрешность, это просто данные не о том. Все равно что считать не количество легковых авто, а количество водителей с категорией на легковые авто и из второго делать вывод о том, что грузовых авто в городе нет.
                                                      сошлась со статистикой 2017 начала…
                                                      «больше 50% репозитариев требует 5-ку» — это из Вашей ссылки статистики 2019 года, а не 2017.
                                                      никогда на собеседованиях не видел проектов с 5 на борту, а я много прошел их
                                                      Просто обычно персонал на них уже есть и его ценят и не отпускают. Да и редко это критично, можно дообучить если что.
                                                      У нас где-то половина проектов так или иначе несут в себе легаси 5-ки. Если проект «современный», то так или иначе убалтываем на плавный рефакторинг на 7-ку. Если проект «классический», то как правило заворачиваем 5-ку (или 4-ку :D есть и такое еще) в докер и пишем интерфейс для общения с легаси. Не проблема абсолютно, но для того и другого надо иметь представление о легаси.
                                          +1
                                          Спасибо за статью, не знал про JSON_UNESCAPED_UNICODE и JsonSerializable, последние вообще красота, по АПИ надо отдавать объекты, которые предназначены только для чтения и конечно у них все свойства приватные, раньше приходилось писать собственный toJson(), а теперь всё ясно что делать:
                                              public function jsonSerialize() 
                                              {
                                                  $fields = get_object_vars($this);
                                                  // что-то делаем ...
                                                  return $fields;
                                              }
                                          


                                          Совет использовать функцию get_object_vars($this) я в своё время нагуглил, а про JsonSerializable узнал только из вашей статьи. спасибо.
                                            0
                                            {"string_float":3.0}

                                            Это кому Вы такой JSON передавать собрались? Если Javascript-у, то ему всё равно.
                                              0
                                              нет лишний кавычек, и как следствие смотреть consil.log приятней, нет сплошной каши из строк, но вообще это был разбор конвертации, вы если не сталкивались, т овам конечно сложно понять в чём боль.

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое