Руководство по PHP7


    php7-tutorial.com


    Цель этого сайта помочь вам обнаружить нововведения в PHP 7. Это руководство представляет из себя набор простых упражнений, в которых вам будет предложено что-либо решить, либо исправить ошибку. Каждое упражнение соответствует стандарту RFC (набор технической спецификации и стандартов) и сопровождается кратким пояснениями.

    От переводчика


    Всем привет, с вами Максим Иванов, и сегодня мы поговорим о нововведениях PHP 7, о которых более подробно поведает нам Гийом Девар (Guillaume Dievart) в своем руководстве, сделанном в форме упражнений. Но прежде чем начинать, я хочу отметить один момент. Я не буду приводить полное руководство по данному языку программирования в этом обзоре, просто оставлю здесь ссылку на самую свежую и достоверную информацию. Джош Локхарт (автор гайдлайна «PHP: правильный путь», разработчик Slim Framework), написал данную книгу с целью помочь новичкам, по его словам: «В последнее время существует много дискуссий о том, что PHP сообществу и, в целом, программистам не хватает достоверной информации по языку PHP, поэтому мое руководство призвано решить эту проблему». Чем именно? Вы знаете, что по интернету разбросано огромное количество материла по PHP, но многое уже устарело или не приводит к написанию качественного кода. В этой книге присутствуют основные актуальные сведения с ссылками на проверенные ресурсы. Если кому интересно, такое есть и по JavaScript. А теперь вернемся к упражнениям и приступим.


    Содержание


    1. Упражнение 1. Измените значение переменной $phpVersion
    2. Упражнение 2. Замените недопустимый тег
    3. Упражнение 3. Замените устаревшую функцию
    4. Упражнение 4. Используйте только __construct()
    5. Упражнение 5. Удалите лишние конструкции по умолчанию в switch
    6. Упражнение 6. Используйте spaceship-оператор для сортировки массива
    7. Упражнение 7. Используйте оператор объединения
    8. Упражнение 8. Необходимо модифицировать условие после оператора объединения
    9. Упражнение 9. Измените значение $b для правильной работы оператора объединения
    10. Упражнение 10. Сгруппируйте пространства имен с одинаковым префиксом
    11. Упражнение 11. Переименуйте метод, используя новый набор разрешенных ключевых слов
    12. Упражнение 12. Используйте более безопасные функции для генерации случайных чисел
    13. Упражнение 13. Используйте новую функцию preg_replace_callback_array
    14. Упражнение 14. Использовать анонимный класс
    15. Упражнение 15. Укажите тип в аргументах функции
    16. Упражнение 16. Модифицируйте правый операнд условия, чтобы поймать значение ожидаемого типа
    17. Упражнение 17. Используйте строгий режим, чтобы перехватывать ошибки, когда функция получает не тот тип
    18. Упражнение 18. Используйте строгий режим для встроенных функций
    19. Упражнение 19. Директива strict_types должна идти первой строкой
    20. Упражнение 20. Укажите тип возвращаемого значения у функции
    21. Упражнение 21. Исправьте возвращаемый тип у функции, чтобы поймать значение ожидаемого типа
    22. Упражнение 22. Определение унаследованного класса должно возвращать один и тот же тип своего родителя
    23. Упражнение 23. Используйте новую юникод-последовательность для описания символов
    24. Упражнение 24. Разрешается передавать объекты в функцию unserialize()
    25. Упражнение 25. Включите в генератор другой генератор
    26. Упражнение 26. Воспользуйтесь замыканием функции
    27. Упражнение 27. Вызовите переменную $c из $a
    28. Упражнение 28. Используйте класс Error для обработки ошибок
    29. Упражнение 29. Используйте класс TypeError для обработки ошибок
    30. Упражнение 30. Используйте класс Throwable для обработки ошибок
    31. Упражнение 31. Используйте класс DivisionByZeroError для обработки ошибок
    32. Упражнение 32. Не используйте шестнадцатеричные числа в строках
    33. Упражнение 33. Получите финальное значение генератора №1
    34. Упражнение 34. Получите финальное значение генератора №2
    35. Упражнение 35. Исправьте прототип (интерфейс) функции
    36. Упражнение 36. Создайте группу констант


    Песочница


    Если вы хотите протестировать некоторые примеры, воспользуйтесь онлайн-интерпретатором.

    Упражнение 1. Измените значение переменной $phpVersion, чтобы перейти к следующему упражнению


    <?php
    $phpVersion = 6;
    echo PHP_MAJOR_VERSION === $phpVersion ? "Next step !" : "No !";
    

    // результат
    No !
    

    Решение
    <?php
    $phpVersion = 7;
    echo PHP_MAJOR_VERSION === $phpVersion ? "Next step !" : "No !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Основные причины, почему пропустили шестую версию и перешли к седьмой
    2. Оператор вывода строки на экран
    3. Тернарный (условный) оператор
    4. Что такое мажорная и минорная версии?

    Упражнение 2. Замените недопустимый тег


    <?%
    echo "Next step !";
    

    // результат
    syntax error, unexpected '%', expecting end of file on line 1
    

    Решение
    <?php
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Какие альтернативные PHP-теги были удалены, а какие оставлены?

    Упражнение 3. Функция ereg_replace является устаревшей, замените ее на preg_replace


    <?php
    if (ereg_replace("PHP([3-6])", "PHP7", "PHP6")) {
        echo "Next step !";
    }
    

    // результат
    Uncaught Error: Call to undefined function ereg_replace() in /tmp/__hoa_6b3Hmf:3
    Stack trace:
    #0 /tmp/__hoa_f8PIGz(52): require()
    #1 {main}
      thrown on line 3
    

    Решение
    <?php
    if (preg_replace("/PHP([3-6])/", "PHP7", "PHP6")) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Устаревшие расширения
    2. Регулярные выражения в PHP
    3. Поиск и замена по регулярному выражению
    4. Шаблоны
    5. Производительность

    Упражнение 4. PHP4 конструкторы признаны устаревшими, используйте __construct


    <?php
    class Foo
    {
        public function foo()
        {
    
        }
    }
    
    echo "Next step !";
    

    // результат
    Methods with the same name as their class will not be constructors in a future version of PHP; Foo has a deprecated constructor on line 3
    

    Решение
    <?php
    class Foo
    {
        public function __construct()
        {
    
        }
    }
    
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Устаревший конструктор
    2. Конструктор (объектно-ориентированное программирование)
    3. Для чего нужны классы?
    4. Зачем нужен ООП?
    5. Объектно-ориентированное программирование
    6. Основы ООП в PHP
    7. Перестаньте писать классы
    8. Плюсы и минусы объектно-ориентированного программирования

    Упражнение 5. Множественные конструкции по умолчанию в операторе switch теперь запрещены, удалите первый


    <?php
    switch ('') {
        default:
            echo "Doesn't pass here ...";
            break;
        default:
            echo "Next step !";
    }
    

    // результат
    Switch statements may only contain one default clause on line 7
    

    Решение
    <?php
    
    switch ('') {
        default:
            echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Почему возникает синтаксическая ошибка в определении нескольких случаев по умолчанию в операторе switch?
    2. Оператор switch

    Упражнение 6. Используйте spaceship-оператор (<=>) для сортировки массива


    <?php
    
    $users = ['Pierre', 'Paul', 'Next step !'];
    usort($users, function ($a, $b) {
    
    });
    
    echo current($users);
    

    // результат
    Pierre
    

    Решение
    <?php
    
    $users = ['Pierre', 'Paul', 'Next step !'];
    usort($users, function ($a, $b) {
        return $a <=> $b;
    });
    
    echo current($users);
    
    // результат
    Next step !
    



    К прочтению:

    1. Новый оператор
    2. Что это за оператор shaceship <=>?
    3. usort — сортирует массив по значениям, используя пользовательскую функцию для сравнения элементов
    4. Внутренний указатель

    Упражнение 7. Используйте оператор объединения со значением NULL (??)


    <?php
    echo $_GET['query'] ? $_GET['query'] : "Next step !";
    

    // результат
    Undefined index: query on line 3
    

    Решение
    <?php
    echo $_GET['query'] ?? "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Новый оператор
    2. Null coalescing operator
    3. Simple PHP isset test
    4. isset() vs empty() vs is_null()

    Упражнение 8. Оператор объединения со значением NULL (??) не проверяет значение в определенных случаях, измените правый операнд в условии


    <?php
    $_GET['title'] = false; // если убрать эту строчку, тогда условие сработает
    $query = $_GET['title'] ?? '*'; // true
    
    // вам необходимо модифицировать условие
    if($query === '*') {
        echo "Next step !";
    }
    

    // результат
    

    Решение
    <?php
    $_GET['title'] = false;
    $query = $_GET['title'] ?? '*';
    
    if($query === false) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Частный случай

    Упражнение 9. Оператор объединения со значением NULL (??) не проверяет значение в определенных случаях, измените значение $b


    <?php
    $b = false;
    
    echo $a ?? $b ?? "Next step !";
    

    // результат
    

    Решение
    <?php
    $b = null;
    echo $a ?? $b ?? "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Пример работы оператора

    Упражнение 10. Можно сгруппировать пространства имен с одинаковым префиксом. Сгруппируйте их в примере.


    <?php
    use Foo\Bar\Email;
    use Foo\Bar\Phone;
    use Foo\Bar\Address\Code;
    use Foo\Bar\Address\Number;
    
    echo "Next step !";
    

    // результат
    Next step !
    

    Решение
    <?php 
    use Foo\Bar\{
        Email,
        Phone,
        Address\Code,
        Address\Number
    };
    
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Пространство имён (программирование)
    2. Обзор пространств имен
    3. Пространства имен в PHP, разъяснение
    4. Пространства имен в PHP
    5. Краткое введение в PHP Пространства имен

    Упражнение 11. Некоторые ключевые слова разрешено теперь использовать в названиях методов (list, foreach, new, ..)


    <?php
    
    class Foo
    {
        // Переименуйте метод
        public function getList()
        {
            return "Next step !";
        }
    }
    
    echo (new Foo)->list();
    

    // результат
    Uncaught Error: Call to undefined method Foo::list() in /tmp/__hoa_FmqgZ0:12
    Stack trace:
    #0 /tmp/__hoa_LbZpe8(52): require()
    #1 {main}
      thrown on line 12
    

    Решение
    <?php
    class Foo
    {
    
        public function list()
        {
            return "Next step !";
        }
    }
    
    echo (new Foo)->list();
    
    // результат
    Next step !
    



    К прочтению:

    1. Ключевые слова

    Упражнение 12. Используйте более безопасные функции для генерации случайных чисел


    <?php 
    $randomInt = mt_rand(0, 42);
    echo $randomInt;
    

    // результат
    5
    

    Решение
    <?php
    $randomInt = random_int(0, 42);
    echo $randomInt;
    
    // результат
    1
    



    К прочтению:

    1. Криптографически безопасная функция для получения псевдослучайных целых чисел
    2. В чем недостаток mt_rand?
    3. Разница между mt_rand() и rand()

    Упражнение 13. Используйте новую функцию preg_replace_callback_array


    <?php
    
    // Use preg_replace_callback_array instead of preg_replace_callback
    echo preg_replace_callback(
        array(
            "/PHP6/",
            "/PHP7/"
        ),
        function($matches) {
            if(strpos($matches[0], 'PHP6') === 0) {
                return 'Ko !';
            } else {
                return "Next step !";
            }
        },
        'PHP7'
    );
    
    

    // результат
    Next step !
    

    Решение
    <?php
    // preg_replace_callback_array вместо preg_replace_callback
    echo preg_replace_callback_array(
        array(
            "/PHP6/" => function() { return "Ko !"; },
            "/PHP7/" => function() { return "Next step !"; },
        ),
        'PHP7'
    );
    
    
    // результат
    Next step !
    



    К прочтению:

    1. Поиск по регулярному выражению и замена с использованием функции обратного вызова
    2. Работа с preg_replace_callback_array

    Упражнение 14. Теперь можно создавать анонимные классы. Использовать анонимный класс вместо MyMessage


    <?php
    
    class Logger
    {
        public static function write(Message $message)
        {
            echo $message->getText();
        }
    }
    
    interface Message
    {
        public function getText();
    }
    
    class MyMessage implements Message
    {
        public function getText() { return "Next step !"; }
    }
    
    Logger::write(new MyMessage());
    
    

    // результат
    Next step !
    

    Решение
    <?php
    
    class Logger
    {
        public static function write(Message $message)
        {
            echo $message->getText();
        }
    }
    
    interface Message
    {
        public function getText();
    }
    
    $message = (new class() implements Message {
        public function getText() { return "Next step !"; }
    });
    
    Logger::write($message);
    
    
    // результат
    Next step !
    



    К прочтению:

    1. Интерфейсы объектов
    2. В чем суть интерфейсов в PHP?
    3. Шаблон программирования «Текучий интерфейс» в PHP. Свежий взгляд
    4. Абстрактные классы
    5. Абстрактные классы и интерфейсы в PHP
    6. Отличия абстрактного класса от интерфейса

    Упражнение 15. Добавьте тип int к аргументам функции add


    <?php
    
    function add($a, $b)
    {
        return $a + $b;
    }
    
    if(add(5.5, 5) === 10) {
        echo "Next step !";
    }
    
    

    // результат
    

    Решение
    <?php
    
    function add(int $a, int $b)
    {
        return $a + $b;
    }
    
    if(add(5.5, 5) === 10) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Тип данных
    2. Введение в типы данных PHP
    3. На сегодняшний день, использование скалярных и смешанных типов данных в PHP 7 не повышает производительности

    Упражнение 16. По умолчанию PHP отливает значение ожидаемого типа. Модифицируйте правый операнд условия


    <?php
    
    function add(int $a, int $b)
    {
        return $a + $b;
    }
    
    // Модифицируйте правый операнд
    if(add(5.5, 5.5) === 11) {
        echo "Next step !";
    }
    
    

    // результат
    

    Решение
    <?php
    
    function add(int $a, int $b)
    {
        return $a + $b;
    }
    
    if(add(5.5, 5.5) === 10) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Инициализация скалярных типов в PHP 7

    Упражнение 17. Используйте строгий режим, если хотите перехватывать ошибки, в случае когда функция получает не тот тип, который ожидает. Исправьте на float.


    <?php
    declare(strict_types = 1);
    
    function add(int $a, int $b)
    {
        return (int)($a + $b);
    }
    
    if(add(5.5, 5.5) === 11) {
        echo "Next step !";
    }
    

    // результат
    Uncaught TypeError: Argument 1 passed to add() must be of the type integer, float given, called in /tmp/__hoa_FKwVHc on line 10 and defined in /tmp/__hoa_FKwVHc:5
    Stack trace:
    #0 /tmp/__hoa_FKwVHc(10): add(5.5, 5.5)
    #1 /tmp/__hoa_rejBtd(52): require('/tmp/__hoa_FKwV...')
    #2 {main}
      thrown on line 5
    

    Решение
    <?php
    declare(strict_types = 1);
    
    function add(float $a, float $b)
    {
        return (int)($a + $b);
    }
    
    if(add(5.5, 5.5) === 11) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Манипуляции с типами данных
    2. Установка директив
    3. Контроль типа
    4. Встроенные директивы

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


    <?php
    declare(strict_types = 1);
    strlen(42);
    
    echo "Next step !";
    

    // результат
    Uncaught TypeError: strlen() expects parameter 1 to be string, integer given in /tmp/__hoa_0HYwi9:3
    Stack trace:
    #0 /tmp/__hoa_CjotyX(52): require()
    #1 {main}
      thrown on line 3
    

    Решение
    <?php
    declare(strict_types = 1);
    strlen('42');
    
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Справочник стандартных функций
    2. Встроенные функции в PHP
    3. Встроенные расширения PHP
    4. Стандартная библиотека PHP (SPL)

    Упражнение 19. Директива strict_types должна идти первой строкой


    <?php
    echo "Next step !";
    
    declare(strict_types = 1);
    

    // результат
    strict_types declaration must be the very first statement in the script on line 5
    

    Решение
    <?php
    declare(strict_types = 1);
    
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. declare используется для установки директив исполнения для блока кода

    Упражнение 20. Теперь можно указать тип возвращаемого значения у функции или метода. Укажите тип возвращаемого значения у функции


    <?php
    
    function reverse(string $string): type
    {
        return strrev($string);
    }
    
    echo reverse("! pets txeN");
    

    // результат
    Uncaught TypeError: Return value of reverse() must be an instance of type, string returned in /tmp/__hoa_ZcQkYd:5
    Stack trace:
    #0 /tmp/__hoa_ZcQkYd(8): reverse('! pets txeN')
    #1 /tmp/__hoa_7JLJ4t(52): require('/tmp/__hoa_ZcQk...')
    #2 {main}
      thrown on line 5
    

    Решение
    <?php
    
    function reverse(string $string): string
    {
        return strrev($string);
    }
    
    echo reverse("! pets txeN");
    
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Возврат значений
    2. Какая разница между возвращаемым и не возвращаемым значением в PHP?
    3. Выигрываем ли мы в производительности, если подсказываем функции ожидаемый тип в PHP?
    4. Существуют ли правила для возвращаемого значения у пользовательской булевской функции?

    Упражнение 21. По умолчанию, PHP выбросит ожидаемый тип. Исправьте возвращаемый тип у функции


    <?php
    // Пример: function foo(): int { return 5.5; } echo foo(); // 5
    
    function add(float $a, float $b): int
    {
        return $a + $b;
    }
    
    // Модифицируйте правый операнд
    if(add(5.3, 5.3) === 10.6) {
        echo 'Next step !';
    }
    

    // результат
    

    Решение
    <?php
    
    function add(float $a, float $b): int
    {
        return $a + $b;
    }
    
    // Modify the right operand.
    if(add(5.3, 5.3) === 10) {
        echo 'Next step !';
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Возвращение по ссылке
    2. Руководство по работе со ссылками

    Упражнение 22. Определение унаследованного класса должно возвращать один и тот же тип своего родителя


    <?php
    
    class Child {}
    class ChildB extends Child {}
    
    abstract class A
    {
        abstract public function foo(): Child;
    }
    
    class B extends A
    {
        public function foo(): ChildB
        {
            return new ChildB;
        }
    }
    
    echo "Next step !";
    

    // результат
    Declaration of B::foo(): ChildB must be compatible with A::foo(): Child on line 17
    

    Решение
    <?php
    
    class Child {}
    class ChildB extends Child {}
    
    abstract class A
    {
        abstract public function foo(): Child;
    }
    
    class B extends A
    {
        public function foo(): Child
        {
            return new ChildB;
        }
    }
    
    echo "Next step !";
    
    // результат
    Next step !
    



    К прочтению:

    1. Немного о наследовании и о переопределении методов, чем о полиморфизме
    2. Что такое полиморфизм на самом деле. В PHP он тоже существует
    2. Когда подтип перекрывает родительский метод, то тип возвращаемого дочернего метода должен точно соответствовать родительскому
    4. Отличный образовательный курс по изучению ООП на PHP

    Упражнение 23. Теперь можно использовать юникод-последовательность для описания символов


    <?php
    
    // Модифицируйте левый операнд
    if("\?{26C4}" === '') {
        echo "Next step !";
    }
    

    // результат
    

    Решение
    <?php
    
    // Modify the left operand.
    if("\u{26C4}" === '') {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Юникод
    2. Символов Unicode в PHP строке
    3. Поддержка юникод управляющих (escape-) последовательностей

    Упражнение 24. Была добавлена новая опция в стандартную функцию unserialize(), теперь разрешается указывать классы. Укажите класс в функции unserialize()


    <?php
    
    class MyClass { }
    
    $myClassSerialized = serialize(new MyClass());
    $myClass = unserialize(
        $myClassSerialized,
        ["allowed_classes" => ['']]
    );
    
    if($myClass instanceOf MyCLass) {
        echo "Next step !";
    }
    

    // результат
    

    Решение
    <?php
    
    class MyClass { }
    
    $myClassSerialized = serialize(new MyClass());
    $myClass = unserialize(
        $myClassSerialized,
        ["allowed_classes" => ['MyClass']]
    );
    
    if($myClass instanceOf MyCLass) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. unserialize
    2. Как использовать в PHP serialize() и unserialize( )?
    3. Оператор проверки типа

    Упражнение 25. Делегирование генераторов позволяет вернуть другую итерабельную структуру — будь то объект, массив, итератор или другой генератор. Включите в генератор другой генератор


    <?php
    
    function generator()
    {
        yield 1; // 'yield' означает «вернуть значение и продолжить с этого места при следующем вызове функции
        yield 2;
        // включите в генератор другой генератор
    }
    
    function subGenerator()
    {
        yield 3;
        yield 4;
        yield "Next step !";
    }
    
    $generator = generator();
    foreach($generator as $value) {
        echo $value.PHP_EOL;
    }
    

    // результат
    1 2
    

    Решение
    <?php
    
    function generator()
    {
        yield 1;
        yield 2;
        yield from subGenerator();
    }
    
    function subGenerator()
    {
        yield 3;
        yield 4;
        yield "Next step !";
    }
    
    $generator = generator();
    foreach($generator as $value) {
        echo $value.PHP_EOL;
    }
    
    // результат
    1 2 3 4 Next step !
    



    К прочтению:

    1. Поддержка генераторов и сопрограмм: суть генератора в том, что это функция, которая возвращает не просто одно значение, а последовательность значений
    2. Генераторы в действии
    3. Экономим память с помощью генераторов
    4. Делегирование генераторов
    5. Про утечку ресурсов в генераторах PHP

    Упражнение 26. Вы можете использовать замыкания у функций. Новый интерпретатор работает слева направо


    <?php
    
    function foo()
    {
        return function() { echo "Next step !"; };
    }
    
    // Воспользуйтесь замыканием функции foo в этой строке
    

    // результат
    

    Решение
    <?php
    
    function foo()
    {
        return function() { echo "Next step !"; };
    }
    
    // или: $foo = foo(); $foo();
    foo()();
    // результат
    Next step !
    



    К прочтению:

    1. Анонимная функция (лямбда-функция)
    2. Анонимные функции (замыкания) в PHP: не стоит путать с замыканиями в JavaScript
    3. Применение замыканий в PHP

    Упражнение 27. Исправьте синтаксис, чтобы вызвать переменную $c из $a


    <?php
    
    $a = ['b' => 'c'];
    $c = 'Next step !';
    
    // Этот код выведет Next step ! в PHP5
    echo $$a['b'];
    
    

    // результат
    Undefined variable: Array on line 7
    

    Решение
    <?php
    
    $a = ['b' => 'c'];
    $c = 'Next step !';
    
    echo ${$a['b']};
    // результат
    Next step !
    



    К прочтению:

    1. Универсальный синтаксис

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


    <?php
    
    try {  // Принудительно вызываем ошибку
        undefinedFunction();
    } catch(Exception $e) {
        echo "Next step !";
    }
    

    // результат
    Uncaught Error: Call to undefined function undefinedFunction() in /tmp/__hoa_PaBzqc:4
    Stack trace:
    #0 /tmp/__hoa_SQZOZG(52): require()
    #1 {main}
      thrown on line 4
    

    Решение
    <?php
    
    try {
        undefinedFunction();
    } catch(Error $e) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Обработка исключений
    2. Зачем нужна обработка исключений?
    3. Исключения в PHP
    4. Throwable exception и ошибки в PHP 7

    Упражнение 29. Можно использовать также класс TypeError для обработки исключений


    <?php
    
    declare(strict_types = 1);
    
    function add(int $a, int $b): int
    {
        return $a + $b;
    }
    
    // Catch the TypeError
    try {
        echo add('1', '1');
    } catch(Exception $e) {
        echo "Next step !";
    }
    
    

    // результат
    Uncaught TypeError: Argument 1 passed to add() must be of the type integer, string given, called in /tmp/__hoa_FvS6wW on line 12 and defined in /tmp/__hoa_FvS6wW:5
    Stack trace:
    #0 /tmp/__hoa_FvS6wW(12): add('1', '1')
    #1 /tmp/__hoa_kfhSdT(52): require('/tmp/__hoa_FvS6...')
    #2 {main}
      thrown on line 5
    

    Решение
    <?php
    
    declare(strict_types = 1);
    
    function add(int $a, int $b): int
    {
        return $a + $b;
    }
    
    // Catch the TypeError
    try {
        echo add('1', '1');
    } catch(TypeError $e) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Виды исключений в PHP

    Упражнение 30. Используйте Throwable, чтобы отлавливать исключения и ошибки (общий интерфейс Errors, Exceptions)


    <?php
    // исправьте неверный класс CallErrorAndException
    
    try {
        if(random_int(0, 1) === 1) {
        	throw new Exception('');
        }
        undefined();
    } catch(CallErrorAndException $e) {
        echo "Next step !";
    }
    
    

    // результат
    Undefined offset: -1 on line 55
    

    Решение
    <?php
    
    try {
        if(random_int(0, 1) === 1) {
        	throw new Exception('');
        }
        undefined();
    } catch(Throwable $e) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Исключение != ошибка
    2. Использование Throwable
    3. Пример деления на ноль

    Упражнение 31. Используйте DivisionByZeroError при делении на ноль


    <?php
    
    try {
        10 % 0;
    } catch(CatchError $e) {
        echo "Next step !";
    }
    
    

    // результат
    Uncaught DivisionByZeroError: Modulo by zero in /tmp/__hoa_46SBwZ:5
    Stack trace:
    #0 /tmp/__hoa_UQ8f3n(52): require()
    #1 {main}
      thrown on line 5
    

    Решение
    <?php
    
    try {
        10 % 0;
    } catch(DivisionByZeroError $e) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. DivisionByZeroError

    Упражнение 32. Не используйте шестнадцатеричные числа в строках


    <?php
    
    // var_dump(12 == "0xC"); // true в PHP 5
    // var_dump(12 == "0xC"); // false в PHP 7
    
    // Исправьте левый операнд
    if('0x2A' == 42) {
        echo "Next step !";
    }
    
    

    // результат
    

    Решение
    <?php
    
    if(0x2A == 42) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Приведение типов в PHP == табурет о двух ножках?
    2. Приведение типа
    3. Удалена поддержка шестнадцатеричных чисел в строках

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


    <?php
    
    // используйте Generator::getReturn() для возврата финального значения
    
    function generator()
    {
        yield 21;
        yield 21;
    
        return true;
    }
    
    $generator = generator();
    foreach($generator as $number) { }
    
    if($generator->callReturn() === true) {
        echo "Next step !";
    }
    
    

    // результат
    Uncaught Error: Call to undefined method Generator::callReturn() in /tmp/__hoa_eOhq2B:14
    Stack trace:
    #0 /tmp/__hoa_sa29ov(52): require()
    #1 {main}
      thrown on line 14
    

    Решение
    <?php
    
    function generator()
    {
        yield 21;
        yield 21;
    
        return true;
    }
    
    $generator = generator();
    foreach($generator as $number) { }
    
    if($generator->getReturn() === true) {
        echo "Next step !";
    }
    
    // результат
    Next step !
    



    К прочтению:

    1. Возврат финального значения

    Упражнение 34. Невозможно получить финальное значение, если внутренний указатель не указывает на него


    <?php
    
    function generator()
    {
        yield 21;
        yield 21;
    
        return "Next step !";
    }
    
    $generator = generator();
    $generator->next();
    
    echo $generator->getReturn();
    

    // результат
    // caught: Cannot get return value of a generator that hasn't returned
    

    Решение
    <?php
    
    function generator()
    {
        yield 21;
        yield 21;
    
        return "Next step !";
    }
    
    $generator = generator();
    $generator->next();
    $generator->next();
    
    echo $generator->getReturn();
    
    // результат
    Next step !
    



    К прочтению:

    1. Как сказать по-русски слово yield???

    Упражнение 35. Вы не можете использовать одинаковые названия аргументов в прототипе функции


    <?php
    
    function foo($a, $a) 
    {
        return $a;
    }
    
    echo foo("Next ", "step !"); // В PHP5: step !
    
    

    // результат
    Redefinition of parameter $a on line 4
    

    Решение
    <?php
    
    function foo($a, $b)
    {
        return $a . $b;
    }
    
    echo foo("Next ", "step !");
    
    // результат
    Next step !
    



    К прочтению:

    1. Аргументы функции

    Упражнение 36. Теперь можно создать массив (группу) констант


    <?php
    
    $conf = [
        'user' => 'root',
        'password' => 'my_password',
        'step' => 'Next step !'
    ];
    
    // определите CONFIGURATION как константу
    
    echo CONFIGURATION['step'];
    
    

    // результат
    /*
     * <br />
     * <b>Warning</b>:  Illegal string offset 'step' in <b>/tmp/__hoa_dBF385</b> on line <b>11</b><br />
     */
    

    Решение
    <?php
    
    $conf = [
        'user' => 'root',
        'password' => 'my_password',
        'step' => 'Next step !'
    ];
    
    define('CONFIGURATION', $conf);
    
    echo CONFIGURATION['step'];
    
    // результат
    Next step !
    



    К прочтению:

    1. Константы
    2. «Волшебные» константы
    3. define() vs const

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

    Какую версию PHP вы использовали в своих последних проектах?
    Поделиться публикацией
    Комментарии 55
      –2
      ?? полезный оператор. Еще бы сделали какой-нибудь оператор типа <?== $something ?>, который бы автоматически оборачивал выводимую строку в htmlspecialchars().
        +1
          –2
          Не забываем про Smarty. Не знаю как сейчас (пока что не сталкиваюсь ни с тем, ни с другим), но раньше он работал гораздо быстрее Twig, предлагая при этом сравнимые или даже большие возможности.
            +3

            1) вы сравниваете скорость рендринга или скорость компиляции?
            2) вы точно знаете на что способен твиг? С возможностью манипулировать AST возможности твига в плане расширения поистене огромны. Я как-то пробовал сделать jade на twig-е (просто как эксперемент). Подозреваю что сделать подобное на смарти будет как минимум неимоверно сложно.

              0
              Вы можете сходить по ссылке, что я привёл, и увидеть, что я там сравнивал как скорость компиляции, так и скорость выполнения уже скомпилированного шаблона.
                +3
                Было бы интересно посмотреть скорость компиляции и выполнения спустя почти 5 лет.
            0
            Шаблонизаторы это конечно хорошо, но я имел в виду проекты, в которых по историческим причинам шаблонизатора нет и не предвидится.
              +1
              Ну значит вам по историческим причинам и дальше придётся использовать htmlspecialchars(). Такой оператор вас не спасёт.
                +2
                Можете написать простой парсер, который будет <?==?> преобразовывать в <?=htmlspecialchars()?>
              0
              http://platesphp.com/
                0

                PHP — не шаблонизатор, и не надо его использовать как шаблонизатор.


                Если вы будете руками везде указывать экранирование для переменных — вы его в конце концов где-нибудь забудете, и получится нехорошо.
                Экранирование должно быть включено по умолчанию. Как и сделано в шаблонизаторах.

                  0
                  PHP таки шаблонизатор))
                    +1

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

                      –2
                      https://ru.wikipedia.org/wiki/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%82%D0%BE%D1%80
                        +1

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

                          +4
                          сам PHP, внезапно, создавался как шаблонизаторр. Да сейчас он уже много больше чем просто шаблонизатор, но шаблонизатором собсвенно он быть не перестал. Как ни крути, но голый PHP самый быстрый из всех возможны PHP-ных шаблонизаторов)
                            +2

                            Мало ли как он создавался. PHP/FI внезапно другой язык, на PHP7 похожий слабо.

                      0

                      с версии 4 уже точно нет. Первые две версии — да, шаблонизатор для Си.

                  –7
                  я юзал php7.0 + laravel5.2 (новый проект) такого натерпелся… К примеру вместо перехвата исключения ларавелом тупо белый экран и т.д. Пришло откатится на 5.6
                    +3
                    Хм… Старый проект на Yii 1(!) пару месяцев как перетащили на семерку. К примеру активно начали использовать статическую типизацию вместо аннотаций. Заметный прирост скорости при прогоне тестов получили.
                    Полёт нормальный, ЧЯДНТ?
                      0
                      А не могли бы выложить результаты тестов до и после, если конечно вас не затруднит ???
                        +1
                        Что именно вы имеете в виду?
                        Результаты PHPUnit выглядят так, например:
                        $ phpunit.phar tests/
                        PHPUnit 4.8.8 by Sebastian Bergmann and contributors.
                        .........................................................................................
                        .........................................................................................
                        .........................................................................................
                        .........................................................................................
                        .........................................................................................
                        ....................................................................................
                        
                        Time: 4.06 minutes, Memory: 54.00Mb
                        
                        OK (400 tests, 600 assertions)
                        

                        и после
                        $ phpunit.phar tests/
                        PHPUnit 4.8.8 by Sebastian Bergmann and contributors.
                        .........................................................................................
                        .........................................................................................
                        .........................................................................................
                        .........................................................................................
                        .........................................................................................
                        ....................................................................................
                        
                        Time: 1.57 minutes, Memory: 54.00Mb
                        
                        OK (400 tests, 600 assertions)
                        


                        PS: паста не натуральная, для примера, цифры по памяти поставил.

                        PPS: а, вероятно вы имели ввиду тесты на перфоманс. Нет, такие мы, к сожалению, ещё не делали.
                        0
                        ЧЯДНТ?


                        Юзаете Yii, а не Laravel, очевидно ;)
                          0
                          Тут дело в прослойке между компьютером и стулом. Я гонял на PHP7 и Symfony 2.8, и Symfony 3.0, и Laravel 5.2 — полет отличный. ^^
                            +1

                            Да понятное дело :)

                        +2
                        Возможно стоило разобраться в причине, посмотреть логи, а не опускать руки увидев белый экран.
                          0
                          в логах пусто. Везде. Помогал migrate refresh
                          +3
                          2 проекта на ларе и 7-й версии php. Может дело не в php?
                            –3
                            дело в пхп. Тот же код нормально заработал на пред. версии.
                              0
                              Дело в конфигах. Прямо сейчас работаю над laravel под php 7.0.7. Всё отлично, полёт нормальный
                                –2
                                Можете залить свои конфиги куда либо?
                                  0
                                  Так я почти ничего не менял в стандартных конфигах. Поставил «их коробки» LAMP окружение, включил в php.ini отображение всех ошибок, поставил чистый laravel, и… всё. Никаких танцов с бубнов вокруг настроек я не устраивал, всё по дефолту. Проверяйте error логи, не может такого быть что всё сломалось а логи чистые.
                                    +2
                                    На самом деле было один раз такое, когда игрался с laravel, когда пытался использовать связку nginx+php-fpm+opcache и то же был белый экран и ошибок нету, и если мне память не изменяет проблема тогда была с opcache, но было давно и деталей не помню, но факт остается фактом — экран белый, логи пустые.
                                      0
                                      Огромное спасибо! Моя проблема решена! Я снёс opcache и всё заработало.
                            –1
                            смотрите настройки пхп.
                            Белый экран — связан именно с неправильными настройками.

                            несколько проектов на пхп, всё ок :)
                              –1
                              error_reporting E_ALL
                              display_error on
                              start_errors On

                              и так дальше.
                              +1
                              Laravel 5.1 + Nginx 1.9.14 + PHP 7.0.6. Летает.
                              +2
                              Из того, что заметил в 7 версии, неработают обработчики сигналов в консоли.
                              declare(ticks=1) limited to scope of file makes Signal handling difficult

                              Еще переименовали модуль mongo в mongodb из-за чего монгу пришлось пришлось убрать из зависимостей composer'а

                              Для разработки сойдет, а для продакшена будем ждать php7.1
                                +1
                                пару месяцев как перевели большой проект в проде на семерку. были проблемы с екстеншинами, но удалось найти альтернативы, или пропатчить самим. в целом довольны)
                                  +1

                                  Уже давно не рекомендуется делать использовать declare tick для обработки сигналов. Используйте: http://php.net/pcntl_signal_dispatch

                                  –2

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

                                    –2

                                    О, заработало. Похоже, он раз в минут 10 перезапускается.

                                      –2

                                      А вот автор мне ответил — говорит, раз в 30 минут перезапускается контейнер.

                                    –4
                                    если своего сервера нет, то хостингеры пока предлагают предустановленную не выше 5.6 версии.
                                      –1
                                      Решение упражнения 6 неверно. Оно сортирует по всем символам.
                                        –2
                                        Упражнение 4. PHP4 конструкторы признаны устаревшими, используйте __construct

                                        Что за дичь!?
                                        И причем в руководстве по ПХП7, говорить о том, что не так в ПХП4?
                                        Или я что-то не понимаю!? Объясните пожалуйста.


                                        Конструктор должен носить такое же имя как и класс
                                        т.е. если класс называется Foo, то и функция также должна называться Foo.


                                        class Foo
                                        {
                                            public function Foo()
                                            {
                                        
                                            }
                                        }
                                        
                                        echo "Next step !";
                                        
                                        // Result
                                        Next step !
                                          +1
                                          Приветствую. Писать нужно
                                          public function __construct() {}

                                          если я правильно помню в php 7.1 ваш код уже не будет работать, в php 7.0 будет писать что то типа:
                                          Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in example.php on line 3


                                          А вообще тут более детально описано: php.net/manual/ru/migration70.deprecated.php
                                            0
                                            При том, что я его на 7.1 и написал и отправил…
                                            0
                                            Конструктор должен носить такое же имя как и класс

                                            добро пожаловать в 2017-ый год. Уже с версии 5.0 имя конструктора __construct. Для консистентности с деструкторами например и прочими методами жизненного цикла объекта (__clone, __sleep и т.д.) было принято решение задепрекейтить эти вещи.


                                            Подробнее тут: https://wiki.php.net/rfc/remove_php4_constructors

                                              –1
                                              в 5й версии да, не работает такая схема, но в 7ом все прекрасно работает.
                                              –1
                                              image

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

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

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