PHP 7. Часть 6. Декларация возвращаемых значений


Содержание материала:

Возврат значений

Значения возвращаются при помощи необязательного оператора возврата. Возвращаемые значения могут быть любого типа, в том числе это могут быть массивы и объекты. Возврат приводит к завершению выполнения функции и передаче управления обратно к той строке кода, в которой данная функция была вызвана. Для получения более детальной информации ознакомьтесь с описанием return .

Если конструкция return не указана, то функция вернет значение NULL .

Использование выражения return

Пример #1 Использование конструкции return

Функция не может возвращать несколько значений, но аналогичного результата можно добиться, возвращая массив.

Пример #2 Возврат нескольких значений в виде массива

Для того, чтобы функция возвращала результат по ссылке, вам необходимо использовать оператор & и при описании функции, и при присвоении переменной возвращаемого значения:

Пример #3 Возврат результата по ссылке

Для получения более детальной информации о ссылках обратитесь к разделу документации Подробно о ссылках.

Объявление типов возвращаемых значений

В PHP 7 добавлена возможность объявлять тип возвращаемого значения. Аналогично объявлению типов аргументов можно задать тип значения, которое будет возвращаться функцией. Типы, которые можно объявить для возвращаемых значений те же, что и для аргументов фукнций.

Режим строгой типизации также работает для объявлении типа возвращаемого значения. В обычном режиме слабой типизации возвращаемое из функции значение приводится к корректному типу. При строгой типизации возвращаемое значение должно быть заданного типа, иначе будет выброшено исключение TypeError.

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

Примеры

Пример #4 Обычное объявление типа возвращаемого значения

function sum ( $a , $b ): float <
return $a + $b ;
>

// Будет возвращаться значение типа float.
var_dump ( sum ( 1 , 2 ));
?>

Результат выполнения данного примера:

Пример #5 То же в режиме строгой типизации

declare( strict_types = 1 );

function sum ( $a , $b ): int <
return $a + $b ;
>

var_dump ( sum ( 1 , 2 ));
var_dump ( sum ( 1 , 2.5 ));
?>

Результат выполнения данного примера:

Пример #6 Возврат объектов

function getC (): C <
return new C ;
>

Новинки в PHP 7

3 декабря был релиз PHP 7. Мы перевели для вас описание новинок со страницы документации http://php.net/manual/en/migration70.new-features.php. Это первая часть.

Объявление скалярных типов

Теперь используются два режима преобразования типов: неявное преобразование (coercive) и явное (strict).

Для параметров доступны типы:

  • строки (string),
  • целые числа (int),
  • числа с плавающей запятой (float),
  • булевы переменные (bool).

Это дополняет набор типов данных в PHP 5: имена классов, интерфейсы, массивы (array) и callable.

Для включения режима строгой типизации используйте директиву declare в начале файла:

Режим типизации применяется к конкретному файлу. Включение строгой типизации влияет на вывод скалярных значений, возвращаемых значений, встроенных функции PHP и функций расширений.

Определение типов возвращаемых значений

В PHP 7 появилась возможность объявлять тип возвращаемого значения. Это напрямую коррелирует с новым режимом типизации: при строгой типизации возвращаемые значения должны строго соответствовать заданному типу, иначе будет выброшено исключение TypeError.

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

Оператор объединения со значением NULL

Оператор объединения со значением NULL (??) введен для улучшения читаемости кода в случае, когда обычно используется тернарный оператор и isset(). Оператор возвращает первый операнд, если аргумент определен и не равен NULL и второй операнд в любых других случаях.

Оператор «космический корабль»

Сравнивает два выражения, возвращая -1, 0 и 1, когда первый аргумент меньше, равен или больше второго соответственно. Сравнение производится с помощью обычных правил сравнения типов PHP.

Определение константных массивов define()

Константные массивы могут быть объявлены с помощью define(). В PHP 5.6 они могли быть определены только с помощью директивы const.

Анонимные классы

Поддержка объявления анонимных классов с помощью new class. Это можно использовать для объявления одноразовых объектов без написания целого класса.

Escape-последовательности юникод-символов

Юникод-символы задаются шестнадцатеричным кодом в строке с двойными кавычками или herdoc-определении. Допускается добавление одной или нескольких цифр «0» перед кодом символа.

Closure::call()

Метод Closure::call() — более производительный способ временной привязки контекста объекта к замыканию и его вызова.

Остальные нововведения — во второй части. Stay tuned.

Тем, кто хочет разрабатывать на PHP, рекомендуем профессию «Программист PHP».

3 декабря был релиз PHP 7. Мы перевели для вас описание новинок со страницы документации http://php.net/manual/en/migration70.new-features.php. Это первая часть.

Объявление скалярных типов

Теперь используются два режима преобразования типов: неявное преобразование (coercive) и явное (strict).

Для параметров доступны типы:

  • строки (string),
  • целые числа (int),
  • числа с плавающей запятой (float),
  • булевы переменные (bool).

Это дополняет набор типов данных в PHP 5: имена классов, интерфейсы, массивы (array) и callable.

Для включения режима строгой типизации используйте директиву declare в начале файла:

Режим типизации применяется к конкретному файлу. Включение строгой типизации влияет на вывод скалярных значений, возвращаемых значений, встроенных функции PHP и функций расширений.

Определение типов возвращаемых значений

В PHP 7 появилась возможность объявлять тип возвращаемого значения. Это напрямую коррелирует с новым режимом типизации: при строгой типизации возвращаемые значения должны строго соответствовать заданному типу, иначе будет выброшено исключение TypeError.

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

Оператор объединения со значением NULL

Оператор объединения со значением NULL (??) введен для улучшения читаемости кода в случае, когда обычно используется тернарный оператор и isset(). Оператор возвращает первый операнд, если аргумент определен и не равен NULL и второй операнд в любых других случаях.

Оператор «космический корабль»

Сравнивает два выражения, возвращая -1, 0 и 1, когда первый аргумент меньше, равен или больше второго соответственно. Сравнение производится с помощью обычных правил сравнения типов PHP.

Определение константных массивов define()

Константные массивы могут быть объявлены с помощью define(). В PHP 5.6 они могли быть определены только с помощью директивы const.

Анонимные классы

Поддержка объявления анонимных классов с помощью new class. Это можно использовать для объявления одноразовых объектов без написания целого класса.

Escape-последовательности юникод-символов

Юникод-символы задаются шестнадцатеричным кодом в строке с двойными кавычками или herdoc-определении. Допускается добавление одной или нескольких цифр «0» перед кодом символа.

Closure::call()

Метод Closure::call() — более производительный способ временной привязки контекста объекта к замыканию и его вызова.

Остальные нововведения — во второй части. Stay tuned.

Тем, кто хочет разрабатывать на PHP, рекомендуем профессию «Программист PHP».

Тишина «Декларация. должна быть совместимой» в PHP 7

После обновления до PHP 7 журналы почти задохнулись от таких ошибок:

PHP Warning: Declaration of Example::do($a, $b, $c) should be compatible with ParentOfExample::do($c = null) in Example.php on line 22548

Как отключить эти и только эти ошибки в PHP 7?

До появления PHP 7 они были E_STRICT типа предупреждений с которыми можно было легко справиться. Теперь они просто старые предупреждения. Поскольку я do хочу знать о других предупреждениях, я не могу полностью отключить все предупреждения.

У меня нет умственной способности переписывать эти устаревшие API, даже не упоминая все программное обеспечение, которое их использует. Угадайте, что, никто не заплатит за это тоже. Я не разрабатываю их, в первую очередь, поэтому я не виноват. (Единичные тесты? Не в моде десять лет назад.)

Я хотел бы избегать любых обманщиков с func_get_args и, насколько это возможно, как можно больше.

На самом деле я не хочу перейти на PHP 5.

