Статьи

Чего ожидать от PHP 5.5

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


Если вы хотите следовать этой статье, вам нужно установить PHP 5.5 для себя. Вы можете найти ссылку на исходный пакет здесь . Кроме того, если вам нужен двоичный файл Windows, вы можете взять его с той же страницы.

Как только вы загрузите исходный код, распакуйте все в папку и перейдите к ней с помощью вашей любимой программы Terminal. Вы можете установить PHP там, где вам нравится, но для удобства я собираюсь создать каталог в корне моего диска, который называется PHP5.5 . Чтобы создать новую папку и затем сделать своего пользователя владельцем указанной папки, введите в свой терминал следующее:

1
2
sudo mkdir /PHP5.5
sudo chown username /PHP5.5

Затем вы должны решить, какие расширения и функции вы хотите установить с вашей копией PHP. Поскольку это альфа-версия, предназначенная только для тестирования, я не буду беспокоиться о ее полной функциональности. Для этого урока я собираюсь установить только cURL, но, возможно, вы захотите добавить и другие вещи, такие как поддержка MySQL или zip. Чтобы просмотреть полный список параметров конфигурации, выполните:

1
./configure -h

Помимо опции установки cURL, нам нужно установить еще два свойства: prefix и опция with-config-file-path . Эти два свойства устанавливают местоположение установки PHP и файла .ini соответственно. Итак, в терминале введите:

1
2
3
4
5
./configure —prefix=/PHP5.5 —with-config-file-path=/PHP5.5 —with-curl=ext/curl
 
make
 
make install

Первая строка настраивает PHP с помощью cURL и задает местоположение для папки, которую мы создали ранее. Следующие две строки собирают PHP и перемещают файлы в указанную директорию. Следующий шаг — скопировать пример файла php.ini в папку PHP. Для этого запустите:

1
cp php.ini-development /PHP5.5/php.ini

Теперь у вас должно быть все правильно установлено. Самый простой способ протестировать эту новую версию — запустить встроенный веб-сервер. Перейдите в папку bin внутри каталога PHP5.5 ( cd /PHP5.5/bin ) и введите ./php -t /Path/To/Directory -S 0.0.0.0:4444 .

  • Опция -t устанавливает корневой каталог сервера (т. Е. Место, где вы будете размещать ваши файлы PHP)
  • Свойство -S устанавливает IP-адрес и номер порта, с которым должен связываться сервер. Использование 0.0.0.0 для IP-адреса указывает серверу прослушивать все IP-адреса (например, localhost, 127.0.0.1, 192.168.0.100 и т. Д.).

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


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

Самое большое дополнение к PHP 5.5 — это генераторы. Генераторы позволяют создавать пользовательские функции, которые сохраняют состояние между запусками. Он работает с новым ключевым словом, называемым yield , которое может использоваться в функции как для ввода, так и для вывода данных.

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

Поначалу это может звучать несколько круто, но если подумать, это открывает двери для множества интересных вариантов дизайна. Во-первых, он имитирует эффекты других языков программирования, которые имеют «Ленивая оценка», таких как Haskell. Одно это позволяет вам определять бесконечные наборы данных и моделировать математические функции после их фактического определения. Кроме того, вам не нужно создавать столько глобальных переменных; если переменная предназначена только для конкретной функции, вы можете включить ее в генератор, и такие вещи, как счетчики, автоматически генерируются самим генератором в форме ключа возвращаемого объекта.

Ну, на сегодня достаточно теории; давайте посмотрим на генератор в действии. Для начала перейдите к корню документа, который вы определили при запуске сервера PHP, и создайте файл с именем «index.php». Теперь откройте файл и введите следующее:

01
02
03
04
05
06
07
08
09
10
11
function fibonacci(){
    $a = 0;
    $b = 1;
 
    while(true)
    {
        $a = $a + $b;
        $b = $a — $b;
        yield $a;
    }
}

Это функция «Hello World» для бесконечных наборов данных. Это функция, которая выведет все числа Фибоначчи. Чтобы использовать генератор, все, что вам нужно сделать, это набрать:

1
2
3
4
5
$fib = fibonacci();
$fib->current();
$fib->next();
$fib->current();
//…

Здесь происходит то, что мы делаем $fib объектом генератора, а затем у вас есть доступ к базовым командам, таким как current() и next() . Функция current() возвращает текущее значение генератора; это значение того, что вы получили в функции — в нашем случае, $a . Вы можете вызывать эту функцию несколько раз, и вы всегда получите одно и то же значение, потому что функция current() не говорит генератору продолжать вычислять свой код. Вот где приходит функция next() ; next() используется, чтобы разморозить итератор и продолжить работу с функцией. Поскольку наша функция находится внутри бесконечного цикла while, она просто снова замерзнет при помощи следующей команды yield , и мы можем получить следующее значение с помощью другого вызова current() .

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

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

