PHP: Curl

Итак, Curl - это проект, целью которого является интерпретация URL и выборка из них данных, за проект Curl отвечает Дениел Стенберг (Daniel Stenberg). Почти все сценарии, использующие Curl - схожи по своему принципу:

1. создание ресурса Curl функцией curl_init
2. установку параметров с помощью функции curl_setopt
3. выполнение запроса с помощью curl_exec.

Недавно в проект Curl был добавлен так называемый мультиинтерфейс. Теперь РНР поддерживает и эти функции, но они ещё сыроваты.


void curl_close(resource curl)
Функция curl_close освобождает память, занятую ресурсом Curl,
string curlerror(resource curl)
Функция curlerror возвращает описание последней ошибки для заданного ресурса Curl.
integer curl_errno(resource curl)
Функция curl_errno возвращает номер последней ошибки, сгенерированной заданным ресурсом Curl.В таблице ниже приведены константы РНР, представляющие коды ошибок, возвращаемые функцией curl_errno()
Коды ошибок, возвращаемые CURL функциями
Константа Описание
CURLE_ABORTED_BY_CALLBACK Функция callback прервала операцию
CURLE_BAD_CALLING_ORDER Неверный порядок вызова функций
CURLE_BAD_FUNCTION_ARGUMENT Неверный параметр функции
CURLE_BAD_PASSWORD_ENTERED Введен неправильный пароль
CURLE_COULDNT_CONNECT Невозможно подключиться к узлу
CURLE_COULDNT_RESOLVE_HOST Невозможно обнаружить узел
CURLE_COULDNT_RESOLVE_PROXY Невозможно обнаружить прокси-сервер
CURLE_FAILED_INIT Ошибка инициализации
CURLE_FILE_COULDNT_READ_FILE Нельзя прочитать файл
CURLE_FTP_ACCESS_DENIED Во время FTP-операции доступ невозможен
CURLE_FTP_BAD_DOWNLOAD_RESUME Неудачное продолжение FTP-загрузки
CURLE_FTP_CANT_GET_HOST Невозможно обнаружить FTP-узел
CURLE_FTP_CANT_RECONNECT Невозможно повторно подключиться к FTP-серверу
CURLE_FTP_COULDNT_GET_SIZE Ошибка FTP-команды SIZE
CURLE_FTP_COULDNT_RETR_FILE Невозможно найти файл по FTP-соединению
CURLE_FTP_COULDNT_SET_ASCII Невозможно установить режим ASCII
CURLE_FTP_COULDNT_SET_BINARY Невозможно установить режим BINARY
CURLE_FTP_COULDNT_STOR_FILE Ошибка FTP-команды STOR
CURLE_FTP_COULDNT_USE_REST Ошибка FTP-команды REST
CURLE_FTP_PORT_FAILED Ошибка FTP-команды PORT
CURLE_FTP_QUOTE_ERROR Ошибка FTP-команды QUOTE
CURLE_FTP_USER_PASSWORD_INCORRECT Неправильная пара пользователь-пароль для FTP-соединения
CURLE_FTP_WEIRD_227_FORMAT Нераспознанный ответ на FTP-команду 227
CURLE_FTP_WEIRD_PASS_REPLY Нераспознанный ответ на FTP-команду PASS
CURLE_FTP_WEIRD_PASV_REPLY Нераспознанный ответ на FTP-команду PASV
CURLE_FTP_WEIRD_SERVER_REPLY Нераспознанный ответ FTPrcepeepa
CURLE_FTP_WEIRD_USER_REPLY Нераспознанный ответ USER FTP-протокола
CURLE_FTP_WRITE_ERROR FTP-сервер сообщает о проблемах при выполнении операций записи
CURLE_FUNCTION_NOT_FOUND Функция LDAP не найдена
CURLE_HTTP_NOT_FOUND HTTP-страница не найдена
CURLE_HTTP_POST_ERROR Ошибка HTTP-команды post
CURLE_HTTP_RANGE_ERROR Ошибка диапазона HTTP
CURLE_LDAP_CANNOT_BIND Ошибка связи библиотеки LDAP
CURLE_LDAP_SEARCH_FAILED Ошибка поиска библиотеки LDAP
CURLE_LIBRARY_NOT_FOUND Библиотека LDAP не найдена
CURLE_MALFORMAT_USER Неправильно задано имя пользователя
CURLE_OK Ошибок нет
CURLE_OPERATION_TIMEOUTED Тайм-аут операции
CURLE_OUT_OF_MEMORY Не хватает памяти
CURLE_PARTIAL_FILE Была передана только часть файла
CURLE_READ_ERROR Ошибка чтения на локальном устройстве
CURLE_SSL_CONNECT_ERROR Ошибка SSL-соединения
CURLE_SSL_PEER_CERTIFICATE Непроверенный сертификат SSL
CURLE_TOO_MANY_REDIRECTS Слишком много переадресаций
CURLE_UNKNOWN_TELNET_OPTION Задан неизвестный параметр утилиты TELNET
CURLE_UNSUPPORTED_PROTOCOL Протокол не поддерживается
CURLE_UNSUPPORTED_PROTOCOL Протокол не поддерживается
CURLE_URL_MALFORMAT Ошибочный URL
CURLE_URL_MALFORMAT_USER Ошибочный URL пользователя
CURLE_WRITE_ERROR Ошибка записи на локальном устройстве
boolean/string curl_ехес(resource curl)
Функция curl_ехес предназначена для выполнения запроса. В зависимости от параметра CURLOPT_RETURNTRANSFER функция curl_ехес возвращает логическое значение или запрашиваемые данные см. пример ниже.
CURL отправка POST запроса:
<?php
  if(!($curl = curl_init()))
  {
    exit ('Невозможно инициализировать ресурс Curl!');
  }
   
  //Настроить процессор поиска php.net для выполнения запроса post 
  curl_setopt($curl, CURLOPT_URL, 'http://www.php.net/search.php');
  curl_setopt($curl, CURLOPT_RETURNTRANSFER,  TRUE);
  curl_setopt($curl, CURLOPT_POST, TRUE);
  curl_setopt($curl, CURLOPT_POSTFIELDS, 'lang=en_US&Zend API&show=nosource');
   
  //сделать запрос
  $results = curl_exec($curl);
   
  print('<pre>');
  print(htmlentities($results));
  print ('</pre>');
?>

string curl_getinfo(resource curl, integer info)
Функция curl_getinfо применяется для поиска информации о Curl-запросе. В таблице ниже приведен перечень констант, используемых в аргументе info.
Заметьте!

Авторы Curl не стали плодить множество функций, для работы, они пошли другим путём. В скрипте используются несколько функций, а вот их поведение, и скрипта в целом, настраивается с помощью функции curl_setopt и её констант - их то как раз хренова куча! Так что Ctrl + F вам в помощь - я специально не стал разбивать материал на несколько страниц, что бы пользуясь встроенной функцией поиска, в вашем браузере, вы могли найти описание нужной константы на одной странице.