Я все еще хочу узнать о других ошибках и предупреждениях.

Есть ли чистый и хороший способ выполнить это?

1. Обходной путь

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

Этот обработчик ошибок возвращает true для предупреждений, начинающихся с Declaration of которое в основном говорит PHP, что предупреждение было обработано. Вот почему PHP не будет сообщать об этом предупреждении в другом месте.

Кроме того, этот код будет работать только в PHP 7 или выше.

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

2. Правильное решение

Что касается фактического исправления другого унаследованного кода, существует ряд случаев, когда это можно сделать между простым и управляемым. В приведенных ниже примерах класс B является подклассом A Обратите внимание, что вы не обязательно удалите любые нарушения LSP, следуя этим примерам.

Некоторые случаи довольно просты. Если в подклассе отсутствует аргумент по умолчанию, просто добавьте его и двигайтесь дальше. Например, в этом случае:

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

Вы можете использовать утверждения или выдать исключение в зависимости от серьезности.

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

Если у вашего подкласса меньше аргументов, чем у суперкласса, и вы можете сделать их необязательными в суперклассе, просто добавьте заполнители в подкласс. Заданная строка ошибки:

Если вы видите некоторые аргументы, требуемые в подклассе, возьмите дело в свои руки.

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

Конечно, это может стать очень утомительным, если вам нужно удалить более одного аргумента.

Все становится намного интереснее, если у вас есть серьезные нарушения принципа замещения. Если у вас нет набранных аргументов, то это легко. Просто сделайте все дополнительные аргументы необязательными, а затем проверьте их наличие. Данная ошибка:

Обратите внимание, что мы не могли использовать func_get_args() здесь, потому что он не учитывает аргументы по умолчанию (не переданные). Нам осталось только func_num_args() .

Если у вас есть целые иерархии классов с расходящимся интерфейсом, возможно, будет проще расходиться еще дальше. Переименуйте функцию с конфликтующим определением в каждом классе. Затем добавьте прокси-функцию в одном родительском посреднике для этих классов:

Таким образом, LSP все равно будет нарушен, хотя и без предупреждения, но вы сохраните все проверки типов, которые вы имеете в подклассах.

Если вы должны отключить эту ошибку, вы можете объявить класс внутри принудительного выражения с немедленным вызовом:


Я бы настоятельно рекомендовал против этого. Лучше исправить свой код, чем отключить предупреждения о том, как он сломался.

Если вам нужно поддерживать совместимость с PHP 5, имейте в виду, что приведенный выше код работает только в PHP 7, потому что PHP 5 не имеет единого синтаксиса для выражений. Чтобы заставить его работать с PHP 5, вам нужно назначить функцию переменной перед ее вызовом (или сделать ее именованной функцией):

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

PHP 7 удаляет уровень ошибки E_STRICT . Информацию об этом можно найти в заметках по совместимости с PHP7. Вы также можете прочитать документ заявки, где он обсуждался, когда разрабатывался PHP 7.

Простой факт: уведомления E_STRICT были введены несколько версий назад, в попытке уведомить разработчиков о том, что они используют плохую практику, но изначально без каких-либо изменений. Однако последние версии и PHP 7, в частности, стали более строгими в отношении этих вещей.

Ошибка, которую вы испытываете, — это классический случай:

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

Большинство современных языков программирования фактически не позволяли бы это делать. PHP использовал, чтобы позволить разработчикам уйти с такими вещами, но язык становится все более строгим с каждой версией, особенно сейчас с PHP 7 — они пошли с новым основным номером версии специально, чтобы они могли оправдать значительные изменения, которые ломаются обратная совместимость.

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

На самом деле не существует той работы, которую вы ищете. Язык PHP развивается, и если вы хотите придерживаться PHP 7, ваш код также должен развиваться. Если вы действительно не можете исправить код, вам придется либо подавить все предупреждения, либо жить с этими предупреждениями, загромождающими ваши журналы.

Другое, что вам нужно знать, если вы планируете придерживаться PHP 7, заключается в том, что с этой версией существует ряд других разрывов совместимости, в том числе некоторые, которые довольно тонкие. Если ваш код находится в состоянии, в котором он имеет ошибки, подобные тому, который вы сообщаете, это означает, что он, вероятно, довольно долгое время, и, вероятно, имеет другие проблемы, которые вызовут проблемы в PHP 7. Для такого кода, Я бы предложил провести более тщательный аудит кода, прежде чем совершать PHP 7. Если вы не готовы сделать это или не готовы исправить найденные ошибки (и подразумевается, что ваш вопрос таков, что вы не являетесь), то я бы предположил, что PHP 7, вероятно, слишком сильно для вас.

У вас есть возможность вернуться к PHP 5.6. Я знаю, что вы сказали, что не хотите этого делать, но в краткосрочной перспективе это облегчит вам жизнь. Честно говоря, я думаю, это может быть вашим лучшим вариантом.

Please verify you are a human

Access to this page has been denied because we believe you are using automation tools to browse the website.

This may happen as a result of the following:

  • Javascript is disabled or blocked by an extension (ad blockers for example)
  • Your browser does not support cookies
Топ-пост этого месяца:  Эффективность различных каналов рекламы в интернете

Please make sure that Javascript and cookies are enabled on your browser and that you are not blocking them from loading.

Reference ID: #425535b0-01f4-11ea-9c18-65c21abde1af

Блог Александра Денисюка

Два месяца назад я перешёл на PHP7 и в этом посте хочу поделиться нововведениями, которые пришлись по нраву мне больше всего. Во первых, переход на новую ветку PHP обусловлен приростом производительности и уменьшением потребляемых ресурсов, т. е. крупные сайты с PHP7 могут в два раза снизить расходы на хостинг и быстрее генерировать конечному пользователю. Здесь выигрывают сразу и владельцы сайтов, и их посетители.

Это сравнение скорости между версиями 5.6 и 7.0 на различных платформах. Zend Framework даёт прирост скорости на 133%, а WordPress — 129%. Такое улучшение PHP имеет позитивные последствия для бизнеса.

В прошлом году Badoo, WordPress.com, Tumblr и многие другие гиганты перешли на PHP7. Так, например, компании Badoo за счёт снижения CPU в два раза и уменьшения потребления памяти в 8 раз удалось сэкономить 1 млн долларов. Сайт WordPress.com также полностью переведён на PHP7, где прирост производительности действительно заметен:

https://t.co/VrQffeOtG0 has been 100% switched over to PHP7, bringing significant performance improvements. #wcus pic.twitter.com/MChiS9QBJh

Быстродействие в новых версиях стало самым крутым и обсуждаемым нововведением. Теперь не нужно заморачиваться по оптимизации каких-то участков кода, а сразу писать понятный и поддерживаемый код. Во вторых, в PHP 7.0 и 7.1 введено большое количество улучшений на уровне синтаксиса и функциональности. Далее на примерах я покажу, что мне понравилось в новых версиях и как эти нововведения поменяют язык PHP в будущем на уровне кода.

Замена тернарного оператора

На замену тернарного оператора пришёл «оператор объединения с null» или «null-коалесцентный оператор». Через два знака вопроса (??) можно указать цепочку значений в одну строку и будет выбрано первое значение, которое не равно null. Раньше этот подход применялся вместе с функцией isset(). Сейчас можно указать даже не существующие переменные и не мучатся c большой вложенностью как с тернарным оператором.

Групповое объявление классов, констант и функций

Начиная с версии 7.0 появилась возможность группировать объявления импорта классов, функций и констант, находящиеся в одном пространстве имён, в одной строке с помощью оператора use. Это нововведение на уровне синтаксического сахара, которое может наделить объявление имён компонентов определённой логикой.

Декларация типов и возвращаемых значений

