Самые маленькие полезные скрипты на PHP
сейчас в списке: 82 скрипта Удивительно, что такие "базовые" вопросы вообще задают, уже якобы изучив весь PHP вплоть до классов и шаблонов... но ведь задают :)
Эта статья будет пополняться примерами маленьких, но полезных скриптов на PHP. Об установке программного обеспечения, нужного для работы с PHP, написано в этой статье (Denwer) или лучше вот в этой, более новой (XAMPP).
Скрипты проверялись на локальном хосте в актуальных на момент добавления того или иного примера версиях PHP 5, а позднее 7 или 8. Для скриптов, работающих со строковыми данными, предполагается использование кодировки Юникода UTF-8.
Для поиска на странице нужных слов нажмите в браузере комбинацию клавиш Ctrl+F
и введите или вставьте слова в окно поиска.
1. Как посмотреть все настройки PHP на моём сервере?
Выполнить на нём следующий файл:
<?php phpinfo(); ?>
2. А как посмотреть все серверные переменные?
Выполните на сервере этот скрипт:
<?php foreach ($_SERVER as $k=>$v) echo "\n<br><b>$k=</b>".$v; ?>
3. Можно ли не писать отдельно обработку для данных формы, переданных методами GET и POST?
Напишите её для массива $_REQUEST. Он ещё и cookies включает.
<?php function get_param ($name,$number=0) { //имя параметра $name и пометка $number, числовой ли он if (isset($_REQUEST[$name])) { //массив $_REQUEST = $_POST+$_GET+$_COOKIE ! $name = trim(htmlspecialchars($_REQUEST[$name],ENT_QUOTES,'UTF-8')); //делать для всех типов параметров return ($number ? doubleval($name) : $name); } else return ($number ? 0 : ""); } $go = get_param('go'); //строковый параметр, обозначающий "действие" скрипта $num = get_param('num',1); //числовой параметр echo "$go,$num"; ?>
4. Как вывести сегодняшний день недели по-русски, стандартная функция date не понимает локали?
<?php $w = Array('Вс','Пн','Вт','Ср','Чт','Пт','Сб'); echo $w[date('w')]; ?>
5. Как показать текущие дату и время на сервере?
<?php echo date('d.m.Y, H:i'); ?>
6. Как определить IP-адрес посетителя?
<?php echo getenv('REMOTE_ADDR'); ?>
Это в простейшем случае. А более грамотно - как вот тут в function get_ip
.
7. Как генерировать случайные числа?
Если целые в заданных пределах, например, от 1 до 100 включительно, то
<?php echo rand(1,100); ?>
8. А если нужны вещественные случайные числа?
<?php echo mt_rand() / mt_getrandmax(); ?>
Получим вещественные равномерно распределённые числа от 0 до 1. Ну а масштабировать в любой другой диапазон легко, например, в [-5;5]
:
<?php $a0 = mt_rand() / mt_getrandmax(); $min = -5; $max = 5; $a = $min + $a0*($max-$min); echo $a; ?>
9. Как отсканировать папку на сервере?
<?php $array = scandir('.'); //здесь сканируется текущая папка (ссылка на неё - одной точкой) echo '<pre>'; print_r($array); echo '</pre>'; ?>
10. Как узнать имя файла скрипта? Как узнать размер файла?
2 ответа в одной строке :)
<?php echo filesize($_SERVER['SCRIPT_FILENAME']).' байт'; ?>
11. Как скачать файл скриптом?
<?php $filename = 'data.zip'; //имя файла для скачивания $filefolder = 'folder/'; //имя папки $filesize = filesize($filefolder.$filename); header('HTTP/1.1 200 OK'); header('Connection: close'); header('Content-Type: application/octet-stream'); header('Accept-Ranges: bytes'); header('Content-Disposition: attachment; filename='.$filename); header('Content-Length: '.$filesize); readfile($filefolder.$filename); ?>
Здесь скачивается файл data.zip
из папки на сервере folder
, но пользователь не видит пути к файлу. В нашем случае для домена domain.com
это путь http://domain.com/folder/file.zip
Также не стоит забывать о возможности защиты папок от просмотра с помощью файла .htaccess
12. Как отобразить чужой сайт/документ?
<?php echo file_get_contents('http://google.com'); ?>
А если нужно загрузить чужой сайт в отдельный фрейм?
<?php $url = 'http://www.anekdot.ru'; $html = file_get_contents($url) or die ('Ошибка получения данных с '.$url); echo '<iframe width="640" height="480" srcdoc="'.htmlentities($html,ENT_QUOTES,'UTF-8').'"></iframe>'; ?>
(здесь предполагается, что документ загружен по протоколу http://
и применяется кодировка Юникода UTF-8).
13. Как показать пользователю адрес своего сайта?
<?php echo 'Вы находитесь на сайте '.$_SERVER['HTTP_HOST']; ?>
Если нужен полный URL выполняемого скрипта, то можно так:
<?php if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') $link = "https"; else $link = "http"; $link .= "://"; $link .= $_SERVER['HTTP_HOST']; $link .= $_SERVER['REQUEST_URI']; echo $link; ?>
14. Как случайно "перемешать" элементы массива?
Для этой цели, как и для многих других типовых действий с массивами, в PHP есть готовые функции.
<?php $items = array (1,2,3,4,5); shuffle ($items); print_r ($items); ?>
15. Как получить/изменить время доступа или модификации файла?
<?php $filename = 'input.txt'; $mtime = filemtime($filename); //получить время изменения файла touch($filename, time(), //установить время изменения в текущее fileatime($filename)); //оставить время доступа неизменным ?>
Существенно, что touch создаст файл, если он не существует.
16. Как сделать замену (модификацию) строк во множестве текстовых файлов?
Если файлы лежат в папке, которую можно задать указанием пути и маски, удобна preg_replace_callback:
<?php foreach (glob("./*.txt") as $filename) { $file = file_get_contents($filename); file_put_contents ($filename, preg_replace_callback("/([a-zA-Z]+)/", function ($matches) { return strtoupper($matches[0]); }, $file)); } ?>
Здесь мы делаем большими все латинские буквы в файлах *.txt
из текущей папки скрипта.
17. Как прочитать содержимое файла построчно?
<?php $file = fopen(__FILE__, 'r'); while ($line = fgets($file)) { $line = rtrim($line); echo htmlspecialchars($line)."<br>\n"; } ?>
Здесь файл выводит в браузер сам себя, а можно, конечно, и другой файл:
<?php $file = fopen('input.txt', 'r'); while (!feof($file)) { $line = rtrim(fgets($file)); if ($line) echo (htmlspecialchars($line)."<br>\n"); } ?>
При этом выводе мы дополнительно игнорируем пустые строки.
18. Как переименовать файл?
<?php rename('input.txt', 'output.txt'); ?>
Ну и другие типовые файловые операции похожи на C/C++.
19. Как безопасно создать временный файл с уникальным именем?
<?php $f = tmpfile(); //работа с файлом $f: fwrite ($f, 'abracadabra'); fseek ($f, 0); echo fread ($f, 1024); fclose($f); //будет удалён при закрытии ?>
20. Как избавиться от лишних пустых строк в тексте?
<?php function removeEmptyLines ($s) { return preg_replace ("/(^[\r\n]*|[\r\n]+)[\s]*[\r\n\s]+/mu","\n",trim($s)); } $s = " За мусор енный \t т екст\r\n\r\n"; echo '<pre>'.removeEmptyLines($s).'</pre>'; ?>
В этом и следующем примере регулярное выражение предполагает, что для скрипта использована кодировка Юникода UTF-8.
21. А как удалить из строки или текста все лишние разделители, в том числе, между словами?
<?php function trimall ($string) { return preg_replace("/\s+/"," ",trim($string)); } $s = " За мусор енный \t т екст\r\n\r\n"; echo '<pre>'.trimall($s).'</pre>'; ?>
Обратите внимание, что этот код также "вытянет" изначально многострочный текст в одну строку, иногда это удобно.
22. Как выбрать из массива случайный элемент?
<?php $arr = Array (1,2,3); echo $arr[array_rand($arr)]; ?>
23. Как оставить от строки только буквы (латинские и русские)?
<?php function keepLettersOnly ($s) { //Оставить ТОЛЬКО БУКВЫ return preg_replace("/[^а-яёa-z]/mui","",$s); } $s = " За мусор\t енный! \t \n\n\n текст hello, world!"; echo '<pre>'.keepLettersOnly($s).'</pre>'; ?>
Здесь также предполагается, что мы работаем с кодировкой Юникода UTF-8.
24. Как оставить в массиве только элементы, отвечающие какому-либо условию?
Поможет функция array_filter
, в которую передана callback-функция, осуществляющая отбор (но не редактирование!) нужных элементов.
<?php $arr = array (1,-2,3,4,0); $arr1 = array_filter ($arr, function ($item) { return $item%2==0; }); print_r ($arr1); //только чётные элементы $arr2 = array_filter ($arr, function ($item) { return $item>0; }); echo '<br>'; print_r ($arr2); //только положительные элементы ?>
25. Как отобразить и отформатировать текущие дату и время, учитывая нужный часовой пояс?
Основные ответы даёт вот этот маленький скрипт, проверенный на XAMPP с PHP 7.
<?php setlocale(LC_ALL, 'ru_RU', 'ru_RU.UTF-8', 'ru', 'russian'); //Пробуем возможные локали, см. // https://www.php.net/manual/ru/function.setlocale.php date_default_timezone_set ('Asia/Novosibirsk'); //Установите свой часовой пояс, список см. на // https://www.php.net/manual/ru/timezones.php echo time().'<br>'; //Секунды с начала эпохи Unix echo microtime().'<br>'; //Формат с микросекундами с начала эпохи Unix ($msec $sec) echo date('D M j H:i:s Y').'<br>'; //Отформатированные дата/время //Форматы см. на https://www.php.net/manual/ru/function.date.php echo date('c').'<br>'; //Формат ISO 8601 echo date('r').'<br>'; //Формат RFC 2822 echo date(DATE_RSS).'<br>'; //Формат RSS. Константы форматов см. на // https://www.php.net/manual/ru/class.datetimeinterface.php#datetime.constants.types echo iconv('Windows-1251', 'UTF-8', strftime('%A, %d %h %Y, %H:%M:%S', time())).'<br>'; //Под Windows всё равно пришлось вызывать iconv //Форматы strftime см. на https://www.php.net/manual/ru/function.strftime.php ?>
1579410514 0.58700900 1579410514 Sun Jan 19 12:08:34 2020 2020-01-19T12:08:34+07:00 Sun, 19 Jan 2020 12:08:34 +0700 Sun, 19 Jan 2020 12:08:34 +0700 воскресенье, 19 янв 2020, 12:08:34
26. Как сделать из строки PHP строку JavaScript, сохраняя переводы строк?
Код ниже выводит строку PHP $s
в документ и в окно сообщения JavaScript.
<?php function make_js_string($s) { $arr = explode("\n",$s); $res=''; $cnt = count($arr); for ($i = 0; $i < $cnt; $i++) $res .= "'".trim($arr[$i]).($i < $cnt-1 ? "\\n" : '')."'".($i < $cnt-1 ? "+\n" : ''); return $res; } $s = " Текст с разрывами строк"; $r = make_js_string($s); echo '<pre>'.$r.'</pre>'; echo '<script>alert('.$r.');</script>'; ?>
27. Как сжать на PHP содержимое HTML, убрав лишние разделители и комментарии?
<?php function minimizeHTML ($code) { $search = [ '/\>[^\S]+/s', //разделители после тегов '/[^\S]+\</s', //разделители перед тегами '/(\s)+/s', //повторяющиеся разделители '/<!--(.|\s)*?-->/' //комментарии HTML ]; $replace = array('>', '<', '\\1', ''); return preg_replace ($search, $replace, $code); ; } $html = '<!DOCTYPE html> <html lang="ru"> <head> <!-- title of page --> <title>Демо страничка </title> </head> <body> <!-- body of page --> <h1>Заголовок</h1> Содержимое,слова слова слова</body> </html> '; echo '<textarea rows="10" cols="80">'.minimizeHTML($html).'</textarea>'; ?>
28. Как реализовать авторизацию с функцией "оставаться в системе"?
В блоге есть другие материалы по теме!
Здесь показано типовое решение с помощью сессии и cookie-файла. Предполагаем, что используется база данных MySQLi. Предполагается, что пароль хранится зашифрованным стандартной функцией md5. Таблица users
может быть устроена как в этой заметке.
<?php session_start(); $my_name = '10.php'; //имя файла скрипта, указать своё if (isset($_GET["logout"])) { //выход if (isset($_COOKIE["user_login"])) setcookie("user_login", "", time() - 1000); if (isset($_COOKIE["user_password"])) setcookie("user_password", "", time() - 1000); if (isset($_SESSION["name"])) unset($_SESSION["name"]); header ("Location: $my_name"); exit; } $name = $password = ''; $connect = mysqli_connect("localhost", "root", "", "guestbook"); //указать правильные хост, логин, пароль, таблицу if (!isset($_SESSION['name'])) { //не авторизован if (!empty($_COOKIE['user_login']) and !empty($_COOKIE['user_password'])) { //есть куки $name = $_COOKIE['user_login']; $password = $_COOKIE['user_password']; } else if (!empty($_POST["user_name"]) and !empty($_POST["user_password"])) { //присланы данные из формы $name = mysqli_real_escape_string($connect, $_POST["user_name"]); $password = md5(mysqli_real_escape_string($connect, $_POST["user_password"])); } else { //нет данных о входе echo '<p>Введите логин и пароль:</p> <form action="'.$my_name.'" method="post"> <p>Логин: <input type="text" size="20" maxlength="18" name="user_name"></p> <p>Пароль: <input type="password" size="20" maxlength="18" name="user_password"></p> <p><input type="checkbox" id="remember_me" name="remember_me"> <label for="remember_me">Запомнить меня</label></p> <p><input type="submit" name="login" value="Вход"></p> </form>'; exit; } $sql = "select * from users where login='" . $name . "' and password='" . $password . "'"; //проверить в запросе имя таблицы (users) и полей (login, password) $result = mysqli_query ($connect, $sql); if (!$result) { echo "Неверные логин или пароль"; exit; } $user = mysqli_fetch_array ($result); if (!$user) { echo "Неверные логин или пароль"; exit; } else { if (!empty($_POST["remember_me"])) { setcookie("user_login", $name, time() + (1 * 365 * 24 * 60 * 60)); //Сохранить на 1 год setcookie("user_password", $password, time() + (1 * 365 * 24 * 60 * 60)); } $_SESSION["name"] = $name; header ("Location: $my_name"); exit; } } echo "Вы вошли в систему. <a href=\"$my_name?logout\">Выйти</a>"; ?>
29. Как определить, использует ли клиент мобильный браузер?
Можно по аналогии с JavaScript.
<?php function isMobileDevice() { return preg_match( "/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop| mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]); } echo (isMobileDevice() ? "Да" : "Нет"); ?>
30. Как "отдать" пользователю файл .pdf?
Код показан ниже, предполагается, что в папке скипта доступен файл demo.pdf
. В отличие от вопроса 11, отдаём файл "порциями".
<?php echo '<a href="'.$_SERVER['PHP_SELF'].'?file=demo" target="_blank">Скачать в новой вкладке</a>'; if (isset($_GET["file"])) { $file = $_GET["file"] .'.pdf'; header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=" . urlencode($file)); header("Content-Type: application/download"); header("Content-Description: File Transfer"); header("Content-Length: " . filesize($file)); flush(); $fp = fopen($file, "r"); while (!feof($fp)) { echo fread($fp, 65536); flush(); //Так как могут быть большие файлы } fclose($fp); } ?>
31. Как определить страну и регион посетителя по IP?
Если не использовать собственных баз данных, поможет ресурс geoPlugin:
<?php function get_ip() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) return $_SERVER['HTTP_CLIENT_IP']; else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) return $_SERVER['HTTP_X_FORWARDED_FOR']; else return $_SERVER['REMOTE_ADDR']; } $ip = get_ip(); echo 'IP-адрес: ' . $ip . '<br>'; $file = file_get_contents("http://www.geoplugin.net/json.gp?ip=".$ip); if ($file === false) { echo 'Ошибка получения данных geoplugin.net!'; exit; } $ipdat = json_decode($file); if (!$ipdat) { echo 'Ошибка интерпретации данных geoplugin.net!'; exit; } echo 'Континент: ' . $ipdat->geoplugin_continentName . '<br>'; echo 'Страна: ' . $ipdat->geoplugin_countryName . '<br>'; echo 'Город: ' . $ipdat->geoplugin_city . '<br>'; echo 'Широта: ' . $ipdat->geoplugin_latitude . '<br>'; echo 'Долгота: ' . $ipdat->geoplugin_longitude . '<br>'; echo 'Символ валюты: ' . $ipdat->geoplugin_currencySymbol . '<br>'; echo 'Код валюты: ' . $ipdat->geoplugin_currencyCode . '<br>'; echo 'Часовой пояс: ' . $ipdat->geoplugin_timezone; ?>
На локальном хосте localhost
функция get_ip
вернёт значение ::1
Чтобы получить публичный IP-адрес компьютера, этот скрипт нужно выполнять на удалённом хосте.
32. Как сгенерировать QR-код для строки?
Хорошая бесплатная библиотека с открытым исходным кодом есть вот тут. Достаточно скачать архив .zip, развернуть его, не создавая новой папки и поместить эту папку в качестве вложенной по отношению к папке расположения скрипта. Скрипт в простейшем случае может быть таким:
<?php include 'phpqrcode/qrlib.php'; $text = "blog.kislenko.net"; QRcode::png($text); ?>
33. Как простым способом проверить, существует ли URL-адрес?
<?php $url = "https://google.com/"; $headers = @get_headers($url); if ($headers === false) { echo 'Не могу получить заголовки '.$url; exit; } if (strpos( $headers[0], '404')) echo '404 - URL '.$url.' не существует'; else echo 'URL '.$url.' существует'; ?>
34. Как получить MAC-адрес клиента?
<?php $MAC = exec('getmac'); $MAC = strtok($MAC, ' '); echo 'MAC-адрес клиента: '. $MAC; ?>
35. Есть ли в PHP структуры данных?
А зачем? Там array правильный :) Впрочем, если хотите возиться с расширениями, для PHP7 есть php-ds
<?php $struct = []; $struct[0] = 'I\'m string item with number key'; $struct['value'] = 2; //number item with string key var_dump($struct); ?>
Вывод этого примера:
array(2) { [0]=> string(31) "I'm string item with number key" ["value"]=> int(2) }
36. Как проверить валидность (корректность) адреса E-mail?
В современных версиях PHP лучше не составлять регулярные выражения, а воспользоваться методом filter_var.
<?php $test = [ "admin@dot.com.ru", //+ "www.dot.com", //- "www@ru", //- "super-bob@i.edu", //+ "маша@магазин.рф" //+, но скажет - ]; for ($i=0; $i<count($test); $i++) { echo $test[$i].': '.(filter_var($test[$i],FILTER_VALIDATE_EMAIL)?'+':'-').'<br>'; } ?>
При этом нужно понимать, что кириллические и другие не-латинские домены метод воспринимать не будет, если они нужны, то помогут как раз регулярные выражения.
<?php $test = [ "Admin@dot.com.museum", //+ "www.dot.com", //- "www@ru", //- "super-bob@i.edu", //+ "маша@магазин.рф" //+ ]; function isEmail ($str) { return (!preg_match( "/[_a-z0-9а-я-]+(\.[_a-z0-9а-я-]+)*@[a-z0-9а-я-]+(\.[a-z0-9а-я-]+)*(\.[a-zа-я]{2,6})$/ui", $str)) ? false : true; } for ($i=0; $i<count($test); $i++) { echo $test[$i].': '.(isEmail($test[$i],FILTER_VALIDATE_EMAIL)?'+':'-').'<br>'; } ?>
37. Как на PHP сравнить две даты?
Вопрос необъятен и зависит от того, как именно представлены даты. Вот несколько подходов к решению задачи при условии, что даты представляют собой строки формата "ГГГГ-ММ-ДД" или "ГГ-ММ-ДД":
<?php $date1 = "20-10-31"; $date2 = "2020-08-21"; echo '$date1 > $date2 :' . ($date1 > $date2 ? 'true' : 'false') . '<br>'; echo 'strtotime($date1) > strtotime($date2) :' . (strtotime($date1) > strtotime($date2) ? 'true' : 'false') . '<br>'; $date1Obj = new DateTime($date1); $date2Obj = new DateTime($date2); echo '$date1Obj > $date2Obj :' . ($date1Obj > $date2Obj ? 'true' : 'false') . '<br>'; echo '$date1 (YYYY-MM-DD)=' . $date1Obj->format("Y-m-d") . '<br>'; echo '$date2 (YYYY-MM-DD)=' . $date2Obj->format("Y-m-d") . '<br>'; ?>
Обратите внимание, что если форматы исходных дат различны, разные способы сравнения могут давать разные результаты:
$date1 > $date2 :false strtotime($date1) > strtotime($date2) :true $date1Obj > $date2Obj :true $date1 (YYYY-MM-DD)=2020-10-31 $date2 (YYYY-MM-DD)=2020-08-21
38. Есть ли в PHP перечисления (enumerations)?
В чистом виде нет (UPD - в PHP 8.1 уже таки есть), но легко эмулировать константами класса:
<?php abstract class enum { const str = 'String value'; const val = 100; const arr = [ 'black' => 0, 'white' => 255 ]; } echo enum::str . '<br>'; echo enum::val . '<br>'; foreach (enum::arr as $key=>$val) echo $key . ': ' . $val . '<br>'; ?>
39. Чем всё-таки echo отличается от print?
echo
: принимает список аргументов через запятую, не возвращает значения;print
: принимает один аргумент-строку, возвращает значение 1, работает медленнее.
<?php $a = 'String'; $b = 100; echo $a, $b, '<br>'; $r = print $a . $b . '<br>'; echo "[$r]<br>"; ?>
40. Как обрабатывать исключения на PHP?
Примерно так же, как на C++, конструкцией try-throw-catch
:
<?php function div ($a,$b) { $c = INF; try { if ($b == 0) throw new Exception('Деление на ноль'); $c = $a / $b; } catch(Exception $e) { echo 'Возникло исключение: ', $e->getMessage(), '<br>'; return INF; //иначе функция будет выполняться дальше } //... return $c; } echo div (4,3),'<br>'; echo div (1,0); ?>
Есть ещё и ветвь finally
, которая будет выполняться всегда после кода в блоках try
и catch
, независимо от того, было ли сгенерировано исключение, перед тем как продолжится нормальное выполнение кода.
<?php function div ($a,$b) { $c = INF; try { if ($b == 0) throw new Exception('Деление на ноль'); $c = $a / $b; } catch(Exception $e) { echo 'Возникло исключение: ', $e->getMessage(), '<br>'; return INF; } finally { echo 'Функция div<br>'; //Выполнится в обоих случаях! } //... return $c; } echo div (4,3),'<br>'; echo div (1,0); ?>
Функция div 1.3333333333333 Возникло исключение: Деление на ноль Функция div INF
Наконец, можно написать свой класс для обработки исключений.
<?php class myException extends Exception { function __toString() { return 'Ошибка в строке '.$this->getLine().' файла '.$this->getFile().': '.$this->getMessage().'<br>'; } } function div ($a,$b) { $c = INF; try { if ($b == 0) throw new myException('Деление на ноль'); $c = $a / $b; } catch(myException $e) { echo 'Возникло исключение: ', $e; return INF; } //... return $c; } echo div (4,3),'<br>'; echo div (1,0); ?>
1.3333333333333 Возникло исключение: Ошибка в строке 11 файла D:\xampp\htdocs\my\24.php: Деление на ноль INF
41. Как прервать скрипт с сообщением об ошибке в браузер?
Использовать конструкцию функция or die ('Сообщение')
(если функция возвращает false
при ошибке) или условный оператор с die
.
Если нужно при этом отключить вывод встроенного сообщения, поместите перед именем функции символ "@
".
В последнем случае нужно обрабатывать ошибку самим! Примеры:
<?php $f = @fopen('data.txt','r') or die ('Не могу открыть файл data.txt'); ?> <?php $a = 1; $b = 0; if ($b == 0) die ('Деление на ноль!'); $c = $a / $b; ?>
42. Как динамически изменить имя вызываемой функции?
Самое простое - хранить имя нужной функции в переменной.
<?php function inc ($x) { return $x+1; } function dec ($x) { return $x-1; } $f = 'inc'; echo $f(1),'<br>'; //2 $f = 'dec'; echo $f(1),'<br>'; //0 ?>
43. Как проверить, является ли массив ассоциативным (то есть, не "си-подобным", имеет ключи, заданные не по умолчанию)?
<?php $arr1= ["Month1" => "January", "Month2" => "February", "Month3" => "March"]; //ассоциативный $arr2 = [ 1, 2, 3] ; //нет $arr3 = [ '1'=>1, '2'=>2, '3'=>3] ; //да, так как ключи не совпадают с умолчаниями $arr4 = [ '0'=>1, '1'=>2, '2'=>3] ; //нет, так как ключи совпадают с умолчаниями function is_associative ($arr) { return array_keys($arr) !== range(0, count($arr) - 1); } echo var_export(is_associative ($arr1)),'<br>'; //true echo var_export(is_associative ($arr2)),'<br>'; //false echo var_export(is_associative ($arr3)),'<br>'; //true echo var_export(is_associative ($arr4)),'<br>'; //false ?>
44. Как получить информацию о DNS хоста?
В примере показаны только IPv4 и IPv6-адреса DNS для выбранного хоста.
<?php $host = "www.google.com"; $ipv4_record = dns_get_record ($host,DNS_A); $ipv6_record = dns_get_record ($host,DNS_AAAA); print "ipv4: " . $ipv4_record[0]["ip"] . "<br>\n"; print "ipv6: " . $ipv6_record[0]["ipv6"]; ?>
45. Как побайтово обработать бинарный файл на PHP?
Подойдут стандартные file_get_contents
и file_put_contents
, так как они бинарно безопасны, но данные нужно будет преобразовать в массив байт (unpack
), а потом изменённые байты упаковать обратно в строку (pack
).
В этом примере мы преобразуем русские алфавитные символы кодировки Юникода UTF-8 в их однобайтовые аналоги из кодировки Windows-1251, а другие байты файла не трогаем.
Файл теста 1.txt
, также сохранённый в UTF-8, был таким:
АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ абвгдеёжзийклмнопрстуфхцчшщъыьэюя
И сам листинг (PHP 5.5 и выше):
<?php $filename = '1.txt'; $data = file_get_contents ($filename); if ($data === false) { echo 'Не могу открыть файл '.$filename; exit (1); } $arr = unpack('C*',$data); //ключи массива будут 1,2,3,... $cnt = count($arr); $res = []; for ($i = 1; $i <= $cnt; $i++) { //пример побайтовой обработки данных из файла $byte = $arr[$i]; if ($byte == 208 or $byte == 209) { if ($i < $cnt) $i++; else { $res[] = $byte; break; } $next = $arr[$i]; if ($byte == 208) { if ($next > 143 and $next < 192) { $res[] = $next + 48; continue; } //А-Яа-п else if ($next == 129) { $res[] = 168; continue; } //Ё else $i--; } else if ($byte == 209) { if ($next > 127 and $next < 144) { $res[] = $next + 112; continue; } //р-я else if ($next == 145) { $res[] = 184; continue; } //ё else $i--; } } $res[] = $byte; } $data = pack('C*',...$res); //именно так, иначе весь массив в pack не передать $flag = file_put_contents ($filename, $data); if ($flag === false) { echo 'Ошибка записи в файл '.$filename; exit (2); } echo 'Выполнена обработка файла '.$filename; ?>
46. Как получить и обработать части строки, разделённые какими-либо символами?
Также в примере показано, как регистронезависимо сортировать массив с кириллицей в кодировке Юникода UTF-8.
Возможна и любая другая "ручная" обработка элементов полученного массива слов.
<?php $s = "Строка с любыми\nпробельными\tразделителями"; $parts = preg_split("/\s+/",$s); echo '<pre>'; print_r ($parts); echo '</pre>'; $parts = array_reverse ($parts); echo '<p>В обратном порядке:</p>'; echo '<pre>'; print_r ($parts); echo '</pre>'; $s = "Строка;разделитель - один символ;;точки с запятой"; $parts = preg_split("/;{1}/",$s); echo '<pre>'; print_r ($parts); echo '</pre>'; usort ($parts, function ($a, $b) { return strcmp(mb_strtoupper($a, 'UTF-8'), mb_strtoupper($b, 'UTF-8')); } ); echo '<p>После сортировки слов:</p>'; echo '<pre>'; print_r ($parts); echo '</pre>'; ?>
Результат работы этого примера:
Array ( [0] => Строка [1] => с [2] => любыми [3] => пробельными [4] => разделителями ) В обратном порядке: Array ( [0] => разделителями [1] => пробельными [2] => любыми [3] => с [4] => Строка ) Array ( [0] => Строка [1] => разделитель - один символ [2] => [3] => точки с запятой ) После сортировки слов: Array ( [0] => [1] => разделитель - один символ [2] => Строка [3] => точки с запятой )
47. Как вывести и позиционировать на картинке строку шрифтом .ttf?
Генерируем на создаваемой картинке цветные прямоугольники, добавляем случайную строку, выведенную поверх них шрифтом стандартного формата TTF.
Предполагается, что в одной папке со скриптом находится файл шрифта arial.ttf
, скопированный из папки \Windows\fonts
<?php //F5 - обновить картинку в браузере function mypic ($n = 200) { $size_x = 512; $size_y = 512; //размеры картинки $img = imagecreate($size_x,$size_y); //создать рисунок $color = imagecolorallocate($img,255,255,255); //создать фоновый цвет - белый imagefilledrectangle ($img,0,0,$size_x-1,$size_y-1,$color); //залить им //Делаем случайные бары: for ($i = 0; $i < $n; $i++) { $color = imagecolorallocate($img,rand(103,255),rand(103,255),rand(103,255)); //случайный цвет $width = rand (50, 100); $height = rand (50, 100); $x = rand (1,$size_x - $width - 1); $y = rand (1,$size_y - $height - 1); imagefilledrectangle ($img,$x,$y,$x+$width-1,$y+$height-1,$color); } //Делаем случайную строку: $cnt = rand(4, 8); //длина от 4 до 8 символов $letter = ''; for ($i = 0; $i < $cnt; $i++) { //Получаем код 'A', добавляем смещение, преобразуем обратно в символ $letter .= chr (ord('A') + rand(0,25)); //Добавляем символ к строке } $color = imagecolorallocate($img,rand(0,102),rand(0,102),rand(0,102)); //случайный цвет $lettersize = 36; //размер шрифта в пунктах $font = dirname(__FILE__).'/arial.ttf'; //путь к шрифту в текущей папке $box = imagettfbbox ($lettersize,0,$font,$letter); //Размеры, возвращаемые imagettfbbox, требуют обработки! //Вычисляем ширину и высоту бокса с текстом: $min_x = min ( [$box[0], $box[2], $box[4], $box[6]] ); $max_x = max ( [$box[0], $box[2], $box[4], $box[6]] ); $min_y = min ( [$box[1], $box[3], $box[5], $box[7]] ); $max_y = max ( [$box[1], $box[3], $box[5], $box[7]] ); $width = $max_x - $min_x; $height = $max_y - $min_y; $left = abs( $min_x ) + $width; //не используется, просто для справки $top = abs( $min_y ) + $height; //не используется, просто для справки $x = rand (1, $size_x - $width - 1); $y = rand (1 + $height, $size_y - 1); //Y-координата в imagettftext - левый нижний угол! imagettftext ($img,$lettersize,0,$x,$y,$color,$font,$letter); return $img; } //Пример вызова функции: if (!function_exists('imagecreate')) die ('No GD support!'); $img = mypic(); //Отдаём контент для браузера: header ('Content-Disposition: inline; filename=image.png'); //У файла будет имя при сохранении header ('Content-Type: image/png'); //Отдаем формат .png imagepng ($img); //Отдали картинку с сервера imagedestroy ($img); //Удалили временный файл ?>
Случайный вывод этого примера:
картинка с барами и строкой
48. Как клонировать составной объект, то есть, создать копию всех его свойств и методов?
В PHP есть готовый метод для этого.
<?php class T { function name() { return "T"; } } class S { function name() { return "S"; } } $obj1 = new T(); $obj2 = new S(); $obj3 = clone $obj1; $obj4 = clone $obj2; echo $obj3->name(), '<br>', $obj4->name(); // "T" "S" ?>
49. Как получить имя файла с кириллицей и пробелами на локалхосте Windows?
Функция проверена в актуальной сборке Windows 10 на локалхосте XAMPP.
function getFileName ($filename) { //Получение имени файла с кириллицей и пробелами - здесь для Windows $f = iconv('UTF-8', 'cp1251', $filename); $f = str_replace('%28','(',$f); $f = str_replace('%29',')',$f); $f = str_replace('+','%20',$f); return $f; } //Далее, например: $string = file_get_contents(getFileName("./Мой файл.txt"));
50. Как в callback или вложенной функции использовать переменную, определённую во внешней функции?
<?php $foo = '+'; $bar = function ($bar) use ($foo) { return $foo.$bar; }; //use работает в этом контексте именно в таком синтаксисе echo $bar(14); //+14 ?>
Не путать с глобальными переменными, которых в PHP давно нет, хотя есть (супер)глобальные системные массивы, например, $GLOBALS.
51. Как на PHP сгенерировать текстовый файл нужного размера со случайным текстовым содержимым?
Если не нужны очень большие объёмы, то проще всего так:
<?php function randomFile ($filename, $filesize, $stringsize = 80) { //Имя файла, размер в байтах, размер строки в однобайтовых символах $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '; //побольше пробелов $charactersLength = strlen ($characters); if ($h = fopen ($filename, 'w')) { while ($filesize > 0) { $str = ''; for ($i = 0; $i < min ($filesize, $stringsize) - 1; $i++) $str .= $characters[rand(0, $charactersLength - 1)]; fwrite ($h, $str); $filesize -= min($filesize, $stringsize); if ($filesize >= 0) fwrite ($h, "\n"); } fclose ($h); umask (0000); chmod ($filename, 0644); return true; } return false; } randomFile ('test.txt', 4096); ?>
52. Как найти разницу между двумя значениями "дата-время", полученными из формы HTML?
Вот пример, разница даётся в днях, часах и минутах. Следует учесть, что поддержка элемента <input type="datetime-local">
пока что ограничена - по сути, только MS Edge и Chrome + новая Opera.
<?php $time1 = $time2 = ''; if (isset($_POST['time1'])) $time1 = strip_tags(trim($_POST['time1'])); if (isset($_POST['time2'])) $time2 = strip_tags(trim($_POST['time2'])); $t1 = new DateTime(str_replace(' ', 'T', $time1)); $t2 = new DateTime(str_replace(' ', 'T', $time2)); $interval = $t1->diff($t2); echo '<p>'.$interval->format('%a д. %H ч. %I м.').'</p>'; echo '<form method="post"> <input type="datetime-local" name="time1" value="'.$time1.'"> <input type="datetime-local" name="time2"value="'.$time2.'"> <input type="submit"> </form>'; ?>
53. Как округлить число до десятков, полусотен, сотен и т.п. в меньшую или большую сторону?
Бывает нужно, например, если речь идёт о ценниках в интернет-магазине. Первым аргументом функции передаётся число, вторым - "база" округления, если она отрицательная, то округляем вниз, иначе вверх.
<?php function fix ($price, $base) { return ($base < 0 ? floor ($price/abs($base)) : ceil ($price/$base)) * abs($base); } $p = 112.50; echo fix ($p, -10).'<br>'. //110 fix ($p, 10).'<br>'. //120 fix ($p, -50).'<br>'. //100 fix ($p, 50).'<br>'. //150 fix ($p, -100).'<br>'. //100 fix ($p, 100); //200 ?>
54. Как узнать, где находится активный файл php.ini?
Выполните скрипт из ответа 1 и проверьте в его выдаче путь к файлу в строке Loaded Configuration File. Директивы, не помеченные в первой позиции строки файла символом ";
" (точка с запятой), являются активными. После изменения настроек обычно нужно перезапустить локальный хост.
55. Как получить дату и время с удалённого хоста?
Не привлекая достаточно сложных решений, связанных с протоколом NTP, это можно сделать так:
<?php $GLOBALS['httpdate'] = null; $url = "http://www.google.com/"; function header_callback($curl, $header) { if (preg_match('/^Date:/', $header)) { $GLOBALS['httpdate'] = trim(substr($header, 5)); $GLOBALS['httpdate'] = DateTime::createFromFormat('D, d M Y H:i:s e', $GLOBALS['httpdate']); } return strlen($header); } $curl = curl_init($url); curl_setopt($curl, CURLOPT_NOBODY, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADERFUNCTION, 'header_callback'); curl_exec($curl); curl_close($curl); echo $GLOBALS['httpdate'] != NULL ? $GLOBALS['httpdate']->format('r') : 'Can\'t get date from URL '.$url; ?>
Предполагается, что целевой сервер возвращает в заголовке HTTP директиву Date
и подключено расширение CURL, то есть, строчка в активном файле php.ini
(см. ответ 54) выглядит как
extension=curl
56. Как реализовать очередь с приоритетом?
Начиная с версии 5.3 есть готовый класс SplPriorityQueue. Отдельно реализованы классы SplHeap, SplMinHeap и SplMaxHeap.
<?php $pq = new SplPriorityQueue; $pq->insert('Помыть посуду', 3); $pq->insert('Накормить кота', 4); $pq->insert('Попить чайку', 5); $pq->insert('Поработать', 1); $pq->insert('Вернуть долги', 2); $pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH); //Извлекать и данные, и приоритет while (!$pq->isEmpty()) { //Как удобно конвертировать ассоциативный массив в строку echo urldecode(http_build_query($pq->extract(),'',', ')).'<br>'; } ?>
data=Попить чайку, priority=5 data=Накормить кота, priority=4 data=Помыть посуду, priority=3 data=Вернуть долги, priority=2 data=Поработать, priority=1
Обратите внимание, что в современных версиях языка есть и другие стандартные структуры данных.
57. Как выполнять некую функцию, например, с именем main
, только тогда, когда скрипт запускается напрямую?
Проще всего, видимо, проверять имя скрипта регулярным выражением.
Файл scriptedmain.php
, при прямом выполнении будет вызвана main
:
<?php function func() { return 42; } function main() { echo "Main: func() returns " . func() . PHP_EOL; } if (preg_match("/scriptedmain/", $_SERVER["SCRIPT_NAME"])) { main(); } ?>
Подключение модуля из другого файла, main
не будет вызвана автоматически:
<?php require_once("scriptedmain.php"); echo "From other module: func() returns " . func() . PHP_EOL; ?>
58. Для заданного текста в кодировке Юникода UTF-8 определить длину максимальной серии подряд идущих символов, отличных от букв латиницы или кириллицы. Вывести саму цепочку символов, сохраняя возможные "лишние" разделители в ней (пробелы, переводы строки и т.п.)
Так как array_reduce "уменьшает" массив до одного элемента, будет найдена только одна цепочка.
<?php header('Content-Type: text/html; charset=utf-8'); mb_internal_encoding('UTF-8'); $text = "Текст и сам файл скрипта - в кодировке Юникода UTF-8, определяем максимальную длину цепочки любых символов простой (не-расширенной) латиницы и кириллицы, отличных от букв... "; preg_match_all ("/[^a-zA-Zа-яёА-ЯЁ]+/", $text, $matches) or die ("Regexp error!"); $longStr = array_reduce($matches[0], function ($a, $b) { return mb_strlen($a) > mb_strlen($b) ? $a : $b; }); echo '<pre>[',$longStr,"]\nДлина=",mb_strlen($longStr),'</pre>'; //найдено многоточие с 2 пробелами и символами CR/LF из конца $text ?>
59. Как удалить из текста все "лишние" разделители, то есть, любую цепочку из нескольких идущих подряд пробелов, табуляций и/или переводов строки заменить одним разделителем?
<?php function trimall ($string) { return preg_replace("/\s+(?=\s)/","$1",$string); } $s = " За мусор енный \t т е\t\t\tкст\r\n\r\n"; echo '<pre>'.trimall($s).'</pre>'; ?>
В отличие от задачи 21, это не удалит все переводы строк из текста, а также оставит последний из цепочки подряд идущих разделителей. Соответственно, может потребоваться дополнительная обработка текста - например, две лексемы могут оказаться разделены табуляцией.
Если не хотим трогать переводы строки, можно попробовать такие регулярные выражения:
^[^\S\r\n]+|[^\S\r\n]+$
заменить на "пусто" (аналог методаtrim
);- затем
[^\S\r\n]+
заменить на один пробел.
За одну замену:
^[^\S\r\n]+|[^\S\r\n]+$|[^\S\r\n]+(?=[^\S\r\n])
заменить на "пусто" (оставит между лексемами последний из цепочки разделителей).
60. Как проверить, передано ли значение хотя бы от одного чекбокса на форме и введён ли текстовый комменатарий? Если ничего не выбрано и не введено, вывести соответствующие сообщения (из серии "вечных вопросов").
В простейшем случае, без применения массивов и единых обработчиков параметров POST
, можно сделать так (файлы сохранены в кодировке Юникода UTF-8).
Файл типа .html
, откуда вызывается zapros.php
, расположенный в той же папке:
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>HTML</title> </head> <body> <h2>Тест</h2> <form action="zapros.php" method="POST"> <p> <input type="checkbox" name="var1" id="var1" value="1"><label for="var1">Вариант 1</label> <br><input type="checkbox" name="var2" id="var2" value="2"><label for="var2">Вариант 2</label> <br><input type="checkbox" name="var3" id="var3" value="3"><label for="var3">Вариант 3</label> </p> <p>Ответ:</p> <p> <textarea name="comments" rows="4" cols="60"></textarea> </p> <p> <input type="submit" value="Отправить"> <input type="reset" value="Очистить"> </form> </body> </html>
Вызываемый файл zapros.php
:
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>Zapros</title> </head> <body> <?php $str = '<p>Вы выбрали вариант(ы): <b>'; $selected = 0; for ($i = 1; $i < 4; $i++) { if (isset($_POST['var'.$i])) { $str .= $_POST['var'.$i].' '; $selected++; } } if (!$selected) $str .= 'ничего не выбрано'; $str .= '</b></p>'; $comment = ''; if (isset($_POST['comments'])) $comment = htmlspecialchars(trim($_POST['comments']),ENT_QUOTES,'UTF-8'); $str .= "<p>Ваш ответ: <b>".(!empty($comment) ? $comment : 'нет ответа'); echo $str; ?> </body> </html>
61. При отправке данных требуется сохранить содержимое многострочного поля ввода в текстовом файле, а при повторной загрузке страницы считывать содержимое файла в эту же область textarea.
Листинг не содержит стандартного обрамления HTML, предполагается использование кодировки Юникода UTF-8.
<?php mb_internal_encoding("UTF-8"); $filename = 'content.txt'; $val = ''; if (file_exists($filename) and is_file($filename)) { $val = file_get_contents ($filename); if ($val === false) die ('Ошибка чтения файла '.$filename); } if (isset($_POST['submit'])) { if (isset($_POST['val'])) $val = trim(htmlspecialchars($_POST['val'])); file_put_contents ($filename, $val) or die ('Ошибка записи в файл '.$filename); } ?> <form method="post"> <p><textarea rows="10" cols="80" maxlength="2048" name="val"><?php echo $val; ?></textarea></p> <p><input type="submit" name="submit"></p> </form>
62. Создать программно $cnt
скриптов в текущей папке и список ссылок на них. Каждый скрипт может учитывать количество своих посещений. Информация о посещениях хранится в текстовом файле.
Этот код довольно мозгодробителен и был предназначен для иллюстративных целей :)
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Список файлов</title> </head> <body> <?php $cnt = 10; $filename = 'cnt.txt'; $c = array_fill (0, $cnt, 0); if (file_exists($filename) and is_file($filename)) { $c = file($filename); } else { file_put_contents ($filename, implode("\n", $c)) or die ('Ошибка записи в файл '.$filename); } for ($i = 0; $i < $cnt; $i++) { $filename = $i.'.php'; if (!file_exists($filename) or !is_file($filename)) { $code = '<?php $filename = \'cnt.txt\'; $n = 0; if (isset($_GET[\'n\']) and intval($_GET[\'n\']) > -1) $n = intval(trim($_GET[\'n\'])); $c = file($filename) or die (\'Ошибка чтения файла \'.$filename); array_walk($c, function(&$val, $key) { $val = intval(trim($val)); }); $c[$n]++; file_put_contents ($filename, implode("\n", $c)) or die (\'Ошибка записи в файл \'.$filename); echo $c[$n]; ?>'; $template = '<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>'.$filename.'</title> </head> <body> <h1>'.$filename.'</h1> <p>Count: '.$code.'</p> </body> </html>'; file_put_contents ($filename, $template) or die ('Ошибка записи в файл '.$filename); } } for ($i = 0; $i < $cnt; $i++) { echo '<p><a href="'.$i.'.php?n='.$i.'">'.$i.'.php</a></p>'; } ?> </body> </html>
63. Задача о садовниках. Известны сорта роз, выращиваемых тремя цветоводами: "Анжелика", "Виктория", "Гагарин", "Ave Maria", "Катарина", "Юбилейная". Определить те сорта, которые имеются у каждого из цветоводов, есть хотя бы у одного из цветоводов, а также сорта, которых нет ни у одного из цветоводов.
В основном, для иллюстрации манипуляций с массивами и ради функции rnd ($cnt, $size)
- выбор $cnt
различных между собой случайных чисел из диапазона значений [0;$size-1]
.
<?php mb_internal_encoding("UTF-8"); $sorts = ["Анжелика" => 0, "Виктория" => 0, "Гагарин" => 0, "Ave Maria" => 0, "Катарина" => 0, "Юбилейная" => 0]; $gardeners = []; $keys = array_keys ($sorts); echo 'Сорта:<pre>'.print_r($keys,true).'</pre>'; //Выводим список сортов for ($i = 0; $i < 3; $i++) { //Даём каждому садовнику по 3-4 разных сорта $gardeners[$i] = array_intersect_key($keys,array_flip(rnd(array_rand(array_flip([3,4])),count($sorts)))); } echo 'Садовники:<pre>'.print_r($gardeners,true).'</pre>'; //Выводим распределение сортов по садовникам foreach ($sorts as $key => $val) { //Считаем по сортам, for ($i = 0; $i < 3; $i++) { //кому из садовников они достались $cnt = array_search ($key,$gardeners[$i]); if ($cnt !== false) $sorts[$key]++; } } foreach ($sorts as $key => $val) { //Делаем выводы echo $key.': '.($val == count($gardeners) ? 'у каждого' : ($val == 0 ? 'ни у кого' : 'хотя бы у одного')).'<br>'; } function rnd ($cnt, $size) { //$cnt различных случайных чисел из диапазона [0;$size-1] if ($cnt < 1 or $size < 1) return []; if ($cnt > $size) $cnt = $size; $arr = range(0, $size-1); shuffle ($arr); return array_slice ($arr, 0, $cnt); } ?>
Пример вывода скрипта:
Сорта: Array ( [0] => Анжелика [1] => Виктория [2] => Гагарин [3] => Ave Maria [4] => Катарина [5] => Юбилейная ) Садовники: Array ( [0] => Array ( [1] => Виктория [2] => Гагарин [3] => Ave Maria [4] => Катарина ) [1] => Array ( [0] => Анжелика [1] => Виктория [3] => Ave Maria [4] => Катарина ) [2] => Array ( [0] => Анжелика [3] => Ave Maria [4] => Катарина ) ) Анжелика: хотя бы у одного Виктория: хотя бы у одного Гагарин: хотя бы у одного Ave Maria: у каждого Катарина: у каждого Юбилейная: ни у кого
64. Как отобразить текущую дату прописью?
Функция strftime (см. ответ 25) начиная с версии PHP 8.1 объявлена устаревшей.
Ниже в одном листинге (с комментариями и примером вывода) показано три подхода к решению задачи без этой функции.
Чтобы вариант 2 cработал и не вылезло сообщение
Fatal error: Uncaught Error: Class "IntlDateFormatter" not found
, в активном файле php.ini
(обычно это \xampp\php\php.ini
) включите соответствующее расширение (уберите точку с запятой в первой позиции строки)
;extension=intl
и перезапустите web-сервер. В более ранних версиях строка может выглядеть и как
;extension=php_intl.dll
<?php //Вариант 1 - самый простой, но он не поддерживает локали! echo date('d F Y, l, H:i:s P'); //Форматирование и вывод //03 April 2022, Sunday, 15:00:39 +02:00 //Вариант 2, с классами DateTimeZone и IntlDateFormatter. Увы, скажет не "апреля", а "апрель" $timezone_string = date_default_timezone_get(); //Временная зона строкой $timezone = new DateTimeZone($timezone_string); $date = new DateTime(null, $timezone); //Объект с текущей датой и временем $formatter = new IntlDateFormatter ('ru_RU', //Объект, выполняющий форматирование IntlDateFormatter::FULL, IntlDateFormatter::FULL, $timezone); $formatter->setPattern('d LLLL Y, eeee, HH:mm:ss OOOO'); //Форматирование echo '<br>'.$formatter->format($date); //Вывод //3 апрель 2022, воскресенье, 15:00:39 GMT+02:00 //Форматы есть на https://unicode-org.github.io/icu/userguide/format_parse/datetime/ //Вариант 3, сами форматируем данные, полученные из DateTime $date = new DateTime(null, new DateTimeZone(date_default_timezone_get())); $date_string = $date->format('H/i/s/j/m/Y/w/P'); list ($h, $m, $s, $d, $mon, $y, $w, $z) = explode("/", $date_string); $months = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']; $days = ['воскресенье','понедельник', 'вторник', 'среда', 'четверг','пятница','суббота']; $date_string = sprintf ("%d %s %d, %s, %02d:%02d:%02d GMT%s", $d, $months[$mon-1], $y, $days[$w], $h, $m, $s, $z); echo '<br>'.$date_string; //3 апреля 2022, воскресенье, 15:00:39 GMT+02:00 ?>
65. Как в тексте целиком выделить слова, содержащие строки из заданного списка тегов?
Вот листинг и вывод примера.
<?php $text = 'Квазимордовороты названы так потому, что некоторые из них образуют даже собственные квазикультуры, такие как хорошо изученные притворец отвратный, задолбыш садюжный выпрямляющийся, подлоносец получервячный, бабояжница плесневидная самодовольная, зловонец пупырчато-перепончатый редкостный и полугениталец лысый веснушчатый. Обратите внимание, что рассматриваемый вид отличается от последнего в списке лишь невероятной тягой к плотоядности, притом что различия между так называемым "человеком" и его ближайшими поедаемыми им сородичами абсолютно ничтожны. Более того, мы можем постулировать, что "человек" на протяжении большей части своей так называемой "эволюции" (а на самом деле типичного "прозябания безысходного, садистически-рвотно-перемежающегося") употреблял в пищу и представителей своего вида, как бы невероятно и чудовищно это не прозвучало для вас.'; //Наш текст $tags = ['Квази', 'человек', 'про', 'ости', '\.']; //Наши теги, слова с которыми выделятся //Точку и другие метасимволы, критичные для PCRE, если они есть в тегах, надо экранировать! //См. список на https://www.php.net/manual/ru/regexp.reference.meta.php $patterns = array_map(function($word) { return "#\w*$word\w*#iu"; }, $tags); $result = preg_replace_callback ($patterns, function($matches) { return "<b>{$matches[0]}</b>"; }, $text); echo $result; ?>
Вывод примера
Если слово целиком выделять не нужно, а только конкретно часть, составляющую тег, меняем в $patterns
строку шаблона на "#$word#iu"
66. Найти наименьшее натуральное число, последние цифры квадрата которого равны заданному числу (задача решается не для всех чисел; задача Бэббиджа).
What is the smallest positive integer whose square ends in the digits 269,696? Babbage, letter to Lord Bowden, 1837; in: Hollingdale and Tootill, Electronic Computers, second edition, 1970, p. 12
<?php $digits = 269696; $depth = pow(10,strlen((string)$digits)); $i = 1; for (; ($i * $i) % $depth != $digits; $i++); echo $i, ' * ', $i, ' = ', ($i * $i), PHP_EOL; ?>
67. Имея документ XML и определение схемы XSD, проверить, соответствует ли документ описанной схеме.
Тестовые документы shiporder.xml
и shiporder.xsd
в кодировке Юникода UTF-8 (сохранены в текущей папке скрипта) взяты отсюда.
<?php libxml_use_internal_errors(true); $xml = new DOMDocument(); $xml->load('./shiporder.xml'); if (!$xml->schemaValidate('./shiporder.xsd')) { var_dump(libxml_get_errors()); exit; } else { echo 'Success, no errors'; } ?>
Файл shiporder.xml
<?xml version="1.0" encoding="UTF-8"?> <shiporder orderid="889923" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="shiporder.xsd"> <orderperson>John Smith</orderperson> <shipto> <name>Ola Nordmann</name> <address>Langgt 23</address> <city>4000 Stavanger</city> <country>Norway</country> </shipto> <item> <title>Empire Burlesque</title> <note>Special Edition</note> <quantity>1</quantity> <price>10.90</price> </item> <item> <title>Hide your heart</title> <quantity>1</quantity> <price>9.90</price> </item> </shiporder>
Файл shiporder.xsd
<?xml version="1.0" encoding="UTF-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="shiporder"> <xs:complexType> <xs:sequence> <xs:element name="orderperson" type="xs:string"/> <xs:element name="shipto"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="address" type="xs:string"/> <xs:element name="city" type="xs:string"/> <xs:element name="country" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="item" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="title" type="xs:string"/> <xs:element name="note" type="xs:string" minOccurs="0"/> <xs:element name="quantity" type="xs:positiveInteger"/> <xs:element name="price" type="xs:decimal"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="orderid" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:schema>
68. Из данных в формате XML извлечь значения заданных атрибутов заданного элемента.
<?php $data = '<Люди> <Человек Имя="Анархия" Пол="Ж" ДатаРождения="1999-01-02" /> <Человек Имя="Стакан портвейна" Пол="М" ДатаРождения="2000-03-04" /> <Человек Имя="Паровоз по делу" Пол="М" ДатаРождения="2001-05-06" /> <Человек Имя="Чудинище" Пол="М" ДатаРождения="2002-07-08"> <Питомец Тип="Собака" Имя="Бобик" /> </Человек> <Человек ДатаРождения="2003-09-10" Пол="Ж" Имя="Мать порядка" /> </Люди>'; $xml = new XMLReader(); $xml->xml($data); while ($xml->read()) if (XMLREADER::ELEMENT == $xml->nodeType && $xml->localName == 'Человек') echo $xml->getAttribute('Имя').'<br>'; ?>
Вывод примера:
Анархия Стакан портвейна Паровоз по делу Чудинище Мать порядка
69. Создать простой DOM и сериализовать его.
<?php $dom = new DOMDocument(); $dom->formatOutput = true; $root = $dom->createElement('root'); $element = $dom->createElement('element'); $element->appendChild($dom->createTextNode('Текстовый элемент')); $root->appendChild($element); $dom->appendChild($root); $xmlstring = $dom->saveXML(); echo '<textarea>'.$xmlstring.'</textarea>'; ?>
Вывод, полученный в текстовом поле <textarea>
:
<?xml version="1.0"?> <root> <element>Текстовый элемент</element> </root>
70. Имея заданный документ XML, выполнить следующие 3 типовых действия над ним:
- получить первый элемент "item";
- выполнить действие над каждым элементом "price" (распечатать его);
- получить массив всех элементов "name".
<?php $doc = new DOMDocument(); $doc->load('./inventory.xml'); //или $doc->loadXML('<inventory title="">...</inventory>'); $xpath = new DOMXPath($doc); //Задача 1: $nodelist = $xpath->query('//item'); $result = $nodelist->item(0); var_dump ($result); //Задача 2: $nodelist = $xpath->query('//price'); for($i = 0; $i < $nodelist->length; $i++) { echo '<br>'.$doc->saveXML($nodelist->item($i)); } //Задача 3: $nodelist = $xpath->query('//name'); $result = []; foreach($nodelist as $node) { $result[] = $node; echo '<br>'.$node->textContent; } echo '<br>'; var_dump($result); ?>
Файл inventory.xml
располагается в той же папке, что и скрипт, предполагается, что он сохранён в кодировке Юникода UTF-8:
<inventory title="Our Store Stuff"> <section name="health"> <item id="1"> <name>Шапка-невидимка</name> <price>1144.50</price> <description>Делает Вас невидимым</description> </item> <item id="2"> <name>Левитационный крем</name> <price>230.99</price> <description>Левитируйте до трёх часов после употребления</description> </item> </section> <section name="food"> <item id="3"> <name>Тухляк в таблетках</name> <price>14.99</price> <description>Вкусная еда в таблетках; просто добавьте водки</description> </item> <item id="4"> <name>Крылышки гробовые</name> <price>13.00</price> <description>Сделают Ваш гроб летающим; просто добавьте водки</description> </item> </section> </inventory>
71. Реализовать мини-сервис для работы с последовательностью натуральных чисел от 1 до N, например: список содержит следующие операции: четные, нечетные, простые, составные. Вывести все числа из диапазона от 1 до N, согласно выбранному из списка действию. Значение N вводится пользователем в текстовое поле.
Полный листинг приложения:
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Numbers</title> </head> <body> <?php $n = 10; if (isset($_POST['n']) and is_numeric($n)) $n = abs(intval($_POST['n'])); if ($n == 0) $n = 1; //нуля нет по условиям if ($n > 9999) $n = 9999; //избегаем чисел вроде 1e99 $task = 1; if (isset($_POST['task']) and is_numeric($task)) $task = abs(intval($_POST['task'])); if ($task < 1 or $task > 4) $task = 1; ?> <form method="post"> <p>Вывести: <select size="1" name="task"> <?php $options = ['четные','нечетные','простые','составные']; for ($i = 1; $i < 5; $i++) echo '<option value="'.$i.'"'.($task==$i ?' selected':'').'>'.$options[$i-1].'</option>'; ?> </select> </p><p>N= <input type="text" name="n" size="5" maxlength="4" value="<?php echo $n; ?>"> </p><p> <input type="submit" name="action" value="Выполнить"> </p> </form> <?php function isPrime ($num) { //Проверка $num на простоту if ($num != floor($num) || $num < 2) return false; //вещественные или отрицательные или 1 - не простые числа if ($num < 4) return true; //2 и 3 - да if ($num % 2 == 0) return false; //чётные - нет $ceil = ceil(sqrt($num)); for ($i = 3; $i <= $ceil; $i += 2) { //остальные проверяем if ($num % $i == 0) return false; } return true; } if (isset($_POST['action'])) { $arr = range (1, $n); $result = []; switch ($task) { case 1: $result = array_filter ($arr, function ($item) { return $item%2==0; }); break; case 2: $result = array_filter ($arr, function ($item) { return $item%2!=0; }); break; case 3: $result = array_filter ($arr, function ($item) { return isPrime($item); }); break; case 4: $result = array_filter ($arr, function ($item) { return !isPrime($item) and $item != 1; }); //1 также не составное число break; } if (count($result) > 0) echo '<p>'.implode(', ',$result).'</p>'; } ?> </body></html>
72. Подсчитать информационную энтропию по Шеннону для заданной текстовой строки.
<?php function shannonEntropy($string) { $h = 0.0; $len = mb_strlen ($string,'UTF-8'); foreach (count_chars($string, 1) as $count) { $h -= (double) ($count / $len) * log((double) ($count / $len), 2); } return $h; } $strings = array( '00001111', 'Hello, world!', 'Привет, мир!' ); foreach ($strings AS $string) { printf ('%s : %s<br>' . PHP_EOL, $string, number_format(shannonEntropy($string), 3)); } ?>
73. Написать скрипт, который вычисляет и показывает информационную энтропию по Шеннону (см. решение 72) для собственного исходного текста.
<?php $h = 0; $s = file_get_contents(__FILE__); $l = strlen($s); foreach (count_chars($s, 1) as $c) $h -= ($c/$l)*log($c/$l,2); echo $h; ?>
74. Подсчитать основные величины, используемые для усреднения - арифметическое среднее, круговое (угловое) среднее, среднее время, медиана, мода, пифагорейские средние, среднее квадратическое.
Все расчёты выполнены в одном скрипте, ссылки на определения из "Вики" есть непосредственно в листинге.
<?php //1. Арифметическое среднее $arr = [ 1, 2, 2, 3, 4, 7, 9 ]; //числа $avg = array_sum($arr) / count($arr); printf ('Arithmetic mean = %s<br>' . PHP_EOL, number_format($avg,3)); //2. Круговое или угловое среднее https://en.wikipedia.org/wiki/Circular_mean function meanAngle ($angles) { $y_part = $x_part = 0; $size = count($angles); for ($i = 0; $i < $size; $i++){ $x_part += cos(deg2rad($angles[$i])); $y_part += sin(deg2rad($angles[$i])); } $x_part /= $size; $y_part /= $size; return rad2deg(atan2($y_part, $x_part)); } $angles = [90, 180, 270, 360]; //углы $mavg = meanAngle($angles); printf ('Mean angle = %s deg.<br>' . PHP_EOL, number_format($mavg,3)); //3. Среднее время ЧЧ:ММ:СС function time2ang($tim) { if (!is_string($tim)) return $tim; $parts = explode(':',$tim); if (count($parts)!=3) return $tim; $sec = ($parts[0]*3600)+($parts[1]*60)+$parts[2]; $ang = 360.0 * ($sec/86400.0); return $ang; } function ang2time($ang) { if (!is_numeric($ang)) return $ang; $sec = 86400.0 * $ang / 360.0; $parts = array(floor($sec/3600),floor(($sec % 3600)/60),$sec % 60); $tim = sprintf('%02d:%02d:%02d',$parts[0],$parts[1],$parts[2]); return $tim; } function meanang($ang) { if (!is_array($ang)) return $ang; $sins = 0.0; $coss = 0.0; foreach($ang as $a) { $sins += sin(deg2rad($a)); $coss += cos(deg2rad($a)); } $avgsin = $sins / (0.0+count($ang)); $avgcos = $coss / (0.0+count($ang)); $avgang = rad2deg(atan2($avgsin,$avgcos)); while ($avgang < 0.0) $avgang += 360.0; return $avgang; } $times = array('15:00:00','18:30:30','00:00:00','23:59:59'); $angs = []; foreach ($times as $t) $angs[] = time2ang($t); $ma = meanang($angs); $result = ang2time($ma); printf ('The mean time of day = %s (angle %s)<br>'. PHP_EOL,$result,number_format($ma,3)); //4. Медиана https://en.wikipedia.org/wiki/Median function median($arr) { sort($arr); $count = count($arr); $middleval = floor(($count-1)/2); if ($count % 2) $median = $arr[$middleval]; else { $low = $arr[$middleval]; $high = $arr[$middleval+1]; $median = (($low+$high)/2); } return $median; } printf ('Median = %s<br>' . PHP_EOL, number_format(median($arr),3)); //тест из расчёта 1 //5. Мода https://en.wikipedia.org/wiki/Mode_(statistics) function mode($arr) { if (count($arr)<1) return null; $count = array_count_values($arr); $best = max($count); $keys = array_keys($count, $best); return $keys[0]; } printf ('Mode = %s<br>' . PHP_EOL, number_format(mode($arr),3)); //тест из расчёта 1 //6. Пифагорейские средние https://en.wikipedia.org/wiki/Pythagorean_means function ArithmeticMean(array $values) { return array_sum($values) / count($values); } function GeometricMean(array $values) { return array_product($values) ** (1 / count($values)); } function HarmonicMean(array $values) { $sum = 0; foreach ($values as $value) $sum += 1 / $value; return count($values) / $sum; } printf ('Arithmetic mean = %s<br>' . PHP_EOL, number_format(ArithmeticMean($arr),3)); //тест из расчёта 1 printf ('Geometric mean = %s<br>' . PHP_EOL, number_format(GeometricMean($arr),3)); printf ('Harmonic mean = %s<br>' . PHP_EOL, number_format(HarmonicMean($arr),3)); //7. Среднее квадратическое https://en.wikipedia.org/wiki/Root_mean_square function RootMeanSquare (array $values) { $sum = 0; foreach ($values as $number) $sum += pow($number,2); return sqrt($sum / count($values)); } printf ('Root mean square = %s<br>' . PHP_EOL, number_format(RootMeanSquare($arr),3)); //тест из расчёта 1 ?>
75. Напечатать символы Юникода в кодировке UTF-8 из заданного диапазона.
Просто используйте mb_chr вместо однобайтовой chr.
<?php for ($c = 1040; $c < 1104; $c++) echo mb_chr($c,'UTF-8'),' '; ?>
76. Удалить из строки в кодировке Юникода UTF-8 все символы набора, заданного строкой.
<?php mb_internal_encoding('UTF-8'); mb_regex_encoding('UTF-8'); function stripchars ($s, $chars) { return mb_eregi_replace('['.$chars.']','',$s); //не пытайтесь делать это через str_replace для кодировки UTF-8 } $s = 'В этом примере мы удалим из строки кириллицы пару гласных.'; echo $s.'<br>'.stripchars($s, 'ае'); ?>
77. Взаимная рекурсия на PHP.
Две функции называются взаимно рекурсивными, если первая вызывает вторую, а вторая, в свою очередь, вызывает первую. Хорошим примером могут служить мужская и женская последовательности Хофштадтера.
<?php function F($n) { if ( $n == 0 ) return 1; return $n - M(F($n-1)); } function M($n) { if ( $n == 0) return 0; return $n - F(M($n-1)); } $ra = []; $rb = []; $cnt = 100; //количество членов последовательностей for($i=0; $i < $cnt; $i++) { $ra[] = F($i); $rb[] = M($i); } echo implode(' ', $ra) . "<br>\n"; echo implode(' ', $rb); ?>
78. Как разбить текст на предложения, которые заканчиваются одним из знаков ".
", "?
", "!
"?
Cм. также примеры 21, 59.
<?php $text = 'Шалтай-Болтай сидел на стене. Шалтай-Болтай свалился во сне! Как собрать?! Не знаем, но собираем ,.?! Соберём или нет - дай ответ '; $html = []; $text = str_replace(array("\r", "\n"), ' ', $text); //Разбить по переводам строк $text = trim(preg_replace('/[ \t]+/', ' ', $text)); //Убрать лишние разделители if (mb_strpos(".?!",mb_substr($text, -1, 1, 'UTF-8'),0,'UTF-8')===false) $text .= '.'; //Если надо, добавить точку в конце preg_match_all("/.*?[.?!](?:\s|$)/s", $text, $items); //Разбить по концам предложений if (!empty($items[0])) { foreach ($items[0] as $item) { //Получить массив предложений $html[] = '<p>'.trim($item).'</p>'; } } else { $html[] = '<p>'.$text.'</p>'; } echo implode(PHP_EOL, $html); ?>
<p>Шалтай-Болтай сидел на стене.</p> <p>Шалтай-Болтай свалился во сне!</p> <p>Как собрать?!</p> <p>Не знаем, но собираем ,.?!</p> <p>Соберём или нет - дай ответ.</p>
79. Как "собрать" обратно URL-адрес, разбитый на части функцией parse_url?
Готовой "обратной" функции нет, но её можно написать. Вот листинг и тест:
<?php function reverse_parse_url(array $parts) { $url = ''; if (!empty($parts['scheme'])) $url .= $parts['scheme'] . ':'; if (!empty($parts['user']) || !empty($parts['host'])) $url .= '//'; if (!empty($parts['user'])) $url .= $parts['user']; if (!empty($parts['pass'])) $url .= ':' . $parts['pass']; if (!empty($parts['user'])) $url .= '@'; if (!empty($parts['host'])) $url .= $parts['host']; if (!empty($parts['port'])) $url .= ':' . $parts['port']; if (!empty($parts['path'])) $url .= $parts['path']; if (!empty($parts['query'])) { if (is_array($parts['query'])) $url .= '?' . http_build_query($parts['query']); else $url .= '?' . $parts['query']; } if (!empty($parts['fragment'])) $url .= '#' . $parts['fragment']; return $url; } $url = "https://neolurk.org/wiki/Если_не_Путин,_то_кто%3F"; $arr = parse_url($url); print_r ($arr); $url = reverse_parse_url ($arr); print_r ($url); ?>
80. Как бороться с частично кириллическими URL?
Примеры таких адресов приведены ниже в листинге. Неведомыми путями они часто попадают на автообработку.
Заметим, что стандартная функция filter_var не работает с кириллицей в ссылках, а согласно RFC, кириллицы там и быть не должно.
Проще всего представляется просто написание своей функции фильтрации, учитывающей конкретные символы кириллицы (или другие), которые нужно заменить в URL-адресе:
<?php function my_url_encode($s) { $s= strtr ($s, array ( " "=> "%20", "а"=>"%D0%B0", "А"=>"%D0%90","б"=>"%D0%B1", "Б"=>"%D0%91", "в"=>"%D0%B2", "В"=>"%D0%92", "г"=>"%D0%B3", "Г"=>"%D0%93", "д"=>"%D0%B4", "Д"=>"%D0%94", "е"=>"%D0%B5", "Е"=>"%D0%95", "ё"=>"%D1%91", "Ё"=>"%D0%81", "ж"=>"%D0%B6", "Ж"=>"%D0%96", "з"=>"%D0%B7", "З"=>"%D0%97", "и"=>"%D0%B8", "И"=>"%D0%98", "й"=>"%D0%B9", "Й"=>"%D0%99", "к"=>"%D0%BA", "К"=>"%D0%9A", "л"=>"%D0%BB", "Л"=>"%D0%9B", "м"=>"%D0%BC", "М"=>"%D0%9C", "н"=>"%D0%BD", "Н"=>"%D0%9D", "о"=>"%D0%BE", "О"=>"%D0%9E", "п"=>"%D0%BF", "П"=>"%D0%9F", "р"=>"%D1%80", "Р"=>"%D0%A0", "с"=>"%D1%81", "С"=>"%D0%A1", "т"=>"%D1%82", "Т"=>"%D0%A2", "у"=>"%D1%83", "У"=>"%D0%A3", "ф"=>"%D1%84", "Ф"=>"%D0%A4", "х"=>"%D1%85", "Х"=>"%D0%A5", "ц"=>"%D1%86", "Ц"=>"%D0%A6", "ч"=>"%D1%87", "Ч"=>"%D0%A7", "ш"=>"%D1%88", "Ш"=>"%D0%A8", "щ"=>"%D1%89", "Щ"=>"%D0%A9", "ъ"=>"%D1%8A", "Ъ"=>"%D0%AA", "ы"=>"%D1%8B", "Ы"=>"%D0%AB", "ь"=>"%D1%8C", "Ь"=>"%D0%AC", "э"=>"%D1%8D", "Э"=>"%D0%AD", "ю"=>"%D1%8E", "Ю"=>"%D0%AE", "я"=>"%D1%8F", "Я"=>"%D0%AF")); return $s; } function myurlencode ($url) { //true или false if (filter_var($url, FILTER_VALIDATE_URL)) return true; if (filter_var(my_url_encode($url), FILTER_VALIDATE_URL)) return true; return false; } $urls = [ "https://neolurk.org/wiki/Если_не_Путин,_то_кто%3F", "https://yandex.ru/search/?text=тестик&lr=65", "https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%81%D1%82", "http://абракадабра.рф", "http://abracadabra.ru?q=Запросик сайту" ]; foreach ($urls as $url) { $result = (myurlencode($url) !== false ? "Да" : "Нет"); echo $url.': '.$result.'<br>'; } ?>
Другие подходы показались мне заметно сложнее.
Нужно учесть, что домен в URL-адресе, отдаваемом функции filter_var
должен быть стандартным, то есть, состоящим из латиницы, а также ссылка должна быть полной, то есть, начинаться с протокола http://
, https://
и т.п.
Можно написать функцию и для обратного преобразования "закодированного" URL в исходный:
function my_url_decode($s){ $s= strtr ($s, array ( "%20"=>" ", "%D0%B0"=>"а", "%D0%90"=>"А", "%D0%B1"=>"б", "%D0%91"=>"Б", "%D0%B2"=>"в", "%D0%92"=>"В", "%D0%B3"=>"г", "%D0%93"=>"Г", "%D0%B4"=>"д", "%D0%94"=>"Д", "%D0%B5"=>"е", "%D0%95"=>"Е", "%D1%91"=>"ё", "%D0%81"=>"Ё", "%D0%B6"=>"ж", "%D0%96"=>"Ж", "%D0%B7"=>"з", "%D0%97"=>"З", "%D0%B8"=>"и", "%D0%98"=>"И", "%D0%B9"=>"й", "%D0%99"=>"Й", "%D0%BA"=>"к", "%D0%9A"=>"К", "%D0%BB"=>"л", "%D0%9B"=>"Л", "%D0%BC"=>"м", "%D0%9C"=>"М", "%D0%BD"=>"н", "%D0%9D"=>"Н", "%D0%BE"=>"о", "%D0%9E"=>"О", "%D0%BF"=>"п", "%D0%9F"=>"П", "%D1%80"=>"р", "%D0%A0"=>"Р", "%D1%81"=>"с", "%D0%A1"=>"С", "%D1%82"=>"т", "%D0%A2"=>"Т", "%D1%83"=>"у", "%D0%A3"=>"У", "%D1%84"=>"ф", "%D0%A4"=>"Ф", "%D1%85"=>"х", "%D0%A5"=>"Х", "%D1%86"=>"ц", "%D0%A6"=>"Ц", "%D1%87"=>"ч", "%D0%A7"=>"Ч", "%D1%88"=>"ш", "%D0%A8"=>"Ш", "%D1%89"=>"щ", "%D0%A9"=>"Щ", "%D1%8A"=>"ъ", "%D0%AA"=>"Ъ", "%D1%8B"=>"ы", "%D0%AB"=>"Ы", "%D1%8C"=>"ь", "%D0%AC"=>"Ь", "%D1%8D"=>"э", "%D0%AD"=>"Э", "%D1%8E"=>"ю", "%D0%AE"=>"Ю", "%D1%8F"=>"я", "%D0%AF"=>"Я")); return $s; } //... $url = "https://neolurk.org/wiki/Если_не_Путин,_то_кто%3F"; echo my_url_decode(my_url_encode($url));
Предполагается, что обе функции работают с кодировкой UTF-8 Юникода.
81. Как выполнить серию замен строк в текстовом файле, например, при замене строк шаблона на их значения?
Предполагаем, что строки шаблона имеют вид %строка%
, их список в виде ассоциативного массива находится в $vars
, а тестовый файл с именем page.html
располагается в той же папке, что и текущий скрипт.
Тогда для следующего содержимого файла page.html
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>%title%</title> <style> body { color: %color%; background-color: %backcolor%; } </style> </head> <body> <p>Содержимое документа</p> </body> </html>
показанным ниже скриптом
<?php function html ($path, $vars){ if (file_exists($path) and is_file($path)) { $file = file_get_contents ($path); return strtr ($file,$vars); } return 'Bad file name: '.$path; } $vars = ['%color%'=>'#000', '%backcolor%'=>'#fff', '%title%'=>'Моя страница']; //список замен echo '<pre>'.htmlspecialchars(html ('./page.html',$vars),ENT_COMPAT,'UTF-8').'</pre>'; //печатаем разметку документа вместо вывода HTML ?>
мы выведем в браузер
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>Моя страница</title> <style> body { color: #000; background-color: #fff; } </style> </head> <body> <p>Содержимое документа</p> </body> </html>
Для печати документа "как есть", разумеется, подойдёт просто
echo html('./page.html',$vars);
Аналогичный подход применялся в этом скрипте для создания "обратимого" транслита из кириллицы.
82. Как подсчитать количество вхождений подстроки в файле?
В PHP есть готовая функция substr_count, которую легко приспособить и для строки, прочитанной из файла:
<?php function file_substr_count ($path, $word) { if (file_exists($path) and is_file($path)) { $file = file_get_contents ($path); return substr_count ($file, $word); } return 0; } echo file_substr_count ('./text.txt','слово'); ?>
21.05.2012, 13:37 [22201 просмотр]