Шпаргалко Сумасшедшего ПрограммЁра Waiting of summer

29Сен/112

Резка строк в UTF-8 в PHP

Время от времени в программизме для веб возникает задача обрезать строчку скажем на 1000 символов - чтобы было нечто типа "строка..." и "Читать далее" (как например сделано в этом блоге на слишком длинных заметках. Проблемы начинаются с резкой UTF-8 строк, потому что стандартная функция substr в этом отношении демотивирует - байта на каждый символ два, а она режет по одному... В результате может от какой-нибудь буквы "ё", остаться неприглядный однобайтовый служебный символ.

Если у вас есть расширение php_mbstring - нет проблем, там есть функция mb_substr, которая корректно обрабатывает юникод. А вот если нету (скажем, на высоконагруженных проектах интерпретатор PHP как правило максимально облегчён - без всяких лишних расширений) то уже сложнее. Однако, выход есть - не обязательно резать по буквам, можно резать по словам. Этот метод я случайно обнаружил в одном из рабочих проектов и просто поразился простоте и эффективности решения такой уже тривиальной задачи. Собственно, сабж:

$arr = explode(' ', $text);
$arr = array_slice($arr, 50);
$text = implode(' ', $arr[0]).'...';
unset($arr);

В результате у нас имеется выборка из 50 слов, которая выглядит куда лучше, чем разрыв слов в неожиданных местах.



Коль хочешь в знаниях прогресс - подпишись на RSS!

16Дек/100

О кэшировании в Web

День добрый, дражайший читатель.

Вообще, я не имею уж очень большого опыта в работе с высоконагруженными системами. Обычно проекты, которые мне доводилось делать, были рассчитаны на посещаемость в 20000 человек в сутки. Ну или около того. Однако, однако... Программисты народ странный. Мы иногда делаем нечто "на будущее". Ну вдруг потребуется. Но вначале немного теории. Как строится высоконагруженная система? Основной её компонент - это балансировщик нагрузки. Фактически он просто обеспечивает обработку запроса пользователя одним из нескольких back-end'ов. Например один балансирощик (и лично мне доводилось слышать, что в его роли может выступать например nginx), раскидывает запросы по нескольким PHP-сборщикам (или бросается смотреть в кэш - нет ли уже того, что требуется). Те, соответственно формируют контент, и отдают его обратно. Это очень упрощённо, прямо скажем. Потому что я всё-таки не администратор веб-серверов, и всех тонкостей не знаю.

Так вот, это я к тому, что кэширование - один из действенных способов снижения нагрузки. Зачем выполнять кучу кода для формирования HTML-контента, если такая работа уже была сделана ранее, и с тех пор ничего не поменялось? Правильно, незачем. Так не логичнее ли сохранить страницу в кэш, и отдавать её каждый раз быстро и без мучений? Логичнее, все так и делают. И вот тут есть выбор - где размещать кэш. Существует много вариантов, но если свести к основным, это либо жёсткий диск, либо оперативная память. Чувствуете разницу? Скорость обращения к жёсткому диску в разы ниже, чем к оперативке, но при этом кэширование на жёстком диске подходит практически для любого хостинга, в том числе и виртуального. Однако важно понимать, что высоконагруженные проекты никогда не размещаются на виртуальном хосте. Его мощностей и возможностей просто не хватит для обработки такого потока данных. Потому для просто посещаемых проектов это минимум VPS. А для проектов с высокой нагрузкой необходимо строить распределённую систему с балансировкой, отдельным сервером для БД, для кэшировщика, для контент-сборщиков и так далее. Это дорого, но как правило ресурс окупает подобные затраты.



Даже последний из недотёп всегда RSS читает взахлёб!

14Дек/102

Внедрение OpenID на PHP

Логотип OpenID. Взято с Википедии.

Логотип OpenID. Взято с Википедии.

Таки здравствуй, дражайший читатель.

Вообще, не люблю я писать о работе (хотя статистика количества записей в рубрике соответствующей и ставит под сомнение данное утверждение). Но тут прямо не мог не написать. Все вы, коллеги-PHP-шники, разумеется слышали про такую адову приблуду, как OpenID. Если вкратце, то оная позволяет авторизовать пользователей на разных сайтах под одной учётной записью. Например у меня есть почтовый ящик Google, и с его помощью я могу быть авторизован на сайтах, поддерживающих такой вид авторизации. Т.е. мне не надо придумывать пароль/логин, для того, чтобы войти на сайт. При этом сам ресурс не узнаёт лишнего, он знает только то, что я - это я (ибо доверенный openid сервер это подтверждает). Так вот, вроде бы идея то, конечно, хорошая... Однако на пути внедрения оной становятся несколько проблем. Первая - отсутствие более или менее подробной информации по протоколу/стандарту на русском языке. Вторая - большой набор библиотек, позволяющих (теоретически) проводить безболезненное внедрение OpenID авторизации у себя на сайте. Третья - это наличие нескольких стандартов openid (хотя само по себе это не проблема). И четвёртая - это разная степень развитости этих библиотек, напрямую вытекающая из третьей. Есть ещё и пятая - библиотеки используют разные способы общения с серверами авторизации, самый распространённый - это curl-запросы, которые априори требуют наличия в установленном на сервере PHP расширения curl или компиляции, с опцией --with-curl. Вообще на нормальных хостингах он должен быть включен, однако... как показывает практика - не везде он есть. В общем, все дальнейшие рассуждения основываются на том, что curl таки есть, либо есть возможность его поставить. Просто найти библиотеку, которая бы его не использовала - на самом деле очень сложно.



Твой сосед в петлю полез? Ну и хуй с ним - читай RSS!

26Дек/090

Водяной знак на PHP+GD

Собственно, совсем недавно была завершена некоторая работа - она была связана с программированием конвейера сборки большого числа изображений из отдельных картинок "конструктора". Для этого, само собой, пришлось накладывать полупрозрачные слои. При теоретических изысканиях данного вопроса - я обнаружил интересную особенность - при запросе "Водяной знак на PHP + GD" в сети нет нормальной, практической информации по этому поводу. Вас сначала погружают в дебри теоретических изысканий, вместо того, чтобы дать самодокументированный код. Я решил пойти иначе. Внизу - функция обеспечивающая наложение водяного знака на изображение. Из недостатков - то, что она работает только с изображениями формата PNG. Впрочем, программисту это исправить не проблема.

function watermark($_source_path, $_watermark_path, $_file='')
{
	/* Проверка - подключена ли библиотека GD - если её нет, вам необходимо либо самому подключить эту библиотеку
	* (В файле php.ini, секция extensions, необходимо прописать либо раскомментировать строку:
	*   extension=php_gd2.dll - в windows. */
	if (!extension_loaded('gd'))
	{
		return false;
	}
	if (!empty($_source_path) && !empty($_watermark_path))
	{
		$i_source    = imagecreatefrompng($_source_path);
		$i_watermark = imagecreatefrompng($_watermark_path);
		$result = imagecreatetruecolor(imagesx($i_source), imagesy($i_source));
		/* Координаты 0,0,0,0 - задают координаты соединения изображений.
		*  Поигравшись с ними можно изменить положение водяного знака (да и исходного изображения)
		*/
		imagecopy($result, $i_source, 0, 0, 0, 0, imagesx($i_source), imagesy($i_source));
		imagecopy($result, $i_watermark, 0, 0, 0, 0, imagesx($i_watermark), imagesy($i_watermark));
		imagedestroy($i_source);
		imagedestroy($i_watermark);
		if (!empty($_file))
		{
			imagepng($result, $_file, 4);
		}
		else
		{
			return $result;
		}
	}
}


Чтобы череп не облез - подпишись на RSS!

Метки записи: Нет комментариев
22Дек/091

Библиотечко для сохранения файлов по 300 штук в папке

Собственно говоря, посидел я тут на досуге, поразмышлял о нелёгкой судьбине веб-программиста. Часто приходится думать не только лишь о том, чтобы пообщаться с заливаемым файлом (ну или генерируемым - какова будет воля начальства либо заказчика), но и о правильном сохранении оного. Поясню, что я имею ввиду.

Как вам известно, просмотр одной папки с содержимым из 40 - 50 ТЫСЯЧ файлов любого формата операция достаточно ресурсоёмкая. В системные причины оного я не вникал, но подозреваю следующее. Перед выдачей файла на запрос, сервер лезет в папку указанную в адресе, и делает что-то вроде ls, ну или dir, что одно и то же. Просмотрев весь список файлов и найдя необходимый он выдаёт его юзеру. Тут впору загнуться и статическому веб-сайту, состоящему из одних html страниц. Так или иначе, решение было найдено многими поколениями программистов. В целевой папке (ну, допустим, uploads) создавать много подпапок, например по-номерам (1,2,3), и сохранять в них по фиксированному количеству файлов. Чаще всего по 300 штук.

Проблема по-большей части состоит в том, что каждый раз приходится сей алгоритм реализовать по-новой. Что совсем некошерно. Я в принципе реализовал его в виде универсального класса. Его достоинства в том, что там только два значимых метода: конструктор и функция save.

Работа тривиальна, создаём экземпляр класса FileSaver, в параметрах __construct() передаем:

1. Адрес родительской папки, к примеру /usr/bla/bla/domain.ru/www/uploads/, 2. максимальное количество файлов в подпапках, 3. создавать ли директорию, если она не существует, и 4. права на создаваемую папку.

Затем - каждый раз, когда нам надо сохранить в эту папку файл, мы вызываем метод save(), параметрами которого являются: 1. путь к перемещаемому файлу, должен содержать имя существующего файла, иначе метод вернёт false.

Второй параметр указывает, надо ли перезаписывать имя файла, либо оставить как есть у оригинала.

Третий параметр указывает на то, как формировать имя файла. При значении false он считает sha1-хэш файла, и именем файла ставит его, + расширение файла, если оно было. Этим мы обеспечиваем 1. уникальность имён, 2. уникальность файлов (если кто-то попробует поместить туда идентичный по содержимому файл, то хэши совпадут, и при условии сохранения в одну и ту же подпапку - ничего не выйдет, файл останется на месте). По умолчанию этот режим отключен, и имя файла формируется из текущего значения времени в unix timestamp + миллисекунды + случайное число из диапазона 1-10 + расширение оригинального файла.

ВНИМАНИЕ! Метод save осуществляет ПЕРЕМЕЩЕНИЕ файла со старого места в новое, если вам оно не надо, найдите в методе save участок (помечен комментарием), и измените там rename на copy. Возможно, в будущих версиях я сделаю более гибкую настройку модуля, но пока так.

Метод Save возвращает полный путь по которому был сохранён файл. Если вам надо иначе - в методе есть участок с комментарием, иллюстрирующим, как это сделать.

Вот, собственно, и всё. По мере наполнения структура директорий будет выглядеть так:

/uploads/

-- /1/

-- /2/

-- /3/

И так далее. По мере заполнения директории с крайнем индексом, создаётся новая, со следующим, и вперёд, с песней... Я сохранял туда 100 000 файлов, и потом благополучно делал обращение. Ничего, апач не загибался. Если попробовать сделать то же самое, когда они лежат в одной папке кучей - можно и не дождаться результата.

В заключение: ссылка на архив с модулем.



Чтобы девушка стонала - подпишись на фид канала!

Метки записи: 1 комментарий
7Ноя/090

Обновлён движок (CMS) сайта.

Ну таки здравствуйте.

Сегодня был обновлён движок для сайта "Шпаргалко", сиречь, этого сайта. Прошу любить и жаловать :) В целом он, как и всё в процессе пуско-наладки, сырой. Зато теперь наконец то сделан не просто набор скриптов, а вполне себе модульная система. Если, скажем, захочется добавить какой-то ещё функционал, кроме блога, то это сделать будет уже значительно проще, чем на старой версии (скажу по секрету, весь двжиок был полностью переписан, равно как и структура БД - она значительно изменилась).