Это самое мощное нововведение для ООП. Теперь при объявлении метода для каждой переменной можно указать свой тип, а также тип данных, который вернёт этот метод. В PHP 7.0 доступны следующие типы: array, callable, bool, float, int, string, имя класса или интерфейса. В версии 7.1 добавили ещё vo >iterable. Тип vo >iterable используется в качестве значения массива или объекта, реализующего интерфейс Traversable.

В примере выше отработала принуждающая декларация типов, т. е. PHP динамически привёл значения к нужному типу, когда в переменную с объявленным типом int мы передали string, например. Вместо того, чтобы сгенерировать ошибку, все значения переменных и результат функции был преобразован к указанному типу на лету. Это поведение установлено по умолчанию.

Строгую типизацию можно включить, если в начале скрипта прописать declare(strict_types=1) . Все значения должны полностью соответствовать указанным типам. В противном случае будет сгенерирована ошибка TypeError. Строгая типизация не затрагивает весь остальной код и её нужно прописывать для каждого скрипта отдельно.

В версии 7.1 появилась возможность обнулить возвращаемые типы. Это расширяет список возвращаеммых типов до null. Теперь функция может вернуть какой-то явно указанный тип или null. Достигается такое поведение путём добавления префикса в виде знака вопроса к указанному типу:

Декларация типов и возвращаемых значений выводит PHP на новый уровень и эти нововведения мне нравятся больше всего, т. к. со стороны разработчика повышается читабельность кода; чёткая согласованность входных и выходных данных; программист может быстрее понять, чего ожидать от функции; легче документировать код; появляется возможность изменять типы данных на лету. Это основополагающая функциональность PHP7, которой не знать уже сейчас недопустимо.

Обработка ошибок и исключений

В PHP 7.0 появился новый класс для внутренних ошибок Error и интерфейс исключений Throwable. Теперь Error и старый класс Excetion реализуют Throwable (пользовательские классы не могут реализовывать данный интерфейс). Exception можно использовать для отлова исключений, которые будут обработаны и выполнение программы продолжится. Класс Error служит для необратимых исключений и выбрасывается в случае ошибки PHP или на уровне ошибок разработчиков.

Большинство ошибок уровня E_ERROR или E_RECOVERABLE_ERROR будут выбрасывать Error, но некоторые будут выбрасывать объекты подклассов: ArithmeticError, AssertionError, ParseError, DivisionByZeroError, TypeError и ArgumentCountError (с версии 7.1). Эти подклассы ошибок не могут быть брошены самостоятельно, а только лишь словлены. Иерархию всех исключений можно представить в виде дерева:

Начиная с версии 7.1 появилась возможность в блоке catch обрабатывать сразу несколько исключений, перечисляя их через символ вертикальной черты. Может быть полезно для обработки одинаковых по логике ошибок или пользовательских исключений.

На место фатальных ошибок пришли исключения, которые могут быть обработаны и позволяют корректно завершить программу в случае каких-то косяков. Это добавляет гибкости PHP-приложению.

Остальные нововведения одним списком

Нововведения в PHP7+ это лишь начало большого перехода на новый уровень языка. С каждым релизом приложения будут становиться быстрее и безопаснее. На версии 7.0 и 7.1 нужно отреагировать уже сегодня и будь в курсе новых тенденций PHP, дабы не выпадать из сферы. Ниже привожу одним списком остальные нововведения:

7.0 Оператор spaceship (космический корабль) ↩
7.0 Задание констант массивов с помощью define() ↩
7.0 Появились анонимные классы ↩
7.0 Синтаксис кодирования Unicode ↩
7.0 Добавлен метод в замыкания Closure::call() ↩
7.0 unserialize() с фильтрацией ↩
7.0 Новый класс IntlChar ↩
7.0 Улучшена старая функция assert() ↩
7.0 Выражение return в генераторах ↩
7.0 Делегация генератора с помощью конструкции yield from ↩
7.0 Новая функция intdiv() для целочисленного деления ↩
7.0 session_start() принимает массив опций ↩
7.0 Новая функция preg_replace_callback_array() ↩
7.0 Новые функции random_bytes() и random_int() ↩
7.0 list() может раскрывать объекты реализующие ArrayAccess ↩
7.0 Обращение к методам и свойствам класса при клонировании (clone $foo)->bar() ↩
7.1 Короткий синтаксис для list() ↩
7.1 Публичные и приватные константы классов ↩
7.1 Поддержка ключей в list() ↩
7.1 Поддержка отрицательных смещений для строк ↩
7.1 Расширены функции openssl_encrypt() и openssl_decrypt() ↩
7.1 Преобразование callable в Closure с помощью Closure::fromCallable() ↩
7.1 Новая функция pcntl_async_signals() ↩
7.1 Поддержка Server Push в CURL 7.46 ↩

Как исправить или убрать ошибки вида “Declaration of … should be compatible with”, появившиеся с переходом на PHP 7

С переходом на PHP 7 лог ошибок по многим старым проектам оказался забит под завязку сообщениями подобного вида:

Это только один пример ошибки. Вариантов таких ошибок может быть множество.

Усложняют проблему следующие моменты:

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

Можно было бы вообще отключить все предупреждения, но тогда есть риск пропустить какие-то действительно важные ошибки. Отключать предупреждения совсем — не вариант.

Не хотелось бы терять все те улучшения в части скорости и стабильности, которые есть в PHP 7. Поддержка PHP 5 уже считай что закончилась, значит переходить на PHP 7 так или иначе будет нужно. Возвращаться на PHP 5 — не вариант.

С учётом вышесказанного, как можно освободить логи сервера только от этих ошибок?

3 ответа 3

Если не засовывать голову в песок, что есть сил стараясь не трогать старый код, которые пока еще работает, то есть ряд случаев когда исправления могут быть внесены либо просто, либо выполнимо. В примерах ниже класс B является подклассом для A . Примеры ниже не обязательно устранят принципиальные нарушения принципа подстановки (LSP), но хотя бы PHP не будет о них ругаться.

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

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

Вы захотите использовать assert или кидать исключение, в зависимости от серьезности ошибки.

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

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

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

Иногда может быть проще изменить метод суперкласса, удалив опциональный аргументы, перейдя на использование магии func_get_args . Не забудьте задокументировать этот виртуальный аргумент.

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

Все гораздо интересней если у вас есть серьезные нарушения принципа Лисковой. Если ваши аргументы не требуют типа, все просто. Достаточно сделать все аргументы опциональными, затем вручную проверяя их наличие. С такой ошибкой:

Обратите внимание что мы не можем использовать функцию func_get_args() в этом случае потому что эта функция не учитывает аргументы со значениями по умолчанию. Их просто не будет в возвращенном значении.

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

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

Такие ошибки как были предусмотрены с PHP 5.0 и самого появления type hinting в PHP так и остались.

Единственное что сначала уровень E_STRICT не входил в E_ALL и должен был быть указан явно, затем начиная с PHP 5.4 начал входить. После этого в PHP 7.0 ошибки из E_STRICT перераспределили по другим типам ошибок. Сообщество сошлось на мнении, что нарушение контракта базового класса — вещь плохая и должна быть заметна, потому присвоили этой ошибке уровень E_WARNING . Жаль, конечно, что в 2004 году изменили изначальную реализацию этой проверки, где такой тип ошибок генерировал вовсе E_COMPILE_ERROR .

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

Что делать дальше:

  • исправлять. Рефакторить такие грубые ошибки будет долго и это говорит об общем качестве кода. Наверняка даже E_NOTICE не включали.
  • игнорировать ошибки в логе
  • прятать голову в песок и прятать ошибки

Настроек «такие варнинги выводи, а такие нет» — к счастью нет.

Конкретную описанную в вопросе ошибку можно перенести в рантайм. В базовом классе указан один параметр без типа с дефолтным значением, дочерний класс может принимать дополнительные необязательные аргументы метода и это не является нарушением контракта класса.