Перечень констант, используемых в аргументе curl_getinfo
Константа Описание
CURLINFO_CONNECT_TIME Время, затраченное на соединение
CURLINFO_CONTENT_LENGTH_DOWNLOAD Значение заголовка HTTP-заголовка Content-length
CURLINFO_CONTENT_LENGTH_UPLOAD Размер выгруженного файла
CURLINFO_CONTENT_TYPE Значение HTTP-заголовка Content - type
CURLINFO_EFFECTIVE_URL URL, использованный во время последнего запроса
CURLINFO_FILETIME Если Curl может определять время изменения запрошенного файла, оно может устанавливаться по временной метке Unix. Curl возвращает значение -1, если не представляется возможным получить время модификации
CURLINFO_HEADER_SIZE Длина всех HTTP-запросов в байтах
CURLINFO_HTTP_CODE HTTP-код, который возвращает сервер
CURLINFO_NAMELOOKUP_TIME Вещественное значение, отражающее время в секундах, необходимое для определения имени
CURLINFO_PRETRANSFER_TIME Вещественное значение, отражающее время в секундах, прошедшее до начала передачи
CURLINFO_REDIRECT_COUNT Количество переадресаций
CURLINFO_REDIRECT_TIME Вещественное значение, отражающее время в секундах, необходимое для всех шагов переадресации
CURLINFO_REQUEST_SIZE Размер HTTP - запроса
CURLINFO_SIZE_DOWNLOAD Общий размер загруженных данных в байтах
CURLINFO_SIZE_UPLOAD Всего выгружено байт
CURLINFO_SPEED_DOWNLOAD Скорость всех загрузок в байтах в секунду
CURLINFO_SPEED_UPLOAD Скорость всех выгрузок в байтах в секунду
CURLINFO_SSL_VERIFYRESULT Результат проверки соединения при SSL-запросе
CURLINFO_STARTTRANSFER_TIME Время, затраченное на начало передачи
CURLINFO_TOTAL_TIME Вещественное значение, отражающее время в секундах, необходимое для завершения передачи за исключением времени, необходимого для подключения
<?php
 
  //принять стартовую страницу узла Zend
  $curl = curl_init('http://www.zend.com/');
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
  curl_exec($curl);
    
  //получить различную информацию
  echo 'CURLINFO_CONNECT_TIME: '.curl_getinfo($curl, CURLINFO_CONNECT_TIME).'<br />';
  echo 'CURLINFO_CONTENT_LENGTH_DOWNLOAD: '.curl_getinfo($curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD).'<br />';
  echo 'CURLINFO_CONTENT_LENGTH_UPLOAD: '.curl_getinfo($curl, CURLINFO_CONTENT_LENGTH_UPLOAD).'<br />';
  echo 'CURLINFO_CONTENT_TYPE: '.curl_getinfo($curl, CURLINFO_CONTENT_TYPE).'<br />';
  echo 'CURLINFO_EFFECTIVE_URL: '.curl_getinfo($curl,  CURLINFO_EFFECTIVE_URL).'<br />';
  echo 'CURLINFO_FILETIME: '.curl_getinfo($curl, CURLINFO_FILETIME).'<br />';
  echo 'CURLINFO_HEADER_SIZE: '.curl_getinfo($curl,  CURLINFO_HEADER_SIZE).'<br />';
  echo 'CURLINFO_HTTP_CODE: '.curl_getinfo($curl,  CURLINFO_HTTP_CODE).'<br />';
  echo 'CURLINFO_NAMELOOKUP_TIME: '.curl_getinfo($curl, CURLINFO_NAMELOOKUP_TIME).'<br />';
  echo 'CURLINFO_PRETRANSFER_TIME: '.curl_getinfo($curl,  CURLINFO_PRETRANSFER_TIME).'<br />';
  echo 'CURLINFO_REDIRECT_COUNT: '.curl_getinfo($curl,  CURLINFO_REDIRECT_COUNT).'<br />';
  echo 'CURLINFO_REDIRECT_TIME: '.curl_getinfo($curl,  CURLINFO_REDIRECT_TIME).'<br />';
  echo 'CURLINFO_REQUEST_SIZE: '.curl_getinfo($curl, CURLINFO_REQUEST_SIZE).'<br />';
  echo 'CURLINFO_SIZE_DOWNLOAD: '.curl_getinfo($curl,  CURLINFO_SIZE_DOWNLOAD).'<br />';
  echo 'CURLINFO_SIZE_UPLOAD: '.curl_getinfo($curl,  CURLINFO_SIZE_UPLOAD).'<br />';
  echo 'CURLINFO_SPEED_DOWNLOAD: '.curl_getinfo($curl,  CURLINFO_SPEED_DOWNLOAD).'<br />';
  echo 'CURLINFO_SPEED_UPLOAD: '.curl_getinfo($curl,  CURLINFO_SPEED_UPLOAD).'<br />';
  echo 'CURLINFO_SSL_VERIFYRESULT: '.curl_getinfo($curl,  CURLINFO_SSL_VERIFYRESULT).'<br />';
  echo 'CURLINFO_STARTTRANSFER_TIME: '.curl_getinfo($curl, CURLINFO_STARTTRANSFER_TIME).'<br />';
  echo 'CURLINFO_TOTAL_TIME: '.curl_getinfo($curl, CURLINFO_TOTAL_TIME).'<br />';
 
?>

