PHP 7 - глубокий взгляд

8 Январь 2017 0 комментариев

PHP 7 был выпущен 3 декабря 2015 года, и всё ещё остаётся много людей, которые не начали использовать его или не узнали о его удивительных особенностях - для них и написана данная статья. Впрочем, даже если вам это всё известно, вы могли бы узнать ещё что-то новое из этой статьи. Расмус Лердорф (создатель PHP) утверждает, что у приложений, работающих на PHP 7, производительность улучшена на 100% или более. Расход памяти также снизился, так что если вы работаете с высоконагруженными серверами, PHP 7 является весьма полезным обновлением для них. Одним из самых больших изменений в PHP 7 является переработанный Zend Engine (PHPNG), который теперь работает быстрее, расходует память меньше, и "зеленая" версия PHP, которая требует менее мощного железа для запуска кода.

Итак, что было удалено из PHP 7?

1) MYSQL:

Оригинальный модуль MySQL подвергался критике в PHP 5.5. Мы использовали такие функции, как mysql_connect() , mysql_query(). Настоятельно рекомендуется использовать улучшенный модуль MYSQL - MySQLi или же PDO для любых операций с базами данных. Если вы начинаете использовать PHP 7 (а вам лучше начать как можно скорее), то учтите, что оригинальный модуль было удален полностью. Но если вы хотите использовать оригинальный модуль MySQL, вы можете найти и установить его на https://pecl.php.net/. PECL является хранилищем для PHP-расширений, с каталогом всех известных расширений и предоставлением хостинг-услуг для загрузки и разработки расширений PHP.

2) POSIX-функции регулярных выражений:

PHP предлагает функции, которые являются специфическими для определенного вида регулярных выражений - функций POSIX-регулярных выражений и регулярных выражений в PERL-стиле. На PHP 7 вы не можете использовать POSIX-функции, такие как ereg(), ereg_replace(), split(), вместо этого вы должны использовать функции PERL-совместимых регулярных выражений (PCRE), такие как preg_match(), preg_replace(), preg_split(). Если вам еще нужны функции POSIX-регулярных выражений в вашем приложении, вы можете также установить их из https://pecl.php.net/.

3) Альтернативные PHP-теги:

В PHP 7, вы больше не можете применять ASP-теги, например <%%> или <% %> и теги скриптов HTML .

4) Присвоение объекта по ссылке:

Вот так больше нельзя писать в PHP 7 - "$car =& new Car()" - уже в PHP 5 это не было нужно, потому что объекты и так всегда присваиваются по ссылке.

5) Комментарии в файлах конфигурации:

Это считалось устаревшим ещё в PHP 5.3, а с PHP 7, вы больше не можете использовать '#' для комментариев в INI-файлах. Требуемый символ является стандартной точкой с запятой ';'

6) SALT-ОПЦИЯЯ В PASSWORD_HASH ():

Опция SALT для функции password_hash() удалена, чтобы предотвратить создание разработчиками собственных солей - ведь это может быть небезопасным.

Вы можете узнать больше здесь - https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7

Итак, мы перечислили то, что было удалено в PHP 7, а что было добавлено?

Новые возможности PHP 7:

"Космический корабль" - оператор <=>

Оператор "космический корабль" (так называемый "комбинированный оператор сравнения") используется для сравнения двух выражений. Он возвращает -1, 0 или 1, при проверке типа "левое выражение меньше правого выражения". Это также работает со строками. Этот оператор в основном используется в функциях обратного вызова, например, в пользовательской сортировке значений.

$a = 6; $b = 8, $c = 6
echo $a <=> $b ; // 1
echo $b <=> $a;  // -1
echo $a <=> $c; // 0

$a = “a”; $b = “”, $c = 6
echo $a <=> $b ; // 1
echo $b <=> $a;  // -1
echo $a <=> $c; // 0

Оператор объединения по Null - ??

С оператором объединения по Null, отпадает необходимости использовать такие функции, как isset(). Он просто возвращает первый операнд, если он не Null, в противном случае возвращает последний. Можно также задать цепь значений с помощью этого оператора. Он использует первое не-Null значение, которое попадется, начиная с левой стороны. Обратите внимание, что это только для значений Null - а не для, например, пустых строк, которые не равны Null в PHP.

