Pull to refresh

Visual PHP для Windows

Reading time 10 min
Views 60K
На сегодняшний день язык PHP широко распространён, он прост в освоении и понимании, и наверное поэтому он так популярен у начинающих программистов. Без знаний PHP не поправить блок голосования на сайте, не отредактировать PHP шаблон, не вставить рекламный баннер. Многие идут дальше и изучают язык более углубленно, ведь это не только интересно, но и приносит стабильный доход, благо разнообразных предложений для PHP программистов всегда в избытке.

Но что делать, если хочется чего-то большего? Если надоело писать однотипные классы для онлайн-казино, ковыряться в Joomla/Drupal/PHPBB очередного заказчика?

Думаю, что многих посещала мысль начать писать Windows программы на любимом языке PHP, но дальше поиска по интернету и поверхностного изучения таких библиотек как PHP-QT и PHP-GTK дело, как правило, не доходит. Почему? Все ответы схожи — запутанно, сложно, ненаглядно, непонятно и т.д. Но сегодня уже есть качественно новая и перспективная среда для визуальной разработки программ на PHP под Windows и имя ей — PHP Devel Studio (сокр. DevelStudio).

Что же представляет собой DevelStudio?


image

Это удобная и понятная визуальная среда программирования, которая позволяет создавать полноценные программы на языке PHP с поддержкой GUI. Теперь, для создания программ под Windows достаточно знать самый популярный язык программирования — PHP.

В этой статье я не буду описывать кнопочки и рюшечки этой среды разработки, не буду говорить о неких абстрактных возможностях и не буду устраивать детский сад с написанием «Hello world».
Мы поверхностно рассмотрим процесс написания полноценной программы под Windows и остановим своё внимание только на оригинальных и нестандартных решениях, которые определённо будут интересны всем.

Предыстория


Итак, в один прекрасный вечер я уже в который раз снова посетил сайт проекта «Denwer» с целью проверить, не вышло ли там обновление. К моему разочарованию ничего нового там не оказалось, по-прежнему я обнаружил лишь новую ругань в адрес разработчиков с обвинениями в выклянчивании пожертвований и абсолютном бездействии.

Меня не покидало желание отказаться от Denwer и написать свою, действителньо удобную и полезную программу для управления локальным веб-сервером. После недолгих поисков моё внимание привлекла среда разработки «DevelStudio». Она оказалось предельно удобной, понятной и самое удивительное — она открыла мне дорогу в мир Windows программ. Поразмыслив над логикой управления веб-сервером я приступил к написанию «Open Server».

Знакомство с DevelStudio


Первые несколько дней были потрачены на изучение среды и написание простейших программ. Нашлось несколько багов в работе самой среды разработки, они будут описаны в конце статьи. Так же были установлены два полезных дополнения (библиотека примеров + каталог классов и функций) и один неофициальный патч, дающий возможность сжатия программы UPX упаковщиком в момент компиляции.

Следует отметить, что у DevelStudio достаточное хорошее комьюнити, поэтому всегда есть возможность задать вопрос или получить совет у опытных пользователей среды, вплоть до самого разработчика.

DevelStudio — это этакая смесь из Delphi и PHP, щедро приправленная компонентами этих самых Delphi и PHP. Чего стоит один только Alphaskin, который я использовал самым непосредственным образом при написании программы. Но обо всём по порядку…

Написание программы


При создании проекта мы получаем пустую форму. Она является основной и именно в этой форме я не создавал никаких элементов управления, в ней мною были добавлены управляющие функции, а сама форма была сделана скрытой. Чтобы при запуске вашей программы не отображалось никаких форм в свойствах проекта нужно установить режим «Тихий». Затем были созданы следующие формы: Настройки, Просмотр логов, О программе, Ошибка и Первый запуск. За короткий срок во все формы были добавлены необходимые управляющие элементы, поля ввода, иконки и прочее. Всё это было сделано без единой строчки кода. Вот она мощь визуальной среды!