Если же базовый класс требует какой-то класс аргументом, а дочерний в этом месте хочет скаляр или совсем другой объект — то меняйте контракт базового класса с type hinting на проверку в рантайме.

PHP 7: Что нового. часть 2

Функции CSPRNG

Криптографически стойкий генератор псевдослучайных чисел (англ. Cryptographically secure pseudorandom number generator, CSPRNG)

Новведение добавляет две новых функции для генерации криптографически стойких целых чисел и строк.
Функции работают одинаково на всех платформах.

Обе функции сгенерируют исключение `Error`, если источник необходимой случайности будет не найден.

Необратимые изменения
зарезервированные имена `random_int`, `random_bytes`.

Поддержка массивов в объявлениях define

В php 5.6 появилась возможность испльзовать массивы в константах (const),
теперь эта возможность добралась и до define.

Доработка Reflection

В PHP7 добавились два новых класса рефлексии.

Первый `ReflectionGenerator`, используется для интроспекции генераторов:

Второй `ReflectionType` для лучшей работы со скалярными и возвращяемыми типами:

Также, класс `ReflectionParameter` обзавелся двумя новыми методами:

Новые методы в `ReflectionFunctionAbstract`:

Необратимые изменения
Зарезервированные имена `ReflectionGenerator`, `ReflectionType`.

Изменения с PHP 5.x

Новые правила использования зарезервированных ключевых слов

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

Т.е. если раньше название метода зарезерварованным словом (new/for/etc. ) приводило к ошибке, теперь это разрешено:

Единственным ограничением остается слово `class`, оно не может быть использовано в названии константы,
иначе возникает конфликт с `ClassName::class`.

Унифицированный синтаксис переменных

Одно из основных изменений!
Теперь обращения к сложносочиненным переменным разбираются последовательно СЛЕВА НАПРАВО .

// вложенность ::
$foo :: $bar :: $baz // доступ к свойству $baz свойства $foo::$bar

// вложенность ()
foo ( ) ( ) // вызываем() результат вызова foo()

// операторы над выражениями заключенными в ()
( function ( ) < >) ( ) // IIFE синтаксис JS

Новый разбор вложенности переменных более интуитивен

Необратимые изменения
Старый код написанный с использованием <> для обработки переменных возможно не будет работать в новой версии PHP7.

Исключения в движке

Ранее движок PHP не позволял перехватывать фатальные ошибки, теперь эти ошибки преобразованы в исключения,
которые пользователь может обработать. И что не менее важно, конструкции finally и деструкторы объектов будут гарантированно вызваны в случае фатальных ошибок.
Дополнительным преимуществом новой системы обработки ошибок являтеся возможность получить стек вызовов (stack traces) во время ошибки.

function sum ( float . $numbers ) : float
<
return array_sum ( $numbers ) ;
>

try <
$total = sum ( 3 , 4 , null ) ;
> catch ( TypeError $typeErr ) <
// ошибки несоответствия типа
>

Необратимые изменения
— Кастомные обработчики ошибок для recoverable fatal ошибок больше не будут работать
— Ошибки разбора в `eval()`-коде теперь генерируют исключения, которые нужно ловить в `try. catch`

Интерфейс Throwable

Теперь класс Exception следует контракту Throwable,
эта унификация нужна для работы выражений catch-all (`catch (Exception $e)`) в легаси-скриптах, когда фатальные ошибки не являлись исключениями.


`Exception` и `Error` следуют интерфейсу `Throwable`

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

Целочисленная семантика

Поменялась семантика работы с целыми чилами для обеспечения кроссплатформенности:
— Кастинг `NAN` и `INF` в integer всегда = 0
— Битовый сдвиг ` >` на отрицательное число теперь запрещена (возврат false, с ошибкой E_WARNING)
— > правый сдвиг с количством бит превышающем размер целого = 0 или -1 (зависит от знака)

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

Расширение JSON Extension заменено на JSOND

Из-за проблем с лицензированием старого расширения JSON, которое создавало проблемы для линуксойдов, решено заменить расширение на JSOND.
В новой библиотеке присутствует выигрыш в производительности и, что печально, обратно несовместимые изменения.

Необратимые изменения
— Число не должно заканчиваться точкой «.» (`34.` должно быть `34.0` или `34`)
— Экспонента `e` не должна следовать сразу за точкой (`3.e3` должно быть `3.0e3` или просто `3e3`)

ZPP ошибка при переполнении

ZPP: zend_parse_parameters
При передаче float параметра в функцию, которая ожидает integer, может произойти обрезание параметра до размеров integer. Это может повлечь за собой трудно выявляемые баги. Поэтому при ошибочном конвертировании float в integer будет возвращен null и сгенерирована ошибка E_WARNING.

Необратимые изменения
Старый код, который раньше работал теперь будет генерировать E_WARNING и может перестать работать, если
результат вызова функции напрямую передается в другую функцию (т.к. будет передаваться `null`).

Доработки foreach()

Цикл foreach имеет несколько неприятных особенностей когда работает с копиями и ссылками на массив;
нерабочие манипуляторы указателя массива current(), reset(); изменение массива, по которому проходит итерация..

Изменение поведения list()

В документации list() сказано, что оператор не поддерживает строки, одно рассмотрим ситуацию

Топ-пост этого месяца:  Курс по PHP. Функция header в PHP

// разыменовывание массива
$str [ 0 ] = ‘ab’ ;
list ( $a , $b ) = $str [ 0 ] ;
echo $a ; // a
echo $b ; // b

// разыменовывание объекта
$obj = new Std >( ) ;
$obj -> prop = ‘ab’ ;
list ( $a , $b ) = $obj -> prop ;
echo $a ; // a
echo $b ; // b

// возврат функции
function func ( )
<
return ‘ab’ ;
>

list ( $a , $b ) = func ( ) ;
var_dump ( $a , $b ) ;
echo $a ; // a
echo $b ; // b

Теперь такую возможность закрыли и list() со строками запрещен совсем.
Также, вызов list() с пустым аргументом вызовет фатальную ошибку;
порядок присвоения переменных изменился с лево-направо:

$a = [ 1 , 2 ] ;
list ( $a , $b ) = $a ;

// БЫЛО: $a = 1, $b = 2
// СТАЛО: $a = 1, $b = null + «Undefined index 1»

$b = [ 1 , 2 ] ;
list ( $a , $b ) = $b ;

// БЫЛО: $a = null + «Undefined index 0», $b = 2
// СТАЛО: $a = 1, $b = 2

Необратимые изменения
list() не распаковывает строки!
Вызов list() без параметров ведет к ошибке
Изменен порядок распаковки, в некоторых случаях может возвращаться null

Изменения в семантике деления на 0

До PHP7, когда делитель был 0 для операторов деления / или модуля %, возвращалась ложь (false) и генерировалось предупреждение E_WARNING.
Это явный бред для математической операции возвращать булево значение, поэтому такое поведение поправили.

Теперь оператор деления возвращает float равный INF, -INF, или NAN.
Оператор остатка больше не выдает E_WARNING, а бросает исключение DivisionByZeroError (intdiv() делает также).
Кстати, intdiv() также выкидывает исключение ArithmeticError, когда в результате слечается переполнение integer.

var_dump ( 3 / 0 ) ; // float(INF) + E_WARNING
var_dump ( 0 / 0 ) ; // float(NAN) + E_WARNING

var_dump ( 0 % 0 ) ; // DivisionByZeroError

intdiv ( PHP_INT_MIN , — 1 ) ; // ArithmeticError

Необратимые изменения
Оператор деления больше не возвращает `false`
Оператор остатка от деления (модуль) бросает исключение при делении на 0 вместо возврата false

