Иван Тепляков

Полезные заметки веб-разработчика

Кроссдоменные ajax запросы с использованием JQuery

Эта тема достаточно хорошо освящена на просторах интернета. Цель поста – подробный практический пример.
Вообще ajax запросы с появлением таких яваскриптовых библиотек как JQuery, Prototype, Dojo и др. стали очень легко и быстро реализуемые. Всю рутинную работу по созданию объекта XMLHttpRequest берет на себя библиотека, нам остается только указать к какому скрипту на сервере надо слать запрос и опции. Проблема возникает, когда скрипт лежит на другом домене. Тогда привычный $.ajax(options) не помогает из-за политики безопасности.
На помощь приходит технология JSONP (JSON Padding). Не буду вдаваться в теоретические подробности ибо воды налито и так не мало, перейдем к практике.
Задача: вывести комментарии к материалу на сайте. Сложность в том, что база и интерфейс лежат на другом сервере.
Создаем там php-скрипт, который будет нам отдавать список комментариев в json формате.
Например так:

// принимаем id материала, к которому нужны комменты
$material_id = intval($_GET['id']);
 
if (isset($material_id) && !empty($material_id))
{
     $posts = /* получаем из базы комменты для материала */
}
else
{
     $posts = array(); // отдаем пустой массив
}
 
echo $_GET['callback'] . '(' . posts2txt($posts) . ');';

Пишем функцию post2txt(), которая будет перебирать массив с комментариями и оформлять их в JSON объект, чтобы например получился результат:

{
     posts: [
          { "htmltxt" : "Автор1 - комментарий"},
          { "htmltxt" : "Автор2 - комментарий"}
     ]
}

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

<div id="cmnts">Идет загрузка комментариев... (Или можно gif поставить)</div>
<script type="text/javascript" language=javascript>
     $(document).ready(function(){
          $.getJSON('http://www.zr.ru/forum/zr_tools/getcomments.php?id=<?= $material_id ?>&callback=?', 
               function(data){ /* в переменную data придут данные*/
		    $("#cmnts").html(""); /* очищаем div от прелоадера */
		    $.each(data.posts, function(i,item){
                         $("#cmnts").append(item.htmltxt); /* вставляем комменты в элемент на странице */
		    });
               });
     });
</script>

Собственно соль в добавлении “&callback=?” в конец строки адреса скрипта. Туда JQuery будет генерировать случайное число для имени callback-функции.

Генератор случайных чисел

Часто бывает нужно сгенерировать определенное количество уникальных чисел в заданном интервале.
Это можно сделать так:

// стартовая конфигурация:
$from = 1; // минимальное число интервала
$to = 100; // максимальное число интервала
$num = 5; // количество чисел в результирующем наборе
 
$res = array(); // массив для хранения результирующего набора
// запускаем "бесконечный" цикл, в условии присваиваем случайное число
while($i = rand($from, $to)) {
    // если числа еще нет в результирующем массиве, то добавляем его туда
    if (! in_array($i, $res) ) $res[] = $i;
    // если в массиве достаточно чисел, то прерываем цикл
    if (count($res) == $num) break;
}
 
// смотрим что получилось в массиве
var_dump($res);

А как бы вы сделали лучше/быстрее/оптимальнее?

POST-запрос без использования сокетов

В php5 есть замечательные средства создания всевозможных запросов без использования сокетов.
Вот например как сделать POST-запрос:

// Создаем "контекст" для запроса
$context = stream_context_create(
                array(
                   "http" => array(
		                  "method" => "POST", // метод запроса
		                  "header" => "Content-Type: multipart/form-data\r\n", // всевозможные хедеры
		                  "content" => $variables // тело запроса
		                  )
                ));
// отправляем запрос и получаем ответ
$response = file_get_contents($url, null, $context);

На мой взгляд намного удобнее, чем мучаться с сокетами.

Проблемы с обрезанием строки в utf-8 при помощи substr()

Возникла такая проблема, что при обрезании строки при помощи substr(), в конце полученной обрезанной строки появляется символ в виде квадратика или знака вопроса, что появляются если браузер не может распознать символ.

Решается проблема, если использовать для обрезания utf-8 строк функцию mb_substr().
Например так:

// указываем кодировку
mb_internal_encoding("UTF-8");
 
$str = 'Строка в кодировке utf-8';
$str = mb_substr($str, 0, 17);

В результате получим красиво обрезанную строку.

Таким же способом можно использовать mb_strlen(), mb_strpos() и другие.

Перекодировка всех файлов проекта

Наконец-то полностью перехожу на utf8.
Чтобы перевести весь код фреймворка в кодировку utf8 на понадобится такой bash-скрипт:

#!/bin/sh
for i in `find . -name "*" -type f`
do
echo $i
iconv -f WINDOWS-1251 -t UTF-8 "$i" > tmp
mv -f tmp "$i"
done