На следующей иллюстрации мы видим форму просмотра логов, а так же специальные вставки-шаблоны, они используются для организации мультиязычности. Замечу лишь, что для смены языка потребуется перезапуск программы.

image

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

1. Стартовая функция (выполняется при загрузке программы)

Вот так получилось реализовать проверку на то, не была ли уже запущена программа:

$output = shell_exec('tasklist /nh /fi "Imagename eq Open Server.exe"'); // получение списка процессов
$ret = iconv('CP866','CP1251',$output);
if (substr_count($ret,'Open Server.exe')>1) {
    c('trayIcon1')->enabled = false; // отключаем трей-меню
    LoadForm(c('message'), LD_NONE); // загружаем форму с сообщением об ошибке
}else{ ... }

Вот так, например, добавляются элементы в выпадающее меню:

$mm = new TMenuItem;
$mm->caption = t("menu_9"); // t - это функция мультиязычности, здесь будет написано Выход
$mm->loadPicture("server/system/data/exit.bmp"); // подгружаем иконку
$mm->onClick = exitfunc; // функция выполняющая остановку сервера / выход из программы

А вот так удалось решить задачу с определением битности Windows и проверке на наличие установленных компонентов Microsoft Redistributable C++. Битый час я не мог понять, почему в 32 и 64 битных версиях Windows ключи реестра имеют разное значение, а то они и вовсе не там, где предполагалось.