Другой способ yield может быть использован для получения данных. Он работает так же, как и раньше: когда функция попадает в строку с ключевым словом yield , она останавливается, но вместо чтения данных с помощью current() мы передаем ей данные с помощью функции send() . Вот пример этого в действии:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
function Logger(){
    $log_num = 1;
 
    while(true){
        $f = yield;
        echo «Log #» .
    }
}
 
$logger = Logger();
 
for($i = 0; $i<10; $i++){
    $logger->send($i*2);
}

Это простой генератор для отображения сообщения журнала. Все генераторы запускаются в состоянии паузы; запрос на send (или даже current ) запустит генератор и продолжится, пока не дойдет до команды yield . Команда send затем введет отправленные данные и продолжит обрабатывать функцию, пока не дойдет до следующего yield . Каждый последующий вызов для send будет обрабатывать один цикл; он введет отправленные данные в $f , а затем продолжит, пока не вернется к следующей yield .

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

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

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


Следующее обновление, которое я нахожу весьма полезным, — это возможность разбить вложенный массив на локальную переменную в операторе foreach . Конструкция list существует уже некоторое время (начиная с PHP4); он отображает список переменных в массив. Итак, вместо того, чтобы писать что-то вроде:

1
2
3
4
5
$data = array(«John», «Smith», «032-234-4923»);
 
$fName = $data[0];
$lName = $data[1];
$cell = $data[2];

Вы могли бы просто написать:

1
2
3
$data = array(«John», «Smith», «032-234-4923»);
 
list($fName, $lName, $cell) = $data;

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

Начиная с версии 5.5 вы можете отключить посредника и очистить свой код. Вот пример старого способа по сравнению с новым:

01
02
03
04
05
06
07
08
09
10
//—Old Method—//
foreach($parentArr as $childArr){
    list($one, $two) = $childArr;
    //Continue with loop
}
 
//—New Method—//
foreach($parentArr as list($one, $two)){
    //Continue with loop
}

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


На встроенной видеокарте моего Mac я смог обработать более 200 миллионов хэшей в секунду!

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

Самый простой способ хэшировать пароль в PHP — это использовать что-то вроде MD5 или алгоритм SHA. Проблема с такими хеш-функциями заключается в том, что их невероятно легко вычислить. Они больше не нужны для безопасности. В настоящее время они должны использоваться только для проверки целостности файла. Я установил GPU-хэш на свой компьютер, чтобы проверить это утверждение. На встроенной видеокарте моего Mac я смог обработать более 200 миллионов хэшей в секунду! Если бы вы были преданы своему делу и вложили деньги в лучшую настройку мультикарты, вы могли бы выполнять миллиарды хэшей в секунду.

Технология для этих методов не должна была длиться долго.

Итак, как вы решаете эту проблему? Ответ в том, что вы несете регулируемую нагрузку на алгоритм. Под этим я подразумеваю, что вам трудно это обрабатывать. Не то чтобы это занимало пару секунд на хеш, так как это испортило бы пользовательский опыт. Но представьте, что вам понадобилось пол секунды для генерации. Тогда пользователь, вероятно, даже не осознает эту задержку, но кто-то, пытающийся ее перебить, должен будет выполнить миллионы попыток — если не больше — и все полсекунды составят десятилетия и столетия. Как насчет проблемы компьютеров, становящихся быстрее со временем? Вот тут-то и появляется «настраиваемая» часть: время от времени вы повышаете сложность создания хэша. Таким образом, вы можете гарантировать, что это всегда занимает одинаковое количество времени. Это то, что разработчики PHP пытаются побудить людей делать.

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

Способ работы bcrypt заключается в том, что он пропускает ваш пароль через шифрование blowfish x раз, но вместо использования blowfish с ключом, чтобы вы могли изменить его позже, он передает предыдущий запуск в качестве ключа для следующей итерации. Согласно Википедии , ваш пароль проходит от 2 до x . Это та часть, которую вы можете настроить. Скажем, прямо сейчас вы хотите использовать уровень стоимости 5: bcrypt выполнит ваш хэш от 2 до 5 или 32 раза. Это может показаться небольшим числом, но, поскольку параметр стоимости корректирует функцию в геометрической прогрессии, если вы изменили ее на 15, то функция будет запускать ее до 32768 раз. Уровень стоимости по умолчанию — 10, но это настраивается в исходном коде.

Изложив теорию, давайте рассмотрим полный пример.

1
2
3
4
5
6
7
8
9
$pass = «Secret_Password»;
$hash = password_hash($pass, PASSWORD_BCRYPT, array(‘cost’ => 12, ‘salt’ => «twenty.two.letter.salt»));
 