resource curl_init(string url)
Функция curl_init используется для создания дескриптора ресурса Curl. Необязательный аргумент url устанавливает параметр CURLOPT_URL.
integer curl_multi_add_handle(resource multi, resource curl)
Функция curl_milti_add_handle добавляет обычный ресурс Curl в мульти ресурсный стек и возвращает код состояния.
curl_multi_close(resource multi)
Функция curl_milti_close закрывает мультиресурс Curl и вызывает функцию curl_multi_cleanup.
integer curl_multi_exec (resource multi)
Функция curl_milti_exec читает и записывает данные на все сокеты мультиресурсного стека. Вызывает функцию curl_milti_perform.
string curl_multigetcontent(resource multi)
Функция curl_multi_getcontent возвращает содержимое из мультиресурса.
array curl_multi_lnfo_read(resource multi)
Функция curl_multi_lnfo_read возвращает массив, содержащий информацию о мультиресурсе.
resource curl_milti_init()
Функция curl_milti_init возвращает ресурс, указывающий на мульти интерфейс.
integer curl_multi_remove_handle(resource multi, resource curl)
Функция curl_multi_remove_handle удаляет обычный ресурс Curl из мульти ресурсного стека. Возвращает код состояния.
curl_multi_select(resource multi, integer timeout)
Функция multi_select выполняет выбор из библиотеки языка С по набору ресурсов Curl в мульти ресурсном стеке. Передается необязательный аргумент timeout.
string curl_version()
Функция curl_version предназначена для определения версии работающей библиотеки Curl.
boolean curl_setopt(resource curl, string option, value setting)
Функция curl_setopt позволяет сделать настройку соединения Curl до выполнения функции curl_exec. Необходимо передавать дескриптор ресурса Curl, созданного функцией curl_init. В таблице ниже, перечислены константы для этой функции
Константа Описание
CURLOPT_BINARYTRANSFER Используется с параметром, CURLOPT_RETURNTRANSFER. Это гарантирует возвращение двоичного значения
CURLOPT_CAINFO Указывает путь к файлу, содержащему один и более сертификатов, необходимых для проверки другого узла. Этот параметр действует только вместе с параметром CURLOPT_SSL_VERIFYPEER
CURLOPT_CAPATH Указывает путь к файлу, содержащему один или более сертификатов, необходимых для проверки другого узла. Этот параметр действует только вместе с параметром CURLOPT_SSL_VERIFYPEER
CURLOPT_CLOSEPOLICY Используется для установки политики закрытия соединения при его заполнении. Может иметь значение CURLCLOSEPOLICY_LEAST_RECENTLY_USED или CURLCLOSEPOLICY_OLDEST
CURLOPT_CONNECTTIMEOUT Задает максимальное время ожидания соединения в секундах
CURLOPT_COOKIE Используется для задания файлов cookie в запросе. Он задается в виде строки со знаком равенства между именем файла cookie и значением value. Имена файлов cookie разделяются точкой с запятой. Например, cookiel=valueA; cookiel=valueB задает два файла cookie: cookiel и cookie2
CURLOPT_COOKIEFILE Путь, по которому размещаются файлы cookie по запросам. Этот файл может соответствовать формату Netscape Navigator или обычному формату HTTP-заголовка
CURLOPT_COOKIEJAR Задает путь к файлу, в котором сохраняются файлы cookie. Curl сохраняет любые файлы cookie, которые он получает во время запроса к этому файлу. Затем этот файл можно указывать в параметре CURLOPT_COOKIEFILE
CURLOPT_CRLF При значении TRUE Curl преобразует символы новой строки, характерные для ОС Unix, в пары символов "возврат каретки перевод строки"
CURLOPT_CUSTOMREQUEST Используется для отсылки альтернативной команды при HTTP-запросе. В нем указывается только команда, а не вся строка запроса
CURLOPT_DNS_CACHE_TIMEOUT Параметр работы с кэшем поиска имен узлов. В нем задается время хранения имени в кэше (в секундах)
CURLOPT_DNS_USE_GLOBAL_CACHE При значении TRUE Curl разделяет кэш поиска имен узлов. Этот параметр не является защищенным с точки зрения потоков
CURLOPT_EGDSOCKET Задает путь к сокету Entropy Gathering Daemon. Curl использует его в качестве генератора случайных чисел, который используется для SSL
CURLOPT_FAILONERROR При значении TRUE коды HTTP-ответов больше 300 не приводят к возвращению страниц, обычно возвращаемых сервером
CURLOPT_FILE Предназначен для вывода сообщений в файл, а не в браузер
CURLOPT_FILETIME При значении TRUE Curl делает попытку получить время модификации запрошенного файла
CURLOPT_FOLLOWLOCATION При значении TRUE Curl просматривает заголовки переадресации, возвращаемые HTTP-серверами. Установите в TRUE, что бы Curl следовал редиректам.
CURLOPT_FORBID_REUSE При значении TRUE Curl закрывает соединение после завершения обработки запроса
CURLOPT_FRESH_CONNECT При значении TRUE Curl независимо от наличия соответствующего соединения в кэше создает новое соединение
CURLOPT_FTPAPPEND При значении TRUE Curl при операции FTP выгрузки, вместо перезаписи выполняет добавление
CURLOPT_FTPLISTONLY При значении TRUE Curl возвращает перечень файлов, хранящихся в FTP-каталоге
CURLOPT_FTPPORT Задает настройки FTP-команды PORT, при этом запрашивается соединение с сервером. В этом параметре указываются IP-адрес, имя узла, имя сетевого интерфейса. Для использования адреса, используемого по умолчанию, указывается -
CURLOPT_FTP_USE_EPSV По умолчанию, при FTP-передачах в пассивном режиме, Curl использует команду EPSV. Для того чтобы запретить использование этой команды, данный параметр должен иметь значение FALSE
CURLOPT_HEADER При значении TRUE Curl включает в вывод заголовки
CURLOPT_HEADERFUNCTION Задает имя функции, которую вызывает Curl для каждого вызванного HTTP-заголовка. Эта функция должна принимать два аргумента: ресурс Curl и строку, содержащую полный заголовок
CURLOPT_HTTPGET При значении TRUE Curl в HTTP-передачах использует метод GET. Это может понадобиться только при повторном использовании ресурса Curl
CURLOPT_HTTPHEADER Позволяет отправить HTTP-заголовки, прописанные вручную. Заголовки должны быть помещены в массив
CURLOPT_HTTPPROXYTUNNEL При значении TRUE Curl передает все запросы, пользуясь туннелем на прокси-сервере
CURLOPT_HTTP_VERSION Используется для того, чтобы вынудить Curl использовать соответствующую версию протокола HTTP. Значение CURL_HTTP_VERSION_NONE задается, если право выбора предоставляется Curl. Для того чтобы использовалась версия HTTP/1.0, необходимо задать значение CURL_HTTP_VERSION_1_0. Для того чтобы использовалась версия HTTP/1.1, необходимо задать значение CURL_HTTP_VERSION_l_l
CURLOPT_INFILE Если в этом параметре указан открытый файловый поток, то Curl будет считывать туда ввод из файла
CURLOPT_INFILESIZE Используется для определения размера выгружаемого файла
CURLOPT_INTERFACE Задает имя используемого интерфейса. Можно задавать имя интерфейса, имя узла или IP-адрес
CURLOPT_KRB4LEVEL Для FTP-передач с помощью этого параметра можно указать уровень безопасности Kerberos. Значением этого параметра могут быть такие строки: clear, safe, confidential и private. Установка значения FALSE отключит безопасность Kerberos
CURLOPT_LOW_SPEED_LIMIT Используется для снижения ограничения скорости передачи, которая задается в байтах в секунду. Если скорость передачи упадет ниже предела, заданного параметром CURLOPT_LOW_SPEED_TIME, Curl прервет передачу
CURLOPT_LOW_SPEED_TIME Предназначен для снижения ограничения скорости передачи и используется с параметром CURLOPT_LOW_SPEED_LIMIT
CURLOPT_MAXCONNECTS Задает размер кэша соединения
CURLOPT_MAXREDIRS Используется для задания максимального количества переадресаций
CURLOPT_MUTE При значении TRUE PHP не генерирует вывод на браузер при выполнении функций Curl
CURLOPT_NETRC При значении TRUE Curl при аутентификации пользователей просматривает путь ~/.netrc
CURLOPT_NOBODY При значении TRUE Curl исключает из вывода основное тело HTTP-страницы
CURLOPT_NOPROGRESS При значении FALSE Curl отображает индикатор работы. По умолчанию этот параметр имеет значение TRUE
CURLOPT_PASSWDFUNCTION Используется для указания имени функции обработки запросов паролей. Эта функция должна принимать три аргумента: ресурс Curl, подсказку пароля, отправленную сервером, и ссылку, куда необходимо поместить пароль. Эта функция возвращает нуль в случае успешного завершения работы и значение, отличное от нуля, в случае возникновения ошибки. Для восстановления стандартной функциональности для этого параметра устанавливается значение FALSE
CURLOPT_PORT Используется для задания номера порта, применяемого в запросах
CURLOPT_POST При значении TRUE Curl делает HTTP-запрос POST с помощью кодировки application/x-www-form-urlencoded
CURLOPT_POSTFIELDS Предназначен для передачи всех данных операции post. Поля форматируются строго в соответствии с порядком приема. Например, строка apple=l&ball=red&cat=45.56 будет соответствовать трем полям: apple, ball и cat
CURLOPT_POSTQUOTE Передает массив FTP-команд, выполняемых после главного запроса
CURLOPT_PROXY Устанавливается на прокси-сервере
CURLOPT_PROXYUSERPWD Используется для установки имени пользователя и его пароля, необходимых для прокси-сервера. При этом используется формат username; password
CURLOPT_PUT При значении TRUE Curl выполняет HTTP-запрос PUT. При этом необходимо задавать параметры CURLOPT INFILE и CURLOPT INFILESIZE
CURLOPT_QUOTE Задает массив FTP-команд, выполняемых до главного запроса
CURLOPT_RANDOM_FILE Задает путь к файлу, который будет читать Curl для задания начальных значений генератора случайных величин SSL
CURLOPT_RANGE Используется для задания диапазона заголовка, отправленного HTTP-сервером. Передается строка, содержащая смещение начала и конца строки в байтах, разделенные тире. При указании нескольких диапазонов они разделяются запятыми, например 100-150,233-502. О диапазонах можно узнать подробнее в спецификации протокола HTTP 1.1
CURLOPT_READFUNCTION Задает имя функции передачи данных другой стороне соединения. Эта функция должна принимать два аргумента: ресурс Curl и строку ссылки. Копирует данные в строку ссылки и возвращает количество байт. Возвращение нулевого значения свидетельствует о достижении конца файла
CURLOPT_REFERER Используется для задания значения поля Ref erer, передаваемого в HTTP-запросах
CURLOPT_RESUME_FROM Предназначен для возобновления передачи. Смещение задается в байтах
CURLOPT_RETURNTRANSFER Обычно Curl отправляет результаты команд непосредственно в браузер. Для получения результатов в виде возвращаемого значения утилиты curl_exec для этого параметра устанавливается значение TRUE
CURLOPT_SSLCERT Задает путь к сертификату SSL в формате РЕМ (Privacy Enhanced Mail)
CURLOPT_SSLCERTPASSWD Задает пароль, необходимый для чтения сертификата SSL, заданного параметром CURLOPT_SSLCERT
CURLOPT_SSLENGINE Задает имя процессора SSL, который будет использоваться для частных ключей
CURLOPT_SSLENGINE_DEFAULT Задает имя процессора SSL, который будет использоваться в большинстве случаев, исключая частные ключи
CURLOPT_SSLKEY Задает путь к частному ключу. По умолчанию задается тип РЕМ, который может быть изменен параметром CURLOPT_SSLKEYTYPE
CURLOPT_SSLKEYPASSWD Задает пароль, необходимый для использования с частным ключом, заданным параметром CURLOPT_SSLKEY
CURLOPT_SSLKEYTYPE Задает тип частного ключа, заданного параметром CURLOPT_SSLKEY. Тип определяется одной из следующих строк: РЕМ, DER или ENG
CURLOPT_SSLVERSION Предназначен для активизации второй или третьей версии SSL. Обычно Curl "угадывает" соответствующую версию протокола
CURLOPT_SSL_CIPHER_LIST Используется для определения списка шифров, которые будут использоваться при SSL-соединениях. Названия шифров разделяются точкой с запятой. Этот список задается в процессе компиляции OpenSSL
CURLOPT_SSL_VERIFYHOST Для этого параметра устанавливается значение 1, если Curl проверяет имя сертификата SSL, или значение 2, для того чтобы было достаточно простого совпадения с именем узла
CURLOPT_SSL_VERIFYPEER При значении TRUE Curl делает попытку проверить идентичность соединения с помощью сертификатов, заданных параметром CURLOPT_CAINFO
CURLOPT_STDERR Задает открытый файловый поток, куда будут перенаправлены сообщения об ошибках
CURLOPT_TIMECONDITION Предназначен для активизации условий передачи на основании анализа времени последней модификации удаленного файла. Для задания временного значения, которое будет использоваться для проверки этого условия, используется параметр CURLOPT_TIMEVALUE. Для соблюдения требования модификации файла с определенного момента времени используется параметр TIMECOND_IFMODSINCE. Для соблюдения требования отсутствия изменений файла с определенного момента времени используется параметр TIMECOND_ISUNMODSINCE
CURLOPT_TIMEOUT Задает максимальное время в секундах, на протяжении которого может выполняться Curl-операция
CURLOPT_TIMEVALUE Устанавливает время в стандартном формате временной метки Unix, который используется параметром CURLOPT_TIMECONDITION
CURLOPT_TRANSFERTEXT При значении TRUE Curl осуществляет FTP-передачи в формате ASCII и в тексте в формате LDAP вместо HTML
CURLOPT_UPLOAD При значении TRUE Curl выполняет НТТР-выгрузку. Необходимо установить CURLOPT_INFILE и CURLOPT_INFILESIZE
CURLOPT_URL Задает исполняемый URL. Этот параметр можно установить и с помощью утилиты curl_init
CURLOPT_USERAGENT Устанавливает значение поля User-agent, переданное в HTTP-запросах
CURLOPT_USERPWD Задает имя пользователя и его пароль, необходимый для соединения. При этом используется формат username:password
CURLOPT_VERBOSE При значении TRUE Curl выводит сообщение о состоянии
CURLOPT_WRITEFUNCTION Задает имя функции, которая будет получать данные при указанном соединении. Эта функция принимает два аргумента: ресурс Curl и строку данных. Она возвращает количество обработанных байтов данных. Если возвращаемое значение не соответствует количеству переданных данных, Curl сообщает об ошибке
CURLOPT_WRITEHEADER Задает открытый файловый поток, который будет получать заголовки. Значением option задается ресурс, возвращаемый функцией fopen