if(getenv("PROCESSOR_ARCHITEW6432")=="AMD64" || getenv("PROCESSOR_ARCHITECTURE")=="AMD64"){
$output = shell_exec("REG QUERY HKLM\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"); // запрос в реестр
$ret = iconv('CP866','CP1251',$output);
if (substr_count($ret,'{86CE85E6-DBAC-3FFD-B977-E4B79F83C909}')<1 || substr_count($ret,'{a0fe116e-9a8a-466f-aee0-625cb7c207e3}')<1) {
    c('trayIcon1')->enabled = false;
    LoadForm(c('proc'), LD_NONE); // загрузка формы с предложением установить недостающие компоненты
}
}else{
$output = shell_exec("REG QUERY HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
$ret = iconv('CP866','CP1251',$output);
if (substr_count($ret,'{86CE85E6-DBAC-3FFD-B977-E4B79F83C909}')<1 || substr_count($ret,'{a0fe116e-9a8a-466f-aee0-625cb7c207e3}')<1 ) {
    c('trayIcon1')->enabled = false;
    LoadForm(c('proc'), LD_NONE); // загрузка формы с предложением установить недостающие компоненты
}
}

2. Форма просмотра логов

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

image

Вот как изначально я обрабатывал переключение табов и установку курсора в конец лога:

$WshShell = new COM("WScript.Shell");
if (c("pages1")->pageIndex == 0)     c("memo1")->setFocus(); // установка фокуса на текстовое поле
elseif (c("pages1")->pageIndex == 1) c("memo2")->setFocus();
...
elseif (c("pages1")->pageIndex == 6) c("memo7")->setFocus();
$WshShell->SendKeys("^{END}"); // нажатие клавиши END чтобы попасть в конец
$WshShell->SendKeys("{HOME}"); // Нажатие клавиши HOME чтобы вернуться в начало последней строки

Как мы видим, были использованы компоненты COM, но по совету одного доброго человека этот код был превращён в следующий:

$ppindex = c("logs->pages1")->pageIndex;
$obmemo = c("logs->memo".($ppindex+1)); // определяем активный таб
$cnlines = $obmemo->items->lines; // получаем содержимое
$seltn  = strlen( $obmemo->text ) - strlen($cnlines[ count($cnlines)-1 ]); // определение последней строки
$obmemo->setFocus();
$obmemo->selStart = $seltn; // установка курсора в начало строки
$obmemo->selLength = 0; // установка длины выделения

3. Форма настроек

image

Чтение и запись настроек в DevelStudio происходят достаточно просто и очевидно:

ini :: open("server/system/config.ini"); // открываем файл настроек
ini :: read("main", "lang", $lang); // читаем параметр
ini :: write("main", "lang", c("settings->combobox1")->inText); // сохраняем параметр

Но кое с чем пришлось повозиться — это получение списка свободных дисков в системе.
Вот что сперва получилось, это довольно интересно:

$fso = new COM("Scripting.FileSystemObject");
$disks = array();
foreach($fso->Drives as $disk) $disks[] = $disk->DriveLetter; // получаем массив дисков

$diskarr = array("D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
$diskar = array();
foreach($diskarr as $fffile) if($fffile == $os_vdisk){$diskar[] = $fffile;}else {if(!in_array($fffile,$disks)) $diskar[] = $fffile;} // если диск существует, то исключаем его из списка
c("combobox2")->text = implode("\n",$diskar);
$icounter = 0;
foreach($diskar as $fffile) {if($fffile == $os_vdisk) c("combobox2")->itemIndex = $icounter; $icounter++;}

Здесь снова был использован компонент COM и опять же не обошлось без доброго совета со стороны.
Я подключил DLL библиотеку phposinfo.dll и итоговый код получился таким:

$dliters = array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
$diskar = array();
$icounter = 0;
$icount = true;
foreach ($dliters as $dliters) // перебираем массив дисков
{
  if ($dliters == $os_vdisk)
  {
    $diskar[] = $dliters;
    $icount = false;
  }
  else
  {
    if (osinfo_drivetype($dliters . ":") == 1)  // функция из phposinfo.dll для получения кода состояния диска
    {
      $diskar[] = $dliters; // если ответ единица добавляем букву диска в список свободных
      if ($icount)
        $icounter++;
    }
  }
}
c("combobox2")->text = implode("\n", $diskar); // добавляем массив дисков в выпадающий список
c("combobox2")->itemIndex = $icounter; // указываем выбранный пункт списка

4. Функция запуска локального сервера

Это самая объёмная функция, нужно было сделать перезапись конфигурации модулей по шаблонам, запустить виртуальный диск, запустить Apache, Mysql, FTP сервер и написать ещё много всего интересного, однако и тут DevelStudio и форум поддержки среды позволили мне реализовать всё задуманное. Далее несколько интересных моментов…

Были проблемы с определением системного диска и получения пути до HOSTS файла, в итоге всё оказалось легко и просто:

$hostsfile = winLocalPath(CSIDL_WINDOWS) . "/System32/drivers/etc/hosts";

Запускаем виртуальный диск (здесь используется системная утилита subst.exe, а так же получение локальной директории и пути до системной папки Windows):

Shell_Execute(0, 'open', 'subst.exe', $os_vdisk . ': "' . substr(realpath('./'), 0, strlen(realpath('./')) - 1) . '"', strtr(winLocalPath(CSIDL_WINDOWS).'/System32/','/','\\'), 0);

Запуск Apache (функция Shell_Execute позволяет запустить стороннюю программу в фоне и без ожидания ответа):

Shell_Execute(0, 'open', 'os-httpd.exe', '', $realospath . '\\server\\http\\' . $os_httpdriver . '\\bin\\', $os_window);

Хотелось бы особо отметить, что один из багов DevelStudio — зависания при использовании фоновых процессов в Windows XP. Из-за этого пришлось сделать все процессы не фоновыми и, как следствие, отключать трей-меню на моменты запуска/остановки сервера. Если этого не сделать может показаться что программа зависла, ибо в моменты выполнения real-time процессов элементы управления ни на что не реагируют.

Для создания красивого и одинаково выглядящего во всех версиях Windows трей-меню был использован компонент Skin, а так же один из скинов AlphaSkin, который был мною предварительно отредактирован.

image

После компиляции на выходе у нас получается обычный исполняемый EXE файл, т.е. собственно сама наша программа. PHP код содержится там в бинарном скомпилированном виде, его дешифровка невозможна, что в принципе позволяет уже сейчас писать платный коммерческий софт. Впрочем преобразование PHP кода в байт-код (используется расширение BCompiler) можно отключить в настройках DevelStudio.

Как видите, с помощью PHP и DevelStudio мне удалось реализовать все поставленные перед собой задачи. Не обошлось без вызова системных утилит и встроенных функций среды разработки. Получилась полноценная Windows программа написанная на языке PHP, точнее даже комплекс программ для организации веб-сервера на локальном компьютере, сейчас проект Open Server живёт и успешно развивается.

Настоящее и будущее DevelStudio


Сейчас DevelStudio базируется на движке PHP 5-ой версии, однако автор ведёт усиленную работу над созданием особой ветки улучшенного PHP — так называемого движка Orion, который будет использоваться в DevelStudio уже со следующей версии. С одной стороны это пугает тем, что больше никаких обновлений от оригинального PHP в самой среде не появиться, кроме того что уже есть в той версии PHP, которая выбрана для разработки Orion. С другой стороны хочется надеяться, что движок Orion преподнесёт нам не мало новых вкусностей, а обещают там очень многое:

image

Отечественные разработчики Devel Studio, сообщают, что их новая среда разработки уже скоро начнёт работать с собственным скриптовым языком программирования Orion, синтаксис которого будет сочетать популярный PHP + новые конструкции языка.
Также сообщается то, что для Devel Studio почти готов абстрактный игровой движок, который основывается на ZenGL и в него будет подключен Orion. GameAbstract Framework — открытый игровой фреймворк быстрой и удобной разработки 2D-игр на Pascal (Delphi/FreePascal), Orion и на прочих ЯП. Абстракция позволит разработчикам заниматься именно логикой игры, взяв на себя всю остальную рутину.
GameAbstract позволит создавать игры на популярные платформы: Windows, Linux, MacOS (а в будущем и iPhone/iPad). Разработчик будет волен выбрать графический интерфейс: OpenGL, DirectX или OpenGL ES для мобильных систем. Физика будет реализована на основе технологии Chipmunk.

По материалам сайта gcup.ru от 2011-05-23


Заключение


В целом DevelStudio оставила после себя хорошее впечатление, далее мои скромные выводы.

Баги:
— зависание php программы при использовании фоновых процессов в WinXP;
— фоновые процессы не убиваются после отработки (занимают память);
— изменение размеров не вручную, а стрелками больше/меньше приводит к краху;
— нельзя использовать режим отладки и вывод ошибок, иначе изменения не сохраняются;
— без патча не работает упаковщик UPX;

Минусы:
— наличие некоторых багов;
— программы получаются довольно объёмные, но при использовании UPX разница не так велика;
— больший объём занимаемой оперативной памяти, чем аналог на Delphi или С++;
— крайне плохая официальная документация, скудная и устаревшая;

Плюсы:
— простота в освоении и удобство разработки;
— хорошее комьюнити;
— широкие возможности по использованию сторонних библиотек;
— высокая скорость разработки программ;
— наслаждение от написания Windows программ на языке PHP ;-)

На мой взгяд, визуальная среда разработки DevelStudio — это очередной шаг к размытию границ между выбором языка разработки программ под Windows. Пишите полезные программы, развивайтесь и не бойтесь экспериментировать!

Полезные ссылки:
Среда разработки PHP Devel Studio
Локальный веб-сервер Open Server

UP: Откуда в Вас столько ненависти? Это всего лишь очередной способ использования языка PHP. Довольно интересная среда разработки, хотя бы в плане саморазвития. Никто не говорит что нужно бросать всё и садиться писать Windows программы на PHP.

Просто задайте себе вопрос — если бы вы узнали, что ваша машина может не только ездить, но и летать, разве вам это было бы не интересно? Ах да, ведь для полётов есть самолеты, не так ли...
Tags:
Hubs:
+75
Comments 106
Comments Comments 106

Articles