if(password_verify($pass, $hash)){
   if(password_needs_rehash($hash, PASSWORD_DEFAULT, array(‘cost’ => 15))){
       $hash = password_hash($pass, PASSWORD_DEFAULT, array(‘cost’ => 15));
   }
   //Do something with hash here.
}

Функция password_hash принимает три параметра: слово для хеширования, константа для алгоритма хеширования и необязательный список настроек, которые включают соль и стоимость. Следующая функция, password_verify , гарантирует, что строка соответствует хешу после шифрования, и, наконец, функция password_needs_rehash гарантирует, что хеш соответствует заданным параметрам. Например, в нашем случае мы устанавливаем стоимость хэша равной двенадцати, но здесь мы указываем пятнадцать, поэтому функция вернет true , что означает, что ее необходимо перефразировать.

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

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

Причина, по которой можно связать стоимость и соль с хешем и не держать его в секрете, заключается в том, как система объединяет свои сильные стороны. Стоимость не должна быть секретной, потому что она предназначена для числа, которое обеспечивает достаточно большую нагрузку на сервер. Под этим я подразумеваю, что, даже если кто-то получит ваш хэш и определит, что вашему уровню затрат требуется 1/2 секунды для вычисления, он будет знать, на каком уровне брутфорс, но взломать его потребуется слишком много времени (например, десятилетия ).

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

Радужная таблица — это в основном хранилище значений ключей со «словарем» слов с соответствующими им хешами в качестве ключей.

Все, что нужно сделать, — это предварительно вычислить достаточно общих слов — или, что еще хуже, все строковые возможности — и тогда они могут мгновенно найти слово для данного хэша. Вот пример того, как соли могут быть полезны: допустим, ваш пароль — это слово «пароль». Обычно это довольно распространенное слово; скорее всего, это будет их радужный стол. Что соль делает, это добавляет случайную строку к вашему паролю; таким образом, вместо хеширования «пароль», это действительно хэширование «passwordRandomSalt524% # $ &». Это значительно реже вычисляется заранее.

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

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

Вот почему функция присоединяет их к хешу.

Помните, что ваша соль не имеет значения, если она уникальна.

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


До сих пор не было простого способа отправки почты через SMTP.

cURL — это еще одна область, где команда PHP добавила несколько интересных новых дополнений и обновлений. Начиная с версии 5.5, теперь у нас есть поддержка директив FTP, директив для установки файлов cookie, директив для SSL и учетных записей, а также директив для протоколов SMTP и RTSP. Обсуждение всех из них займет слишком много времени, но, чтобы просмотреть полный список, вы можете обратиться к странице НОВОСТИ .

Однако я хочу поговорить об одном конкретном наборе, который меня больше всего интересовал: о наборе директив SMTP. До сих пор не было простого способа отправки почты через SMTP. Вам придется либо изменить программу sendmail вашего сервера для отправки сообщений через SMTP-сервер, либо загрузить стороннюю библиотеку — ни один из них не является лучшим вариантом. Благодаря новым директивам CURL вы можете общаться напрямую с SMTP-сервером, таким как Gmail, всего за несколько коротких строк.

Чтобы лучше понять, как работает код, стоит немного узнать о протоколе SMTP. Что происходит, ваш скрипт подключается к почтовому серверу, почтовый сервер подтверждает ваше соединение и возвращает вам информацию (например, домен, программное обеспечение). Затем вы должны ответить на сервер с вашим адресом. Будучи болтливым (но вежливым) протоколом, SMTP приветствует вас, чтобы вы знали, что он был получен.

На данный момент вы готовы отправлять команды. Необходимые команды: MAIL FROM и RCPT TO ; они отображаются непосредственно в директивы cURL, CURLOPT_MAIL_FROM и CURLOPT_MAIL_RCPT , соответственно. У вас есть только один адрес, но вы можете указать несколько адресов. Как только это будет сделано, вы можете просто вызвать команду DATA и начать отправку самого сообщения и заголовков сообщений. Чтобы завершить передачу, вы должны отправить пустую строку, за которой следует точка, а затем еще одна пустая строка. Об этих двух последних частях (то есть команда DATA и конечная последовательность) заботится cURL, поэтому нам не нужно об этом беспокоиться.