Добавлено: 14 Июня 2019 20:12:48 Добавил: Андрей Ковальчук

Простые правила работы с UTF-8 кодировкой в PHP

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

Я думаю, не надо рассказывать, что UTF-8 уже является стандартом для большинства web-приложений и пока не планируется особых замен. Но на текущий момент множество начинающих "познавателей" PHP сталкиваются с проблемами в этом месте и постят кучу топиков в связи с тем, что PHP пока не поддерживает кодировку UTF-8 "из коробки" и приносит вышеуказанным людям кучу непонимания и проблем. Кракозяблики, кракозяблики, кракозяблики... Проблема с UTF-8... Что делать? Помогите - слышно тут и там... На самом деле всё очень просто. Ниже я опишу несколько правил, которые позволяют избавиться от "проблем" с UTF-8 при разработке приложений на PHP.

Для начала, когда, пользуясь здравым смыслом, мы решаем работать с UTF-8 для простоты дела мы утверждаем, что от ныне абсолютно всё у нас будет храниться, писаться, выводиться в UTF-8. Второе, что нам будет нужно, это наличие php_mbstring расширения на сервере, которое предоставляет функции для работы со строками в многобайтном режиме. Для тех, кто в танке это функции, которые начинаются на mb_. Если ваш хостинг провайдер не потрудился установить у себя это расширение - смело выбирайте другого. Итак, если если ваш php поддерживает mb_ функции - пол дела сделано. Остальные пол дела для работы с UTF-8 в PHP заключаются в следующем:

1. В начале работы скрипта необходимо указать кодировку входа и выхода с помощью функции mb_internal_encoding:

Listing №1 (PHP)

mb_internal_encoding('UTF-8');

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

2. При работе со строками, преобразованиями символов, необходимо использовать функции работы со строками из расширения php_mbstring. Это, например, такие как mb_substr, mb_strpos, mb_strlen и т.п. или же те функции, которые безопасны для обработки данных в двоичной форме, такие как explode, str_replace и т.д. Эта особенность указана в мануале по этим функциям. Иногда нельзя просто заменить функцию на её mb-аналог, потому как такой там просто нет. Например, ucfirst, которая преобразует первый символ строки в верхний регистр. Решение тут очень простое - изящной комбинацией mb_substr и mb_strtoupper получаем необходимый результат. Попробуйте проделать это сами )). Также в этот пункт стоит отнести такие функции как htmlspecialchars, htmlentities и т.п., которые производят различные преобразования строк. Пожалуйста, передавайте в них третий аргумент $charset в виде строки 'UTF-8'.

3. Так как мы используем строки символов в самих скриптах, то строго необходимо сохранять их в UTF-8 кодировке. Это также относиться ко всем остальным файлам, которые вы используете - HTML шаблоны, различные подключаемые файлы, текстовые и т.д. Это всё должен делать ваш редактор кода. Согласуйте с ним эти вещи. Но смотрите внимательно, что бы он кодировал или преобразовывал файлы в UTF-8 без особой метки, называемой BOM. Так будет намного лучше.

4. Немаловажным фактором, является работа браузера с кодировкой UTF-8, а точнее с данными, которые вы посылаете ему, и теми данными, которые он отсылает вам. Для того, что бы браузер правильно понимал в какой кодировке вы отправили ему данные нужно отсылать заголовок с указанием кодировки. Это можно сделать так:

Listing №2 (PHP)
header('Content-Type: text/html; charset=UTF-8');

Только не забудьте отправлять этот заголовок до какого либо вывода с помощью echo, print или просто пробелов в начале скрипта до тега <?php или где то между парой этих тегов ?> <?php. Ну, а для того, чтобы браузер отсылал вам данные в нужной кодировке, нужно помечать сам html документ соответствующим мета-тегом. Например таким:

Listing №3 (HTML)
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

5. Наверное больше всего трудностей вызывает работа с базой данных. Обычно используется MySQL СУРБД. Тут всё тоже очень просто. Перед тем как послать и принимать данные нужно сказать серверу базы данных, что вы будете отсылать ей данные в кодировке UTF-8. Не вдаваясь в особые подробности, скажу лишь, что перед любым обращением к базе лишь единожды, т.е. один раз, нужно выполнить два запроса. Вот они:

Listing №4 (SQL)
SET NAMES "utf8"
-- и
SET CHARACTER SET "utf8"

Поверьте, она с радостью воспримет ваш призыв. Но не только обмениваться, а и хранить данные нужно соответственно. Посему изначально создавайте поля, хранящие строки в UTF-8 кодировке. Я думаю, вам не составит труда указать это при создании таблицы ;)


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

Добавлено: 08 Августа 2018 07:58:54 Добавил: Андрей Ковальчук

Мой родной PHP шаблонизатор

Целью этой статьи является разработка простого шаблонизатора, который смог бы удовлетворить основные потребности разработчика в моём лице, да и не только в моём. Принцип работы его будет основан на native методе, который вместе с другим детальнее описан тут для тех, кто еще не в курсе.

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

Удобное извлечение переменных в шаблоне
Вставка шаблона в шаблон
Корректная работа с HTML кодом
Режим отладки
Этим списком, думаю, я буду полностью удовлетворен.

Начнем с переменных. Тут, как и везде далее все просто - магический метод __get нам поможет обращаться к переменной по ее имени. Всё начинает выглядеть примерно так:


Listing №1 (PHP)

class Template {
  /**
   * @var array
   */
  private $_Vars;
  /**
   * @var string
   */
  private $_Name;
  /**
   * @var string
   */
  private $_Path;
 
  public function __construct()
  {
    $this->_Name = '';
    $this->_Vars = array();
    $this->_Path = '';
  }
  /**
   * @param string $VarName имя переменной
   * @param string $VarValue значение переменной
   * @return Template
   */
  public function AddVar($VarName, $VarValue)
  {
    if ($VarName !== '') {
      $this->_Vars[$VarName] = $VarValue;
    }
    return $this;
  }
  /**
   * @param string $Varname имя переменной
   * @return mixed
   */
  public function __get($VarName)
  {
    if (array_key_exists($VarName, $this->_Vars)) {
      if ($this->_Vars[$VarName] instanceof Template) {
        return $this->_Vars[$VarName]->Prepare();
      }
      else{
        return $this->_Vars[$VarName];
      }
    }
    return NULL;
  }
  /**
   * @var string $Name имя шаблона
   */
  public function SetName($Name)
  {
    $this->_Name = $Name;
  }
  /**
   * @var string $Path путь к шаблону(ам)
   */
  public function SetPath($Path)
  {
    $this->_Path = $Path;
  }
}


Теперь двумя следующими методами обеспечим корректность выводимых данных. Первый заботиться об спецсимволах HTML, а второй о валидности ccылок:


Listing №2 (PHP)
  /**
   * @param mixed $Var
   * @return mixed
   */
  protected function EscapeHtml($Var)
  {
    if(is_array($Var)) {
      foreach($Var as &$VarItem) {
        $VarItem = $this->EscapeHtml($VarItem);
      }
    }
    else {
      $Var = htmlspecialchars($Var, ENT_QUOTES);
    }
    return $Var;
  }
  /**
   * @param mixed $Var
   * @return mixed
   */
  protected function EscapeUrl($Var)
  {
    if(is_array($Var)) {
      foreach($Var as &$VarItem) {
        $VarItem = $this->EscapeUrl($Var);
      }
    }
    else {
      $Var = htmlentities($Var, ENT_QUOTES);
    }
    return $Var;
  }


Идем дальше.

Что я подразумеваю под словами "режим отладки"? Это, скорее всего, больше похоже на режим удобного чтения. В таком режиме на выходе мы получим код шаблона в том же виде, что и до его парсинга, то есть со всеми табуляциями, переводами строк и прочей нечистью. Это довольно удобно, потому что native шаблоны могут сложно восприниматься и то и дело приходится всё табулировать и переносить. В противоположность этому режиму будет обычный рабочий режим, где ненужные символы будут удалены за ненадобностью. За это будет отвечать метод _Zip, а за переключение между режимами статический метод SetDebug:


Listing №3 (PHP)
  /**
   * Свойство хранящее текущий режим
   * @static
   * @var bool
   */
  private static $_Debug = FALSE;
  /**
   * Вкл/выкл дебаг режим
   * @static
   * @param bool $TrueOrFalse TRUE
   */
  public static function SetDebug($TrueOrFalse = TRUE)
  {
    self::$_Debug = $TrueOrFalse;
  }
  /**
   * Возвращает $Text с удаленными "\t", "\n" и "\r"
   * @param  string $Text
   * @return string
   */
  private function _Zip($Text)
  {
    return (empty($Text)) ? $Text : str_replace(array("\t", "\n", "\r"), '', $Text);
  }


Теперь нам нужен метод Prepare, который выполнит всю основную работу, но не выведет данные, а возвратит их строкой. Это нам понадобиться для реализации вставки шаблона в шаблон, которая и происходит при извлечении переменной в шаблоне (метод __get). Думаю, без буферизации вывода тут не обойтись:


Listing №4 (PHP)
  /**
   * @return string
   */
  public function Prepare()
  {
    if (file_exists($this->_Path . $this->_Name)) {
      ob_start();
      ${__CLASS__} = $this;
      include $this->_Path . $this->_Name;
      unset(${__CLASS__});
      return (self::$_Debug) ? ob_get_clean() : $this->_Zip(ob_get_clean());
    }
    else {
      throw new Exception('Template file "' . $this->_Path . $this->_Name . '" does not exists');
    }
  }


Сначала проверяем наличие шаблона. Затем "по родному" парсим шаблон и возвращаем контент из буфера, очистив ненужные символы, если это необходимо. Также, меня очень напрягает писать в шаблонах $this, поэтому я решил писать там $Template. Мне так очень нравится.

Наконец, добавив метод непосредственного вывода, получаем нужный "полный фарш":


Listing №5 (PHP)
class Template {
  /**
   * @var string
   */
  private $_Name;
  /**
   * @var array
   */
  private $_Vars;
  /**
   * @var string
   */
  private $_Path;
  /**
   * @static
   * @var bool
   */
  private static $_Debug = FALSE;
  /**
   * @static
   * @param bool $TrueOrFalse TRUE
   */
  public static function SetDebug($TrueOrFalse = TRUE)
  {
    self::$_Debug = $TrueOrFalse;
  }
 
  public function __construct()
  {
    $this->_Name = '';
    $this->_Vars = array();
    $this->_Path = '';
  }
  /**
   * @param string $VarName
   * @param string $VarValue
   * @return Template
   */
  public function AddVar($VarName, $VarValue)
  {
    if ($VarName !== '') {
      $this->_Vars[$VarName] = $VarValue;
    }
    return $this;
  }
  /**
   * @param string $Varname
   * @return mixed
   */
  public function __get($VarName)
  {
    if (array_key_exists($VarName, $this->_Vars)) {
      if ($this->_Vars[$VarName] instanceof Template) {
        return $this->_Vars[$VarName]->Prepare();
      }
      else{
        return $this->_Vars[$VarName];
      }
    }
    return NULL;
  }
  /**
   * @var string $Name
   */
  public function SetName($Name)
  {
    $this->_Name = $Name;
  }
  /**
   * @var string $Path
   */
  public function SetPath($Path)
  {
    $this->_Path = $Path;
  }
  /**
   * @return string
   */
  public function Prepare()
  {
    if (file_exists($this->_Path . $this->_Name)) {
      ob_start();
      ${__CLASS__} = $this;
      include $this->_Path . $this->_Name;
      unset(${__CLASS__});
      return (self::$_Debug) ? ob_get_clean() : $this->_Zip(ob_get_clean());
    }
    else {
      throw new Exception('Template file "' . $this->_Path . $this->_Name . '" does not exists');
    }
  }
 