$food = $_GET['food'] ?? 'Eba';
echo $food; // if $_GET['food'] is null echo's Eba;

// chain null coalescing
$favourite_food = 'Garri';
$my_food = $null ?? $favourite_food ?? 'Eba';
echo $my_food; // Garri

Объявление массивов-констант через define()

Массивы-константы теперь могут быть объявлены через define(). В PHP 5.6, они могли быть объявлены только через const.

define('COUNTRIES', [
    'Nigeria',
    'Ghana',
    'South Africa'

]);
echo COUNTRIES[1]; // outputs "Nigeria"

Unicode - поддержка смайликов

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

echo "PHP 7 has smiley! \u{1F600}";

Целочисленное деление intdiv()

С помощью функции целочисленного деления - intdiv(), вы получите результат операции деления как целое без применения (int)

echo (int) (5/2); // result is 2
  // Initial proposal: new operator
  // echo 5 %% 2; // its ugly!!

  // using intdiv()
  echo intdiv(5, 2); // result is 2 

Случайные байты - random_bytes()

Функция создает строку случайных байтов. Длина строки задаётся в качестве параметра. Это может быть использовано для создания непредсказуемых значений для куков. Используйте вместе с bin2hex(), чтобы получить шестнадцатеричную строку.

echo random_bytes(20); // prints out 8����R�q����G|��k� 
echo bin2hex(random_bytes(20)); // prints out947e5baf0da168d4c89cab97d89fcafa624a441a

Случайное целое - random_int(int $min, int $max)

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

echo random_int(100, 999); // 211, 307, 336

1.0 PHP 7 - ПРОВЕРКА ТИПОВ

Возвращение заявленного типа

Преимущества использования данной функции включают в себя: предотвращение нежелательных возвращаемых значений - это вызовет фатальную ошибку, если тип возвращаемого значения не тот, что вы объявили. Декларирование типа возвращаемого значения не является обязательным в PHP 7. Следующие типы данных могут быть использованы: class name/Interface name, array, callable, bool, float, int, string, self и parentю

// This will make sure the value returned is an array
function wordsToUpper($string) : array
{
    if (empty($string) || is_null($string))
        return [];
    
    $string = explode(' ', $string);
    return array_map('strtoupper', $string);
}
$input = '';

$converted = wordsToUpper($input);
echo '<pre>';
print_r($converted);
echo '</pre>';

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

PHP имеет четыре скалярных типа: Boolean, Integer, Float и String. Скалярные типы используются для идентификации только одного значения. Допустимые типы данных BOOL, INT, float и string. Синтаксис похож на проверку, которые мы рассмотрели выше. Скалярные типы в PHP 7 имеет два режима - слабый (по умолчанию) и строгий (должны быть указаны в явном виде).

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

Строгий режим - типы данных указываются заранее. Этот режим должен быть включен в файле - вы объявляете "declare(strict_types=1)" в качестве первого оператора в файле PHP. Обратите внимание, что это не влияет на код в подключенных файлах.

function addIntegers(int $a, int $b) : int
{
    return $a + $b;
}

declare(strict_types=1);
function getTotal(float $a, float $b)
{
      return $a + $b;
}
getTotal(2, "1 week"); // Fatal error: Uncaught TypeError: Argument 2 passed to getTotal() must be of the type float, string given

2.0 КЛАССЫ И ГЕНЕРАТОРЫ

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

В PHP 5.6 были анонимные функции. В PHP 7, у нас теперь есть анонимные классы. Анонимный класс не имеет имени, но вы можете присвоить его переменной, вернуть его из функции, передать его как аргумент в функцию, расширить класс, реализовать интерфейс и использовать свойства. Однако вы не можете сериализовать анонимный класс.

// Pre PHP 7 code
class Logger
{
    public function log($msg)
    {
		echo $msg;
    }
}
$util->setLogger(new Logger());
// PHP 7+ code
$util->setLogger(new class
{
    public function log($msg)
    {
        echo $msg;
    }
});

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

Возврат значения из генераторов

Генераторы были включены в PHP 5.5, это был простой способ перебора больших наборов данных, при небольшом потреблении памяти. В PHP 7, теперь вы можете вернуть значение из генератора через $generator->getReturn().