Итак, в PHP все, что нам нужно сделать, это указать почту from и to директив, а затем отправить реальное сообщение — все в пределах cURL. Чтобы упростить задачу, я собираюсь создать класс под названием Gmail , который будет принимать имя пользователя / пароль и детали сообщения, а также отправлять электронные письма через вашу учетную запись Gmail.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Gmail{
        private $mail;
        private $email;
        private $pass;
         
        public function __construct($email, $pass){
            $this->email = $email;
            $this->pass = $pass;
        }
        private function mailGen(){
            $from = yield;
            $to = yield;
            $subject = yield;
            $body = yield;
            yield «FROM: <» .
            yield «To: <» .
            yield «Date: » .
            yield «Subject: » .
            yield «\n»;
            yield $body;
            yield «»;
        }
        public function getLine(){
            $resp = $this->mail->current();
            $this->mail->next();
            return $resp;
        }
        public function send($to, $subject, $body){
            $this->mail = $this->mailGen();
            $this->mail->send($this->email);
            $this->mail->send($to);
            $this->mail->send($subject);
            $this->mail->send($body);
            $ch = curl_init(«smtps://smtp.gmail.com:465»);
 
            curl_setopt($ch, CURLOPT_MAIL_FROM, «<» . $this->email . «>»);
            curl_setopt($ch, CURLOPT_MAIL_RCPT, array(«<» . $to . «>»));
            curl_setopt($ch, CURLOPT_USERNAME, $this->email);
            curl_setopt($ch, CURLOPT_PASSWORD, $this->pass);
            curl_setopt($ch, CURLOPT_USE_SSL, CURLUSESSL_ALL);
            //curl_setopt($ch, CURLOPT_VERBOSE, true);
            curl_setopt($ch, CURLOPT_READFUNCTION, array($this, «getLine»));
 
            return curl_exec($ch);
        }
    }

Надеюсь, ваша реакция на этот код была такой: «Вау, это коротко для полной реализации SMTP!» На случай, если это покажется сложным, мы разберемся с этим. Мы начнем с определения трех личных переменных: одна для генератора сообщений, одна для хранения электронной почты пользователя и одна для хранения его пароля. Далее у нас есть конструктор, который хранит электронную почту и пароль для дальнейшего использования; это так, мы можем отправлять несколько электронных писем, не вводя это каждый раз. Функция mailGen — это генератор PHP 5.5, который используется для вывода сообщения в соответствии с протоколом электронной почты прямо в cURL. Причина, по которой это необходимо, заключается в том, что команда, используемая в cURL для ввода данных, предназначена для чтения из файла построчно. Таким образом, вместо того, чтобы иметь дополнительную переменную, чтобы запомнить, к какой строке мы подошли, я использовал генератор, который сохраняет свою позицию.

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

Последняя функция в классе — это та, которая связывает все это вместе. Сначала мы инициализируем генератор для закрытой переменной, определенной ранее. Затем мы отправляем генератору всю необходимую информацию и создаем новую переменную cURL. Мы уже обсуждали CURLOPT_MAIL_FROM и CURLOPT_MAIL_RCPT ; они сопоставляются с эквивалентными командами SMTP. CURLOPT_MAIL_RCPT является массивом, поэтому вы можете ввести несколько адресов. Далее нам нужно добавить учетные данные для входа в GMail. Я оставил там подробный вариант; раскомментируйте его, если хотите увидеть всю транзакцию SMTP. Последние две строки просто устанавливают функцию, откуда CURL должен получать данные для сообщения, а затем мы возвращаем результаты.

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

1
2
3
$gmail = new Gmail(«[email protected]», «password»);
$gmail->send(«[email protected]», «Subject of email», «Hello Guy,\n What’s going on.»);
$gmail->send(«[email protected]», «Different Subject», «Important message.»);

Чтобы закончить эту статью, я расскажу о некоторых небольших обновлениях PHP 5.5.

Одна довольно крутая вещь — это добавленная поддержка константного разыменования строк / строк. Это означает, что вы можете получить доступ к отдельным символам в статической строке, как если бы строка была массивом символов. Быстрый пример этого:

1
2
echo «Hello World»[1];
echo [«one», «two», «three»][2];

Далее у нас есть ключевое слово finally . Это добавляется в конец блока try / catch; он инструктирует PHP, что независимо от того, были ли вызваны try или catch, вы хотите обработать раздел finally . Это хорошо для ситуаций, когда вы хотите обработать результат оператора try / catch. Вместо того, чтобы повторять код в обоих, вы можете просто поместить «рискованную» часть в блок try / catch, а всю обработку — в блок finally.

Еще одно использование, которое было предложено создателем как лучший метод, — поместить весь код очистки в блок finally. Это гарантирует, что вы, например, не пытаетесь закрыть один и тот же поток несколько раз (например, ваш код упал и вошел в блок catch после закрытия, и вы попытаетесь закрыть его снова).

Последнее, что стоит упомянуть, это то, как расширение MySQL будет объявлено устаревшим в этом новом выпуске. Вместо этого вы должны преобразовать свой код в расширения mysqli или PDO . Хотя это давно считается анти-паттерном, приятно, что команда PHP официально отказалась от него.

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


Спасибо за прочтение; Я надеюсь, что вы узнали немного! Как всегда, если у вас есть какие-либо комментарии или вопросы, перейдите к разговору ниже, и давайте поговорим!