  public function Display()
  {
    print ($this->Prepare());
  }
  /**
   * @param mixed $Var
   * @return mixed
   */
  protected function EscapeHtml($Var)
  {
    if(is_array($Var)) {
      foreach($Var as &$VarItem) {
        $VarItem = $this->EscapeHtml($VarItem);
      }
    }
    else {
      $Var = htmlspecialchars($Var, ENT_QUOTES);
    }
    return $Var;
  }
  /**
   * @param mixed $Var
   * @return mixed
   */
  protected function EscapeUrl($Var)
  {
    if(is_array($Var)) {
      foreach($Var as &$VarItem) {
        $VarItem = $this->EscapeUrl($Var);
      }
    }
    else {
      $Var = htmlentities($Var, ENT_QUOTES);
    }
    return $Var;
  }
  /**
   * @param  string $Text
   * @return string
   */
  private function _Zip($Text)
  {
    return (empty($Text)) ? $Text : str_replace(array("\t", "\n", "\r"), '', $Text);
  }
}


Ну и напоследок, небольшой пример использования.

Допустим, у нас есть два шаблона - главная страница page.php и список пользователей userslist.php. Нужно отобразить этот список вместе с информацией на главной странице. Поскупившись на контент, рисуем главную:


Listing №6 (PHP)
<div style="border: 1px solid #E0E3F3;">
  <?php echo $Template->UserList;?>
</div>

<a href="<?php echo $Template->EscapeUrl($Template->Link)?>">About</a>

А также список пользователей:


Listing №7 (PHP)
<div>
  <?php foreach($Template->EscapeHtml($Template->UserNames) as $UserName) { ?>
  <span style="color: #FF0000;"><?php echo $UserName;?></span><br>
  <?php } ?>
</div>


За логику отвечает некая модель:


Listing №8 (PHP)
//Подключаем шаблонизатор
require 'Template.php';
//Устанавливаем режим отладки включенным для всех шаблонов
Template::SetDebug(TRUE);
//Инициализируем подшаблон списка пользователей
$UsersListView = new Template();
$UsersListView->SetName('userslist.html');
//Список пользователей
$UserNames = array('Den Rights©', 'Dasha Nasha', 'Samuil Kakojto');
$UsersListView->AddVar('UserNames', $UserNames);
//Инициализируем главный шаблон страницы
$PageView = new Template();
$PageView->SetName('page.html');
$PageView->AddVar('UserList', $UsersListView);
$PageView->AddVar('Link', 'http://www.itdumka.com.ua/index.php?cmd=shownode&node=1');
$PageView->Display();



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


Listing №9 (HTML)
<div style="border: 1px solid #E0E3F3;">
  <div>
    <span style="color: #FF0000;">Den Rights©</span><br>
    <span style="color: #FF0000;">Dasha Nasha</span><br>
    <span style="color: #FF0000;">Samuil Kakojto</span><br>
  </div>
</div>
<a href="http://www.itdumka.com.ua/index.php?cmd=shownode&node=1">About</a>


Вот так.

Добавлено: 08 Августа 2018 07:45:41 Добавил: Андрей Ковальчук

Определение конструкторов объектов

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

Решение
Определите метод с тем же самым именем, что и имя класса:

class user {
function user($username, $password) {
...
}
}


Обсуждение
Если функция имеет то же имя, что и класс, она действует как конструктор:

class user {
var $username;
function user($username, $password) {
if ($this->validate_user($username, $password)) {
$this->username = $username;
}
}
}
$user = new user('Grif', 'Mistoffelees'); // используем встроенный конструтор


PHP не всегда поддерживал конструкторы. Поэтому программисты создавали псевдоконструкторы, следуя соглашению об именах и вызывая эти функции после создания объекта:

class user {
...
init($username, $password) { ... }
}
$user = new user();
$user->init($username, $password);


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

Однако стандартное наименование всех конструкторов облегчает вызов родительских конструкторов (поскольку нет необходимости знать имя родительского класса), а также не требует модификации конструктора, если изменяется имя класса. В Zend Engine 2 соглашения об именах конструкторов были изменены, и новое имя конструктора теперь __construct(). Однако в целях обратной совместимости, если такой метод не найден, PHP пытается вызвать конструктор с тем же именем, что и имя класса.

Добавлено: 21 Июля 2018 13:37:52 Добавил: Андрей Ковальчук

Создание динамических функций

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

Решение
Это делается при помощи функции create_function():

$add = create_function('$i,$j', 'return $i+$j;');
$add(1, 1); // возвращает 2


Обсуждение
Первый параметр функции create_function() представляет собой строку, содержащую аргументы функции, а второй параметр – тело функции. Функция create_function() работает крайне медленно, поэтому, если возможно заранее определить функцию, лучше так и сделать.

Чаще всего функция create_function() используется при разработке пользовательских вариантов функций сортировки usort() или array_ walk():

// сортирует файлы в порядке, обратном обычному
usort($files, create_function('$a, $b', 'return strnatcmp($b, $a);'));

Добавлено: 21 Июля 2018 13:37:13 Добавил: Андрей Ковальчук

Доступ к глобальной переменной внутри функции

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

Решение
Поместите глобальную переменную в локальную область видимости с помощью ключевого слова global:

function eat_fruit($fruit) {
global $chew_count;
for ($i = $chew_count; $i > 0; $i--) {
...
}
}


Или сошлитесь на нее непосредственно в массиве $GLOBALS:

function eat_fruit($fruit) {
for ($i = $GLOBALS['chew_count']; $i > 0; $i--) {
...
}
}


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

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

global $age,$gender,shoe_size;


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

$which_var = 'age';
global $$which_var; // ссылается на глобальную переменную $age


Однако если функция unset() вызывается для переменной, помещенной в локальную область видимости с помощью ключевого слова global, то переменная становится не установленной только внутри функции. Для того чтобы сбросить переменную в глобальной области, надо вызвать функцию unset() для элемента массива $GLOBALS:

$food = 'pizza';
$drink = 'beer';
function party() {
global $food, $drink;
unset($food); // едим пиццу
unset($GLOBALS['drink']); // пьем пиво
}
print "$food: $drink\n";
party();
print "$food: $drink\n";
pizza: beer
pizza:


Видно, что переменная $food остается той же самой, в то время как переменная $drink стала неустановленной. Объявление переменной глобальной внутри функции подобно присваиванию адреса глобальной переменной локальной переменной:

$food = &GLOBALS['food'];

Добавлено: 21 Июля 2018 13:36:38 Добавил: Андрей Ковальчук

Вызов переменных функций

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

Решение
Используйте переменные переменные:

function eat_fruit($fruit) { print "chewing $fruit."; }
$function = 'eat_fruit';
$fruit = 'kiwi';
$function($fruit); // вызов функции eat_fruit()


Обсуждение
При наличии нескольких вариантов вызова следует обратиться к ассоциативному массиву имен функций:

$dispatch = array(
'add' => 'do_add',
'commit' => 'do_commit',
'checkout' => 'do_checkout',
'update' => 'do_update'
);
$cmd = (isset($_REQUEST['command']) ? $_REQUEST['command'] : '');
if (array_key_exists($cmd, $dispatch)) {
$function = $dispatch[$cmd];
$function(); // вызываем функцию
} else {
error_log("Unknown command $cmd");
}


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

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

$dispatch = array(
'add' => 'do_add',
'commit' => 'do_commit', 'ci' => 'do_commit',
'checkout' => 'do_checkout', 'co' => 'do_checkout',
'update' => 'do_update', 'up' => 'do_update'
);

Добавлено: 21 Июля 2018 13:35:51 Добавил: Андрей Ковальчук

Возвращение информации об ошибке

Задача
Необходимо показать ошибку, произошедшую в результате работы функции.

Решение
Возвращаем значение false:

function lookup($name) {
if (empty($name)) { return false; }
...
}
if (false !== lookup($name)) { /* реакция на результат поиска */ }


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

