::: PHP.com.ua - учимся вместе. ::: ::: PHP.com.ua - учимся вместе. :::



 
   - Вакансия PHP-программист, Днепропетровск...
  - Проблема с передачей переменной в PHP ск...
  - Как хранить конфигурацию cms'ки?
  - Проблема с сортировкой массива
  - коллизии md5
  - Странный глюк функции date
  - Скроллинг в iframe


Главная
Новости
Статьи
Шпаргалки
Файлы
О проекте
Форум
Футболки


FREEhost.com.ua - купил хостинг 10 у.е. на Begun в подарок.

iName.com.ua - регистрация доменных имен и хороший хостинг.

Библиотека программиста - нужный вам исходник или документация по необходимому для вас языку программирования.

Designclub - Клуб дизайнеров Украины.

Регистрация доменов
Хостинг

 HowtoForge.ORG.UA - Это первый Украинский ресурс развития open source программного обеспечения


Путь: Статьи > Общие вопросы

Общие вопросы

Автор: - KievMan
Дата публикации - 20.03.2006
Просмотров: - 5030

PHP_Application – первое знакомство.


PHP_Application (PApple) - это платформа для разработки событийно-ориентированных приложений на PHP5. Основой любого событийно-ориентированного фрэймворка является модель событий. Остальной код является надстройкой, использующей функциональность модели событий. Модель событий PHP_Application можно считать устоявшейся, определена она в трёх классах: CustomObject - модель событий объекта; Component и Application – модель событий приложения. Подробнее о событиях PHP_Application можно прочитать в статье [url=http://php.com.ua/ru/articles/other/php_events.htm]'Событийно-ориентированные приложения в PHP'[/url].

Цель проекта, как и у всех фрэймворков, снижение себестоимости разработки приложений путём снижения трудозатрат. Для достижения цели используется несколько подходов. Первый, и основной – вынесение большей части приложения в повторно используемый код. Достигается это путём использования событий. Второй – это снижение трудозатрат по повторному использованию кода. Это включает в себя контроль ошибок программиста, расширенные диагностические сообщения, соглашения об именовании и некоторые другие, менее значительные приёмы. Совокупность всех подходов может дать значительный эффект. Время на освоение проекта не включается в эти трудозатраты, так как эти затраты времени одноразовые и зависят от сложности проекта, и уровня подготовки программиста.


[p]С чего начать[/p]
Предполагается, что у вас уже установлен веб-сервер, и настроена поддержка PHP сценариев, поэтому этот этап рассматриваться не будет.

Для начала загрузите проект (если вы этого ещё не сделали) с сайта url=http://sourceforge.net/projects/papple/]http://sourceforge.net/projects/papple//url] , и распакуйте его в корневую директорию вашего веб-сервера. Затем создайте каталог с каким-нибудь именем, например MyProject. В этом каталоге создайте три файла следующего содержания:

[php]
<?
//config.php
define('APPLICATION_ROOT'dirname(__FILE__).'/');
define('SERVER_ROOT'$_SERVER['DOCUMENT_ROOT']);
define('SESSION_NAME''PApple');

$path[] = SERVER_ROOT.'/PHP_Application';

$search implode(PATH_SEPARATOR$path);

ini_set('include_path'$search.ini_get('include_path'));
ini_set('session.name'SESSION_NAME);
?>
[

/php]
[php]
<?
//index.php
require_once('config.php');

session_start();

require_once(
'Application.php');
require_once(
'Project.php');

$Application->init();
$Application->run();
$Application->close();
?>
[

/php]
[php]
<?
//Project.php – оставьте пока пустым.
?>
[

/php]

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

[p]Файл index.php[/p]
В PHP_Application подразумевается, что приложением является вся совокупность страниц сайта. Все обращения к приложению происходят не через отдельные страницы, а только через файл index.php, т.е. структура приложения не привязана к структуре каталогов сайта.

Итак, в первой строчке подключается файл config.php. В нём находятся все настройки, необходимые уже в самом начале работы приложения, поэтому он подключается первый, до любого другого кода.

Далее стартует поддержка сессий PHP, и подключается основной файл Application.php. В этом файле подключается минимально необходимый набор классов для работы приложения, а также создаётся объект класса Application. В приложении может быть только один объект класса Application, и для него зарезервирована переменная $Application.

Следующим подключается файл нашего проекта Project.php. Он пока пустой и дальше мы начнём его заполнять.

В следующих трёх строчках заключается вся работа приложения. Абстрактная модель PHP_Application предполагает, что любое приложение проходит три стадии: инициализация, выполнение и завершение. Именно это и отражено в коде.

Переменная $Application, как было сказано выше, была инициализирована в файле Application.php, и содержит объект класса Application.

В методе Application::init() посылается широковещательное событие приложения onInit, в ответ на которое каждый объект приложения проходит инициализацию.

В методе Application::run() происходит обработка очереди событий приложения, т.е. события, стоящие в очереди, распространяется по иерархии приложения для обработки каким-нибудь объектом. Так происходит до тех пор, пока очередь не окажется пустой. Для того чтобы очередь не оказалась пустой в самом начале работы приложения, нужно чтобы какой-нибудь объект, во время инициализации, поместил в очередь событие. Естественно, в приложении должен оказаться объект, который способен обработать это событие. Таким образом, событие за событием, происходит вся работа приложения. Т.е. функциональность приложения полностью зависит от объектов, входящих в приложение и потока событий.

После того как все события были обработаны, метод Application::run() завершает работу и вызывается метод Application::close(). Этот метод посылает широковещательное событие onClose, в ответ на которое все объекты приложения выполняют необходимые действия по завершению работы.

Так как в нашем случае в приложение не было добавлено ни одного объекта, приложение просто завершило работу, и мы ничего не увидели кроме пустой страницы.


[p]Файл config.php[/p]
В этом файле находятся настройки необходимые в самом начале работы. Необходимой для PHP_Application является только первая строчка с объявлением константы APPLICATION_ROOT. Эта константа используется всеми объектами, которые осуществляют доступ к файловой системе. Все пути для таких объектов должны задаваться относительно этой константы. Все остальные строчки вы можете менять по своему усмотрению и добавлять новые.

Также, именно в config.php вы можете переопределять некоторые константы объявленные в файле system/Constants.php как
[php]
<?
if (!defined(constant_name)) {
    
define(constant_nameconstant_value);
}
?>
[

/php]

[p]Файл Project.php[/p]
Это основной файл нашего проекта, в котором будут подключаться все необходимые для приложения библиотеки, файлы страниц, обработчиков событий и т.д.

Для начала добавьте следующие строчки:
[php]
<?
print '<pre>';
$_PApple_debug true;
?>
[

/php]
и снова наберите в браузере адрес http://myserver/MyProject/. На странице должны появится следующие строки:
[code]
Application::pushEvent(onInit sender: Application, not clear, preprocess, broadcasting, synchronous)
Application::fireEvent(onInit, )
Application::pushEvent(onClose sender: Application, not clear, preprocess, broadcasting, synchronous)
Application::fireEvent(onClose, )
[/code]
Это диагностические сообщения, отражающие ход работы приложения. Из первой строки видно, что в приложение было помещено событие с именем onInit. Отправителем этого события является сам объект Application (помните, в методе Application::init()). Далее перечисляются свойства этого события: не очищенное, ещё не обработанное, широковещательное, синхронное.

Нужно отметить, что для всех типов событий приложения, а также для событий объектов используется один и тот же объект Event. Поэтому для разных событий актуальны разные свойства события. Например, свойства широковещательных событий всегда будут not clear и preprocess, так как эти события предназначены для обработки несколькими объектами, и распространяются только вниз по иерархии приложения (подробности будут в отдельной статье).

Во второй строке видно, что произошло событие onInit объекта Application, не путать с событием приложения. Обратите внимание, что событие происходит после того, как успешно прошла инициализация всего приложения.

С последними двумя сообщениями вы уже можете разобраться сами.

Продолжим работу над нашим проектом. Но для начала немного теории. Работа всякого приложения связана с определённой последовательностью действий. Например, типичная последовательность действий любого веб-приложения: обработка запроса –> подготовка страницы -> отображение результата. Как видите, эта последовательность действий относится к самому верхнему уровню абстракции – уровню приложения. Каждый из этапов (обработка, подготовка и т.д.) состоит из низкоуровневых операций. Те, в свою очередь, из операций ещё более низкого уровня, и так до вызовов функций PHP. Каждый уровень операций реализуется по разному: какие-то являются методами объектов, какие-то являются взаимодействием объектов разных уровней.

В PHP_Application самый верхний уровень операций реализуется с помощью событий приложения. Это означает, что каждый этап (обработка, подготовка и т.д.) начинается и заканчивается событием приложения. В ответ на эти события, объекты приложения, отвечающие за их обработку, выполняют низкоуровневые операции.

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

Теперь добавьте в Project.php следующие строчки:
[php]
<?
require_once('system/RequestRedirection.php');
require_once(
'system/Controller.php');
require_once(
'hcl/hcl.php');
?>
[

/php]
Это те самые объекты, которые понадобятся нам для веб-приложения. RequestRedirection, это объект, отвечающий за перенаправление запросов к приложению, и ответов приложения между источниками запросов.

Дело в том, что PHP_Application может работать с несколькими источниками. Первый – это веб-сервер, например Apache, который передаёт PHP скрипту массив $_REQUEST с данными запроса. Второй – это встроенный HTTPServer, о котором будет рассказано в отдельной статье. Так как PHP скрипт может запускаться из командной строки, то третьим источником может стать командная строка, нужно только научить RequestRedirection с ней работать.

Controller, это объект, который инкапсулирует взаимодействие объектов, т.е. контролирует последовательность действий самого высокого уровня (обработка, подготовка и т.д.). Т.е. объекты, участвующие в эти этапах, взаимодействуют друг с другом не напрямую, а посредством объекта Controller. Если понадобиться реализовать на PHP_Application другую последовательность действий, то нужно будет написать другой контроллер.

Далее подключается библиотека HTML элементов: Select, Edit, Button, Checkbox и т.д. Нужно отметить, что приложение может использовать два способа для генерации страницы. Первый – это простенький движок шаблонов, задача которого только разместить объекты приложения в HTML шаблоне. Никакой логики представления в нём нет. Второй – это PHP-ый XSLT процессор. Приложение может легко переключаться на тот или другой способ, подключая необходимую библиотеку элементов: HCL (HTML Component Library) для движка шаблонов, XCL (XML Component Library) для XSLT процессора. Что бы перейти, достаточно поменять строчку 'hcl/hcl.php' на 'xcl/xcl.php'. Названия классов в обеих библиотеках совпадают, поэтому никаких изменений больше делать не нужно (кроме самих шаблонов). Таким образом, даже уже готовое приложение легко перевести на другой способ генерации страницы.

Наконец то мы готовы для непосредственного создания приложения. Создайте в каталоге файл Default.html и оставьте его пока пустым. Закомментируйте строки
[php]
<?
//print '<pre>';
//$_PApple_debug = true;
?>
[

/php]
Затем добавьте в Project.php следующие строки:
[php]
<?
try {

    new 
RequestRedirection(Application);
    new 
Controller(Application);
    new 
Output(Application);
    new 
Window(Application'Window');
    
    new 
Page(Window'pgDefault',
        array(
            
PCaption    => 'PApple example',
            
PStyle      => 'margin: 2%; margin-left: 20%; margin-right: 20%;',
            
PTemplate   => 'Default.html',
            
PVisible    => true
        
)
    );
    
} catch (
Exception $e) {
    
$Application->handleException($e);
}
?>
[

/php]
И снова откройте в браузере адрес http://myserver/MyProject/. Если страница осталась пустой, значит всё нормально. Теперь снова рассмотрим добавленный код.

Во-первых, весь код заключён в конструкцию try…catch, чтобы перехватывать возможные ошибки. Обработка ошибок производится в объекте Application. При необходимости обработчик ошибок может быть переназначен (об этом в отдельной статье).

Далее создаются уже известные нам объекты RequestRedirection и Controller. Затем добавляются объекты Output и Window. На них остановимся подробнее.

Существует две реализации класса Output для двух библиотек соответственно (HCL и XCL). Для библиотеки HCL этот объект выполняет роль движка шаблонов. В библиотеке XCL он просто использует XSLT процессор для генерации страницы. Необходимая версия класса подключается вместе с остальными элементами в файлах hcl.php и xcl.php соответственно.

Класс Window тоже существует в двух реализациях. Объект этого класса на данном этапе не имеет никаких методов и выполняет исключительно логическую функцию. Как следует из названия класса, он представляет собой окно приложения. Все объекты, которые отображаются в шаблоне, должны включаться в иерархию приложения как дочерние, по отношению к объекту Window.

Вы наверно уже заметили, что вновь созданные объекты не присваиваются никакой переменной. Это делается в конструкторе самого объекта. Имя объекта указывается во втором параметре конструктора. Это имя сохраняется в самом объекте, а также используется для создания глобальной переменной с таким же именем. Если имя объекта не указывается, то используется имя класса и свободный индекс. Например, для объекта RequestRedirection будет назначено имя RequestRedirection1 и создана глобальная переменная $RequestRedirection1. Такое решение позволяет отчасти контролировать использование имён глобальных переменных, и немного уменьшить трудозатраты по использованию фрэймворка.

На примере объекта Page мы рассмотрим все остальные особенности кода. Конструктор большинства объектов PHP_Application является унифицированным, что облегчает его запоминание. В первом параметре в конструктор передаётся имя объекта или переменная, содержащая объект, к которому будет подключен создаваемый объект. Например, строчка [php]
<? new Page(Window'pgDefault'); ?>[

/php] означает, что объект Page будет помещён в иерархию приложения как дочерний по отношению к объекту Window. Для ссылки на объект Window, используется его имя. Строчка [php]
<? new Page($Window'pgDefault'); ?>[

/php] идентична предыдущей, только для ссылки на объект Window используется переменная. Обратите, также, внимание, что при передаче объекта по имени, кавычки можно не использовать.

Таким способом формируется иерархия объектов приложения. Т.е., нынешний код из Project.php сформирует следующую иерархию:
[php]
Application--
            |-RequestRedirection
            |-Controller
            |-Output
            |-Window--
                     |-Page
[

/php]

Во втором, необязательном, параметре в конструктор передаётся имя объекта. Как было сказано выше, это имя используется, также, для глобальной переменной, содержащей объект.

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

Есть три способа установки начальных значений свойств объекта. Первый способ – задать их в виде массива в третьем параметре конструктора. Массив должен быть вида [php]
<? array(prop_name => prop_value?>[

/php]. Для каждого публичного свойства объектов определена константа с именем этого свойства и добавлением заглавной буквы P (property). Например, для свойства Page::caption определена константа PCaption = caption. Использование констант позволяет сделать код нагляднее, а также использовать такие возможности IDE как 'Code Completion List'. Это ещё одна мелочь, направленная на уменьшение трудозатрат по работе с фрэймворком. Конечно же, вы всегда можете использовать непосредственно имя свойства, например, следующие строчки идентичны:
[php]
<?
array(
    
PCaption    => 'PApple example'
)
?>
[

/php]
[php]
<?
array(
    
'caption'   => 'PApple example'
)
?>
[

/php]
Второй способ – использование метода setProperties(). Этот метод принимает такой же массив, как и конструктор. Естественно, воспользоваться этим методом можно после создания объекта.

Третий способ – это непосредственное назначение свойств объекта. Например, свойства установленные для страницы в нашем примере можно было бы установить так:
[php]
<?
new Page(Window'pgDefault');
$pgDefault->caption  'PApple example';
$pgDefault->style    'margin: 2%; margin-left: 20%; margin-right: 20%;';
$pgDefault->template 'Default.html';
$pgDefault->visible  true;
?>
[

/php]

Продолжим создавать наше приложение. Добавьте в Project.php следующие строки:
[php]
<?
try {

    
// […]

    
new Label(pgDefault'lbLabel');

    new 
Edit(pgDefault'edEdit',
        array(
            
PStyle  => 'width: 200;',
            
PValue  => 'Enter your text here',
            
PHint   => 'Example of "Edit" events'
        
)
    );
    
    new 
Button(pgDefault'btSubmit',
        array(
            
PCaption    => 'Submit',
            
PHint       => 'Press for submit'
        
)
    );

} catch (
Exception $e) {
    
$Application->handleException($e);
}
?>
[

/php]
так, чтобы они находились внутри уже существующей конструкции try…catch. А в файл Default.html добавьте такой код:
[php]
<html>
  <head>
    <title>{pgDefault/@caption}</title>
    <style>div {margin: 5px}</style>
  </head>
  <body {pgDefault/@attributes}>
    <fieldset>
      <legend>PHP_Application example</legend>
      <form action="index.php">
        <div> {lbLabel} </div>
        <div> {edEdit} </div>
        <div> {btSubmit} </div>
      </form>
    </fieldset>
  </body>
</html>
[

/php]
Теперь откройте в браузере адрес http://myserver/MyProject/. Вы должны увидеть поле для ввода текста и кнопку. Осталось добавить код, который будет обрабатывать связанные с ними события. Для элемента Edit определено три события: onInput, onChange и onEmpty. Напишем для каждого события свой обработчик. После добавления нового кода итоговый Project.php будет выглядеть так:
[php]
<?
//print '<pre>';
//$_PApple_debug = true;

require_once('system/RequestRedirection.php');
require_once(
'system/Controller.php');
require_once(
'hcl/hcl.php');

function 
edEditOnInput(Event $event)
{
    global 
$lbLabel;
    if (
'Enter your text here' == $event->sender->value) {
        
$lbLabel->caption 'Значение поля не изменилось.';
    }
}

function 
edEditOnChange(Event $event)
{
    global 
$lbLabel;
    
$lbLabel->caption 'Вы именили значение поля.';
}

function 
edEditOnEmpty(Event $event)
{
    global 
$lbLabel;
    
$lbLabel->caption 'Вы убрали значение поля.';
}

try {

    new 
RequestRedirection(Application);
    new 
Controller(Application);
    new 
Output(Application);
    new 
Window(Application'Window');
    
    new 
Page(Window'pgDefault',
        array(
            
PCaption    => 'PApple example',
            
PStyle      => 'margin: 2%; margin-left: 20%; margin-right: 20%;',
            
PTemplate   => 'Default.html',
            
PVisible    => true
        
)
    );
    
    new 
Label(pgDefault'lbLabel');
    
    new 
Edit(pgDefault'edEdit',
        array(
            
PStyle  => 'width: 200;',
            
PValue  => 'Enter your text here',
            
PHint   => 'Example of "Edit" events'
        
)
    );
    
    new 
Button(pgDefault'btSubmit',
        array(
            
PCaption    => 'Submit',
            
PHint       => 'Press for submit'
        
)
    );
    
    
$edEdit->addEventHandler('edEditOnInput'onInput);
    
$edEdit->addEventHandler('edEditOnChange'onChange);
    
$edEdit->addEventHandler('edEditOnEmpty'onEmpty);
    
} catch (
Exception $e) {
    
$Application->handleException($e);
}
?>
[

/php]
Итак, что мы сделали. Мы написали функции edEditOnInput(), edEditOnChange(), edEditOnEmpty() и указали их в качестве обработчиков событий объекта Edit. Теперь поработайте с получившейся формой, и посмотрите как она себя ведёт.

На этом первое знакомство с PHP_Application можно считать законченным. В проекте прилагаются более сложные примеры, с которыми вы уже можете разобраться самостоятельно.



Обсудить в ФОРУМе - комментариев (0)


Путь: Статьи > Общие вопросы

Если вы заметили орфографическую, стилистическую или другую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Контакты Design by webFaction Ukrainian PHP Group 2004-2005