Исправления в возвращаемых значениях кастомных обработчиках сессий

При реализации своего обработчика сессий, функции `SessionHandlerInterface` которые ждут возврата `true` или `false` не работают как положено.
Ошибка приводила к тому, что только -1 трактовалась как false, а реальный false выдавался за истину..

class FileSessionHandler implements SessionHandlerInterface
<
private $savePath ;

function open ( $savePath , $sessionName )
<
return false ; // always fail
>

function read ( $id )

function write ( $id , $data )

function destroy ( $id )

function gc ( $maxlifetime ) < >
>

session_set_save_handler ( new FileSessionHandler ( ) ) ;

session_start ( ) ; // до PHP 7 ошибка не возникала

Теперь этот код упадет с фатальной ошибкой.

Необратимые изменения
— boolean false воспринимается как false. false, -1 вызовут фатальную ошибку
— Любое другое значение помимо boolean, `0`, или `-1` будет неудачно и вызовет предупреждение

Конструкторы в стиле PHP4 устарели

Конструкторы вида className::className() больше не используются, остался только __construct().

Удалено предупреждение date.timezone

Если не установлена временная зона date.timezone в файле конфигурации, php выдавал предупреждение. Теперь зона по-умолчанию принимается за UTC и ошибки не возникает.

Альтернативные PHP тэги удалены

Раритеты , окончательно выпилены

Множественный default блок в Switch-e

Раньше можно было указать несколько меток default в операторе switch (исполнялась только последняя),
Теперь данное поведение вызовет фатальную ошибку.

Одинаковые названия аргументов фукнции

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

function foo ( $version , $version )
<
return $version ;
>

// PHP 7+
Fatal error : Redefinition of parameter $version in / redefinition — of — parameters . php

Удаленные SAPI

Следующие модули удалены из ядра (доступны в PECL):
— sapi/aolserver
— sapi/apache
— sapi/apache_hooks
— sapi/apache2filter
— sapi/caudium
— sapi/continuity
— sapi/isapi
— sapi/milter
— sapi/nsapi
— sapi/phttpd
— sapi/pi3web
— sapi/roxen
— sapi/thttpd
— sapi/tux
— sapi/webjames
— ext/mssql
— ext/mysql
— ext/sybase_ct
— ext/ereg

HEX-числа в строках

Удалена поддержка преобразований строк содержащих шестнадцатеричные числа.

var_dump ( is_numeric ( ‘0x123’ ) ) ;
var_dump ( ‘0x123’ == ‘291’ ) ;
echo ‘0x123’ + ‘0x123’ ;

// до PHP 7
bool ( true )
bool ( true )
582

// PHP 7+
bool ( false )
bool ( false )

Вместо простого кастига, строковые hex-числа должны валидироваться и конвертироваться в целое число с помощью функции filter_var():

Необратимые изменения
Новое поведение поломает функцию is_numeric() и операторы `==`, `+`, `-`, `*`, `/`, `%`, `**`, `++`, and `—`

Удаление старого функционала

— mysql extension (ext/mysql)
— ereg extension (ext/ereg)
— присвоение &new по ссылке
— вызов нестатических методов из вне Class::method(), где method() — нестатический метод

Необратимые изменения
Код с предупреждениями об устаревании (deprecation warning) в PHP 5 больше не будет работать (предупреждали же!)

Переклассифицирование и удаление сообщений E_STRICT

Предупреждения категории E_STRICT удалены из PHP, или переквалифицированны в E_DEPRECATED / E_NOTICE / E_WARNING.

Необратимые изменения
Так как E_STRICT низший уровень ошибок, любое повышение ошибки до E_WARNING может поломать кастомные обработчики ошибок

Устаревание опции Salt функции password_hash()

С появлением нового API хэширования паролей в PHP5.5, многие стали использовать его и генерировать свои собственные «соли». К сожалению программисты зачастую используют криптографически не безопасные функции типа mt_rand(), делая свою «соль» слишком слабой, по отношению к сгенерированной по-умолчанию. В общем, пользователям запретили использовать несекьюрные соли.

Ошибки восьмеричных литералов

Неправильные восьмеричные литералы теперь генерируют ошибку парсинга, а не проглатываются как раньше.

substr() изменение возвращаемого значения

substr() теперь возвращает пустую строку вместо false, когда начальная позиция подстроки совпадает с длиной строки.

var_dump ( substr ( ‘a’ , 1 ) ) ;

// до PHP 7
bool ( false )

// PHP 7+
string ( 0 ) «»

В остальных случаях substr() может попрежнему возвращать false

Что там с PHP6

Он утонул. В PHP6 планировали внедрить полную поддержку юникода в ядро, но эта затея оказалась слишком неподъемной, объем работ слишком велик.
Когда ребята это поняли, решено было пропустить мажорную версию (6), чтобы PHP не ассоциировался с фейлом, так началась работа над PHP7,
в который вошли многие наработки нерожденного.

Развитие синтаксиса PHP — новинки версий 5.3-7.1

В этой статье я рассмотрю интересные моменты в развитии синтаксиса PHP — получится своего рода список изменений PHP. Что появилось в версиях PHP 5.3 и выше. Основная цель этой статьи создать некую карту изменений синтаксиса, что можно было быстро освежить в памяти «фишки» синтаксиса PHP, которые упрощают коддинг. У меня в последнее время частенько возникает необходимость убедиться, что можно в PHP 5.3, а чего нельзя.

При написании плагинов или тем WordPress можно использовать только возможности PHP 5.3, выше пожалуй не стоит. Все что можно в PHP 5.4 и выше, нужно решать через создание вспомогательных переменных. Впрочем, даже 5.3 не всегда работает, есть еще серверы с PHP 5.2, но хорошо что это редкость. К слову, сам WordPress еще поддерживает PHP 5.2.

Итак, к новинкам.

$str1 <0>— синтаксис получения символа строки

Новый синтаксис обращения к символам строки:

$str2[0] не рекомендуется, хотя и работает точно также. Рекомендация использовать фигурные скобки <> связана с тем, чтобы при прочтении кода было сразу понятно, что обрабатывается строка, а не элемент массива. Как мы знаем квадратными скобками в PHP принято обозначать массивы, а не строки.

В PHP 5.3, как и во всей пятой ветке PHP, включена новая машина-интерпретатор скриптов Zend Engine 2.0. Благодаря этому PHP стал работать быстрее примерно на 15-20%.

Новые возможности в PHP 5.3 (ссылка на офф. сайт):

?: — сокращение тернарного оператора

С PHP 5.3 стало возможным не писать среднюю часть тернарного оператора. Выражение expr1 ?: expr3 возвращает expr1 если expr1 не пустой, и expr3 в противном случае.

Тернарный — состоящий из трёх частей, компонентов.

Пример тернарного оператора:

В короткой записи есть еще момент производительности, например:

В полной записи функция get_post_meta() вызывается 2 раза. В короткой один раз, и если она что-то вернула, второму аргументу сразу передается полученное значение: не нужны дополнительные переменные.

$func = function()<>; — анонимные (лямбда) функции

Лямбда-функции еще называют «анонимными функциями», потому что для них не указывается название.

Лямбда-функции представляют собой замыкание (англ. closure) — это особый вид функции, которая определена в теле другой функции и создаётся каждый раз во время её выполнения. Синтаксически это выглядит как функция, находящаяся целиком в теле другой функции. Насколько я понял, любая функция — это замыкание текущего контекста, т.е. контекст не будет очищен пока работает функция. Но если в функции есть лямбда-функция, то она становится замыканием, и если в неё передаются переменные из «верхней» функции, то они не будут очищены, до тех пор пока работает вложенная-функция, даже если «верхняя» функция работу закончила.

В ранних версиях, анонимные функции создавались с помощью функции create_function() .

Пример создания анонимной функции для сортировки usort():