Другие возможности – это '' или 0. Однако, хотя все три значения оцениваются в операторе if как неистинные, между ними есть существенная разница. Кроме того, иногда возвращаемое значение 0 представляет значащий результат, а требуется еще возвратить сообщение об ошибке.

Например, функция strpos() возвращает позицию в строке первого вхождения подстроки. Если подстрока не найдена, то strpos() возвращает значение false, а если найдена, – позицию в виде целого числа. Итак, определить расположение подстроки можно следующим образом:

if (strpos($string, $substring)) { /* нашли! */ }


Однако если $substring обнаружена точно в начале строки $string, то возвращается значение 0. К сожалению, внутри оператора if это значение оценивается как false, поэтому условие не выполняется. Ниже показан корректный способ обработки значения, возвращаемого функцией strpos():

if (false !== strpos($string, $substring)) { /* нашли! */ }


Кроме того, значение false всегда будет ложным – в текущей версии PHP и во всех последующих. Для других значений это не гарантируется. Например, в PHP 3 функция empty('0') возвращала значение true, но оно было заменено на false в PHP 4.

Добавлено: 21 Июля 2018 13:35:07 Добавил: Андрей Ковальчук

Пропуск определенных возвращаемых значений

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

Решение
Пропустить переменные позволяет функция list():

// Интересуют только минуты
function time_parts($time) {
return explode(':', $time);
}
list(, $minute,) = time_parts('12:34:56');


Обсуждение
Это похоже на ошибку в программе, но фрагмент кода из раздела «Решение» имеет в PHP полное право на существование. Чаще всего это встречается, когда программист выполняет цикл по массиву с помощью функции each(), но нужны ему только значения массива:

while (list(,$value) = each($array)) {
process($value);
}


Однако оператор foreach позволяет написать более понятный код:

foreach ($array as $value) {
process($value);
}


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

while ($fields = fgetcsv($fh, 4096)) {
print $fields . "\n"; // третье поле
}


Если это описанная в коде функция, а не встроенная, то можно определить ключи возвращаемого массива в виде строк, поскольку трудно запомнить, например, что элементу 2 соответствует значение 'rank':

while ($fields = read_fields($filename)) {
$rank = $fields['rank']; // третье поле теперь называется rank
print "$rank\n";
}


Однако ниже показан более эффективный метод:

while (list(,,$rank,,) = fgetcsv($fh, 4096)) {
print "$rank\n"; // непосредственно присваиваем $rank
}


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

Добавлено: 21 Июля 2018 13:34:27 Добавил: Андрей Ковальчук

Возвращение более одного значения

Задача
Необходимо вернуть из функции более одного значения.

Решение
Верните массив и используйте функцию list() для разделения элементов:

function averages($stats) {
...
return array($median, $mean, $mode);
}
list($median, $mean, $mode) = averages($stats);


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

function time_parts($time) {
return explode(':', $time);
}
list($hour, $minute, $second) = time_parts('12:34:56');


Передается строка времени в том виде, как она выглядит на экране цифровых часов, и вызывается функция explode(), чтобы разобрать строку на части в виде элементов массива. К значению, возвращенному функцией time_parts(), применяется функция list(), чтобы извлечь каждый элемент и занести его в скалярную переменную. Это не очень эффективно, но другие возможные решения еще хуже, т. к. в результате код получится запутанным.Есть и еще одна возможность – передача значения по ссылке. Однако это несколько неуклюже и делает логически неочевидной передачу необходимых переменных функции. Например:

function time_parts($time, &$hour, &$minute, &$second) {
list($hour, $minute, $second) = explode(':', $time);
}
time_parts('12:34:56', $hour, $minute, $second);


Не имея прототипа функции, невозможно, взглянув на этот фрагмент, определить, чем же, по существу, являются переменные $hour, $minute и $second, т. е. значения, возвращаемые функцией time_parts().

Можно также использовать глобальные переменные, но это загромождает глобальное пространство имен и затрудняет возможность определить, какая из переменных была неявно изменена в функции. Например:

function time_parts($time) {
global $hour, $minute, $second;
list($hour, $minute, $second) = explode(':', $time);
}
time_parts('12:34:56');


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

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

Добавлено: 21 Июля 2018 13:33:21 Добавил: Андрей Ковальчук

Возвращение значений по ссылке

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

Решение
Синтаксис возвращения переменной по ссылке подобен синтаксису передачи ее по ссылке. Однако вместо размещения символа & перед параметром располагаем его перед именем функции:

function &wrap_html_tag($string, $tag = 'b') {
return "<$tag>$string</$tag>";
}


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

$html =& wrap_html_tag($string);


Обсуждение
В отличие от передачи значения в функцию, когда аргумент передается либо по значению, либо по ссылке, в данном случае не обязательно выбирать присваивание ссылки, а можно просто взять возвращенноеb значение. Достаточно заменить обычным оператором = оператор =&, и PHP присвоит значение вместо ссылки.

Добавлено: 21 Июля 2018 12:52:26 Добавил: Андрей Ковальчук

Создание функции, принимающей переменное количество аргументов

Задача
Необходимо определить функцию, принимающую переменное количество аргументов.

Решение
Передайте массив и поместите в него переменные аргументы:

// определение среднего группы чисел
function mean($numbers) {
// инициализируем, чтобы избежать предупреждений
$sum = 0;

// количество элементов в массиве
$size = count($numbers);

// выполняем цикл по массиву и суммируем числа
for ($i = 0; $i < $size; $i++) {
$sum += $numbers[$i];
}
// делим на количество чисел
$average = $sum / $size;
// возвращаем среднее
return $average;
}
$mean = mean(array(96, 93, 97));


Обсуждение
Есть два хороших решения, зависящих от стиля программирования и предпочтений программиста. Более традиционным для PHP является метод, описанный выше в разделе «Решение». Мы предпочитаем именно его, т. к. применение массивов в PHP – обычное дело, и все программисты хорошо знакомы с массивами и их поведением.

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

Кроме того, внутри функции синтаксис доступа и манипуляции эле-ментами массива включает такие основные команды, как $array[$i] и count($array).
Однако выглядеть это может неуклюже, поэтому PHP обеспечивает альтернативу и разрешает прямой доступ к списку аргументов:

// определение среднего группы чисел
function mean() {
// инициализируем, чтобы избежать предупреждений
$sum = 0;

// количество аргументов, переданных в функцию
$size = func_num_args();

// выполняем цикл по аргументам и суммируем числа
for ($i = 0; $i < $size; $i++) {
$sum += func_get_arg($i);
}
// делим на количество чисел
$average = $sum / $size;
// возвращаем среднее
return $average;
}
$mean = mean(96, 93, 97);

В этом примере задействован ряд функций, возвращающих данные, основанные на аргументах, переданных функции, из которой они вызываются. Сначала функция func_num_args() возвращает целое число, показывающее количество аргументов, переданных в вызывающую ее функцию; в данном случае это функция mean(). Затем отсюда можно вызвать функцию func_get_arg(), чтобы определить конкретное значе-
ние аргумента для каждой позиции.

При вызове функции mean(96, 93, 97) функция func_num_args() возвращает 3. Первый аргумент находится в позиции 0, поэтому цикл выполняется от 0 до 2, а не от 1 до 3. То есть это происходит в цикле for, когда переменная $i пробегает значения от 0 до числа, меньшего $size. Как можно видеть, это та же самая логика, что была реализована в первом примере, в котором был передан массив. Можно не беспокоиться о возможных накладных расходах от вызова функции func_get_arg() внутри цикла.

Эта версия в действительности быстрее метода передачи массива.

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