function gen()
{
    $total = 0;
    for ($i = 1; $i <= 10; $i++)
    {
        yield $i;
        $total += $i;
    }
    return $total;
}
$counter = gen();
foreach ($counter as $num)
{
    echo $num . '
'; } echo 'Total: ' . $counter->getReturn(); // returns the total 55

Делегирование генератора

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

function generator1()
{
    yield "Lagos";
    $g2 = yield from generator2();
    yield "Borno";
    return $g2;
}

function generator2()
{
    yield "Abuja";
    yield from ["Enugu", "Imo", "Ogun"];
    yield "Kano";
    return 'This came from generator 2';
}

$gen = generator1();
foreach ($gen as $yielded)
	echo $yielded . '<br>';

echo $gen->getReturn();

/* Output */
Lagos
Abuja
Enugu
Imo
Ogun
Kano
Borno
This came from generator2 */

Нововведения в классе Closure

Вместо того чтобы использовать Closure::bindTo который дублирует замыкание с указанием связанного объекта и области видимости класса, в PHP 7 вы можете использовать Closure::call, который связывает и вызывает замыкание. При использовании Closure::call, нет необходимости указывать имя класса, с объектом которого связывается замыкание - функция автоматически обнаружит его.

class Drink
{
    private $myMessage;
    public function __construct($beverage)
    {
		switch($beverage)
		{
            case 'COKE':
                $this->myMessage = 'Coke is the bomb.';
                break;
            case 'BEER':
                $this->myMessage = 'We are in for some alcohol';
                break;
            case 'ORIJIN':
                $this->myMessage = 'The boss of all is Orijin';
                break;
        }
    }
}

$getMessage = function($number)
{
    return $this->myMessage . ". I must take like " . $number . " per week";
};

$drink = new Drink('ORIJIN');

// PHP 5 >= PHP 5.40
// $m = $getMessage->bindTo($drink, 'Drink');
// echo $m(2); outputs: The boss of all is Orijin. I must take like 2 per week

// PHP 7
echo $getMessage->call($drink, "5"); // The boss of all is Orijin. I must take like 5 per week

Группировка объявлений импорта

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

// PRE PHP 7
use some\namespace\ClassA;
use some\namespace\ClassB as B;

use function some\namespace\FUNCA;
use function some\namespace\FUNCB;

use const some\namespace\ConstA;
use const some\namespace\ConstB;

// PHP 7+ code
use some\namespace\{ClassA, ClassB as B};
use function some\namespace\{FUNCA, FUNCB};
use const some\namespace\{ConstA, ConstB};

// PHP 7+ import misture
use some\namespace\{
    CLASSA,
    const ConstA,
    function FUNCTA
};

3.0 ОБРАБОТКА ОШИБОК

Перехват фатальных ошибок

PHP 7 изменяет то, как PHP сообщает о большинстве ошибок. Вместо использования традиционного механизма отчетности об ошибках, используемого PHP 5, большинство ошибок теперь генерируют исключения Error. Если вы запустите код из приведенного ниже примера в предварительной версии PHP 7, блок finally не вызывается, и _destruct() тоже. Если затем запустить его в PHP 7, блок finally будет выполнен, но исключение не перехватывается в блоке catch (Exception $e) - вместо этого оно будет перехвачено в блоке catch (Error $e), потому что фатальные ошибки не являются исключениями Exception, их класс называется Error, также деструктор объекта будет вызван при фатальной ошибке.

class MyResource
{
    public function __construct()
    {
        echo 'Get resource
'; } public function __destruct() { echo 'release resource in destructor'; // pre PHP 7: not called but called in PHP 7+ } } function crash($obj) { $obj->crashMethod(); } try { $myResource = new MyResource(); // pre PHP 7 and PHP 7+: prints out Get resource crash(null); // pre PHP 7 and PHP 7+: fatal error } catch (Exception $e) { echo $e->getMessage() . '<br>'; } // caught in PHP 7+ only catch (Error $e) { echo $e->getMessage() . '<br>'; } finally { echo 'Finally block called
'; // in pre PHP 7 it is not called but in PHP 7+ it is called }

Throwable

PHP 7 генерирует большинство фатальных ошибок как исключения, которые могут быть перехвачены в блоке try. Исключения и ошибки принадлежат в PHP 7 разным классам. Классы Exception и Error класс реализуют интерфейс Throwable - то есть они имеют такие методы, как getMessage(), getCode(), getFile(), getLine(), getTrace(), _toString() и т.д., и ведут себя очень похожим образом. Есть три подкласса, расширяющих класс Error:

TypeError - генерируется, если тип данных аргумента функции или возвращённого значения не соответствуют объявленному.
ParseError - срабатывает, когда включаемый файл или PHP код, передаваемый в eval() содержит ошибку синтаксиса.
AssertionError - срабатывает, если попытка использовать assert() терпит неудачу. Чтобы включить генерацию этих ошибок, в вашем конфигурационном файле PHP, установите zend.assertion = 1 и assert.exception = 1.

try
{
 	// Code that may throw an error or exception 
}
catch(Exception $e)
{
 	// handle exception error here 
}
catch(Error $e)
{
 	// handle error here 
}
// To catch all in one catch block
try
{
 	// Code that may throw an error or exception 
}
catch(Throwable $e)
{
  	// handle error or exception here
}

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

interface MyThrowable extends Throwable
{
  // your customizations
}

class MyError extends Error implements MyThrowable
{
  // your customizations
}

Новые зарезервированные слова

PHP 7 имеет новые зарезервированные слова, такие как int, float, bool, string, true, false, null, resource, object, mixed и numeric. В шоке? Я тоже! Псевдонимы, такие как integer, double и boolean не зарезервированы.

Значения по умолчанию в Switch

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

$a = 1;
$b = 0;
switch($a)
{
    default:
        $b += 1;
        break;
    default: // not work in PHP 7+
        $b += 2;
}
echo '$b is ' . $b; // pre PHP 7: prints out '$b is 2'. PHP 7+ Fatal error: Switch statements may only contain one default clause ...

4.0 Прочие изменения

Произведено значительное улучшение функций, таких как:
- unserialize(string $str [, array $options ]) - улучшена для предотвращения инъекций PHP-объекта (вы можете прочитать об этом здесь и в PHP-документации здесь).
- json_encode($value) - в предварительной версии PHP 7 если у вас есть числовое значение с плавающей запятой в переменной $value, json_encode($value) удалит дробную часть, если она равна 0, и преобразует её в целое число. В PHP 7+, новая константа JSON_PRESERVE_ZERO_FRACTION позволяет сохранить нулевую дробную часть.

$weights = ['weight1' => 5.2, 'weight2' => 6.0];
echo json_encode($weights); // pre PHP 7: {"weight1": 5.2,"weight2": 6}
echo json_encode($floats, JSON_PRESERVE_ZERO_FRACTION); // PHP 7+: {"weight1":5.2,"weight2":6.0}

"Наполовину" зарезервированные слова
Такие слова, как abstract, and, case, array, as, break, callable, case, catch, clone, const, continue, declare, default, die, do, echo, else, elseif, enddeclare, endfor, endforeach, endif, endswitch, endwhile, exit, extends, final, finally, for, foreach, function, global, goto, if, implements, include, include_once, instanceof, instedof, interface, list, namespace, list, new, or, parent, print, private, protected, public, require, require_once, return, self, static, switch, throw, trait, try, use, var, while, xor, yield теперь могут быть использованы в качестве констант и имен методов (хотя так не рекомендуется делать) в созданных вами классах в PHP 7+, но срабатывает ошибка синтаксиса при произведении таких действий в предварительной версии PHP 7. Единственное "железно" зарезервированное слово - это "class" - его вы не можете использовать. С помощью этой новой информации в вашем распоряжении, перед тем, как начать новый проект на PHP, убедитесь, что вы используете PHP 7, или же вы можете перенести существующие проекты с PHP 5.6.x на PHP 7.0.X, с помощью этого руководства.

Ссылки и дополнительная литература
http://php.net/manual/en/migration70.new-features.php

php php7

Популярные статьи

То, что еще нравится нашим читателям

Оставьте комментарий

Нам важно ваше мнение
Укажите корректный e-mail
Укажите ваше имя
Напишите текст комментария

Заявка на сотрудничество с нами

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

Не корректный email