Еще одна фишка лямбда-функций — это использование переменных из текущей области видимости, с помощью оператора use :

Переменные передаются как значение, но можно передать и ссылку на переменную, указав & :

method()->var — получение объекта из метода/функции

В PHP ниже 5.3 писали как-то так:

В php 5.3 можно использовать аналог HEREDOC, который называется NOWDOC. Особенность его в том, что внутри него переменные остаются простым текстом, как если бы мы указали её в строке с одинарными кавычками: ‘текст $foo’ :

namespace — поддержка пространств имен


Пространства имен нужны, чтобы избежать конфликтов при совпадении названий функций/классов/переменных/констант. Если коротко: одинаковые называния в разных пространствах — это разные названия.

Пример ниже должен объяснить почти все, что возможно в пространствах имен. За подробностями идем в официальную документацию.

__DIR__ — новая магическая константа

__DIR__ содержит директорию текущего файла — файла в котором она используется. Возвращает полный путь до текущего файла без закрывающего слэша, за исключением корневой директории.

__DIR__ можно заменить:

$class::$foo — динамичное указание класса

Это дает динамичный доступ к статическим методам/свойствам класса:

const — ключевое слово для создания констант вне классов

Сразу пример, где все понятно:

В отличие define() , такие константы, должны быть объявлены в самой верхней области видимости, потому что они определяются при компилировании скрипта. Это значит, что их нельзя объявлять внутри функций/циклов/выражений if или try/ catch блоков.

static::method() — статическое связывание

Статическое объявление метода/свойства связывает его с классом из которого оно вызывается, а не с тем в котором оно зарегистрировано. Посмотрим на примере:

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

goto hell; — оператор goto

Используется для перехода в другую часть программы. Место, куда необходимо перейти указывается с помощью метки, за которой ставится двоеточие, после оператора goto указывается желаемая метка для перехода.

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

Также нельзя перейти внутрь любой циклической структуры или оператора switch. Но можно выйти из любой циклической структуры, поэтому «goto» удобен как замена многоуровневых break.

Пример использования goto:

Пример использования goto в цикле:

__callStatic() , __invoke() — магические методы

__callStatic() — срабатывает, когда вызывается несуществующий метод из статического контекста: Foo::bar() :

__invoke() — срабатывает, когда объект выполняется как функция: $obj() :

Возможности, добавленные в версии PHP 5.4. Ссылка на офф. сайт.

— короткая запись вывода на экран работает всегда

Короткая запись о которой идет речь это: вместо .

Для работы такой короткой записи вывода на экран в версиях ниже 5.4 нужно было, чтобы опция short_open_tag в php.ini была включена.

Пример длинной и короткой записи:

[1,2] — запись массива, без слова array

trait Class <> — примеси (трейты)

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

Несколько примесей можно задавать через запятую:

Приоритеты трейтов

При совпадении названий свойств/методов приоритеты расставляются так: текущий класс имеет наивысший приоритет, затем трейт, а затем расширяемый класс. Другими словами: элементы из текущего класса переопределяют элементы в трейте, которые в свою очередь переопределяют унаследованные элементы.

Статический доступ к методу примеси из класса

Когда в класс подмешивается trait, то его методы становятся методами класса, включая статические и статический доступ:

foo()[0] — быстрое получение элемента массива

Теперь не нужно сохранять массив, который вернула функция/метод в переменную и получать элемент массива из этой переменной. Можно сразу получать элемент из функции/метода:

(new Foo)->method() — доступ к элементу объекта при его создании

Class::<'foo'>() — динамичное указание метода

Чтобы вызвать статический метод/свойство класса, не нужно запоминать его в отдельную переменную:

callable — новый тип для аргументов функции/метода

Авто-проверка передаваемых данных в функции/методы, известная как «контроль типа» (typehint), продолжает развиваться и теперь понимает слово callable .

Раньше для автоматической проверки типа передаваемого параметра, в аргументах функции/метода можно было указывать только: array или имя класса .

Теперь, можно указать еще: callable — значит, что передаваемый аргумент должен быть вызываемым, т.е. удовлетворяет условию is_callable( $arg, false ) .

Оператор @ нужен для подавления вывода ошибок любого уровня. Вообще его использовать не рекомендуется, но иногда с ним короче:

Использовать @ нужно как можно реже и очень осторожно, потому что часто заметки и предупреждения дают понять, что логика кода работает неправильно. Например, у меня бывало что лезу поправить казалось бы безобидный NOTICE, но при анализе выясняется что ошибка появилась из-за неправильной логики кода, которая изменилась в процессе расширения кода.

Новые возможности в PHP 5.5 (ссылка на офф.сайт):

[1,3,4][2] , «foobar» <2>— разыменования только-созданных массивов и строк

empty() — можно применять к результатам функций и выражений

Раньше empty() мог принимать только переменные, теперь можно передавать сами выражения без необходимости сохранять результат в отдельную переменную:

В foreach стало возможным использовать list():

finally — в конструкции try/catch

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

А с версии 5.5. в эту конструкцию добавили третий блок finally . Блок finally выполняется всегда после завершается конструкции try/catch. Он выполняется даже когда код try вызвал фатальную ошибку:

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

Пару домонстрационных примеров:

Меньше кода

Допустим, нам нужно выполнить функцию close() в любому случае, было выброшено исключение или нет:

Больше возможностей

Допустим мы открыли соединение с БД до выполнения кода и есть вероятность что код вызовет ошибку и открытое соединение не закроется, а нам нужно его закрыть в любом случае. finally как раз кстати:

Подробнее про finally читайте статью на хабре.

Class::class — для получение имени класса в пространствах

Появилось ключевое слово class для классов, которое выводит название класса. В обычном режиме нам это не нужно, а вот при работе с пространствами (namespace) — это удобно:

yield — создание генераторов

Если говорить простым языком: yield похожа на return, она также возвращает значение, но она не обрывает работу функции, а приостанавливает её до тех пор пока не будет запрошено следующее значение. Благодаря этому создавать генераторы стало удобнее.

Как это работает на самом деле?

yield возвращает специальный объект — Generator. Когда функция generator() вызывается в цикле, например foreach, PHP выполнит код функции до первой встречи слова yield , на котором PHP прервет работу функции, запомнит позицию и выбросит значение (объект Generator). Затем, foreach обработает значение и вызовет метод next() у полученного объекта Generator. PHP снова выполнит код функции generator() , только начнет его не с начала, а с прошлой позиции, и опять, до слова yield, которое опять выбросит объект Generator. Работа цикла прервется тогда, когда функция generator() дойдет до конца (не вернет yield), или если она будет прервана с помощью return; .

Пример генератора который возвращает пару: ключ/значение:

Кратко о генераторах

— Не добавляют нового функционала в язык
— Быстрее
— Возобновление работы генератора происходит с последнего «выброса» yield
— В генератор можно отправлять значения и исключения (через метод throw())
— Генераторы однонаправлены, т.е. нельзя вернуться назад
— Меньше кода в большинстве случаев, более простые для понимания конструкции

Топ-пост этого месяца:  Как сделать в Grid CSS колонки с автоматическим подбором размера auto-fit и auto-fill

Чтобы лучше понять генераторы прочитайте эту статью на Хабре.

API для хэширования паролей

Теперь PHP из коробки предлагает правильный способ хэшировать пароли. Новый API хэширования паролей предоставляет четыре функции:

password_hash() — используется для хэширования пароля. В WP для этого есть своя функция wp_hash_password().

password_verify() — используется для проверки пароля на соответствие хэшу. В WP для этого есть своя функция wp_check_password().