Изменения в пользовательской части, в принципе, минимальны. Разве что теперь сайт (имеется ввиду вёрстка) поддерживает W3C стандарт, и валидатор проходит нормально.

Также напоминаю, что тут есть дохлый форум )) На нём 4 пользователя и 7 постов в данный момент.

Пока, собсна, всё :)



Раз - бес. Два - бес. Три - бес...
Допился до чёртиков. Надо скорее читать RSS!

Метки записи: , Нет комментариев
18Сен/090

Как преобразовать (изменить) кодировку в PHP

Читал тут в сети кучу опусов на тему определения, преобразования, конвертации кодировок в PHP. Нет, оно всё работает, правда я не понимаю, нахер оно надо, если есть расширение iconv ? Описывать как с ним работать я не буду, ибо там всё элементарно.

Сслыка здесь: http://ru.php.net/manual/en/ref.iconv.php



Чтобы Ктулху не воскрес - подпишись на RSS!

30Авг/090

Регулярное выражение для проверки email-адреса

Короче сегодня сидел ебался с поиском RegEx - выражения для проверки корректности введённого мыла. После того как потратил 15 минут на поиск в сети, сказал "а ну его на хуй", и поискал в своих старых исходниках. Нашёл. Нате, может кому пригодится :)

// проверка email на корректность
function valid_email($email)
{
    return eregi("^[a-zA-Z0-9._-]+@[a-z0-9._-]+.[a-z]{2,4}$", $email);
}


