Склонение числительных на PHP

Для красоты вывода информации, иногда приходится склонять числительные.

Например: 1 комментарий, 2 комментария, 10 комментариев, 101 комментарий, 151 комментарий, 511 комментариев, 777 комментариев, 1001 комментарий и т.д.

Функция склонения числительных
Пишем простую функцию string numberof(int numberof, string value, array suffix)

<?php
/**
 * Склонение числительныхфывфывфывф
 * @param int $numberof — склоняемое число
 * @param string $value — первая часть слова (можно назвать корнем)
 * @param array $suffix — массив возможных окончаний слов
 * @return string
 *
 */
function numberof($numberof, $value, $suffix)
{
    $keys = array(2, 0, 1, 1, 1, 2);
    $mod = $numberof % 100;
    $suffix_key = $mod > 4 && $mod < 20 ? 2 : $keys[min($mod%10, 5)];
    
    return $value . $suffix[$suffix_key];
}

// значения
$values = array(1, 2, 10, 101, 151, 511, 777, 1001);

// перебираем массив
foreach ($values as $number)
{
    echo $number.' ';
    
    // получаем нужное склонение
    echo numberof($number, 'комментари', array('й', 'я', 'ев'));
    echo '<br>';
}
?>

Результат
На экране вы увидите:

1 комментарий
2 комментария
10 комментариев
101 комментарий
151 комментарий
511 комментариев
777 комментариев
1001 комментарий

Разъяснение по слову «комментарий»
Слово комментарий может принимать всего 3 значения: комментари(й), комментари(я), комментари(ев).

Алгоритм
Число заканчивающееся на 1 (1, 21, 31, 101, 1001, 1161 и т.д.), исключение 11, получает первое окончание:комментари(й)
Далее все числа в диапазоне от 2 до 4 (2-4, 22-24, 32-34, 102-104, 1122-1124), исключение 12-14, получает второе окончание: комментари(я)
Все остальные числа получают значение комментари(ев)
Примечание
P.S.: Реализовать алгоритм можно разными способами, но, способ показанный выше, мне кажется, самый короткий. Можно обойтись двумя строками, только читаемость кода ухудшится.

Добавлено: 29 Мая 2018 21:39:06 Добавил: Андрей Ковальчук

Транслит (PHP)

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

С русского на английский
Самый простой и удобный вариант, создать 2 массив. Первый с русским алфавитом, второй с соответствующей каждой русской букве английской транслитерации.

<?php

// Функция русского текста в английскую транслитерацию
function rus2translit($text)
{
    // Русский алфавит
    $rus_alphabet = array(
        'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й',
        'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф',
        'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
        'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й',
        'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф',
        'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я'
    );
    
    // Английская транслитерация
    $rus_alphabet_translit = array(
        'A', 'B', 'V', 'G', 'D', 'E', 'IO', 'ZH', 'Z', 'I', 'I',
        'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F',
        'H', 'C', 'CH', 'SH', 'SH', '`', 'Y', '`', 'E', 'IU', 'IA',
        'a', 'b', 'v', 'g', 'd', 'e', 'io', 'zh', 'z', 'i', 'i',
        'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f',
        'h', 'c', 'ch', 'sh', 'sh', '`', 'y', '`', 'e', 'iu', 'ia'
    );
    
    return str_replace($rus_alphabet, $rus_alphabet_translit, $text);
}

$lorem = 'Но чтобы вы поняли, откуда возникает это превратное представление людей, порицающих
наслаждение и восхваляющих страдания, я раскрою перед вами всю картину и разъясню, что именно
говорил этот человек, открывший истину, которого я бы назвал зодчим счастливой жизни. Действительно,
никто не отвергает, не презирает, не избегает наслаждений только из-за того, что это наслаждения,
но лишь из-за того, что тех, кто не умеет разумно предаваться наслаждениям, постигают великие
страдания. Равно как нет никого, кто возлюбил бы, предпочел и возжаждал бы само страдание только
за то, что это страдание, а не потому, что иной раз возникают такие обстоятельства, когда страдания
и боль приносят некое и немалое наслаждение. Если воспользоваться простейшим примером, то кто из нас
стал бы заниматься какими бы то ни было тягостными физическими упражнениями, если бы это не приносило
с собой некоей пользы? И кто мог бы по справедливости упрекнуть стремящегося к наслаждению, которое
не несло бы с собой никаких неприятностей, или того, кто избегал бы такого страдания, которое
не приносило бы с собой никакого наслаждения?';

echo rus2translit($lorem);

?>

Результат
В результате на экране вы увидите:

No chtoby vy poniali, otkuda voznikaet eto prevratnoe predstavlenie liudei, poricaiushih
naslazhdenie i voshvaliaiushih stradaniia, ia raskroiu pered vami vsiu kartinu i raz`iasniu, chto imenno
govoril etot chelovek, otkryvshii istinu, kotorogo ia by nazval zodchim schastlivoi zhizni. Deistvitel`no,
nikto ne otvergaet, ne preziraet, ne izbegaet naslazhdenii tol`ko iz-za togo, chto eto naslazhdeniia,
no lish` iz-za togo, chto teh, kto ne umeet razumno predavat`sia naslazhdeniiam, postigaiut velikie
stradaniia. Ravno kak net nikogo, kto vozliubil by, predpochel i vozzhazhdal by samo stradanie tol`ko
za to, chto eto stradanie, a ne potomu, chto inoi raz voznikaiut takie obstoiatel`stva, kogda stradaniia
i bol` prinosiat nekoe i nemaloe naslazhdenie. Esli vospol`zovat`sia prosteishim primerom, to kto iz nas
stal by zanimat`sia kakimi by to ni bylo tiagostnymi fizicheskimi uprazhneniiami, esli by eto ne prinosilo
s soboi nekoei pol`zy? I kto mog by po spravedlivosti upreknut` stremiashegosia k naslazhdeniiu, kotoroe
ne neslo by s soboi nikakih nepriiatnostei, ili togo, kto izbegal by takogo stradaniia, kotoroe
ne prinosilo by s soboi nikakogo naslazhdeniia?

Добавлено: 29 Мая 2018 21:10:32 Добавил: Андрей Ковальчук

Преобразование числа в текст

Данный скрипт реализует преобразование чисел в текст, т.е., на примере денежной суммы,
из 1256.18 получим Одна тысяча двести пятьдесят шесть рублей 18 копеек.

В этом классе всё настолько прозрачно, что он почти не загружен лишними комментариями.

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

<?php

class NumToText
{
   var $Mant = array(); // описания мантисс
   // к примеру ('рубль', 'рубля', 'рублей')
   // или ('метр', 'метра', 'метров')
   var $Expon = array(); // описания экспонент
   // к примеру ('копейка', 'копейки', 'копеек')

   function NumToText()
   {
   }

   // установка описания мантисс
   function SetMant($mant)
   {
      $this->Mant = $mant;
   }

   // установка описания экспонент
   function SetExpon($expon)
   {
      $this->Expon = $expon;
   }

   // функция возвращает необходимый индекс описаний разряда
   // ('миллион', 'миллиона', 'миллионов') для числа $ins
   // например для 29 вернется 2 (миллионов)
   // $ins максимум два числа
   function DescrIdx($ins)
   {
      if(intval($ins/10) == 1) // числа 10 - 19: 10 миллионов, 17 миллионов
      return 2;
      else
      {
         // для остальных десятков возьмем единицу
         $tmp = $ins%10;
         if($tmp == 1) // 1: 21 миллион, 1 миллион
         return 0;
         else if($tmp >= 2 && $tmp <= 4)
         return 1; // 2-4: 62 миллиона
         else
         return 2; // 5-9 48 миллионов
      }
   }

   // IN: $in - число,
   // $raz - разряд числа - 1, 1000, 1000000 и т.д.
   // внутри функции число $in меняется
   // $ar_descr - массив описаний разряда ('миллион', 'миллиона', 'миллионов') и т.д.
   // $fem - признак женского рода разряда числа (true для тысячи)
   function DescrSot(&$in, $raz, $ar_descr, $fem = false)
   {
      $ret = '';

      $conv = intval($in / $raz);
      $in %= $raz;

      $descr = $ar_descr[ $this->DescrIdx($conv%100) ];

      if($conv >= 100)
      {
         $Sot = array('сто', 'двести', 'триста', 'четыреста', 'пятьсот',
         'шестьсот', 'семьсот', 'восемьсот', 'девятьсот');
         $ret = $Sot[intval($conv/100) - 1] . ' ';
         $conv %= 100;
      }

      if($conv >= 10)
      {
         $i = intval($conv / 10);
         if($i == 1)
         {
            $DesEd = array('десять', 'одиннадцать', 'двенадцать', 'тринадцать',
            'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать',
            'восемнадцать', 'девятнадцать' );
            $ret .= $DesEd[ $conv - 10 ] . ' ';
            $ret .= $descr;
            // возвращаемся здесь
            return $ret;
         }
         $Des = array('двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят',
         'семьдесят', 'восемьдесят', 'девяносто' );
         $ret .= $Des[$i - 2] . ' ';
      }

      $i = $conv % 10;
      if($i > 0)
      {
         if( $fem && ($i==1 || $i==2) )
         {
            // для женского рода (сто одна тысяча)
            $Ed = array('одна', 'две');
            $ret .= $Ed[$i - 1] . ' ';
         }
         else
         {
            $Ed = array('один', 'два', 'три', 'четыре', 'пять',
            'шесть', 'семь', 'восемь', 'девять' );
            $ret .= $Ed[$i - 1] . ' ';
         }
      }
      $ret .= $descr;
      return $ret;
   }

   // IN: $sum - число, например 1256.18
   function Convert($sum)
   {
      $ret = '';

      // имена данных перменных остались от предыдущей версии
      // когда скрипт конвертировал только денежные суммы
      $Kop = 0;
      $Rub = 0;

      $sum = trim($sum);
      // удалим пробелы внутри числа
      $sum = str_replace(' ', '', $sum);

      // флаг отрицательного числа
      $sign = false;
      if($sum[0] == '-')
      {
         $sum = substr($sum, 1);
         $sign = true;
      }

      // заменим запятую на точку, если она есть
      $sum = str_replace(',', '.', $sum);

      $Rub = intval($sum);
      $Kop = $sum*100 - $Rub*100;

      if($Rub)
      {
         // значение $Rub изменяется внутри функции DescrSot
         // новое значение: $Rub %= 1000000000 для миллиарда
         if($Rub >= 1000000000)
         $ret .= $this->DescrSot($Rub, 1000000000,
         array('миллиард', 'миллиарда', 'миллиардов')) . ' ';
         if($Rub >= 1000000)
         $ret .= $this->DescrSot($Rub, 1000000,
         array('миллион', 'миллиона', 'миллионов') ) . ' ';
         if($Rub >= 1000)
         $ret .= $this->DescrSot($Rub, 1000,
         array('тысяча', 'тысячи', 'тысяч'), true) . ' ';

         $ret .= $this->DescrSot($Rub, 1, $this->Mant) . ' ';

         // если необходимо поднимем регистр первой буквы
         $ret[0] = chr( ord($ret[0]) + ord('A') - ord('a') );
         // для корректно локализованных систем можно закрыть верхнюю строку
         // и раскомментировать следующую (для легкости сопровождения)
         // $ret[0] = strtoupper($ret[0]);
      }
      if($Kop < 10)
      $ret .= '0';
      $ret .= $Kop . ' ' . $this->Expon[ $this->DescrIdx($Kop) ];

      // если число было отрицательным добавим минус
      if($sign)
      $ret = '-' . $ret;
      return $ret;
   }
}

class ManyToText extends NumToText
{
   function ManyToText()
   {
      $this->SetMant( array('рубль', 'рубля', 'рублей') );
      $this->SetExpon( array('копейка', 'копейки', 'копеек') );
   }
}

class MetrToText extends NumToText
{
   function MetrToText()
   {
      $this->SetMant( array('метр', 'метра', 'метров') );
      $this->SetExpon( array('сантиметр', 'сантиметра', 'сантиметров') );
   }
}

?>
<HTML>
<HEAD>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251">
</HEAD>
<BODY>
<?php
if( isset($HTTP_POST_VARS['num']) )
{
   $mt = new ManyToText();
   $nt = new MetrToText();
   echo $mt->Convert($HTTP_POST_VARS['num']) . '<BR />';
   echo $nt->Convert($HTTP_POST_VARS['num']) . '<BR />';
}
?>
<FORM ACTION ="<?php echo $HTTP_SERVER_VARS['PHP_SELF']; ?>" METHOD="post">
Input number:<BR />
<INPUT TYPE="text" NAME="num"><BR />
<INPUT TYPE="submit" VALUE=" GET ">
</FORM>
</BODY></HTML>

Если не использовать subclassing, то строку $mt = new ManyToText() замените на:
$mt = new NumToText();
$mt->SetMant( array('рубль', 'рубля', 'рублей') );
$mt->SetExpon( array('копейка', 'копейки', 'копеек') );
echo $mt->Convert($HTTP_POST_VARS['num']);

Добавлено: 29 Мая 2018 17:47:59 Добавил: Андрей Ковальчук

Определение кодировки текста

Автоматическое определение кодировки текста

PHP скрипт для автоматического определения кодировки текста.

<?php
define('LOWERCASE',3);
   define('UPPERCASE',1);
   function detect_cyr_charset($str) {
      $charsets = Array(
         'k' => 0,
         'w' => 0,
         'd' => 0,
         'i' => 0,
         'm' => 0
      );
      for ( $i = 0, $length = strlen($str); $i < $length; $i++ ) {
         $char = ord($str[$i]);
      //non-russian characters
      if ($char < 128 || $char > 256) continue;
      //CP866
      if (($char > 159 && $char < 176) || ($char > 223 && $char < 242))
         $charsets['d']+=LOWERCASE;
      if (($char > 127 && $char < 160)) $charsets['d']+=UPPERCASE;
      //KOI8-R
      if (($char > 191 && $char < 223)) $charsets['k']+=LOWERCASE;
      if (($char > 222 && $char < 256)) $charsets['k']+=UPPERCASE;
      //WIN-1251
      if ($char > 223 && $char < 256) $charsets['w']+=LOWERCASE;
      if ($char > 191 && $char < 224) $charsets['w']+=UPPERCASE;
      //MAC
      if ($char > 221 && $char < 255) $charsets['m']+=LOWERCASE;
      if ($char > 127 && $char < 160) $charsets['m']+=UPPERCASE;
      //ISO-8859-5
      if ($char > 207 && $char < 240) $charsets['i']+=LOWERCASE;
      if ($char > 175 && $char < 208) $charsets['i']+=UPPERCASE;
   }
   arsort($charsets);
   return key($charsets);
} 
?>

Добавлено: 26 Мая 2018 21:39:35 Добавил: Андрей Ковальчук

Определение кодировки страницы сайта.

Чтение страницы сайта и преобразование в UTF-8 или в Windows-1251
При формированнии карт сайтов с помощью сервиса периодически сталкивался с проблемами некорректного указания кодировки страницы или неуказания кодовой страницы вообще. В настоящий момент у меня работает функция анализа кодовой страницы похожая на представленную ниже.

Представленный ниже пример читает страницу, преобразует её в UTF-8, загружает в DOM-объект, получает из него title и выводит его в кодировке windows-1251.

<form method=\"get\">
Страница для анализа: <input type=\"text\" name=\"url\">
</form>

PHP анализ и обработка:
<?php
$url=@$_GET['url'];

echo "<br>Страница <b>".$url."</b><br>\n";

   $curl = curl_init($url);
   curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
   curl_setopt($curl, CURLOPT_HEADER, 1);    // включать header в вывод
   curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);    // следовать любому "Location: " header
   curl_setopt($curl, CURLOPT_TIMEOUT, 20);    // максимальное время в секундах, для работы CURL-функций.
   $html = @curl_exec($curl);
   @file_put_contents($file,$html);
   $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
   curl_close($curl); // close cURL handler

   $headers = substr($html, 0, $header_size - 4)."\n";
   $body = substr($html, $header_size);

if (preg_match("|Content-Type: .*?charset=(.*)\n|imsU", $headers, $results))$ct0=trim($results[1]);
else $ct0=false;

if (preg_match_all('/(<meta\s*http-equiv=[\'\"]Content-Type[\'\"]\s*content=[\'\"][^;]*;\s*charset=([^\"\']*?)(?:"|\;|\')[^>]*>)/i',$body,$arr,PREG_PATTERN_ORDER)){
    $ct1=strtolower(trim($arr[2][0]));
    // не учитываю, что заголовки могут быть разными. Это в платной версии.
    if ($ct1=='utf-8')$ct1=false;
    $ct0=false; // meta не добавлять
}else $ct1=false;

if ($ct1){
    echo "<br>Преобразование ".$ct1." -> UTF-8";
    $body=@iconv($ct1,'utf-8//IGNORE',$body);
}

// добавляю в head Content-Type
if($ct0)$body=preg_replace('/<head[^>]*>/','<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
',$body);

$doc = new DOMDocument();

@$doc->loadHTML($body);

if ( ($tags = @$doc->getElementsByTagName('title')) ) {
    $title = @$tags->item(0)->nodeValue;
    print "<br>Заголовок страницы: ".@iconv("UTF-8", "windows-1251//IGNORE", $title).'<br />';
}
?>

Приведенный пример упрощен и не содержит обработку "трудных" случаев, когда кодовая страница в header указанна одна, а в META другая. Также не содержит обработку двойных мета с разными кодовыми страницами(и такое у меня попадалось). Полный пример дополнительно осуществляет кеширование и "борется" с кривыми страницами. Представленный код будет корректно работать на 95% страниц/сайтов в рунете.

Добавлено: 26 Мая 2018 21:37:18 Добавил: Андрей Ковальчук

Определение кодировки curl страницы

После получения страницы с помощью Curl-запроса Возникает необходимость привести её в требуемую кодирвку. Но вот тут и кроется "подвох". Мы часто не знаем начальную кодировку, из которой нужно перекодировать. Роясь в интернете, я нашел интересное решение charset_x_win, скачать можно здесь. Решение есть, но очень тяжелое. Потом я попробовал проанализировать что есть среди стандартных функций PHP... И нашел решение:

Определение кодировки полученной строки:

<?php
print mb_detect_encoding($str,"auto")."<br>\n"; // ASCII или UTF-8
?>

Преобразование кодировки полученной строки:
<?php
print mb_convert_encoding($str, "windows-1251", "auto")."<br>\n";
?>

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

Обработка строк в РНР

Одной из наиболее часто встречающихся задач в программировании является обработка символьных последовательностей. Если проще – строк. Как это делается на языке гипертекстового препроцессора РНР и есть тема этой статьи.

Откуда и как можно получить символьнуюпоследовательность? В самом простомслучае – присвоить ее нужной переменной.Другие варианты – получить из формы илииз файла. Если Вы присваиваетепеременной нужное значение, то оно, какправило, не нуждается в обработке, таккак программист делает присвоение вкоде программы, и конечно, в нужном виде.Но если строка считывается из файла, илиполучается посредством формы, она (символьнаястрока) нуждается в обработке.

Самое первое, что стоит сделать, это удалить повторяющиеся пробелы. Дляэтого в РНР есть специальная функция: chop(str);
Пример ее записи:

$str = chop ($str);

В результате, обработанное значениестроки $str не будет содержатьповторяющихся пробелов. Если нужноубедиться в том, что строка не содержитпробелов в начале и в конце, применяетсяфункция trim(str); ( $str = trim ($str); ). Когдатребуется удалить пробелы только сначала строки, нужно использовать ltrim. Иесли уж зашла речь о начале строки,давайте убедимся, что первый символзаглавный. Что бы сделать его таковым,примените ucfirst(str); Есть и функция дляперевода во всех словах в строке ихпервых букв в заглавные - ucwords(str);. Крометого, очень часто бывает необходимосравнить строку с некоторым шаблоном.Частный случай – поиск в строке (о немнесколько позже). Но нет никакойгарантии, что полученная строка введенапользователем или получена из файла всоответствии с правилами правописания.Другими словами – строка можетсодержать в середине слова илипредложения чередующиеся заглавные ипрописные символы. Решение даннойпроблемы – в применении функций strtolower(str);и strtoupper(st);. Эти функции, соответственно,переводят символьные строки в нижний иверхний регистр. Комбинирование данныхвозможностей языка РНР приводит ккорректному построению строки независимо от того, как она была введенаили получена в начальном виде.

Еще одна необходимая вещь при работе состроками – их обрезка. Часто онаприменяется при обработке форм дляввода данных. Представьте, что кто-нибудьиз Ваших «доброжелателей» введет в Вашугостевую книгу текст этой статьи.Представляете, что получится? Вот дляэтого и нужно ограничить количествовводимых символов в любом поле формы.Тем более что делается это очень просто.Для начала, нужно прописать ограничениев самой форме:
<input maxlength="100" name="form">

Теперь форма с именем form ограничена вколичестве вводимых символов числом 100.Но это еще далеко не все. Дело в том, чтообойти такое ограничение очень просто, инужно оно скорее для того, что быпоказать посетителю предел ограничения.Дальше нужно воспользоваться функциейРНР $form =substr($form,0,99);. Этим вы простоотрезаете часть полученной строки,превышающую 100 символов (стоит цифра 99,так как счет символов начинается с нуля).Теперь все потуги Ваших знакомыхзавалить Вас информацией будут тщетны,так как Ваш умный скрипт не пропуститбольше определенного Вами количествасимволов.

Собственно говоря, у функции substr(string, start,length); совсем другое предназначение. Онавозвращает часть строки string,определяемую параметрами start (начало) иlength (длина). Если параметр startположительный, то возвращаемая строкабудет начинаться с start-ого символастроки string.
Примеры:
$form = substr("abcdef", 1); // вернет "bcdef"
$form = substr("abcdef", 1, 3); // вернет "bcd"

Если параметр start отрицательный, товозвращаемая строка будет начинатьсяstart-ого символа от конца строки string.
Примеры:
$rest = substr("abcdef", -1); // вернет "f"
$rest = substr("abcdef", -2); // вернет "ef"
$rest = substr("abcdef", -3, 1); // вернет "d"

Если параметр length указан и онположительный, то возвращаемая строказакончится за length символов от начала start.Это приведет к строке с отрицательнойдлиной (потому что начало будет законцом строки), поэтому возвращаемаястрока будет содержать один символ отначала строки start. Если length указан и онотрицательный, то возвращаемая строказакончится за length от конца строки string.Это опять приведет к строке сотрицательной длиной, поэтомувозвращаемая строка будет содержатьодин символ от начала строки start.
Примеры:
$rest = substr("abcdef", -1, -1); // вернет "bcde"

Вот такая полезная функция. Кроме нее,при обработке данных формы очень важноуметь вырезать из полученной строкилишние или просто недопустимые символы.Можно в этом случае применитьспециальную функцию, которая заменяетвсе вхождения строки needle в строке haystackна указанную строку str. Эта функциязаписывается так: str_replace(needle, str, haystack);.Если вам не требуются причудливыеправила замены, то вам следует всегдаиспользовать эту функцию вместо ereg_replace().
Примеры:
$str = str_replace("", "\n", $str); //вырезается символ ввода.
$str = str_replace("red", "black", $str); // встроке черный цвет будет заменен накрасный.

Следующая важная и полезная функция –нахождение длинны строки. Синтаксис -strlen(string str);Пример – $a = strlen(“qwerty”);. Впеременной $a будет число 6, так какдлинна строки – 6 символов. Еще однаинтересная возможность языка РНР –перевод текста (а значит – и символьныхстрок) из одной кодировки в другую. Этоочень полезно, если нужно согласоватькодировки, например, сайта и почтовойпрограммы. Причем поддерживаются самыераспространенные русские кодировки: stringconvert_cyr_string(str, from, to);. Аргументы from и toявляются одним символом, которыйопределяет исходную и целевую кодовуютаблицу. Поддерживаемые типы:

k - koi8-r 
w - windows-1251 
i - iso8859-5 
a - x-cp866 
d - x-cp866 
m - x-mac-cyrillic


Htmlspecialchars - переводит специальныесимволы в коды HTML. Htmlspecialchars( string);Определенные символы имеют особоезначение в HTML и должны быть замененыкодами HTML, если они таковые имеют. Этафункция возвращает строки спроизведенными такими изменениями.Функция полезна для отчисткиполученного от пользователя текста отразметки HTML (доски сообщений, гостевыекниги). Осуществляются следующие замены:
'&' (амперсанд) становится '&amp;' 
'"' (двойные кавычки) становится '&quot;' 
'<' (знак меньше) становится '&lt;' 
'>' (знак больше) становится '&gt;'

Следует отметить, что эта функция незаменяет ничего, кроме указанного выше.Для полной обработки применяют функциюhtmlentities(). Она переводит все возможныесимволы в коды HTML. Htmlentities(string); Этафункция идентична htmlspecialchars() , кроме того,что все символы, которые имеютсоответствующий код HTML, заменяются наэтот HTML код. В настоящее времяприменяется кодовая таблица ISO-8859-1.

Отдельно следует рассмотреть функциипоиска в строке. Strchr - Находит первоепоявление символа. strchr(haystack, needle); Этафункция является псевдонимом дляфункции strstr(), и полностью ей идентична.Возвращает все haystack с первого появлениястроки needle и до конца. Если параметр needleне найден, то возвращается false. Еслипараметр needle не является строкой, то онпереводится в целое число ирассматривается как числовое значениесимвола. Strrpos - Находит позициюпоследнего появления символа в строке.Strrpos(haystack, needle); Возвращает номер позициипоследнего появления символа needle встроке haystack. Следует отметить, что needle вэтом случае может быть толькоединственным символом. Если в качествепараметра needle указывается строка, тотолько первый символ будет использован.Если needle не найден, то возвращается false.Если параметр needle не является строкой,то он переводится в десятичное число ирассматривается как числовое значениесимвола. Strrchr -- Находит последнеепоявление символа в строке.
Strrchr(haystack, needle); Эта функция возвращаетпозицию haystack, с которой начинаетсяпоследнее появление needle и продолжаетсядо конца haystack. Возвращает false если needle ненайдена. Если параметр needle содержитболее чем один символ, то используетсяпервый символ. Если параметр needle неявляется строкой, то он переводится вцелое число и рассматривается какчисловое значение символа.
Пример:
// получение всего после последней новойстроки
$text = "Line 1\nLine 2\nLine 3";
$last = substr( strrchr( $text, 10 ), 1 );

Strtok - разбивает строку. strtok( arg1, arg2);Используется для разбиения строки. Этозначит, что если вы имеете строку типа"Как хорошо программировать", то выможете разбить эту строку на отдельныеслова, используя пробел в качестверазделителя.
$string = " Как хорошо программировать";
$tok = strtok($string," ");
while($tok) { echo "Word=$tok<br>"; $tok = strtok(""); }

Следует отметить, что только первыйвызов функции strtok использует строковыйаргумент. Для каждого последующеговызова функции strtok необходим толькоразделитель, так как это позволяетконтролировать положение в текущейстроке. Для начала заново или дляразбития новой строки вам необходимопросто вызвать strtok с параметром строкиопять для ее инициализации. Вы можетевставлять несколько разделителей впараметр разделителя. Строка будетразделяться при обнаружении любого изуказанных символов. Также будьтевнимательны к разделителям равным"0". Это может вызвать ошибку вопределенных выражениях.

Вот то, что понадобится Вам для работы состроками в первую очередь. Тут приведендалеко не полный перечень всехстроковых функций. Рассмотрены только самые основные.

Добавлено: 26 Мая 2018 21:30:55 Добавил: Андрей Ковальчук

Эмулятор функции iconv

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

Замена функции iconv:

<?php
function Encode($str, $type = 'w'){
    // $type:
    // 'w' - encodes from UTF to win
    // 'u' - encodes from win to UTF

        static $conv='';
        if (!is_array ( $conv )){
            $conv=array();
            for ( $x=129; $x <=143; $x++ ){
                $conv['utf'][]=chr(209).chr($x);
                $conv['win'][]=chr($x+112);
        }
            for ( $x=144; $x <=191; $x++ ){
                $conv['utf'][]=chr(208).chr($x);
                $conv['win'][]=chr($x+48);
        }
            $conv['utf'][]=chr(208).chr(129);
            $conv['win'][]=chr(168); // Ё
            $conv['utf'][]=chr(209).chr(145);
            $conv['win'][]=chr(184); // ё
            $conv['utf'][]=chr(209).chr(128);
            $conv['win'][]=chr(240); // р
        }

        if ( $type=='w' )
            return str_replace ( $conv['utf'], $conv['win'], $str );
        elseif ( $type=='u' )
            return str_replace ( $conv['win'], $conv['utf'], $str );
        else
            return $str;
}
?>

Добавлено: 11 Мая 2018 11:38:52 Добавил: Андрей Ковальчук

Функция проверки орфографии на PHP

Функция проверки орфографии на PHP (на входе проверяемый текст, на выходе список слов с ошибками):

function spell_check ( $str ){
        $str = stripSlashes($str);
        $tocheck = strtr($str, "\n", ' ');
        $tocheck = escapeShellCmd($tocheck);
	exec("echo $tocheck | /usr/bin/ispell -d russian -l", $warnings);
	sort($warnings);
	$sp_prev = '';
	$sp_errors = '';		
	while (list($sp_key, $sp_val) = each($warnings)) {
           if ($sp_val != $sp_prev) {
              $sp_errors = $sp_errors . "<a
href=\"/vhq/info_spell.php3?spell=" . urlencode($sp_val) . "\"
target=_blank>$sp_val</a>, ";
    	   }
           $sp_prev = $sp_val;
	}
	return $sp_errors;
    }

Добавлено: 11 Мая 2018 11:34:51 Добавил: Андрей Ковальчук

ASCII to HEX средствами PHP

Для этого воспользуемся 4-я функциями:
strlen - подсчитаем кол-во символов
substr - возвращает часть строки
ord - возвращает ASCII-значение символа
dechex - 10-ричное в 16-ричное

и напишем несложный замысловатый код:

<?php
$my_url='microsoft.com';
$strlength = strlen($my_url);
    for($i=0; $i<$strlength; $i++){
        $returnval .= '%'.dechex(ord(substr($my_url, $i, 1)));
    }
echo 'http://'.$returnval;
?>

Добавлено: 10 Мая 2018 21:23:18 Добавил: Андрей Ковальчук

Функция PHP strlen().

Иногда необходимо получить информацию о длине той или иной строки. Функция PHP strlen() помогает определить количество символов конкретной строки.

Синтаксис функции:

int strlen (string string)

Функция strlen возвращает целое число (тип integer), а в качестве параметра принимает значение строкового типа (string).

Примеры использования:
<?php
$str = 'Привет мир!';
echo strlen($str); // вернет 11
 
$str1 = 'Тест';
echo strlen($str1); // 4
?>

Если строка будет пустой, то функция вернет 0. Функция также учитывает пробелы, считая и их тоже.

Данную функцию нередко используют в циклах при обработке символов строки. Обычно в этих случаях делается перебор символов начиная от 1 до конца строки.

Название функции образовано от сокращений двух слов: string (строка) и length (длина).

Добавлено: 10 Мая 2018 15:28:41 Добавил: Андрей Ковальчук

Функция strpos() в PHP.

Функция strpos() осуществляет поиск заданной строки в другой строке. Возвращает позицию первого вхождения искомой строки, либо FALSE, если подстрока не найдена. При этом отсчет ведется с 0, то есть первый символ занимает нулевую позицию.

Общий синтаксис:

int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )

Первый параметр $haystack – это строка, в которой осуществляется поиск. Второй параметр $needle – искомая подстрока. Третий параметр – необязательный и указывает позицию, с которой необходимо осуществлять поиск.

Обратите внимание, что данная функция может возвратить 0, если искомая подстрока находится на нулевой позиции, а это значит, что при проверке возвращаемого значения с помощью «$pos == FALSE» мы получим совсем не то, что нужно, то есть 0 будет преобразован в FALSE. Чтобы избежать ошибки, лучше использовать знак «===», где сравнение используется с учетом типа данных.

Рассмотрим пример:
<?php
$teststr = 'алгоритм';
$search   = 'a';
$pos = strpos($teststr, $search);
 
if ($pos === false) {
    echo "Строка '$search' не найдена в строке '$teststr'";
} else {
    echo "Строка '$search' найдена в строке '$teststr'";
    echo " в позиции $pos";
}
?>

В этом примере мы получим верное значение 0, так как использовали сравнение с учетом типа возвращаемого значения.

Пример 2.
<?php
$teststr = 'мама';
$search   = 'м';
$start = '1';
$pos = strpos($teststr, $search, $start);
 
if ($pos === false) {
    echo "Строка '$search' не найдена в строке '$teststr'";
} else {
    echo "Строка '$search' найдена в строке '$teststr'";
    echo " в позиции $pos";
}
?>

Здесь будет выведено 2, так как поиск ведется с 1 позиции (это второй символ в строке), а искомая подстрока (символ) занимает 0 и 2 позиции.

Название функции strpos() образовано от двух слов string (строка) и position (позиция).

Добавлено: 10 Мая 2018 15:26:40 Добавил: Андрей Ковальчук

Функция для обрезания длинного текста

Маленькая функция, которая часто используется — обрезание длинного текста.
Функция обрезает текст до нужной длинны и приписывает в конце многоточие «…». Код функции написан на php, и довольно простой, поэтому что-либо тут описывать нет смысла, единственное что скажу — это то, что функция работает и с кириллицей и с английскими символами, для этого все операции с текстом осуществляются в кодировке utf-8.
Ниже приведу код:

// пример использования
$text = "ооооочень длинный текст";
$cutText = cut_text($text, 15);
echo $cutText;
 
// функция для обрезания длинного текста
function cut_text($text, $maxLen = 10){
    $lenTitle = mb_strlen($text, 'utf-8'); // длина всего текста
    $result = $text;
    if(($lenTitle-3) > $maxLen){ // -3 нужно для исключения замены 3х последних символов точками
        $result = mb_substr($text, 0, $maxLen, 'utf-8') . '...'; // обрезаем и дописываем точки
    }
    return $result;
}

Добавлено: 10 Мая 2018 15:25:35 Добавил: Андрей Ковальчук

Склонение слов по падежам на php

У Яндекса есть очень удобный api сервис, который может трансформировать любое слово, или даже несколько слов, во все падежи. Воспользоваться сервисом очень просто, достаточно сделать запрос по адресу export.yandex.ru/inflect.xml?name=СЛОВО — в ответ будет получен xml со всеми склонениями слова.
Ниже я привел функцию, которая работает с api Яндекса и возвращает нужную форму слова.
Код функции:

/**
* Склонение слов по падежам. С использованием api Яндекса
* @var string $text - текст 
* @var integer $numForm - нужный падеж. Число от 0 до 5
*
* @return - вернет false при неудаче. При успехе вернет нужную форму слова
*/
function getNewFormText($text, $numForm){
    $urlXml = "http://export.yandex.ru/inflect.xml?name=".urlencode($text);
    $result = @simplexml_load_file($urlXml);
    if($result){
        $arrData = array();
        foreach ($result->inflection as $one) {
           $arrData[] = (string) $one;
        }
        return $arrData[$numForm];
    }
    return false;
}

И пример использования функции:
$text = "любой текст";
echo "Именительный падеж : " . getNewFormText($text, 0) . "<br/>";
echo "Родительный падеж : " . getNewFormText($text, 1) . "<br/>";
echo "Дательный падеж : " . getNewFormText($text, 2) . "<br/>";
echo "Винительный падеж : " . getNewFormText($text, 3) . "<br/>";
echo "Творительный падеж : " . getNewFormText($text, 4) . "<br/>";
echo "Предложный падеж : " . getNewFormText($text, 5) . "<br/>";

Добавлено: 10 Мая 2018 15:14:08 Добавил: Андрей Ковальчук

Удаление строки из файла с помощью php

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

Функция реализующая удаление строки из файла
Ниже приведу код функции, которая удаляет строку из файла по номеру. Код подробно прокомментирован:

/**
* Функция для удаления строки из файла
*
* @param string $fileName - расположение файла
* @param string $num - номер строки, которую нужно удалить
*/
function delStringByNum($fileName, $num){
    // Открываем файл
    $file = @file($fileName);
    // если файл не найден, выводим ошибку
    if(!$file){
        trigger_error("File '$fileName' not found!");
        return false;
    }
    // если номер строки не корректный, сообщим об этом
    if(!isset($file[$num-1])){
        trigger_error("Incorrect number string: ($num)");
        return false;
    }
    // удаляем строку
    $num = intval($num)-1;
    unset($file[$num]);
    // открываем файл для записи
    $fileOpen = @fopen($fileName,"w"); 
    // если файл невозможно редактировать, сообщаем об этом
    if(!$file){
        trigger_error("File '$fileName' is not writable!");
        return false;
    }
    // перезаписываем файл
    fputs($fileOpen,implode("",$file)); 
    fclose($fileOpen);
    return true;
}

И приведу пример использования нашей функции:
// пример использования функции
$result = delStringByNum('/files/test.txt', 3);
var_dump($result);

Добавлено: 10 Мая 2018 14:56:46 Добавил: Андрей Ковальчук