password_needs_rehash() — используется для проверки необходимости создать новый хэш.

  • password_get_info() — возвращает имя алгоритма хеширования и различные параметры, используемые при хэшировании.
  • Новые возможности PHP 5.6. Ссылка на офф.сайт.

    const PLUS = 1 + 2; — скалярные выражения в константах/свойствах/аргументах функции

    Теперь стало возможным указывать в значения констант примитивные PHP выражения (выражения из скаляров).

    Точнее, новинка касается не только констант, а всего где раньше PHP ожидал статическое значение. Теперь вместо статики можно указать выражение из чисел/строк/констант. Если точнее, то PHP выражение можно указывать: в константах/свойствах класса и в значении аргумента функции по умолчанию.

    const ARR = [‘a’, ‘b’]; — константа может хранить массив

    Стало возможным держать в константе массивы:

    func( . $args ) или func( . [2, 3] ) — неизвестное число аргументов функции или распаковка массива с помощью ‘. ‘ (splat оператор)

    Когда мы не знали заранее, сколько параметров может получить функция, нам приходилось внутри функции обрабатывать переданные параметры с помощью специальных функций: func_num_args(), func_get_arg(), func_get_args().

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

    Оператор . еще называют «Splat Оператор», например в языке Ruby

    Быстрая распаковка передаваемых параметров функции

    Теперь с помощью splat оператора . , можно указать параметры функции сразу из значений массива:

    Замена медленной функции call_user_func_array()

    Теперь call_user_func_array( $callback, $param_arr ) , которая обычно не самая быстрая, можно заменить так:

    ** — оператор возведения в степень

    До php 5.6, чтобы возвести число в степень нужно было использовать функцию pow(2,2); , а теперь есть оператор ** :

    use function и use const — импорт функций и констант в пространство

    Теперь стало возможным при помощью ключевого слова use подключать функции или константы другого пространства в наше:

    Остальные новинки PHP 5.6 не связанные с синтаксисом, смотрите в статье на Хабре.

    Куда делся PHP 6?

    Умер не родившись. В ядро PHP 6 планировали внедрить полную поддержку юникода, но затея оказалась слишком амбициозной, а объем работ слишком велик. К тому моменту, когда это стало понятно, о PHP 6 уже было написано не мало статей. Чтобы не было путаницы, из-за того что новая версия стала преследовать совсем другие цели (производительность) и сильно отличалась по концепции от PHP 6, было решено пропустить PHP 6. Еще одной причиной стало наличие весомого количества недоделанного кода в репозитории PHP, который решили не трогать, чтобы тот в ответ тоже никого не трогал.

    3 декабря 2015 года было объявлено о выходе PHP 7. Новая версия основывается на экспериментальной ветке PHP, которая изначально называлась phpng (PHPNextGeneration — следующее поколение), и разрабатывалась с упором на увеличение производительности и уменьшение потребления памяти.

    Самой важной новинкой стало изменение ядра интерпретатора: теперь он называется PHPNG (Next Generation). Благодаря PHPNG удалось увеличить скорость обработки скриптов почти в двое по сравнению с PHP 5.x. Так же появился более эффективный менеджер памяти.

    Прирост в скорости на практике хорошо виден на этой картинке. А для WordPress прирост в скорости выглядит так:

    Синтаксические новинки PHP 7:

    $a ?? » — одновременная проверка isset и получение значения

    Новый оператор слияния с NULL (NULL coalescing operator) ?? — это сокращение проверки isset и получения значения, если проверка пройдена.

    Такая проверка часто была нужна в тернарном операторе ?: :


    Так же, проверять можно по цепочке:

    $a $b — одновременное выполнение трех сравнений: больше, равно или меньше.

    Новый оператор сравнения — «spaceship operator» (космический корабль). Сравнивает 2 переменные и возвращает результат сравнения в виде числа:

    • -1 — если в сравнении подходит первый символ оператора
    • 0 — подходит второй символ =
    • 1 — подходит третий символ >

    Удобен для использования в колбэках для usort().

    define(‘FOO’, [1,2]); — передача массива константе через define()

    Константы могут содержать массивы еще с PHP 5.6. Но тогда их можно было передавать только через ключевое слово const. Теперь их можно указывать еще и через define().

    use name\space\; — группировка импорта при помощи use

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

    int, float, bool — новые типы для аргументов функции/метода

    Авто-проверка типа передаваемых данных в функции/методы, известная как «контроль типа» (typehint), продолжает развиваться и теперь понимает скаляры: int , float , bool , string . Раньше понимались только типы: array , имя класса или callable (с версии 5.4).

    Режим строгой типизации

    Если указан тип int и передать строку ‘123’ то проверка все равно будет пройдена, и php превратить строку в число.

    Но что, если нужно получать именно число 123? Для этого можно включить режим строгой типизации, поместив в самое начало файла такую строку:

    Это объявление должно быть первой строкой в файле, до выполнения какого-либо кода. Оно затрагивает только код файла и только вызовы и возвращаемые значения в этом файле.

    Заметка: если строгая типизация указана в файле X, но не указана в файле Y и в файле Y вызывается функция из файла X. То вызов такой функции не будет подвержен строгой типизации!

    int, float, bool, array — указание возвращаемых типов для функции/метода

    Указывать принимаемый тип, можно еще с версии PHP 5.3. А вот указать какой тип функция/метод должна вернуть доступно только с версии PHP 7. Тут понимаются все типы: string , int , float , bool , array , callable , self (в методах), parent (в методах) , Closure , имя класса , имя интерфейса .

    Возвращаемые типы при наследовании методов класса

    При наследовании в классах, дочерние методы должны иметь такие же возвращаемые типы как и в родительском классе/интерфейсе:

    Навороченный пример того, как можно писать в PHP 7

    Тут сразу несколько новинок:

    1. принимаемый и возвращаемый тип;
    2. объединение и распаковка параметров с помощью . ;
    3. пример создания анонимной функции с указанием возвращаемого типа данных.

    foo()(), $a::$b::$c, $$foo->bar — единый синтаксис переменных: СЛЕВА НАПРАВО

    Очень важная новинка! Теперь обращения к сложносочиненным переменным разбираются последовательно СЛЕВА НАПРАВО.

    Примеры новых возможностей:

    Примеры разницы старого и нового распознавания:

    Старый код написанный с использованием <> для обработки переменных возможно не будет работать в новой версии PHP7.

    foreach — изменена логика работы

    Теперь foreach не переключает автоматически внутренний указатель перебираемого массива, т.е. next() не работает автоматически.

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

    Переключение указателей и влияние на работу цикла в PHP 7:

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

    Расширение классов работает как и ожидается:

    Подробнее про анонимные классы читайте в документации и на wiki.php.net.

    yield . return 99; — возврат (return) выражений в генераторах

    Функции-генераторы появились в PHP 5.5. Но там можно было использовать return, только чтобы прервать работу генератора. Теперь return может возвращать выражение (значение/массив/другой генератор), а не только NULL. Но сделать это можно только в конце работы генератора.

    Получить возвращенное значение можно методом getReturn() , но только по завершении работы генератора.

    Возможность явно вернуть последнее значение упрощает работу с генераторами:
    теперь не нужно проверять является ли значение последним, а просто вызываем getReturn().

    yield from gen() — делегирование генераторов

    Позволяет разбить сложный генератор на несколько простых.

    Для этого используется новый синтаксис: yield from , где может быть значением (скаляром), массивом или другим генератором.

    будет работать до тех пор, пока возвращает данные, затем выполнение продолжится в генераторе откуда был вызван. Смотрите пример:

    Пример с массивом:

    Пример с return из дочернего генератора:

    Еще новинки PHP 7.0

    Синтаксис конструкторов в стиле PHP 4 (имя метода конструктора совпадает с именем класса) теперь считается устаревшим.

    Статичные вызовы :: нестатичных методов теперь считаются устаревшими.

    list() — изменение поведения. В PHP 5, list() устанавливал значения начиная с правого крайнего значения указанного массива, в PHP 7 параметры устанавливаются начиная с левого крайнего значения массива. Так же в PHP 5 list() умела разбивать строки на символы, в PHP 7 не работает со строками вообще.

    Поддержка юникод управляющих (escape-) последовательностей. Т.е. в строках «» и heredoc можно использовать конструкцию \uXXXX для создания юникод символа. Вот так:

    Класс IntlChar. Cодержит методы и константы для работы с юникодом.

    Функция intdiv() — делит 2 числа и возвращает только целую часть от деления:

    session_start() умеет получать параметры (стандартные настройки сессий из php.ini):

    Функция preg_replace_callback_array() — альтернатива preg_replace_callback(). Позволяет передать в качестве обратной функции — массив [‘/regex’/ => callback, . ] :

  • Можно использовать глобальные ключевые слова в названиях методов. Т.е. раньше нельзя было назвать метод словами: with/new/for/foreach/. — это приводило к ошибке. Теперь можно:
  • Подробнее о новинках PHP 7 читайте в этой статье и вторая часть.

    void — возвращаемый тип

    Теперь функции и методы, которые не должны ничего возвращать, можно помечать возвращаемым типом void . Оператор return при этом должен отсутствовать или должен быть пустым — return; . Вызов return null; вызовет ошибку.

    iterable — новый псевдо-тип

    Введен новый тип iterable для передаваемых/возвращаемых значений. Может использоваться при передаче массивов или объектов, которые соответствуют интерфейсу Traversable.

    null — тип передаваемых/возвращаемых значений

    В PHP 7.0 стало возможным указать тип возвращаемых/передаваемых значений, но типизация не допускала использование null в качестве значения параметра.

    В PHP 7.1 для разрешения null-значений перед типом параметра указывается «?»:

    <-1>— отрицательное значение смещения в строках

    Добавлена возможность использовать отрицательное значение для смещения в строках

    [‘key’=>$a] = [‘key’=>’Значение’] — поддержка ключей и новый синтаксис list()

    Теперь, можно использовать новый синтаксис — аналог list(), в котором разрешено использовать строковые ключи:

    Область видимости констант в классах

    Конец публичным константам, теперь для констант можно указать видимость:

    Заметки по PHP 7.1

    PHP движется в сторону строгой типизации данных и при переходе на 7.1 я столкнулся с ФАТАЛЬНОЙ ошибкой. И мне это показалось очень странным. Приведу пример:

    При Warning PHP еще работает, а дальше уже нет! А еще в 7.0 код просто работал, даже без предупреждений и нотисов. Похоже на недоработку в PHP 7.1.

    К примеру, ошибка такого типа есть в популярном плагине WP Super Cache (отписал авторам, надеюсь скоро поправят).

    PHP 7 — Часть 2

    Это вторая часть статьи о PHP 7, если Вы не читали, прочитайте первую часть про PHP 7. И так продолжаем про новую седьмую версию PHP.

    6. Новые операторы

    PHP 7 идет с двумя блестящими новыми операторами: spaceship (или объединенный оператор сравнения) и null coalesce operator.

    Оператор spaceship ( ), также известный как объединенный оператор сравнения, может использоваться для создания цепочечного сравнения более коротким. Рассмотрите следующее выражение:

    Это выражение оценит к -1, если $a будет меньшим, чем $b, 0, если $a равняется $b, и 1, если $a больше, чем $b. Это в основном краткая запись следующего выражения:

    Null coalesce operator (??) также работает как краткая запись случая общего использования: условное приписывание, проверяющее, установлено ли значение перед использованием его. В PHP 5 вы обычно делали бы что-то вроде этого:

    С null coalesce operator в PHP 7, мы можем просто использовать:

    Вот как новый оператор сокращает время:

    7. Return Type Declarations

    Как предотвратить непреднамеренные возвращаемые значения? Объявить тип возврата функции. И новый PHP 7 позволяет разработчикам повысить качество кода с помощью деклараций типа возвращаемого значения (Return Type Declarations).

    На рисунке ниже показан очень простой случай , когда использование Foo () функция должна возвращать массив.

    Для усиления функции, PHP 7 вводит 4 новых деклараций типа для скалярных типов: INT, Float, String и BOOL . Новые скалярные типы позволяют разработчикам обозначивать, что они ожидают: целые числа, с плавающей запятой, строки или булевы должны быть возвращены. Новые скалярные типы , введенные PHP 7 также будет поддерживаться аргументом типа подсказки , что позволяет разработчикам установить тип параметров , как и в PHP 5.X.

    8. Добавляет анонимных классов

    В новой версии PHP нам позволяется использовать анонимные классы, которые уже давно используются в моих двух любимых объектyо-ориентированных языков программирования, таких как Java и C#. Анонимный класс — это класс без имени, что позволяет объявить классы вложенные в другие классы. В некоторых моментах данные классы помог укорить кодинг и соответственно повысить производительность работы программиста.

    9. Облегчает импорт из того же пространства имен

    Новая Группа использует объявления функция godsent для тех из вас , кто хочет импортировать много классов из того же пространства имен, что делает ваш код опрятнее и легче на глазах, и экономит много времени. Его будет легче читать, а значит и производить отладку и отлавливать ошибки.

    10. Освобождаем пространства

    PHP 7 ставит себе цель стать быстрее и производительней. И конечно же, не возможно стать лучше, не убрав старое наследие. PHP 7 избавляется от множества устаревших функций, не поддерживаемых API и расширений. Подробней о них Вы можете узнать на сайте PHP.

    Кстати не стоит беспокоится тем, кто использовали функции и оформление кода из PHP 5, так как большую часть это касается предыдущих версий, ниже пятерки. И если такой код у вас работал в пятой версии, то в новой PHP 7 он уже может не работать или работать не правильно.

    Какова цель возвращение декларации значения типа PHP7 в

    Я читаю новые возможности PHP7 и это сомнение приходит ко мне с этим:

    Единственной целью я могу найти быть более конкретным в определении интерфейса (что является преимуществом). Но есть ли другая причина включать их в каждый метод?

    Создан 27 сен. 17 2020-09-27 08:17:15 CarlosAS

    он также помогает вам предотвратить переопределение типов из родительского класса. если ваш класс возвращает float, ваш переопределенный метод должен также возвращать float. который действительно полезен, хотя – Anar Bayramov 27 сен. 17 2020-09-27 08:22:33

    Одной из других причин может быть проверка типа IDE. Это означает, что IDE помогает вам, если вы можете передать эту переменную, если она принимает только bool. – Vastlik 27 сен. 17 2020-09-27 08:22:47

    1 ответ

    Если вы пишете библиотеку для использования другого кода, хорошо иметь четко определенный API, и объявленные типы возврата являются частью этого. Это избавляет людей от необходимости перебираться в исходном коде для его работы.

    Для вашего собственного использования кода, это проверка безопасности, что вы правильно пишете свою функцию и остаетесь «по плану». Он поощряет ваши функции к тому, чтобы сделать одно и сосредоточиться. Сам PHP немного беспорядок в тех местах, где он имеет функции, которые могут возвращать целое значение или boolean, если что-то не пойдет в соответствии с планом. Это довольно ужасное кодирование. Это означает, что вызывающий код должен кодировать оба события, которые ему не нужно делать. Если вы укажете тип возврата в своей функции, вы не сможете спуститься по этому маршруту.

    Также, как говорили другие, это помогает вашей среде IDE выработать то, что должно продолжаться. Это удобно. IDE также будут использовать эти комментарии аннотации phpdoc, но они являются комментариями, поэтому они лгут и фактически не применяют контракт, так что на самом деле это не очень . хорошо.

    Создан 27 сен. 17 2020-09-27 08:48:53 Adam Cameron

    Добавить комментарий