Чтобы Ленин не воскрес - Подпишись на RSS

28Июл/090

Расчёт расстояний между двумя точками на поверхности Земли

Встала тут задачка - задан массив точек (с гео. координатами). Есть опорная точка (тоже две координаты). Есть радиус в километрах. Надо посчитать число точек в массиве, которые удовлетворяют условию - т.е. находятся в пределах радиуса.

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

Второй - выяснить, какой шаг по географическим координатам соответствует шагу реальному, допустим, в 10 метров? К примеру это 0.00005. Вычисляем сдвиг, и по нему делаем выборку из БД (обычно всё это там хранится) по условию. Получится, правда не радиус, а квадратик. Но то не беда.

По некоторым причинам решили сделать по-тупому, т.е. получить все записи, а потом по ним пройтись.Целый день я ел себе мозг, пытаясь перевести какую-то хуйню и недоразумение (cos(d)) в нормальное число d в радианах, а затем и в километрах. После долгой и пиздецкой ебли, наконец таки нашёл формулу, которая выдаёт РАБОЧЕЕ значение в километрах. Короче вот кусок кода, отвечающий непосредственно за расчёт:

$dist_km = 111.2 * acos( abs(sin($db_latitude)*sin($_latitude) +
cos($db_latitude)*cos($_latitude)*cos( abs($db_longitude - $_longitude) ) ) );



Если дядя Моня взял у вас взаймы таки три рубля, и не отдаёт - угрожайте ему подпиской на мой RSS канал... Может быть и не поможет. Но точно и не повредит.

Метки записи: , Нет комментариев
23Июл/090

Как отправить POST, GET запросы, а также сымитировать браузер на сайтах с авторизацией…

В общем, недели две назад передо мной встала перспективная задача. Неважно, в чем она заключалась, но смысл в том, что в процессе работы программы (на PHP) она должна была обращаться к разным сайтам, авторизоваться, и прочим образом извращаться с его контентом. Вручную это писать довольно таки долго. Порыскав по сети, нашёл любопытную вещь: snoopy. Это класс на 1200 где-то строчек, который позволяет имитировать веб-браузер. Отправлять формы, получать ответ, авторизоваться, и так далее. Короче говоря это уже выполненная задача на 50%. Если перед вами вдруг встала подобная задача, и поисковик привёл вас на этот сайт - то надеюсь, вы нашли что искали - ссылка на проект выше :) Пролистайте исходники, методы класса интуитивно понятны.



Маленький мальчик куда-то полез... Лучше бы он читал RSS!

Страница 1 из 212