// определение среднего группы чисел
function mean() {
// инициализируем, чтобы избежать предупреждений
$sum = 0;// загружаем аргументы в массив $numbers
$numbers = func_get_args();

// количество элементов в массиве
$size = count($numbers);

// выполняем цикл по массиву и суммируем числа
for ($i = 0; $i < $size; $i++) {
$sum += $numbers[$i];
}
// делим на количество чисел
$average = $sum / $size;
// возвращаем среднее
return $average;
}
$mean = mean(96, 93, 97);


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

К сожалению, этот способ несколько медленнее первых двух.

Добавлено: 21 Июля 2018 12:51:46 Добавил: Андрей Ковальчук

Передача значений по ссылке

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

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

function wrap_html_tag(&$string, $tag = 'b') {
$string = "<$tag>$string</$tag>";
}


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

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

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

В действительности это утверждение не на 100% правда. Если конфигурационная директива allow_call_time_pass_reference разрешена, то PHP разрешает не передавать значение по ссылке, если символ амперсанда предшествует имени переменной. Однако начиная с версии PHP 4.0 Beta 4 использование этой возможности не приветствуется, и
PHP предупреждает, что эта функциональность в будущем может быть исключена при использовании вызовов с передачей параметров по ссылке. Программистам следует быть внимательными.

Кроме того, если параметр объявлен для передачи по ссылке, то нельзя передавать строку (или число), иначе PHP завершит работу с фатальной ошибкой.

Добавлено: 21 Июля 2018 12:50:00 Добавил: Андрей Ковальчук

Пару полезных PHP функций

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

1. Функции с произвольным числом аргументов

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

//функция с 2мя необязательными аргументами
function foo($arg1 = '', $arg2 = '')
{

        echo "arg1: $arg1\n";
        echo "arg2: $arg2\n";

}

foo('hello','world');
/* выводит:
    arg1: hello
    arg2: world
*/

foo();
/* выводит:
    arg1:
    arg2:
*/

Это был пример функции с необязательными аргументами, теперь давайте рассмотрим функцию с использованием произвольного числа аргументов, будем использовать func_get_args():
// список аргументов может быть пустым
function foo()
{
        // возвращает массив всех переданных аргументов
        $args = func_get_args();

        foreach ($args as $k => $v)
    {
                echo "arg".($k+1).": $v\n";
        }
}

foo();
/* не выведет ничего */

foo('hello');
/* выведет
    arg1: hello
*/

foo('hello', 'world', 'again');
/* выведет
    arg1: hello
    arg2: world
    arg3: again
*/

2. Использование Glob() для поиска файлов

Нужная функция.. благодаря glob() можно выполнять поиск файла в текущей директории… приведу пару примеров:
// ищет все php файлы то есть * обозначает все возможные значения
$files = glob('*.php');

print_r($files);
/* результат будет примерно таким:
    Array
    (
        [0] => phptest.php
        [1] => pi.php
        [2] => post_output.php
        [3] => test.php
    )
*/

Вы можете искать сразу несколько типов файлов
// ищет все php и txt файлы
$files = glob('*.{php,txt}', GLOB_BRACE);

print_r($files);
/* результат будет примерно таким:
    Array
    (
        [0] => C:\AppServ\www\testing\phptest.php
        [1] => C:\AppServ\www\testing\pi.php
        [2] => C:\AppServ\www\testing\post_output.php
        [3] => C:\AppServ\www\testing\test.php
        [4] => C:\AppServ\www\testing\log.txt
        [5] => C:\AppServ\www\testing\test.txt
    )
*/

3. Магические константы

Php поддерживает использование так называемых “magik constants” для нахождения текущей строки (__LINE__), пути расположения файла (__FILE__), пути папки в которой находится текущий файл (__DIR__), имя функции (__FUNCTION__), имя класса (__CLASS__), имя метода (__METHOD__). Посмотрим их применение на примере:
$i=__DIR__;
echo '
DIR: ',$i;

$i=__FILE__;
echo '
FILE: ',$i;

$i=__LINE__;
echo '
LINE: ',$i;

function my_one(){
$i=__FUNCTION__;

echo '
FUNCTION: ',$i;}
my_one();

/* Выдаст результат типа
    DIR: C:\AppServ\www\testing
    FILE: C:\AppServ\www\testing\functions.php
    LINE: 42
    FUNCTION: my_one
*/

4. Генерация уникальных ID

Возникает много таких ситуаций когда требуется с генерировать уникальный id. Некоторые для этого используют функцию md5() для этого но он не совсем подходит для этих целей выглядит это у них как то вот так:
//генерация уникальной строки
    echo md5(time() . mt_rand(1,1000000));

Но для этих целей существует более актуальная функция uniqid(), используется он так:
echo uniqid();
echo uniqid();
/*
    выведет два разных id
*/

Вы можете уменьшить шансы выпадения одинаковых id поставив префикс:
echo uniqid('foo_');
/*выведет примерно
    foo_4bd67d6cd8b8f
*/

//с большей энтропией
echo uniqid('',true);
/*выведет примерно
    4bd67d6cd8b926.12135106 
*/

//вместе
echo uniqid('bar_',true);
/*выведет примерно
    bar_4bd67da367b650.43684647
*/

Вот и все следующие полезные функции ждите в следующих постах…)

Добавлено: 13 Июля 2018 07:50:59 Добавил: Андрей Ковальчук

JavaScript array_chunk function

A JavaScript equivalent of PHP’s array_chunk

function array_chunk (input, size, preserve_keys) {
  // http://kevin.vanzonneveld.net
  // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
  // +   improved by: Brett Zamir (http://brett-zamir.me)
  // %        note 1: Important note: Per the ECMAScript specification, objects may not always iterate in a predictable order
  // *     example 1: array_chunk(['Kevin', 'van', 'Zonneveld'], 2);
  // *     returns 1: [['Kevin', 'van'], ['Zonneveld']]
  // *     example 2: array_chunk(['Kevin', 'van', 'Zonneveld'], 2, true);
  // *     returns 2: [{0:'Kevin', 1:'van'}, {2: 'Zonneveld'}]
  // *     example 3: array_chunk({1:'Kevin', 2:'van', 3:'Zonneveld'}, 2);
  // *     returns 3: [['Kevin', 'van'], ['Zonneveld']]
  // *     example 4: array_chunk({1:'Kevin', 2:'van', 3:'Zonneveld'}, 2, true);
  // *     returns 4: [{1: 'Kevin', 2: 'van'}, {3: 'Zonneveld'}]

  var x, p = '', i = 0, c = -1, l = input.length || 0, n = [];

  if (size < 1) {
    return null;
  }

  if (Object.prototype.toString.call(input) === '[object Array]') {
    if (preserve_keys) {
      while (i < l) {
        (x = i % size) ? n[c][i] = input[i] : n[++c] = {}, n[c][i] = input[i];
        i++;
      }
    }
    else {
      while (i < l) {
        (x = i % size) ? n[c][x] = input[i] : n[++c] = [input[i]];
        i++;
      }
    }
  }
  else {
    if (preserve_keys) {
      for (p in input) {
        if (input.hasOwnProperty(p)) {
          (x = i % size) ? n[c][p] = input[p] : n[++c] = {}, n[c][p] = input[p];
          i++;
        }
      }
    }
    else {
      for (p in input) {
        if (input.hasOwnProperty(p)) {
          (x = i % size) ? n[c][x] = input[p] : n[++c] = [input[p]];
          i++;
        }
      }
    }
  }
  return n;
}

example
array_chunk(['Kevin', 'van', 'Zonneveld'], 2);

Should return
returns
[['Kevin', 'van'], ['Zonneveld']]

Example 2
array_chunk(['Kevin', 'van', 'Zonneveld'], 2, true);

Should return
returns
[{0:'Kevin', 1:'van'}, {2: 'Zonneveld'}]

Example 3
array_chunk({1:'Kevin', 2:'van', 3:'Zonneveld'}, 2);

Should return
returns
[['Kevin', 'van'], ['Zonneveld']]

Добавлено: 24 Июня 2018 08:47:30 Добавил: Андрей Ковальчук