Imagick и аватарки
Последние несколько дней посвящены изучению загрузки и обработки аватарок. Умнее я себя не чувствую, но я определенно накопал несколько интересных вещей. Конечно же, для обработки используется горячо любимая ImageMagick и ее объектный API для php. Проблема этого API только одна - оно практически не документировано. В таком количестве функций черт ногу сломит, а к большинству из них нет даже элементарного описания того, что они делают. Ну, да не об этом речь.
Вот целый блог гражданина, который, по всей видимости, серьезно занимается этой библиотекой:
http://valokuva.org/
Вот небольшая заметка о том, как делать симпатичные превьюшки (thumbnail) для картинок:
<?php
$thumb = new Imagick();//читаем картинку по полному пути
$thumb->readImage($fullpath)//создаем белый фон
$canvas = new Imagick();
$canvas->newImage($width, $height, new ImagickPixel(“white”));//делаем превью, размер меньше, чем у фона, чтобы было куда впихнуть тень
$thumb->thumbnailImage($width-10, $height-10);//наводим резкость, если превью мелкое
if ($width < 300) $thumb->sharpenImage(4, 1);//делаем копию превьюхи, чтобы сделать тень
$shadow = $thumb->clone();//цвет тени
$shadow->setImageBackgroundColor(new ImagickPixel(‘black’));//собственно, делаем тень
$shadow->shadowImage(80, 2.5, 5, 5);//накладываем тень на фон
$canvas->compositeImage($shadow, $shadow->getImageCompose(), 0, 0);//накладываем превью на фон
$canvas->compositeImage($thumb, $thumb->getImageCompose(), 0, 0);//убираем комменты и т.п. из картинки
$canvas->stripImage();//записываем картинку
$canvas->writeImage($writeTo);//подчищаем за собой
$canvas->destroy();
$shadow->destroy();
$thumb->destroy();?>
via http://habrahabr.ru/blogs/php/43511/
Надо только отметить, что этот метод плохо работает с GIF’ами (видимо, с PNG тоже), у которых есть прозрачный цвет. Ибо тень в таком случае получается очень коряво. Я потратил еще несколько часов на попытки адаптировать его под работу с GIF’ами, но так ничего и не получилось. В другой раз, видимо.
2 years ago
April 4, 2010
Необходимый фокус с кодировками
Итак, все настроено для работы с UTF-8:
- в заголовке страницы есть <meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8“>
- в базе данных указана кодировка по умолчанию utf-8
- apache настроен отдавать страницы в utf-8
Остается только одно: когда данные формы передаются в php и затем помещаются в базу данных, через phpmyadmin они выглядят как не понятно что. И все вроде бы хорошо, потому что если через тот же php вывести данные из БД, то они отображаются нормально. Но эта фигня в phpmyadmin режет глаза.
Решается оно вот как. После подключения к базе данных, вписываем следующие строчки:
mysql_query (“set character_set_client=’utf8’”);
mysql_query (“set character_set_results=’utf8’”);
mysql_query (“set collation_connection=’utf8_general_ci’”);
Ну или какая там кодировка, соответственно. Эти строчки настраивают соответствие кодировок клиента и сервера MySQL, и приводят этот бардак в порядок.
2 years ago
April 3, 2010
И еще последствия перехода на UTF-8
И конечно же, с мультибайтовыми строками обламываются стандартные функции для работы со строками. Облом заключается в том, что один символ они начинают считать за два. Исправляется, опять же, использованием расширения mb_string:
http://ru2.php.net/manual/en/ref.mbstring.php
Лично я просто заменил функции:
strlen = mb_strlen
substr =mb_substr
и все чудесным образом исцелилось.
2 years ago
March 3, 2010
Еще одно решение проблемы mail в php
Поступило еще одно решение проблемы с темой (subject) письма, отправляемого функцией mail в php (подробности здесь: http://itruns.ru/post/422397378/sendmail). За решение спасибо ereptoris:
$subject = '=?UTF-8?'; //Говорим, что у нас в теме текст в соответствующей кодировке
$subject .= 'B?'; //А текст зашифрован алгоритмом base64
$subject .= base64_encode($content) . '?='; // Кодируем текст и дописываем завершающее выражение
Нечто похожее описано на той же странице на php.net. Может быть кому-то так и удобнее, не спорю. Лично для меня, более простой и очевидный способ я описал в предыдущей заметке, тем более, mb_string в любом случае подключен и никакой его глючности я пока что не заметил.
2 years ago
March 3, 2010
Новые потрясающие выкрутасы с sendmail
В темпе вальса переводим все письма в UTF-8! И, само собой, ничто никогда не работает сразу так, как хочется =).
Если в header просто заменить кодировку на UTF-8:
Content-type: text/html; charset=utf-8
само тело письма преобразуется нормально. Однако тема (subject) продолжает подражать самым изысканным иероглифам. На сайте php.net нашлась вот такая строчка:
$subject= mb_encode_mimeheader($subject, “UTF-8”, “B”, “\n”);
Сработало. Почему-то, не с первого раза, но это я уже не в силах объяснить.
2 years ago
March 2, 2010
geoip
В общем, нужно было отфильтровать американцев от всех остальных, по IP. Один вариант это сделать - установить модуль для веб-сервера. В этом случае в глобальном массиве $_SERVER появляются несколько переменных, которые, соответственно, можно просто использовать в коде.
Другой вариант - PECL-расширение для php. Тут просто набор функций, которым передается IP юзера, и они возвращают что надо:
http://ru2.php.net/manual/en/book.geoip.php
К нему надо еще установить сишную библиотеку geoip, затем установить само PECL-расширение, а потом не забыть добавить extension=geoip.so в php.ini. Более точно и подробно процесс описан тут:
http://www.outofcontrol.ca/2009/02/10/installing-pecl-geoip-problem/
Не знаю, кстати, чего там требует способ №1 - этим занимаюсь не я. Но мне кажется, он гораздо удобнее второго.
2 years ago
February 18, 2010
imagick загрузка картинок
Просто кусок кода, который берет картинку из файла, изменяет ее размер и записывает в файл. Для работы нужен imagick с объектным интерфейсом.
$image = new Imagick($_FILES[‘userfile’][‘tmp_name’]);
$width = $image->getImageWidth();
if ($width > 100) {
$image->thumbnailImage(100, null, 0);
}
$height = $image->getImageHeight();
if ($height > 100) {
$image->thumbnailImage(null, 100, 0);
}
//$image->thumbnailImage(100, 100, true);
//$image->resizeImage(100, 100, imagick::FILTER_LANCZOS, 1);
$image->writeImage($uploadfile);
$image->clear();
$image->destroy();
2 years ago
February 17, 2010
Ветви
При создании CLI скриптов часто приходится делать разветвленные программы чтобы ускорить обработку чего-либо (можно использовать в кэшерах и спайдерах). При этом основной процесс должен запускать дочерние в бэкграунде (с & на конце). Проблема в том, что как только основной процесс запустил все дочерние, сам он завершается. А хотелось бы чтобы он дождался пока все дочерние тоже закончат и записал общее время работы и т.д. в лог.
Для этого был придуман вот такой кусок кода:
$flag = true;
while($flag){
$str = `ps aux | grep ИМЯ_ДОЧЕРНЕГО_ПРОЦЕССА`;
$num_arr = explode(“\n”, $str);
$proc_count = 0;
foreach($num_arr as $strin){
if(strpos($strin,”/usr/local/bin/php”) !== false) $proc_count++;
}
if($proc_count > 0) sleep(60);
else $flag = false;
}
Оно ставиться в конец основного скрипта и тормозит его до тех пор, пока все дочерние не закончат. while(true) - не очень красиво и не очень безопасно. Но служит мне верой и правдой уже год. Как-нибудь сяду и напишу функцию, чтобы было короче.
2 years ago
February 17, 2010
Переменные переменных
Большего бреда в жизни не слышал. Но штука забавная =))
Переменные переменных
РНР предоставляет еще один тип переменных — т.н. переменные переменных. Переменные переменных позволяют динамически изменять имена переменных. (Как видите, РНР допускает очень большую свободу в этом вопросе — все языки разрешают изменять значение переменной, но лишь немногие позволяют изменять тип переменной, а уж совсем немногие — имя переменной.)
Способ достижения этого заключается в использовании значения одной переменной в качестве имени другой. Например, можно было бы определить
$varname = “tireqty”;
Затем вместо $tireqty можно использовать $$varname, например, так:
$$varname = 5;
Это может показаться несколько запутанным, однако позже мы еще вернемся к этому вопросу. Вместо того чтобы перечислять и использовать каждую переменную формы отдельно, можно организовать цикл и переменную для автоматической обработки всех из них. Пример, иллюстрирующий такой метод, приводится в разделе, посвященном циклам for.
2 years ago
February 17, 2010
Анти-brute
Только что наткнулся на интересную мысль, на сайте php, в комментах к функции sleep:
Very useful to prevent password brute forcing! Simply add few seconds timeout to login script and the probability to guess the password decreases a lot!
Действительно, если в обычной ситуации робот может сделать несколько десятков запросов в секунду, если в скрипт логина добавить пару секунд задержки, эффективность подбора снижается в разы.
Хотя эффективнее делать ограничение числа ввода пароля, имхо.
2 years ago
February 17, 2010
Комменты в Eclipse
Только что в порыве страсти к своему коду случайно нашел горячие клавиши для комментариев в Eclipse:
CTRL+/ - комметирует строчку или выделенный кусок с помощью // комментария
CTRL+SHIFT+/ - берет выделенный кусок в /* */ комментарий
2 years ago
February 17, 2010
ООП на PHP
Нашел замечательную коротенькую статью:
Итак, семь хороших объектно-ориентированных привычек при программировании на PHP:
- Будьте скромны.
- Будьте хорошим соседом.
- Не смотрите на Медузу Горгону.
- Применяйте самое слабое связывание.
- Обеспечьте высокое сцепление.
- Поддерживайте семейственность.
- Мыслите шаблонами.
Продолжение и подробности:
Семь хороших объектно-ориентированных привычек при программировании на PHP
2 years ago
February 17, 2010
Оповещения
Еще одна проблема, возникшая сегодня - оповещения об ошибках. Ситуация такая: на сервере живет около 30 php-скриптов, которые запускаются кроном. Некоторые из них собирают информацию с других сайтов и кладут ее в базу данных. Когда на внешнем сайте неожиданно меняется структура html, скрипт обламывается и выдает ошибку. Или просто не собирает ничего. Происходит такое не часто, но когда случается, шума из-за этого много. Но ходить и каждый день руками проверять, все ли работают не хочется.
Старое решение:
Пишется функция, которая проверяет данные, которые собирает скрипт. Если данные не подходят по формату, функция останавливает скрипт и отсылает письмо админу с сообщением, что что-то не так. Решение работает, но есть несколько проблем:
- для каждого нового скрипта нужна новая функция проверки формата данных
- получается сильное нагромождение кода со всеми конструкциями if-else и так далее
- если скрипт обламывается много-много раз подряд, то почта админа сильно засоряется, не говоря уже о том, что большие очереди sendmail могут серьезно перегрузить сервер.
Последнее, собственно и произошло, после чего было принято решение изобрести другой метод оповещения.
Новое решение (еще не опробовано):
Все скрипты в процессе работы создают файлы с расширением .script_log, ну или вообще каким угодно, кладут их в папочки, и забывают об оповещениях об ошибках. Если в процессе выполнения возникает ошибка, то скрипт просто записывает ее в лог, а перед ней ставит что-то вроде “scripterror: “. Раз в сутки (2 раза в сутки - не важно) запускается скрипт, который выполняет команду
grep “scripterror” /siteroot/*.script_log
которая находит все файлы, в которых есть строчка “scripterror”. Остается только слегка обработать эту информацию и подсчитать количество ошибок. И можно отсылать письмо админу. Таким образом, имеем ежедневный отчет о происходящем на сервере.
2 years ago
February 17, 2010
Кусочек кода
Сегодня уже в который раз столкнулся с такой проблемой: есть сайт, с которого нужно нагло содрать какую-то информацию. На этом сайте html-сущности закодированы не очень понятно чем и выглядят на подобии & (представление амперсанда). Вроде интуитивно понятно, что к чему. Вот только обычными функциями php это не возьмешь. Нашелся вот такой кусочек кода:
$str = preg_replace(‘~&#x([0-9a-f]+);~ei’, ‘chr(hexdec(“\1”))’, $str);
$str = preg_replace(‘~&#([0-9]+);~e’, ‘chr(“\1”)’, $str);
Он работает. Лежал на самом видном месте - в примерах к функции html_entity_decode.
Кстати, скорее всего пригодиться при работе со всякими языками вроде китайского.
RSS
Archive
Mobile