OpenBiz Manual

This is the OpenBiz Manual.

Cubi Development Guide

Cubi Development Guide is on google docs. You are welcome to drop comments on all Cubi topics.

Openbiz Cubi Experience Slides (PPT version)

Openbiz 2.4 Manual

Openbiz 2.4 Manual

  1. Openbiz 2.4 Overview

  2. Openbiz Architecture Overview

  3. Openbiz Configuration Guide

  4. Openbiz Development Guide

  5. Openbiz Design Tool Guide (AppBuilder)

  6. Glossary

  7. Openbiz Metadata DTD

Openbiz 2.4 API document

Thanks for the great work done by Mr Ton (Agus Suhartono),

2.4 API document is published with coding standard document.

 

Openbiz 2.3 Guide

Openbiz 2.3 Overview

Openbiz 2.3 Installation

Openbiz 2.3 New Features


This document introduces the new enhanced features of Openbiz 2.3 upon version 2.2. Openbiz 2.2 manual still apply on version 2.3.

Openbiz 2.3 Installation

Download and Install Openbiz 2.3

Openbiz 2.3 source is available at sourceforge openbiz project site. Optional downloads. Third party libraries are included under openbiz/bin/others. User are free to download latest releases of Zend Framework, Smarty engine.

Run demo applications

User Openbiz web installer to install demo application and trac application. 

To install demo application, launch http://server_path/openbiz_install_path/baseapp/index.php. Follow the install wizard.

To install trac application, launch http://server_path/openbiz_install_path/baseapp/index_trac.php. Follow the install wizard.

Upgrade from 2.2.2

Openbiz 2.3 can work with 2.2.2 metadata files. If you have customer classes on BizForm or BizDataObj, you need to make code change on BizDataObj query. Please refer to the Openbiz 2.3 sample code section.

Openbiz 2.3 New Features

New source tree structure

In openbiz bin directory, 3 new directories are created to store data, presentation and utility classes.

Openbiz demoapp is renamed to baseapp to indicate it is not a separate application out of openbiz package. 2 new directories are added - files and modules. Files directory is to store runtime generated files. Modules is a logic location to store source, metadata and templates files of modules.

Where to create a new module? In Openbiz 2.2 and earlier release, users need to put metadata, php, templates souces under app/metadata/my_module/, app/bin/my_module/ and app/templates directories. In 2.3, users can put all files under the app/module/my_module/. Openbiz 2.3 still works with 2.2 structure to make upgrading easy. 

Comparison of module in 2.2 and 2.3 openbiz applications:

Openbiz 2.2 application Openbiz 2.3 application
app/
---bin/
------my_module/
   (php files)
---medata/
------my_module/
   (metadata files)
---templates
       (tempalte files)
app/
---modules
------my_module/
     (php and metadata files)
----------templates/
   (template files) 

Openbiz 2.3 core and baseapp structure:

Openbiz core library
openbiz_root/ 
---bin/        
(openbiz core php source)
------data/       
(data layer classes)
----------private/     
(data layer non-public classes)
------service/     
(openbiz core service classes)
------ui/         
(presentation layer classes)
----------private/     
(presentation layer non-public classes)
------util/       
(utility helper classes)
---languages/   
(languages files)
---medata/     
(openbiz metadata files)
------service/     
(service package)
---others/      (third party libraries)
------phpmailer/   
(phpmailer lib)
------Smarty/     
(smarty package)
------zendfrwk/    (Zend Framework)
Openbiz base application
baseapp/     (baseapp web pages)
---bin/         (baseapp php source)
------shared/      
(baseapp shared library)
------service/     
(baseapp service library)
---css/        
(baseapp style sheets)
---files/       
(baseapp files)
------cache/
       (cache files)
----------data/      
(data cache files)
----------metadata/  
(metadata compiled files)
------sec_upload/ 
(secured uploaded files)
------tmpfiles/   
(temporary files)
------upload/     
(public
accessed  uploaded files)
---js/
          (baseapp javascript files)
---pages/       (baseapp HTML files)
---images/     
(baseapp images)
---log/        
(baseapp logs)
---medata/     
(baseapp metadata files)
------shared/      
(baseapp shared package)
------service/     
(baseapp service package)
---modules     
(baseapp modules files)
------demo/
        (demo module)
----------templates/
   (template files of demo module) 
------trac/
        (trac module)
----------tempaltes/
   (template files of trac module)
---session     
(baseapp session files)
---templates    (baseapp smarty templates files)
------cpl          (baseapp smarty compiled templates)
------cfg          (baseapp smarty configuration files)

Data layer refactor

BizDataObj becomes 3 classes:

Data object query API changes:

Openbiz 2.2 DataObj Openbiz 2.3 DataObj
RunSearch(&$resultRecords) $resultRecords = Fetch()
FetchRecords($searchRule, &$resultRecord, $recNum=-1, $pageNum=-1, $clearSearchRule=true, $noAssociation=false)

Recommend using DirectFetch($searchRule="", $count=-1, $offset=0); to replace FetchRecords

Still has the same FetchRecords

$pdo_statement = Query() $pdo_statement = Find()
$num_pages = GetTotalPageCount() $num_records = Count()

Openbiz 2.3 sample code of query

/* Fetches SQL result rows as a sequential array according the query rules set before.
  * sample code: 
 */

$do->ResetRules();
$do->SetSearchRule($search_rule1);
$do->SetSearchRule($search_rule2);
$do->SetSortRule($sort_rule);
$do->SetOtherRule($groupby);
$total = $do->Count();
$do->SetLimit($count, $offset=0);
$recordSet = $do->Fetch();

/* Fetches SQL result rows as a sequential array without using query rules set before.
  * sample code:
 */
// fetch all record with firstname starting with Mike
$do->DirectFetch("[FirstName] LIKE 'Mike%'");
// fetch first 10 records with firstname starting with Mike
$do->DirectFetch("[FirstName] LIKE 'Mike%'", 10);
// fetch 20th-30th records with firstname starting with Mike
$do->DirectFetch("[FirstName] LIKE 'Mike%'", 10, 20);

/* Do the search query and return results set as PDOStatement
  * sample code:
 
 */
$do->ResetRules();
$do->SetSearchRule($search_rule1);
$do->SetSearchRule($search_rule2);
$do->SetSortRule($sort_rule);
$do->SetOtherRule($groupby);
$total = $do->Count();
$do->SetLimit($count, $offset=0);
$resultSet = $do->Find();
$do->GetDBConnection()->setFetchMode(PDO::FETCH_ASSOC);
while ($record = $resultSet->fetch()) 
{
   print_r($record);
}

Presentation layer refactor

BizForm becomes 3 classes

Paging logic is moved from BizDataObj to BizForm.

Other code enhancement

List-Detail views

In many data centric applications, List/Detail views are commonly used as an UI pattern to present data.

Openbiz trac application Ticket tab is the type of List/Detail views pattern.

Multi-selection (multi-delete) support

Selecting multiple records on a data grid is a common function in many applications. Openbiz 2.3 starts to support it. To add a checkbox in the first column of a grid, the following line needs to be added.

<BizCtrl DisplayName="" FieldName="Id" Name="row_selections" Class="RowSelector" DisplayMode="READ"/>

The example is baseapp/modules/demo/FMEvent.xml

Dynamic value set on record update/creation

Sometimes we want to set value to certain fields on record creation and update. For example, when a record is create, we want to set the current time in "create_time" column. And when this record is updated, we want to set the current time in "update_time" column. Openbiz introduces 2 new attributes in BizDataObj to take are of such work.

ValueOnCreate can set the value on record creation, ValueOnUpdate can set the value on record update.

You can find example in baseapp/modules/trac/DO_Ticket.xml

<BizField Column="time" Name="time" Type="Datetime" ValueOnCreate="{date('Y-m-d H:i:s')}" Format="%m/%d/%Y"/>
<BizField Column="changetime" Name="changetime" Type="Datetime" ValueOnCreate="{date('Y-m-d H:i:s')}" ValueOnUpdate="{date('Y-m-d H:i:s')}"/>

Ajax file upload

Openbiz add Ajax file upload support to give better user experience on uploading files. Example can be found at  baseapp/modules/trac/FM_Attachment.xml and  baseapp/modules/trac/FM_Attachement.php. Uploaded file is stored into sec_upload directory (in 2.2.2, only support upload file to a blob column in a table).

Display a BizForm in a Modal or Resizable Window

Beta support for modals and resizeable windows has been introduced in the latest SVN (Rev. 306) version of of 2.3.  Using either of these elements requires no custom coding and can be configured entirely within the Eclipse Plugin.  Edit an existing Toolbar button to display in a Modal/Window by specifyingFunctionType="Modal or "FunctionType="Window" .  This will also change the way Context Menus are rendered.  Likewise, double clicking on a record will trigger the new display element.

Here is a simple example of having the QUERY form show up in a Modal dialog instead of within the main page.  For a window, replace the word Modal with Window.

<Control Caption="Search" DisplayMode="READ" Enabled="" Function="SearchRecord()" FunctionType="Modal" HTMLAttr="" Height="" Image="search.gif" Name="btn_search" Style="" Type="Button" Width=""/>

Using the new Event Handler style of buttons, the same can be written as

      <Control Caption="Edit" DisplayMode="READ" Enabled="" Function="EditRecord()" FunctionType="Modal" HTMLAttr="" Height="" Image="edit.gif" Name="btn_edit" Style="" Type="Button" Width="">
        <EventHandler Event="onclick" Function="EditRecord()" FunctionType="Modal" Name="edit_attendee" ShortcutKey="Ctrl+E"/>
      </Control>

A Modal's size and title can also be customized from by adding an "OnMouseOver" even hanlder.

      <Control Caption="New" DisplayMode="READ" Enabled="" Function="NewRecord()" FunctionType="Modal" HTMLAttr="" Height="" Image="new.gif" Name="btn_new" Style="" Type="Button" Width="">
        <EventHandler Event="onmouseover" Function="js:formatModal('height=600&amp;width=750&amp;title=New Attendee')" FunctionType="" Name="format_new_modal"/>
        <EventHandler Event="onclick" Function="NewRecord()" FunctionType="Modal" Name="new_attendee" ShortcutKey="Ctrl+N"/>
      </Control>

 

DHTML Tabs

Coming Soon.... In the mean time, check out the demo and flip between Attendees and Registration tabs.  Look ma, no page reloads!

http://localhost/latest_openbiz/baseapp/bin/controller.php?view=demo.Eve...

 

Improved Excel Export Features

Now you can customize the way OB's Excel service behaves.  
New features include:

  1. Export the contents of a different BizForm than the BizForm that holds the Export Button.
  2. Export field data from different displaymodes (READ, EDIT or even EXCEL)
  3. Choose from three output formats, HTML, CSV and TAB

Consider the following example:

      <Control Caption="Excel Export" DisplayMode="READ" Image="excel.gif" Name="btn_excel" Type="button">
         <EventHandler ContextMenu="Export to Excel" Event="onclick" Function="CallService(service.excelService,renderCSV,demo.FMAttendee,READ)" FunctionType="Popup" Name="onclick"/>
      </Control>

Notice the additional paramters that drive each new feature.  First call the excel service, pick your format (renderCSV, renderTAB and renderHTML), choose the BizForm whose data you wish to export and finally, choose the display mode from which to draw fields.

Check it out in action here: http://phpopenbiz.org/demo/23/baseapp/bin/controller.php?view=demo.Atten...

 

 

Openbiz 2.3 API doc

The 2.3 API docs are available at http://www.phpopenbiz.org/document/apidoc23/index.html.

2.2.2 OpenBiz

The new 2.2.2 manual is being compiled from the old 2.0 manual along with developer submitted updates and examples.  Any registered user can make changes so jump in and improve the developer docs!

 

2.2 New Features

Openbiz 2.2 Installation

  • Download and install 
  • Run demo application
  • Upgrade guide

Openbiz 2.2 New Features

  • Build on Zend Framework
  • Openbiz client build on prototype library
  • Leverage APC to improve performance
  • Enhancement of Openbiz objects
    • BizDataObj enhancement
    • BizForm enhancement
    • BizView enhancement
  • DataObject class as ActiveRecord
  • Multi-language support
  • Integration with BIRT report
  • Application tabs and sub tabs support
  • New look and feel
  • Solution of tree structure - BizFormTree
  • Auto suggestion text input
  • Validation Service
  • Multiple Check Boxes
  • Access control on Tabs and Menu
  • Openbiz grid enhancement
    • Context menu, Resizable columns and Double click handler

 

Openbiz Eclipse Plugin 1.0

  • Work smoothly with Zend PDT 1.0
  • Other enhancement

SVN Access and Contribution

Appendix - metadata DTD files


This document introduces the new enhanced features of Openbiz 2.2 upon version 2.1. Openbiz 2.1 manual still apply on version 2.2.

Openbiz 2.2 Installation

NOTE: From Openbiz 2.2.1.1, Web Installer is highly recommended. After download Openbiz source and unzip it under a directory. In Browser address bar, type in http://localhost/openbiz_install_dir/demoapp/index.php. Then follow the steps of the installer.

To get higher performance, enabling APC extension is highly recommended. A topic on apachelounge covers installing APC on windows.

If you want to use your own Zend Framework installation, please follow the steps below:

1. Download Openbiz 2.2 source, download Zend Framework source

2. Configure Zend framework path in openbiz_home/bin/sysheader.inc. For example, if Zend framework library is under /htdocs/zf101/, the following part is added in sysheader.inc.

// defined Zend framework library home as ZEND_FRWK_HOME
define('ZEND_FRWK_HOME',$_SERVER['DOCUMENT_ROOT']."/zf101/library");
// add zend framework to include path
set_include_path(get_include_path() . PATH_SEPARATOR . ZEND_FRWK_HOME);

Run Openbiz 2.2 demo application

1. Change Config.xml Driver attribute. http://us2.php.net/manual/en/ref.pdo.php#pdo.drivers gives the list of supported PDO drivers.

2. Run Openbiz dempapp by launching http://localhost/ob22/demoapp/demo.html in web browser. The home of the demo event management application is changed to http://localhost/ob22/demoapp/bin/home.php instead of http://localhost/ob22/demoapp/pages/EventMgr.htm in 2.1 version.

Upgrade guide

Openbiz release zip file has 2 directories - openbiz and demoapp. Openbiz directory has the core openbiz classes library, while demoapp has openbiz core javascript files as well as all application code, metadata and template files. Keep in mind the template files have critical code to work with BizForm.

1. Download new Openbiz release and overwrite the old openbiz directory

2. Say your current application is under myapp directory. You need to

  • Copy demoapp/js directory to myapp/js. Do merge files if you make change on these js files.
  • Copy demoapp/templates/*.* to myapp/templates/. Do merge file if you make change on demoapp template files. Don't delete your own application specific templates.

Openbiz 2.2 New Features

Build on Zend framework

  • Replace ADODB database abstraction library with Zend_Db (based on PDO). Benefits include higher performance and lower memory footprint.
  • Use Zend_Translate for internationalization 
  • Zend framework provides many useful functionalities
  • Zend framework is the official php framework, but it is still a low level library. Openbiz application framework bring your development inches away to your applications.

Openbiz client build on prototype library

From version 2.2.2 beta2, the most popular and well-written client javascript library becomes the foundation of openbiz client. Benefit of this:

  • prototype library gives solid foundation of AJAX and other powerful functionalities
  • prototype.js has many extensions. The famous one is script.aculo.us which is used to support AutoSuggestion.
  • The AJAX posted data by prototype is different than previous versions. The new posted data is like normal form submission. You get the read the data with $_POST or $_REQUEST. Of course we still recommend using clientproxy::GetFormInput.
  • Another UI observation is that users can see a spinning waiting icon when an ajax action happens.

Leverage APC to improve performance

 

DataObject class as ActiveRecord

DataRecord class is introduced in 2.2.2 RC2. DataRecord has ActiveRecord-like interface. BizDataObj query returns results in format of record array. DataRecord is an object wrapper on such record array. With DataRecord, developers can easily do record update/delete at object level.

Insert a record Update a record Delete a record
 $dataRec = new DataRecord(null, $dataobj);
$dataRec->first_name = 'Steve';
$dataRec->last_name = 'Jobs';
$dataRec->save( );
 Note: the following code works too.
$dataRec['first_name'] = 'Steve';
$dataRec['last_name'] = 'Jobs';
$dataRec->save( );
 $dataRec = new DataRecord($recordArray, $dataobj);
$dataRec->first_name = 'Steve';
$dataRec->last_name = 'Jobs';
$dataRec->save( );
 Note: the following code works too.
$dataRec['first_name'] = 'Steve';
$dataRec['last_name'] = 'Jobs';
$dataRec->save( );
 $dataRec = new DataRecord($recordArray, $dataobj);
$dataRec->delete( );

For the demo of the DataRecord usage, please check the change in BizForm::SaveRecord( ).

Multi-language support

From Release 2.2.2, Openbiz provides an easy way to support multi-language applications. Great thanks for the contribution from Loic Devaux!

Multi-language support before Openbiz 2.2.2

You can only build application with single language (the data can be multi-language due to Unicode support). You need to have the right language in both metadata files and template files. It is hard to switch languages in the same applications.

Multi-language support in Openbiz 2.2.2 or later

If you want to support 2 languages in your application, what you should do is

  • No change on metadata files. In Smarty template files, include translatable message into {t}{/t} pair. Example: {t}Name{/t}. Note, if you don't use Smarty template in openbiz/others/ directory, you need to copy openbiz/bin/block.t.php to the plugin directory of your smarty installation.
  • Run 2mo.php (under yourapp/bin/languages/) to extract UI messages into language files. For example, English language file is  yourapp/languages/en/LC_MESSAGES/lang.en.po and Spanish language file is yourapp/languages/es/LC_MESSAGES/lang.es.po

  • Edit *.po file with POEdit (downloadable from http://www.poedit.net). It auto-generates *.mo files that are compiled language files

  • To switch language on the same application, you can add lang parameter in the URL. For example, home.php?lang=es.

At run time, Zend_Translate is used to read in correct language messages.

Integration with BIRT report

Generating report is a very critical feature for business applications. By leveraging BIRT report server, Openbiz application can generate business reports from BizForm/BizDataObj.

BIRT is an open source Eclipse-based reporting system that integrates with your Java/J2EE application to produce compelling reports. Among open source reporting tools, BIRT is one of the best. It keeps growing. Its Eclipse report designer let you to create a decent report from database tables and other data source (i.e. xml and csv files). 

The simplest installation of BIRT server is using BIRT viewer. A good reference can be found at Installing the BIRT Viewer in Tomcat.

Openbiz uses its reportService to integrate with BIRT viewer server. Steps to create a BIRT report template and show the report with BIRT viewer:

  1. Make sure Openbiz code can access the BIRT viewer server report directory. Openbiz reportService wil generate a BIRT report design and copy it to BIRT viewer report directory on the fly.
  2. Create a BIRT report with Eclipse designer. Use cvs file as its data source and data set. Now we have a BIRT report design file as abc.rptdesign.
  3. Convert the above .rptdesign file to template with smarty template syntax. For example, replace the resultset structure with {foreach}. abc.rptdesign becomes abc.rptdesign.tpl. The table below is an example of converting design to a template.

    resultset in .rptdesign resultset in template
    <list-property name="resultSet">
    <structure>
    <property name="position">1</property>
    <property name="name">AttendeeId</property>
    <property name="nativeName">AttendeeId</property>
    <property name="dataType">string</property>
    <property name="nativeDataType">12</property>
    </structure>
    <structure>
    <property name="position">2</property>
    <property name="name">Income</property>
    <property name="nativeName">Income</property>
    <property name="dataType">string</property>
    <property name="nativeDataType">12</property>
    </structure>
    </list-property>
    <list-property name="resultSet">
    {foreach item=fld from=$rpt_fields}<structure>
    <property name="name">{$fld.name}</property>
    <property name="nativeName">{$fld.name}</property>
    <property name="dataType">{$fld.type}</property>
    <property name="nativeDataType">12</property>
    </structure>
    {/foreach}
    </list-property>
  4. Copy the template file to Openbiz application template. Openbiz demoapp has a default BIR design template file "dataobj.rptdesign.tpl" under its template directory.
  5. Create a reportService metadata that can specify the TargetReportPath, ReportTemplate and BIRTViewer url. You can find a sample reportService metadata at openbiz/metadata/service/reportService.xml
  6. Add a button on BizForm to invoke reportService render method. Openbiz demoapp Attendee BizForm (in Attendee tab) has a Report button. Similar button can be created in any BizForm UI.
  7. When user clicks the Report button, he/she will get some options of displaying reports.

Application tabs and sub tabs support

Tabs are very popularly used in both business web applications and consumer web sites. In many business applications, subtabs are common widgets to organize the parent-children relationship between UI components in a page.

Openbiz 2.2 supports tabs and subtabs with combination of enhanced HTMLTab class and ViewSet attribute that is a new attribute of BizView.

The sample metadata xml file of HTMLTab class is at demoapp/metadata/demo/Tabs.xml and demoapp/metadata/demo/EventTabs.xml.

demo/Tabs.xml
<?xml version="1.0" standalone="no"?>
<Tabs Name="Tabs" Package="demo" Class="HTMLTabs" TemplateFile="tabs.tpl">
<TabViews>
<View Name="home" URL="./home.php" Caption="Home"/>
<View Name="event" URL="" View="demo.EventView" ViewSet="EventSet" Caption="Events" Icon=""/>
<View Name="regist" URL="" View="demo.RegistView" Caption="Registration" Icon=""/>
<View Name="attendee" URL="" View="demo.AttendeeView" Caption="Attendees" Icon=""/>
<View Name="reports" URL="./report.php" Caption="Reports" Icon=""/>
<View Name="test" URL="" View="demo.FieldDepTestView" Caption="Test 2.1 Features" Icon=""/>
</TabViews>
</Tabs>
demo/EventTabs.xml
<?xml version="1.0" standalone="no"?>
<Tabs Name="EventTabs" Package="demo" Class="HTMLTabs" TemplateFile="subtabs.tpl">
<TabViews>
<View Name="EventAttendee" URL="" View="demo.EventView" Target="" Caption="Attendees" Icon=""/>
<View Name="EventRegist" URL="" View="demo.EventRegistView" Target="" Caption="Registration" Icon=""/>
</TabViews>
</Tabs>

Corresponding views who have same ViewSet as "EventSet": 

demo/EventView.xml demo/EventRegistView.xml
<?xml version="1.0" standalone="no"?>
<BizView Name="EventView" ViewSet="EventSet"
Description="Event BizView" Package="demo"
Class="BizView" Template="view.tpl">
<ControlList>
<Control Name="_tabs" Form="Tabs"/>
<Control Name="fm_event" Form="FMEvent" SubCtrls="FMAttendeeChild"/>
<Control Name="_subtabs" Form="EventTabs"/>
<Control Name="fm_attd" Form="FMAttendeeChild"/>
</ControlList>
</BizView>
<?xml version="1.0" standalone="no"?>
<BizView Name="EventRegistView" ViewSet="EventSet"
Description="Event BizView" Package="demo"
Class="BizView" Template="view.tpl">
<ControlList>
<Control Name="_tabs" Form="Tabs"/>
<Control Name="fm_event" Form="FMEvent" SubCtrls="FMRegistChild"/>
<Control Name="_subtabs" Form="EventTabs"/>
<Control Name="fm_regist" Form="FMRegistChild" />
</ControlList>
</BizView>

Because EventView and EvenrRegistView share the same ViewSet, switching between them will keep the context of the same objects which are FMEvent and its BOEvent. For example, on EventView user searches for event name as "*Tennis*" in the top form, when he clicks on Registration sub tab to switch to EventRegistView, same found set is kept on the new view. 

New look and feel

Designing a business web application with decent look and feel usually needs web designers. Openbiz 2.2 demoapp bring a new set of styles which include change on:

  • Tabs and subtabs
  • BizForm title bar
  • Table column hearder and selected row
  • 3D style buttons

Of course developers can always change the .css file under demoapp/css to make their own styles.

Solution of tree structure - BizFormTree

A new class BizFormTree is brought back from Openbiz 1.1 to 2.2. This class is to solve a common issue that a tree structure is stored in a database table that has both ID and ParentID columns. BizFormTree allows users to navigate through the tree and add/delete/edit tree nodes. 

BizFormTree is a special BizForm. It uses BizForm.dtd file as its XML schema. BizFormTree is designed to represent the tree hierarchy relationship within a database table.

For example, event table schema: (every record has PARENT_ID column which builds tree hierarchy relationship between the records in the same table)

Column Comments
SYSID Primary key
NAME Event name
PARENT_ID Store the SYSID of its parent event.

BizFormTree requires 2 BizFields "Id" and "PId" from underline BizDataObj. "PId" maps to the columns that stores parent id. The class provides 2 new public methods

  • ListChildren($id) - List all children records of a given record
  • ListSiblings($id) - List all sibling records of a given record

Also this class output a parent object array to smarty template. With the parent array, developer can show parent hierarchy of current sibling records. A example of BizFormTree metadata is 

<BizCtrlList>
   <BizCtrl Name="bctrl_Id" FieldName="Id" DisplayName="Id"/>
   <BizCtrl Name="bctrl_name" FieldName="Name" DisplayName="Name" Link="javascript:CallFunction('{@:Name}.ListChildren({@:Control[bctrl_Id].Value})')"/>
   <BizCtrl Name="bctrl_pid" FieldName="PId" DisplayName="PId"/>
</BizCtrlList>

The template is like

{section name=i loop=$parents}
{if $smarty.section.i.index != 0} > {/if}<a href="javascript:CallFunction('demo.FMEventTree.ListSiblings({$parents[i].Id}))')">{$parents[i].Name}</a>
{sectionelse} {/section}

A screenshot below shows one UI that based on BizFormTree and list_tree.tpl.

 

 

Auto suggestion text input

Thanks for the effort and Jim and Rocky, Auto Suggestion text input is available in release 2.2.2 beta2. To configure an auto suggestion input, simply set the "Type" of a HTMLControl or FieldCtrl as "AutoSuggest", then set the suggestion list in SelectFrom attribute. For example, to add a control that suggests the first name of attendees,

<BizCtrl Name="attd_fname" FieldName="FirstName" DisplayName="Auto Suggestion Field - Attendee First Name" Type="AutoSuggest" SelectFrom="demo.BOAttendee[FirstName], [FirstName] like '{@:Control[attd_fname].Value}%'"/>
</BizCtrlList>

The demo can be found at the "UI Components" tab in the demoapp. Its metadata is at demoapp/metadata/demo/FMFieldDepTest.xml.

Validation Service

Prior version of OpenBiz offered limited support for validation in the form of setting a field to Required or through the use of basic expressions.  Starting with version 2.2.2 RC2, OpenBiz supports a new validation service containing several standard validations along with the ability to extend the service for your own purposes.  The validation service is accessed via the "Validator" attribute of a standard BizDataObject XML file.  Call the validate service in a manner similar to other services...

    <BizField Name="Email" Column="EMAIL" Validator="{@validate:email('[Email]')}"/>
    <BizField Name="Phone" Column="PHONE" Validator="{@validate:phone('[Phone]')}"/>

The latest 2.2.2 RC 2 demo contains several working examples. Check out demoapp/metadata/demo/BOAttendee.xml

Multiple Check Boxes

A new feature to the existing Check Box html control is to allow for multiple selections.  To create this field, use the SelectFrom attribute in conjuction with the Type attributed on a standard BizForm.  When a checkbox has multiple checks, the resulting values are combined into a comma separated value (blue, green, red).  Developers can easily override this behavior.  For example, one can write custom logic to create new records for each check box.

   <BizCtrl Name="evt_host" FieldName="Host" DisplayName="Host" order="3" DisplayMode="" SelectFrom="demo.Selection(Host)" Type="Checkbox"/>

The latest 2.2.2 RC 2 demo contains a working example. Check out demoapp/metadata/demo/FMEvent.xml

 

Access control on Tabs and Menu

Thanks for contribution from wasiko, access control can be applied on Tabs and Menu (> 2.2.2 beta2). Usually a tab or a menu item points to an openbiz view. So it you want to block the a user to see the tab or menu item, you just need to configure the access service metadata to block certains roles on these views. For details of configuring access service, please refer to http://www.phpopenbiz.org/jim/manual/2_0#dev_access.

 

Openbiz grid enhancement (in release 2.2.2 RC or later)

There are some UI enhancement on Openbiz grid (also called table, list).

  • Context Menu. By defining ContextMenu attribute for EventHandler of Toolbar/Navbar controls, user can see context menu by right-clicking mouse on grid.
    Example: <EventHandler Name="onclick" Event="onclick" Function="SearchRecord()" ShortcutKey="Ctrl+Shift+Q" ContextMenu="Search"/>. In the demoapp, Event grid has context menu enabled.
    Remember to add oncontextmenu="return showmenu(event, '{$name}_contextmenu');" in your grid template (i.e. list.tpl).
  • Resizable grid columns. Openbiz leverages Tablekit.js to make grid columns resizable. Remember to add <script>TableKit.Resizable.init($('{$name}_data').down('table'));</script> in your grid template (i.e. list.tpl).
    Note: due to sortable and editable features are not useful for current Openbiz grid, the Tablekit.js in Openbiz package is not the original Tablekit.js.
  • Double-click handler. Double-click to enter edit mode is a popular request from Openbiz users. It is added in release 2.2.2 RC.

 

 


Openbiz Eclipse Plugin 1.0

Openbiz Eclipse plugin goes to 1.0 release along with the release of Eclipse PHP Development Tools PDT 1.0.

Work smoothly with Zend PDT 1.0

In the new Openbiz Eclipse plugin, developers can click the class link (the Class attribute of Openbiz metadata objects) to open the PHP source code. It can work with other PHP IDE such as PHPEclipse.

Other enhancement

  • Open metadata files with Openbiz Metadata editor at the end of new Openbiz metadata wizards.
  • Tooltip is applied to most labels to give the hint of correct configuration
  • In Config.xml, driverFile can accept jar file name (you need to copy jdbc file into Openbiz plugin/lib/ directory) or full jar file path

SVN Access and Contribution

In order to do commit your code contribution, you need to have a sourceforge.net account and send it to rockyswen@phpopenbiz.org. Then you will be added to the developer list of the project. Then you can access svn repository at http://bigchef.svn.sourceforge.net/viewvc/bigchef/branches/2.2/.

To pull the SVN repository by svn client to your box, use url https://bigchef.svn.sourceforge.net/svnroot/bigchef/branches/2.2. To commit file changes, use your sourceforge login and password (your name needs to be added in openbiz developer list first).


Appendix - metadata DTD files

Blue color text indicates new element in Openbiz 2.2

BizDataObj metadata DTD file

<!--OpenBiz BizObj metadata DTD-->

<!ELEMENT BizObj (BizFieldList, TableJoins, ObjRefernces, Parameters) >
<!ATTLIST BizObj Name CDATA #REQUIRED >
<!ATTLIST BizObj Description CDATA #REQUIRED >
<!ATTLIST BizObj Package CDATA #IMPLIED >
<!ATTLIST BizObj Class CDATA #REQUIRED >
<!ATTLIST BizObj InheritFrom CDATA #IMPLIED >
<!ATTLIST BizObj DBName CDATA #IMPLIED >
<!ATTLIST BizObj Table CDATA #REQUIRED >
<!ATTLIST BizObj SearchRule CDATA #IMPLIED >
<!ATTLIST BizObj SortRule CDATA #IMPLIED >
<!ATTLIST BizObj OtherSQLRule CDATA #IMPLIED >
<!ATTLIST BizObj AccessRule CDATA #IMPLIED >
<!ATTLIST BizObj UpdateCondition CDATA #IMPLIED >
<!ATTLIST BizObj DeleteCondition CDATA #IMPLIED >

<!ATTLIST BizObj Stateless CDATA #IMPLIED >

<!ELEMENT BizFieldList (BizField+) >
<!ELEMENT BizField EMPTY >
<!ATTLIST BizField Name CDATA #REQUIRED >
<!ATTLIST BizField Class CDATA #IMPLIED >
<!ATTLIST BizField Join CDATA #IMPLIED >
<!ATTLIST BizField Column CDATA #REQUIRED >
<!ATTLIST BizField SQLExpr CDATA #IMPLIED >
<!ATTLIST BizField Type CDATA #IMPLIED >
<!ATTLIST BizField Format CDATA #IMPLIED >
<!ATTLIST BizField Required CDATA #IMPLIED >
<!ATTLIST BizField Validator CDATA #IMPLIED >
<!ATTLIST BizField DefaulValue CDATA #IMPLIED >
<!ATTLIST BizField Value CDATA #IMPLIED >
<!ATTLIST BizField OnAudit CDATA #IMPLIED >
<!ELEMENT TableJoins (Join+) >
<!ELEMENT Join EMPTY >
<!ATTLIST Join Name CDATA #REQUIRED >
<!ATTLIST Join Table CDATA #REQUIRED >
<!ATTLIST Join Column CDATA #REQUIRED >
<!ATTLIST Join JoinRef CDATA #IMPLIED >
<!ATTLIST Join ColumnRef CDATA #REQUIRED >
<!ATTLIST Join JoinType CDATA #REQUIRED >

<!ELEMENT ObjReferences (Object+) >
<!ELEMENT Object EMPTY >
<!ATTLIST Object Name CDATA #REQUIRED >
<!ATTLIST Object Description CDATA #IMPLIED >
<!ATTLIST Object Relationship CDATA #REQUIRED >
<!ATTLIST Object Table CDATA #REQUIRED >
<!ATTLIST Object Column CDATA #REQUIRED >
<!ATTLIST Object FieldRef CDATA #REQUIRED >
<!ATTLIST Object CascadeDelete CDATA #IMPLIED >
<!ATTLIST Object XTable CDATA #IMPLIED >
<!ATTLIST Object XColumn1 CDATA #IMPLIED >
<!ATTLIST Object XColumn2 CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizView metadata DTD file.

<!--OpenBiz BizView metadata DTD-->

<!ELEMENT BizView (ControlList, Parameters) >
<!ATTLIST BizView Name CDATA #REQUIRED >
<!ATTLIST BizView Description CDATA #REQUIRED >
<!ATTLIST BizView ViewSet CDATA #IMPLIED >
<!ATTLIST BizView Package CDATA #IMPLIED >
<!ATTLIST BizView Class CDATA #IMPLIED >
<!ATTLIST BizView Template CDATA #IMPLIED >

<!ELEMENT ControlList (Control+) >
<!ELEMENT Control EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Form CDATA #REQUIRED >
<!ATTLIST Control SubCtrls CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizForm metadata DTD file.

<!--OpenBiz BizForm metadata DTD-->

<!ELEMENT BizForm (BizCtrlList, DisplayModes, Toolbar, Navbar, Parameters) >
<!ATTLIST BizForm Name CDATA #REQUIRED >
<!ATTLIST BizForm Description CDATA #REQUIRED >
<!ATTLIST BizForm Package CDATA #IMPLIED >
<!ATTLIST BizForm Class CDATA #REQUIRED >
<!ATTLIST BizForm InheritFrom CDATA #IMPLIED >
<!ATTLIST BizForm jsClass CDATA #REQUIRED >
<!ATTLIST BizForm Title CDATA #REQUIRED >
<!ATTLIST BizForm BizDataObj CDATA #REQUIRED >
<!ATTLIST BizForm PageSize CDATA #REQUIRED >
<!ATTLIST BizForm SearchRule CDATA #IMPLIED >
<!ATTLIST BizFomr Stateless CDATA #IMPLIED >

<!ELEMENT BizCtrlList (BizCtrl+) >
<!ELEMENT BizCtrl (EventHandler+) >
<!ATTLIST BizCtrl Name CDATA #REQUIRED >
<!ATTLIST BizCtrl Class CDATA #IMPLIED >
<!ATTLIST BizCtrl FieldName CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayName CDATA #IMPLIED >
<!ATTLIST BizCtrl Type CDATA #IMPLIED >
<!ATTLIST BizCtrl Width CDATA #IMPLIED >
<!ATTLIST BizCtrl Height CDATA #IMPLIED >
<!ATTLIST BizCtrl HTMLAttr CDATA #IMPLIED >
<!ATTLIST BizCtrl Link CDATA #IMPLIED >
<!ATTLIST BizCtrl Image CDATA #IMPLIED >
<!ATTLIST BizCtrl Hidden CDATA #IMPLIED >
<!ATTLIST BizCtrl Enabled CDATA #IMPLIED >

<!ATTLIST BizCtrl Sortable (Y|N) "" >
<!ATTLIST BizCtrl Order CDATA #IMPLIED >
<!ATTLIST BizCtrl Style CDATA #IMPLIED >
<!ATTLIST BizCtrl ValuePicker CDATA #IMPLIED >
<!ATTLIST BizCtrl PickerMap CDATA #IMPLIED >
<!ATTLIST BizCtrl DefaultValue CDATA #IMPLIED > <!ATTLIST BizCtrl SelectFrom CDATA #IMPLIED >
<!ATTLIST BizCtrl DrillDownLink CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayMode CDATA #IMPLIED >

<!ELEMENT Toolbar (Control+) >
<!ELEMENT Navbar (Control+) >
<!ELEMENT Control (EventHandler+) >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Class CDATA #IMPLIED >
<!ATTLIST Control Image CDATA #IMPLIED >
<!ATTLIST Control Caption CDATA #IMPLIED >
<!ATTLIST Control Type CDATA #IMPLIED >
<!ATTLIST Control Width CDATA #IMPLIED >
<!ATTLIST Control Height CDATA #IMPLIED >
<!ATTLIST Control HTMLAttr CDATA #IMPLIED >
<!ATTLIST Control Style CDATA #IMPLIED >
<!ATTLIST Control Hidden CDATA #IMPLIED >
<!ATTLIST Control Enabled CDATA #IMPLIED >
<!ATTLIST Control SelectFrom CDATA #IMPLIED >

<!ATTLIST Control DisplayMode CDATA #IMPLIED >

<!ELEMENT EventHandler EMPTY >
<!ATTLIST EventHandler Name CDATA #REQUIRED >
<!ATTLIST EventHandler Event CDATA #REQUIRED >
<!ATTLIST EventHandler Function CDATA #REQUIRED >
<!ATTLIST EventHandler FunctionType CDATA #IMPLIED >
<!ATTLIST EventHandler ShortcutKey CDATA #IMPLIED >
<!ATTLIST EventHandler PostAction CDATA #IMPLIED >
<!ELEMENT DisplayModes (Mode+) >
<!ELEMENT Mode EMPTY >
<!ATTLIST Mode Name CDATA #REQUIRED >
<!ATTLIST Mode TemplateFile CDATA #REQUIRED >
<!ATTLIST Mode DataFormat CDATA #REQUIRED >
<!ATTLIST Mode FormatStyle CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

Plugin service metadata DTD file.

<!--OpenBiz Plugin service metadata DTD-->

<!ELEMENT PluginService ANY >
<!ATTLIST PluginService Name CDATA #REQUIRED >
<!ATTLIST PluginService Description CDATA #IMPLIED >
<!ATTLIST PluginService Package CDATA #REQUIRED >
<!ATTLIST PluginService Class CDATA #REQUIRED >

 

Openbiz 2.x Architecture

 

Openbiz 2.x architecture

Openbiz 2.x is a metadata-driven framework. All openbiz objects are declared in their own metadata files. Openbiz 2.x architecture follows the Model-View-Controller (MVC) design pattern, it also implements basic Object/Relational Mapping (ORM) to reduce the time you spend coding CRUD operations.

 

Metadata-driver framework

Openbiz is XML metadata-driven framework, which means openbiz objects are constructed based on metadata files containing pre-defined attributes. Building an Openbiz application means creating metadata files that are read by Openbiz to produce functional web pages. Due to the self-expanatory nature of XML, the application is easy to maintain and extend.

The diagram below shows metadata based objects in Openbiz framework. These objects cover most functional needs of web application development.

The main XML files used in an Openbiz application are BizView, BizForm and BizDataObj.  Let's take a moment to briefly describe each before getting into their role with the MVC model. 

A BizDataObj represents a series of records from one or more tables in your database.  It contains XML attributes that are used to create basic CRUD functions in your application.  Information like the columns that should be included in the Object as well as what tables to join to the object.

A BizForm describes how a BizDataObj is to be displayed.  This includes the actual data columns and rows as well as what CRUD operations are available to the end users.

A BizView groups one or more BizForm onto a single web page.  BizViews also provide rules for how BizForms should be displayed.  Ie. Together on one page or in a Wizard format.

Openbiz's implementation of MVC

One of the key advantages of Openbiz is that it is a framework that follows the Model-View-Controller (MVC) design pattern. This makes Openbiz applications much more manageable because the presentation code (View) is cleanly separated from the application data and logic (Model). All user interactions with the application are handled by a front-end controller.

Comparing Openbiz MVC design with existing MVC frameworks as JSF and Struts shows that Openbiz is more similar to JSF because both share a component based architecture. Openbiz's View layer comprises components of BizView, BizForm and ojects within a BizForm. These components are accessible during request processing. Many developers prefer JSF over struts.  Here are the Top Ten Reasons to Prefer JSF over Struts as well a table showing how Openbiz provides similar advantages.

JSF's advantages 
over Struts
Openbiz implementation
Components BizView and BizForm as persistent UI objects 
Render Kits Associate different templates to UI objects
Renderers Customer class to implement Render() method
Value Binding Support static and dynamic value bindings
Event Model Associate client event to server function
Extensibility Developers can link their own class to openbiz object
other four .... Not applicable

Openbiz's implementation of persistent object and ORM

Similar with the popular Hibernate approach, Openbiz uses sessions to maintain the persistency of objects. Unlike J2EE web containers who have objects pools in memory, PHP objects are be constructed and released for each request (this is called share-nothing architecture). To keep the persistency of objects (BizDataObj, BizForm ...) Openbiz saves a set of states in session, then reconstructs the object with these same states. Also to avoid multiple object instances of same class in the same session, Openbiz uses an ObjectFactory class to protect from duplications.

Openbiz implements the necessary object/relational mapping (ORM) features to allow BizDataObj to represent the data and relationships of database tables. The following table list the features of Openbiz ORM.

Flexible mapping table-per-class, N table to 1 class
Many to one, one to many, many to many, one to one
Query facilities SQL like query language - supports SQL functions and operators, supports SQL aggregate functions, supports group by, having and order by
Metadata facilities XML metadata describes the mapping

Openbiz security model

Openbiz supports web security in three ways - user authentication, view access control and data access control. Openbiz mainly uses plugin services to control security. This implementation allows customers to implement their own logic within these services. This subject will get a full treatment  in the developer guide - Implement authentication, view and data access control.

Basic user authentication flow:

View access control flow:

Security concept Openbiz implementation with plugin services
User authentication Openbiz uses an authentication service (bin/service/authService.php) to authenticate username and password
Role-based view access control  Openbiz uses a profile service (bin/service/profileService.php) to get a user's profile that includes one or more "role" entries. 
These roles are run against the access service (bin/service/accessService.php) to determine the users' accessibility to the view.
Attribute-based data access control Openbiz uses a profile service (bin/service/profileService.php) to get a user's profile that includes their attributes.
These attributes are run again s a BizDataObj's rules to determine if the user has permission to browse/update/delete a data record.

Openbiz 2.0 package organization

OpenBiz simplifies small to medium applications by using the following multi-layer architecture.

Usually a business application can be boiled down to three layers namely a Data layer, Business Logic layer and Presentation layer. In OpenBiz architecture, these 3 layers map to several packages. The Presentation layer is implemented by the BizView package and GUI layers which is implemented by the jbForm javascript package. Business Logic layer is implemented by the BizDataObj package. Openbiz uses the Zend Framework, which is based ond PDO, to make SQL queries.  Finally, a Plugin service provides functional service components that can be invoked by both the presentation and data layer.

Package Class
BizSystem BizSystem
- Provide a global variable accessed anywhere in openbiz application
- Provide the Get method for ObjectFactory, SessionContext, TypeManager, ClientProxy and Configuration
- Provide static methods for accessing XML metadata, logging and error reporting.
ObjectFactory 
- It's a factory class to get metadata-driven objects (BizView, BizForm, BizdataObj and their extended classes) 
SessionContext
- Session management class that has additional methods to save/get session variables of metadata-driven stateful objects through their GetSessionVars|SetSessionVars interfaces
TypeManager
- Type management class that has help methods to format data to UI and unformat UI input to data
ClientProxy
- It's a class that is treated as the bi-direction proxy of client. Through this class, others can get client form inputs, redraw client form or call client javascript functions.
Configuration
- A class that has help methods to get data from config.xml
BizDataObj BizDataObj
- It's the base class of all data object classes. Before Openbiz 1.2, BizDataObj was called BizObj. Since BizObj means Business Object, but it acts as business data unit, in 1.2 it is changed as BizDataObj.
BizRecord
- BizRecord class implements basic function of handling record
BizField
- BizField is the class of a logic field which mapps to a table column
BizDataSql
- BizObjSql is the class to construct SQL statement for BizDataObj
CacheRecordList
- CacheRecordList implements the cache for BizDataObj
ObjRefernces
- ObjReferences contains a list of BizDataObj whose relationship to this object is defined in the ObjReference
TableJoins
- Table Joins contains a list of table joins to the main table of this object
BizView BizView
- BizView is the class that contains list of forms. View is same as html page.
BizForm
- BizForm is the base class that contains UI controls. BizForm is a html form that is included in a BizView which is a html page.
RecordRow
- RecordRow is the class that contains FieldControls
ToolBar
- ToolBar is the class that contains HTMLControls
NavBar
- NavBar is the class that contains navigation buttons
HTMLControl
- HTMLControl is the base class of HTML controls
FieldControl
- FieldControl is the base class of field control who binds with a bizfield
DisplayMode
- contains the BizForm display mode information
jbForm  jbForm (javascript bizForm) 
- the base class that handles RPC function call and callback
PDO Database access is abstracted out through the the Zend Framework and the underlying PDO library. 

Class diagram of multi-layer architecture

Sequence diagram of a typical RPC call

Openbiz client browser communicates with server through AJAX JS-based RPC invocation.

 

 

Openbiz 2.2 Installation

Requirements

PHP 5.1 or greater
 *For installs greater than 5.1.6 see this fix...
1.X Series of Zend Framework or Greater
PDO extension and the PDO_YOURDATABASEOFCHOICE (ie. PDO_Mysql)
Smarty Template Engine
PHP Mailer

A good PHP OpCode caching engine is highly recommended.  Consider using APC or as an alterantive eAccelerator.  A google search should turn up several ways to get them working.

Note: These are requirements for OpenBiz 2.2, for requirements involving 2.0 check here.

Installation

Start by downloading the OpenBiz source here.

Extract the source files in a web accessible directory.  You should see two folders, demoapp and openbiz.  OpenBiz comes with it's own core files as well as any needed libraries such as phpmailer, smarty and Zend FW.

Install the Demo Application by navigating to the following location.
http://*YOUR DOMAIN*/*YOUR OB INSTALL*/demoapp/index.php


 

Configure Database Access

1. Change Config.xml Driver attribute. http://us2.php.net/manual/en/ref.pdo.php#pdo.drivers gives the list of supported PDO drivers.

2. Run Openbiz dempapp by launching http://localhost/ob22/demoapp/demo.html in web browser. The home of the demo event management application is changed to http://localhost/ob22/demoapp/bin/home.php instead of http://localhost/ob22/demoapp/pages/EventMgr.htm in 2.1 version.

Use Your Own Zend Framework
You can optionally use a newer version of the Zend Framework by changing it's associated config file.  The Zend Framework path can be changed in openbiz_home/bin/sysheader.inc. For example, if Zend framework library is under /htdocs/zf101/, the following part is added in sysheader.inc.

// defined Zend framework library home as ZEND_FRWK_HOME
define('ZEND_FRWK_HOME',$_SERVER['DOCUMENT_ROOT']."/zf101/library");
// add zend framework to include path
set_include_path(get_include_path() . PATH_SEPARATOR . ZEND_FRWK_HOME);

 

Upgrade Tips

Openbiz release zip file has 2 directories - openbiz and demoapp. Openbiz directory has the core openbiz classes library, while demoapp has openbiz core javascript files as well as all application code, metadata and template files. Keep in mind the template files have critical code to work with BizForm.

1. Download new Openbiz release and overwrite the old openbiz directory

2. Say your current application is under myapp directory. You need to

  • Copy demoapp/js directory to myapp/js. Do merge files if you make change on these js files.
  • Copy demoapp/templates/*.* to myapp/templates/. Do merge file if you make change on demoapp template files. Don't delete your own application specific templates.

 

Build Applications with Openbiz

Specify application requirements

OpenBiz is a perfect tool that helps you comprehensively develop complicated web applications easily. Based on its 3-layer architecture, your application will enjoy a clear logical model. It takes care the basic and advanced features of a data-oriented application. In order to tell whether OpenBiz can help building your application, you need ask these questions:

  • Is your application web-based or can it be converted to web-based application?
  • Does your application need to manipulate different types of data stored in a database?
  • Doe your application need to interoperate with other web technologies?

If the answers are YES, OpenBiz may work for you!

Plan your web applications

When you install the Openbiz package, you should notice there are two main directories "openbiz" and "demoapp" in the zip file. Openbiz contains the openbiz core library and metadata. Demo contains the source for a demo application (event management  and calendar demo).  Use the Demo folder as you model for creating you own application.

The above structure is different from that of Openbiz 2.0 RC1 and prior versions where you see demo in the openbiz directory.  Why the change?

  • Seperatation makes for a clearer picture of core code and and application code.
  • Openbiz core library is more portable than the openbiz application, it can be shared by multiple applications.
  • Upgrades are eaier with seperate folders.

Develop web application with your own directory

Your own development Where to put
Your source code your_app_root/bin/
Your metadata files your_app_root/metadata/your_package/
Your web templates your_app_root/templates/
Your web pages your_app_root/
Your style sheet files your_app_root/css/
You image files your_app_root/images/
Your log files your_app_root/log/
Your session files your_app_root/session/
Your temporary files your_app_root/tmpfiles/

This is a more organized way to develop an openbiz-based web application. Your application specific files are in a separate directory, not mixed with openbiz core files. You can build multiple web applications based on single openbiz core. You need to do some extra steps to set up your own application directory. The following steps are suggested.

  1. Copy demoapp directory and rename it to your application name, say "testapp"
  2. Open testapp/bin/app.inc, change the constants appropriately. If the default values may work for you, no change is needed.
  3. Open testapp/bin/login.php, change the $application_homepage to the first web page shown to users after they login.

In the app.inc file, OPENBIZ_HOME has to be define to point to the installed path of openbiz core library. Your applications will use the openbiz core library as well as core objects defined in metadata directory.

Another important change from RC2 is that metadata and code have to match up under /metadata and /bin directories. If you have an object's metadata under /metadata/aaa/ directory, if the object implementing code is a user-defined class (not openbiz core class), the class code file must be under /bin/aaa/ directory. For example, /metadata/shared/FMCalendar.xml has a special implementing class "FMCalendar", this FMCalendar class must be located in /bin/shared/FMCalendar.php. If the object's implementing class is openbiz core class, no special code is needed, thus there's no matching code under /bin. This match-up rule is to give a clear view of the metadata and code.  

How to upgrade to the new structure if you are using the structure in RC1 or prior version? In Openbiz RC1 and prior version, application code is under bin/usrlib/ directory. Based on the metadata/code match-up rule, you need to create subdirectories with the same names of the metadata packages under /bin directory and move the code under /bin/usrlib to those subdirectories.

Create your database model

Modeling your business data with Relational database tables is a necessary step for building your whole application.

Create a new database

  • Assign the new database to be Default database in config.xml
  • Create "ob_users" table which stores user id and password. Since 2.0, openbiz counts on authentication service to authentiate user and password, so the user id and password can be stored in the storage that is queried by the authentication service.
  • Create "ob_sysids" table which stores SYSID information for all tables who have SYSID column
  • Create customer tables. Each table must have a SYSID column and add a record in ob_sysids table (TABLE=your table name, PREFIX=prefix of sysid, IDBODY=starting integer)

Use existing database

  • Assign the new database to be Default database in config.xml
  • Create "ob_users" table or reuse an existing table which contains userid and password columns. Ensure that authentication service queries the user id and password on the right table (or source).
  • Set IdGeneration attribute to the existing id generation algorithm. For example, if your oracle database uses sequence to generate value for PK column, the IdGeneration should be "Sequence:seqname". Please refer the chapter of Primary Key (Id) Generation for details.

Build new application

Business requirement -> UI design + data modeling + objects design

User Interface: Pages, forms, interactivities

Data Modeling: Database table schema

Objects Design:

  • UI objects - BizView, BizForm
  • Data objects - BizDataObj with object/relational mapping
  • Functional objects - Plugin services

Convert existing application

Convert existing UI to BizViews, BizForms

Map existing database tables to BizDataObjs

Port existing business functionalities to plugin services

Example: Calendar Application

 

Requirement:

  • users can see their calendar in day, week, month formats
  • users can create/delete/edit an event on calendar
  • users can invite attendees to an event and see the schedule of attendees
Step 1. Data Modeling with table schemas
  • Create the needed tables in any PDO supported database
Step 2. Map tables to BizDataObjs
  • Map driving table columns to BizFields
  • Join other table columns to BizFields
  • Map table relationship using ObjReference
Step 3. Bind UI controls with data
  • Associate a BizDataObj to a BizForm
  • Map FieldControl of BizForm to BizField of BizDataObj
  • Configure drilldown link on FieldControl
  • Configure value picker form on FieldControl
Step 4. User Interactions
  • Map action to UI control (usually a button)
  • Associate UI control to a function
  • Implement the function as a BizForm method
Step 5. Implement special logic by extending openbiz
  • Write special data logic by extending BizDataObj
  • Write special presentation logic by extending BizForm

Calendar view: event navigation

User Interface Objects Calendar form
  - day, week, month and all events display modes
  - FieldControls: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd
Data Objects Calendar data object
  - Fields: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd
Tables calevts table
  - Columns: SYSID, SUBJECT, LOCATION, TYPE, NOTES, STARTTIME. ENDTIME, REPEATCYCLE, REPEATEND

Calendar Detail view: event editing and invite attendees

User Interface Objects Calendar Detail form
  - SubForm is Event Attendee form
  - New, Edit modes
  - FieldControls: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd, AttendeeId, AttendeeName
Event Attendee form
  - Parent form is "Calendar Detail form"
  - List and Schedule modes
  - FieldControls: Id, LastName, FirstName, ...
Data Objects Calendar detail data object
  - Fields: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd
  - ObjReference: Calendar Attendee data object
  - Joined Fields: Attendee Id, AttendeeName (from calattds table)
Calendar Attendee data object
  Fields: Id, LName, FName, ...
Table calevts table
  - Columns: SYSID, SUBJECT, LOCATION, TYPE, NOTES, STARTTIME. ENDTIME, REPEATCYCLE, REPEATEND

calevts_attds table (intersection table of calevts and calattds)

calattds table
  Columns: SYSID, LASTNAME, FIRSTNAME, ...

Class Diagram:

Note: Calendar Form and Calendar Detail Form have special rendering logic, they are based on FMCalendar and FMCalAttendee classes which are extended from BizForm base class.

User interaction - UI controls maps to server functions

User action UI Control Function Method implementation
Show Day calendar: switch to day mode, draw the day calendar Day button ShowDay() class FMCalendar
public function ShowDay()
Show Week calendar: switch to week mode, draw the week calendar Week button ShowWeek() class FMCalendar
public function ShowWeek()
Show Month calendar: switch to month mode, draw the month calendar Month button ShowMonth() class FMCalendar
public function ShowMonth()
Show all calendar events: switch to list mode, list all events page by page All Events button ShowList() class FMCalendar
public function ShowList()
New a calendar event: Click New button on Calendar View, jump to Calendar Detail View with new mode New Event button NewEvent() class FMCalendar
public function NewEvent()
Delete a calendar event: In Calendar Detail View, click Delete button to delete an event Delete button DeleteRecord() class BizForm
public function DeleteRecord()
Edit a calendar event: Click an event link on the Calendar view, jump to Calendar Detail with edit mode Drill down link URL = "bizController.php? view=shared.CalDetailView &amp;form=shared.FMCalDetail &amp;mode=NEW"  
Add event attendees: In Calendar Detail View, click Add button on the Calendar Attendee form to pick an attendee Add button ShowPopup (shared.FMAttendeePopup) class BizForm
public function ShowPopup()
Remove event attendees: In Calendar Detail View, click Remove button on the Calendar Attendee form to remove an attendee Delete button RemoveRecord() class BizForm
public function RemoveRecord()
Show attendees' schedule: In Calendar Detail View, click Show Schedule button to switch to schedule mode Schedule button ShowSchedule() class FMCalAttendee
public function ShowSchedule()

To see the sample calendar, open http://localhost/openbiz/bin/BizController.php?view=shared.CalendarView in your browser.

Openbiz Configuration Guide

Eclipse Editor

Developers can use any XML editor to edit metadata files or they can use Openbiz's Eclipse Plug-in.  The latter is recommended to be used by new OB users or by anyone when rapidly design and configuring a new application. Please refer to Openbiz Eclipse plug-in designer manual.

Organize metadata by package

In a big application, user may need to build lots of objects, therefore they might have a big metadata file list. Meta files under a single directory can be difficult to manage.  From openbiz 1.1, metadata files can be organized by package name. Bear in mind, metadata package is different with the (BizObj, BizView ...) packages which are the code units. Metadata package is a naming system, different package maps to different directory. It is like the package concept used in Java. 

PackageX.PackageY.metaA.xml refers to the metaA.xml under META_PATH/PackageA/PackageB directory. Where META_PATH is the root metadata directory. This setting is defined in sysheader.inc and app.inc. 

How to configure  package in metadata files?

Let's explain it with the demo example. After you unzip the source, find the demo directory under metadata directory. Open FMRegist.xml file with a text editor. You'll see a Package="demo" attribute in the BizForm element. This attribute is to say the default package of any type of openbiz object is under "demo" package. Here the openbiz objects refer to the following object types.

Object Type Referred as attributes in metadata files
BizObj BizForm[BizObj]
BizObj->BizFieldList->BizField[SelectBizObj]
BizForm BizView->ControlList->Control[Form]
BizView->ControlList->Control[SubCtrl]
BizForm->BizCtrlList->BizCtrl[SelectFrom]
BizView  
BizPopup BizForm->BizCtrlList->BizCtrl[SelectBizForm]
BizFormTree Same as BizForm

If an object name doesn't contain dot symbol ("."), the system uses the package attribute defined in the object root element as its package. Otherwise, if an object name has format as aaa.objectname, the system thinks such object under package "aaa" and will locate such object under aaa directory.

Go back to the example, you can find

<BizForm Name="FMRegist" Package="demo" ... BizObj="BORegist"...>
...
<BizCtrl Name="reg_attdln" ...  SelectBizForm="AttendeePopup"...>
<BizCtrl Name="reg_fee" ... SelectFrom="Selection(Fee)"...>

They all use default package, so the system will try to locate the metadata files as demo/BORegist.xml, demo/AttendeePopup.xml and demo/Selection.xml.

If you want to refer to an object under another package, just add the package name as the prefix of the object name. Notice, there're a Selection.xml under /demo directory and another Selection.xml under /design directory, they belong to different packages. In FMRegist, whose package is "demo", you can use <BizCtrl ...  SelectFrom="design.Selection(Mode)" ...> to configure a comboBox whose values are from the "Mode" element of "design/Selection.xml".

You cannot refer to an object in different a application. But you can refer to any object in openbiz core application. For example, the core application has references to objects under metadata/shared/ directory. Openbiz tries to locate objects in same application and then in core application. If no object is found, it reports an error.

Use object metadata inheritance

If you have a complex application, you want to reuse the existing object to different places, but you want the object behave a little differently in different scenarios. Object inheritance will help with this frequent problem. Since objects map to metadata files in OB, object inheritance becomes metadata file inheritance.

How to specify inheritance between metadata files?

Specify an object attribute, InheritFrom = "parent object name". For example, in demo application, BOEventX has
<BizObj Name="BOEventX" Description="Event BizObj Extended from BOEvent" Package="demo" Class="BizObj" InheritFrom="demo.BOEvent"...>
This indicates that is BOEventX is inherited from BOEvent. 

Metadata file inheritance is similar with class inheritance in programming languages, child objects can inherit parent object settings.  OB will use the child object attributes where they conflict with parent object attributes.

Object Type which can has inheritance What CAN be inherited or overridden What CANNOT be inherited - must be specified in child metadata file
BizObj Object Attributes: Description, DBName, Table, SearchRule, SortRule, OtherSQLRule, CacheMode

Object BizFieldList: BizField

Object Attributes: Name, Package, Class, InheritFrom
BizForm Object Attributes: Description, jsClass, Title, BizObj, PageSize, Width, Height, SearchRule

Object BizCtrlList: BizCtrl
Object DisplayModes: Mode
Object Toolbar: Control
Object Navbar: Control

Object Attributes: Name, Package, Class, InheritFrom

Simple Expression Language

In order to add flexibility to metadata configuration, Openbiz accepts simple expressions in metadata files. If a statement has {expr} pattern, the expression is evaluated and used by the metadata config file.   Expression can be used in a number of ways including:

  • A single PHP statement which returns a value. ie {Date()}
  • Reference registered services such as the Validate service.  ie. {@validate:email('[Email]')}
  • Reference OB object variables ie. {@:Control[attd_fname].Value}
  • Simple expression language also allow developers to use any global variables supported by PHP. Please read http://us2.php.net/manual/en/reserved.variables.php for details

Because it's a simple expression language, users should put more complicated logic in an associated object.  Developers can also extend property support by modifying/overriding GetProperty() method. The input of GetProperty() can be either "property_name" or "*[child_name]" or something new supported by customer code.

Where To Use Expressions

  • BizDataObj
    SearchRule, SortRule, OtherSQLRule, AccessRule, UpdateCondition, DeleteCondition. These attributes are query related attributes of BizDataObj element, [field_name] is not evaluated to field value. [field_name] is the syntax of query lanaguage, it will be replaced by table column name. Please see Query Language in BizDataObj for details.
  • BizDataObj.BizFied
    Required, Validator, Value, DefaultValue 
  • BizForm
    Link, Style, Hidden, Enabled, SelectFrom
  • BizForm.EventHandler
    Function, PostAction

Literal Support

The simple expression language defines the following literals:

  • Boolean: true and false
  • Integer: as in PHP
  • Floating point: as in PHP
  • String: with single and double quotes; " is escaped as \", ' is escaped as \', and \ is escaped as \\.
  • Null: null

Operator Support

The simple expression language provides the following operators:

  • Arithmetic: +, - (binary), *, / and div, % and mod, - (unary)
  • Logical: and, &&, or, ||, not, !
  • Relational: ==, !=, <, >, <=, >=.  Comparisons can be made against other values, or against boolean, string, integer, or floating point literals.
  • Conditional: A ? B : C. Evaluate B or C, depending on the result of the evaluation of A. 

Variable Support

Simple expression allows developers to use variables of openbiz metadata objects:

  • <BizDataObj SearchRule="[Start]>'date(\"Y-m-d\")'">
  • <BizDataObj AccessRule="[OwnerId]='{@profile:USERID}'">
  • <BizDataObj UpdateCondition="[OrgId]=={@profile:ORGID}">
  • <BizDataObj DeleteCondition="'admin'=={@profile:ROLEID}">
  • <BizField Name="NeedApprove" Required="{[Amount]>1500}"/>
  • <BizField Name="Fee" Validator="{[Fee]>=15}"/>
  • <BizField Name="FullName" Value="{[LastName]}, {@:Field[FirstName].Value}"/>

The following table describes variable support in more detail.

Syntax to get metadata object variables Meaning Implementation Sample usage
@object_name:property_name get the given property of the given object. Call object->GetProperty ($propname) @BOEvent:Name
@FMEvent:Title
@object_name:*[child_name].property_name get the given property of the given object's child element Call object->GetProperty ($propname), where $propname="*[child_name]", to get the child object. 
Then call child_object->GetProperty($propname)
@BOEvent:Field[Id].Value
@FMEvent:Control[evt_id].Value
@:property_name or 
@this:property_name
get the given property of this object ("this" object is the object defined in the metadata file) Call this->GetProperty ($propname) In BOEvent, @:Name or @this:Name means getting the "Name" property of BOEvent.
@:*[child_name].property_name or
@this:*[child_name].property_name
get the given property of this object's child element Call this->GetProperty ($propname), where $propname="*[child_name]", to get the child object. 
Then call child_object->GetProperty($propname)
In BOEvent, @:Field[Id].Value or @this:Field[Id].Value means getting the "Id" field value of BOEvent.
[field_name] get the value of a given BizField of this BizDataObj. 
It is evaluated to field value only if it is used in BizField element
Call object->GetProperty ($field_name) to get the child BizField object. 
Then call field_object->GetProperty("Value")
In BOEvent, [Id] means getting the "Id" field value of BOEvent.
@object_name:param[param_name] or
@:param[param_name]
get the given parameter's value of this object Call object->GetProperty ($propname), where $propname="param[param_name]" @:param[Evt_Id]
@profile:property_name get the user profile property.  User profile is provided with ProfileService. @profile:ROLEID

 

Functions

Developers can invoke any PHP functions in simple expression. A user defined functions can be invoked if the file that contains such function is included. For example, if the metadata object A is based on a customer class, the class file is A.php that includes another A_help.inc. In this case, you can invoke functions defined in A_help.inc in simple expression.

 NEED EXAMPLE

BizView and BizForm Configuration

BizView Configuration

BizView metadata DTD file can be found in Appendix B

BizView is the physical web page that contains multiple BizForms and other HTML elements. Its layout is based on the smarty template enginee. A BizView defines the layout of BizForms as well as relationship between BizForms.  Below is a sample BizView, notice how you can control which smarty template is used for a BizView via the Template attribute.   Developers can also override the default BizView by specifiying their own derived class by changing the Class attribute.  All BizForms, Tabs and Menu elements are specified in the ControlList.  Finally, underlying relationships between BizForms can be configured here via the SubCtrls attribute.

<BizView Name="AttendeeView" Description="Attendee View" Package="demo" Class="BizView" Template="view.tpl" AccessControl="">
   <ControlList>
      <Control Name="fm_attd" Form="FMAttendee" SubCtrls="shared.FMAttachment"/>
      <Control Name="fm_attach" Form="shared.FMAttachment" SubCtrls=""/>
   </ControlList>
</BizView>

Use SubCtrls to map relationship amont BizForms

Many times a page displays two BizForms that are related, usually in a Parent->Child relationship.  OB provides a way where clicking on a record in the parent BizForm filters the Child BizForm to only show related records.  These relationships are configured in a parent BizForms BizDataObj and can be enabled on the BizView via SubCtrls.   In the example below, shared.FMAttachement will only shows records related to its parent form, FMAttendee.

...
      <Control Name="fm_attd" Form="FMAttendee" SubCtrls="shared.FMAttachment"/>
      <Control Name="fm_attach" Form="shared.FMAttachment" SubCtrls=""/>

...

The underlying PARENT BizDataObjs spells out how these two BizForms are connnected.  In the example FieldRef points to the Parent's Primary Key while Column points to the Child's related Foreign Key.  It is important to use the child's BizDataObj in the Name Attribute and also specify the type of relationship being used.

<BizDataObj Name="BOAttendee" Package="demo" Class="BizDataObj" DBName="" Table="attendee" ... >
    <BizFieldList>
...
    <BizField Name="Id" Column="SYSID"/>
    </BizFieldList>
   <ObjReferences>
     <Object Name="shared.BOAttachment" Relationship="1-M" Table="attach" Column="PARENT_ID" FieldRef="Id" CascadeDelete="Y"/>
   </ObjReferences>
...
</BizDataObj>

Multiple SubCtrls can be specifed using the following syntax

SubCtrls="childform1_name;childform2_name;...".

Let's take a look at expressing a more complex example where the underlying tables are expressed as a Many to Many relationship.

BOEvent and BOAttendee have just such a relationship where the event form and attendee form will take the M-M as their relationship.  In the case of a M-M relationship, a third object is incorporated to connect the two indirectly related tables.

<BizDataObj Name="BOEvent" Package="demo" Class="BizDataObj"  Table="events" ...>
    <BizFieldList>
...
   <BizField Name="Id" Column="SYSID"/>
   </BizFieldList>
   <ObjReferences>
...
      <Object Name="BOAttendee" Description="Attendees of events" Relationship="M-M" Table="attendee" Column="SYSID" FieldRef="Id" CascadeDelete="Y" XTable="regist" XColumn1="EVENT_ID" XColumn2="ATTENDEE_ID" XDataObj="BORegist"/>
   </ObjReferences>
...
</BizDataObj>

The chain of related fields is:

FieldRef="ID" -> XColumn1="EVENT_ID" (Same Table) -> XColumn2="ATTENDEE_ID" -> Column="SYSID"

- Sample Event View:

EventView (Event-Attendee as M-M)
FMEvent as BizForm
 |-- BOEvent as BizDataObj
FMAttendeeChild as BizForm
 |-- BOAttendee as BizDataObj

BizForm Configuration

BizForm metadata DTD file can be found in Appendix B

Basic Layout: Data, Toolbar and Navigation bar
 

Openbiz BizForm is composed with three parts - data part, toolbar and navigation bar.

  • Data part is the area showing the data. It can be shown as list, table, form, tree and so on.
  • Toolbar is a list of controls where users can invoke standard or custom commands on the BizForm.
  • Navigation bar is a set of controls that controls data navigation or paging.

Here's a sample layout of a BizForm:

Toolbar                                     Navigation bar

Data part Row 1

Data part Row 2

Present BizDataObj by BizForm

BizForm represents data configured in a BizDataObj right down to the column level.  But should a column be rendered as a ListBox or a Radio button.  Better still, should the data be hidding in one display mode but not in another? To answer these questions a BizForm contains BizCtrls to map to BizFields in a BizDataObj. These BizCtrols contain information on how OB is to render the control.  Here's an example.

<BizForm Name="FMRegist" ... BizObj="BORegist" ...>
<BizCtrlList>
      <BizCtrl Name="reg_id" FieldName="Id" DisplayName="Registration Id" Enabled="N"/>
      <BizCtrl Name="reg_evtid" FieldName="EvtId" DisplayName="Event Id" ValuePicker="EventPopup" Enabled="N"/>
      <BizCtrl Name="reg_attdid" FieldName="AttendeeId" DisplayName="Attendee Id" Enabled="N"/>
      <BizCtrl Name="reg_attdfn" FieldName="AttdFName" DisplayName="First Name" Enabled="Y"/>
      <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" Enabled="Y" ValuePicker="FMAttendeePopup" DrillDownLink="AttendeeView,FMAttendee.attd_id=reg_attdid">
         <EventHandler Name="onchange" Event="onchange" Function="AutoPickValue(reg_attdln)" FunctionType="" />
      </BizCtrl>
      <BizCtrl Name="reg_attdnm" FieldName="FullName" DisplayName="Full Name" Enabled="N"/>
      <BizCtrl Name="reg_fee" FieldName="Fee" DisplayName="Fee" SelectFrom="Selection(Fee)" ColumnStyle="text-align:right;font-weight:bold"/>
      <BizCtrl Name="reg_onschd" FieldName="OnSchedule" DisplayName="On Schedule" Type="Checkbox" SelectFrom="Y"/>
</BizCtrlList>
</BizForm>

Present data with various HTML elements

HTMLControl or BizCtrl can present its data with various HTML elements by specifying element type and attributes. HTML elements are displayed in edit/query modes

Attributes of BizCtrl element in BizForm

Type Width Height HTMLAttr* Style** SeclectFrom Caption Image Comments
Text x x x
Limit the input length
x       Single line text input. Default type
Textarea x x x x       Multi-line Text input
RichText x x x x       Rich text editor edit HTML source
ListBox x x x
Show ListBox or ComboBox
x x
Set list of values
    ListBox or ComboBox
CheckBox x x x x x
Set True value
    CheckBox
Radio x
Arrange radio list 
x x x x
Set list of values
    Radio buttons
HTMLButton x x x x   x   Standard HTML Button
SubmitButton x x x x   x   Standard HTML Submit Button
ResetButton x x x x   x   Standard HTML Reset Button
Password x x x x       HTML password
Button x x x x   x x OpenBiz image button
Date x x x x       Textbox with date picker icon
Datetime x x x x       Textbox with datetime picker icon
HTMLBlock x x   x   x
Special Characters
  Caption is treated as HTML block
File x x x x       File control to upload file
AutoSuggest x x x
Limit the input length
x       Hybrid Text/Listbox

* HTMLAttr field can contain any valid additional HTML attribute applied on the HTML element type

** Style field can contain any valid style properties (css)

Limit the input length: 

HTMLAttr="maxlength=N" to limit the maximum number of characters that the user can enter in a text control. 

Show ListBox or ComboBox: 

By default show comboBox. If HTMLAttr="size=N", show N-row listbox.

Set list of values: 

SelectFrom="XmlFile(Key)" means this field control is a listbox or radio buttons whose data is from the "Key" elements in XmlFile.

Set True value: 

SelectFrom="Value" means this checkbox returns the Value when user check the checkbox.

Arrange radio list: 

By default the radion buttons are arranged horiztionally. If Width="1", you can force them arranged vertically.

Special characters:

"<" and ">" used in HTML block have to be replaced by "&lt;" and "&gt;". Please refer to http://www.w3schools.com/html/html_entities.asp for more details.

Rich text editor

Openbiz rich text editor primarily uses the code (LGPL license) from Kevin Rothhttp://www.kevinroth.com/rte/demo.htm. Thanks Kevin for his excellent work. It supports IE5.5+ and Firfox 1.x. Below is a screenshot.

Date/Datetime picker

Openbiz 2.1 uses the open source DHTML calendar 1.0 (LGPL license) provided by dynarch.com. The DHTML calendar is well documented at  http://www.dynarch.com/demos/jscalendar/doc/html/reference.html. Many thanks to Nik Chankov for his help on integrating openbiz with DHTML calendar. Openbiz by default uses system style for the calenar.

 

Auto suggestion text input

Thanks for the effort and Jim and Rocky, Auto Suggestion text input is available in release 2.2.2 beta2. To configure an auto suggestion input, simply set the "Type" of a HTMLControl or FieldCtrl as "AutoSuggest", then set the suggestion list in SelectFrom attribute. For example, to add a control that suggests the first name of attendees,

<BizCtrl Name="attd_fname" FieldName="FirstName" DisplayName="Auto Suggestion Field - Attendee First Name" Type="AutoSuggest" SelectFrom="demo.BOAttendee[FirstName], [FirstName] like '{@:Control[attd_fname].Value}%'"/>
</BizCtrlList>

The demo can be found at the "UI Components" tab in the demoapp. Its metadata is at demoapp/metadata/demo/FMFieldDepTest.xml.

Additional attributes of BizCtrl

  • FieldName - the BizField name of BizForm's BizDataObj
  • DisplayName - the label of the control, it is the column head in table format
  • Link - the hyperlink of the control under READ display mode. An example: <BizCtrl Name="LName" FieldName="LastName" Link="a valid relative or absolute url"/>. Users will see on the UI the last name (i.e. Wilson) hyperlink (the link is the url).
  • DrilldownLink - refer to "Configure drilldown link to another view"
  • Sortable - indicates if the field is sortable column in table format
  • Order - the sequence of BizCtrls
  • ValuePicker - refer to "Configure a BizCtrl to show popup"

Event handling in BizForms

As a html element can trigger events like onclick and onblur, each html Control or BizCtrl may have event handling functions associating to events. Event handling is defined in following syntax.

<Control Name="ControlName" Type="ControlType">
   <EventHandler Name="ehName" Event="eventName" Function="..." FunctionType="..." PostAction=""/>
</Control>

More than event handlers can be associated with a control.  Function and FunctionType attributes are moved from a Control Element to an EventHandler element under a Control element.

- Event is the html element event name. Please refer to http://www.w3.org/TR/REC-html40/interact/scripts.html, 18.2.3 Intrinsic events.

- Function gives a BizForm method name and arguments. Usually developers create their own methods in a customer class derived from BizForm. When the request hits BizController, it is routed to the BizForm method. If the method doesn't exist, an error is returned. Consider the following example:

  <EventHandler ... Function="objectName.methodName(arg1, arg2...)" .../>. 

If the objectName is empty, OB looks for the method in the current BizForm. For example, <EventHandler ... Function="SaveRecord()" .../>. Users can only invoke methods of objects who have metadata files. These objects include BizForm, BizDataObj, BizView and PluginService. BizForm methods and PluginService methods are callable from the client side in this way.

- FunctionType can be either RPC or Page or Form or Popup.

FunctionType Explanation Example
RPC the function is invoked on server side by HTTPRequest (AJAX). RPC is default value New record button:
<Control Name="btn_new" Function="NewRecord()" FunctionType="RPC"/>
Page the function is invoked on server side with page reload, form data is not passed to server Export button to bring up a file save dialog in the page
<Control Name="btn_export" Function="CallService(ioService,exportXML)" FunctionType="Page"/>
Form the function is invoked on server side by form submission Save button when there's file to upload in the form:
<Control Name="btn_save" Function="SaveRecord()" FunctionType="Form"/>
Popup the function is invoked on server side targeting to a new popup window Excel output button to show excel format in a popup:
<Control Name="btn_excel" Function="CallService(excelService,renderHTML)" FunctionType="Popup"/>

- ShortcutKey associates a shortcut key to the function. It is explained in "Keyboard navigation on BizForm".

- PostAction is the redirected page/view after an action is taken. It is explained in "Controlling page navigation".

 

Keyboard navigation on BizForm

BizForms can support user defined keyboard shortcuts.  This is another example of porting the rich client experience to the browser.   Shortcuts are defined in the BizForm and allow users to specify a wide variety of combinations that map to existing toolbar or navbar buttons such as Next Page, Last Page, Edit, New, Delete etc.  A control's EventHandler stor the shortcut definition as shown in the example provided.

<Control Name="" Function="" ShortcutKey="key_combination".../>

A BizForm only recognizes shortcut keys defined in controls of its Toolbar and Navbar.

Openbiz recognizes keys including:

Key input key text to use in ShortcutKey attribute
0,1,...9 0,1,...9
a,b,...z or A,B,...Z A,B,...Z
Ctrl key Ctrl
Shift key Shift
Alt key Alt
Enter key Enter 
Escape key Escape
Page up key PageUp
Page down key PageDown
Left arrow key Left
Right arrow key Right
Up arrow key Left
Down arrow key Down
Insert key Insert
Delete key Delete

Developers can configure a combination of Ctrl and/or Shift and/or Alt with other key, just use "+" to link them together. Be aware of not conflicting with default shortcut keys of browsers. Please refer to http://www.mozilla.org/support/firefox/keyboard for shortcut keys for different browsers.

See shortcut key sample in demoapp/metadata/demo/FMEvent.xml. This BizForm supports following shortcut keys:

Shortcut key Command to execute
Ctrl+Shift+Right go to next page
Ctrl+Shift+Left go to previous page
Ctrl+Shift+Down go to next record
Ctrl+Shift+Up go to previous record
Ctrl+Shift+N create a new record
Ctrl+Shift+E edit the selected record
Delete delete the selected record
Ctrl+Shift+Q switch to search record mode
Enter run search, or save record
Escape cancel search or cancel editing
Ctrl+Shift+C copy the selected record
Ctrl+Shift+R refresh form with default query

Form controls dependency

In a complex form, there are usually some controls depending on the values of other controls. When the parent control changes, child controls change accordingly. This is so called form controls dependency.  With the help of OB's expression language, a controls relationships can specified in BizForm metadata files. With the help of event handlers, events on the parent control will cause changes to specified child controls on the fly.

A sample form is delivered  under demoapp/metadata/demo/FMFieldDepTest.xml

The first combobox is the parent control. Based on its value,
- 2nd control will be enabled or disabled (BizForm configuration)
- 3rd control will be hidden or shown (BizForm configuration)
- 4th control will have different lists (BizForm configuration)
- 5th control will change value and color when monuseover the 1st control (customer js class extending from jbForm)

Configuration of record-selecting popup BizForm 

Users may need to pick records from a different form in the following cases:

  • Add/change the child record (parent-child is M-1) by picking another child record.
  • Add a child record in the child form (parent-child is M-M) by picking an existing child record
  • Add/change the joined fields by picking a record from joined dataobj.

Note: Openbiz keeps only one instance of a metadata object (of BizDataObj, BizForm, BizView) in a user session, so always configure a different object when two instances of same entity needed in one view. For example, on an Event form (FMEvent / BOEvent), we usually configure an event popup as (FMEventPopup / BOEventX). There're two ways to configure a record-selecting popup BizForm.

  • Configure a html control to show popup

To configure a html control to show popup form, users can set "ShowPopup($popupFormName)" in the control Function attribute and set FunctionTarget="Popup". This configuration can be used in picking a child record (M-1 or M-M) in the child form.

<Control Name="btn_new" Caption="Add" Type="Button" Function="ShowPopup(demo.FMAttendeePopup)" FunctionTarget="Popup"/>

On the popup form, add a button to call AddToParent() to add the currently selected record to the parent form (the form trigger the popup). 

  • Configure a BizCtrl to show popup

To configure a BizCtrl to show a popup from a user ValuePicker attribute.

<BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup"/>

On the popup form, add a button to call JoinToParent() to join the current selected record to the parent form (the form trigger the popup).

  • Configure an automatic value picker for a BizCtrl

You can use a ValuePicker attribute to allow users to click the icon to show the picker popup window. Users may want to type in the value in the control and the system will automatically pick the right record according to the user input. Openbiz supports this feature by BizForm's AutoPickValue($ctrlname) method. To configure auto picker.

<BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup">
   <EventHandler Name="onchange" Event="onchange" Function="AutoPickValue(reg_attdln)" />
</BizCtrl>

According to the user input, the behavior is described in the following table:

Case User input Behavior
1 empty delete all related controls values
2 not empty query the DataObj of valuepicker BizForm with searchRule as [field] LIKE 'input_value%'. Based on the query results:
  • if single record returned, auto fill all related controls values with returned value
  • if no record returned, show value picker popup with no searchRule
  • if multiple records returned, show value picker popup with the searchRule

Configure drilldown link to another view

You can configure a BizCtrl to render with a hyperlink that will navigate to another view and display the record that clicked.  In this way users can "drilldown" to a different view of a give record.  For example an application may display high level records with drilldown links to a detail view.

In a BizForm, set a DillDownLink attribute of a BizCtrl. The syntax is

DrillDownLink="OtherView,OtherBizForm.OtherBizCtrl=MyBizCtrl".
OtherView - a view name the link takes to;
OtherBizForm - an independent BizForm, which is not a subforml of any other BizForm, in OtherView;
OtherBizCtrl - a BizCtrl of OtherBizForm
MyBizCtrl - a BizCtrl in current BizForm 

Here's an example: <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup" DrillDownLink="AttendeeView,FMAttendee.attd_id=reg_attdid"/>.

Select field data from comboBox or ListBox

- Bind static list to comboBox

In your BizForm, you assign SelectFrom="Selection(Fee)" for a BizCtrl, which means this field control is a comboBox whose data is from the "Fee" elements in Selection.xml file. Please see example in demo FMRegist.xml where BizCtrl reg_fee is defined as a comboBox.
<Selection>
  <Fee Value=""/>
  <Fee Value="15"/>
  <Fee Value="20"/>
</Selection>

Also, you can give both value and text. If only give value, openbiz uses the value as the display text.
<Selection>
   <ChartOption Value="AAA" Text="BarLine Chart"/>
   <ChartOption Value="BBB" Text="Pie Chart"/>
   <ChartOption Value="CCC" Text="GroupBar Chart"/>
</Selection>
You can make up your own xml file that has list of values for selection.

- Bind dynamic list (Table column) to comboBox

In your BizForm, you assign SelectFrom="BizDataObjName[BizFieldName]" for a BizCtrl, which means this field control is a comboBox whose data is from the table column mapping to the BizFieldName of the BizObjName. To avoid same values appear in the comboBox, you need to make sure the BizObj query returns an unique list.

Format SelectFrom="BizDataObjName[BizFieldName4Text:BizFieldName4Value]" is supported too. So users can show BizFieldName4Text field in comboBox and set BizFieldName4Value for value.

A SearchRule can be applied on the SelectFrom with syntax as SelectFrom="BizDataObjName[BizFieldName4Text:BizFieldName4Value], SearchRule_of_the_BizDataObj". For example, <BizCtrl Name="" ... SelectFrom="BOEvent[Name], [Name] LIKE '%Soc%'"/>.

Controlling page navigation

Openbiz has an unique concept of display mode. BizForm can have more than one display modes. Basically each display mode is a rendering mode of the BizForm. A Bizform presents a BizDataObj data to UI, the same data set can be rendered in different modes which is called "display modes".

- Display modes in a BizForm

Display modes are specified in the <DisplayModes> section of a BizForm metadata file. You can associate a smarty template with each mode. For details please refer to build view and form web templates.

Usually a BizForm can have READ, NEW, EDIT, QUERY display modes. But developers can specify their own modes for the BizForm. An example is under /demoapp/metadata/shared/FMCalendar.xml. It has display modes such as "LIST", "DAY", "WEEK", "MONTH".

Switching between display modes in a BizForm is done in code by calling BizForm method SetDisplayMode($mode). Code may be applied to each display mode to implement special logic.

Each control or BizCtrl has a DisplayMode attribute specifying which modes will show that BizCtr. By default leaving this attribute empty means the BizCtrl will be shown in all displaymodes.  You can set one or more modes using DisplayMode = "MODE1|MODE2|...". For example,
<BizCtrl Name="LastName" ... DisplayMode="EDIT|NEW"/>
means that LastName will only show on EDIT and NEW modes.

- Page redirection after an action is finished

It's very common that users click on a button to trigger an action on server side and after the action is finished the page is redirected to another page. Page redirection can be specified as a post action in BizForm metadata file. The syntax is

<EventHandler Name="..." Function="..." PostAction="url|view"/> PostAction can accept url:url_string or view:view_name.

An example is the login form demoapp/metadata/shared/FMAuth.xml

<Control Name="btn_submit" Image="" Caption="Submit" Type="HTMLButton" Function="Login()" PostAction="url:login.php?login=success"/>

- Error page and error message

If an action errors out, OB should return an error page or error popup to the users browser.

TODO FILL THIS IN

Import and export from BizForm

Data import and export support is and important feature for off-line users. Off-line users usually run the application (web application also can be run in local box) locally on their laptops and take the work back to synchronize with server database. Openbiz provides import and export support in the following ways:

Data export - implemented in exportXML method of ioService. The exported xml file has format as 

<BizDataObj Name="demo.BOAttendeeX">
  <Record>
   <Field Name="field name" Value="field value" /> *
  </Record>
</BizDataObj>

Data import - implemented in importXML method of ioService. The xml file to import has the same format as described above.

Example import and export buttons are configured in the FMAttendee form. Pressing the export button invokes ioService's exportXML method directly, while the ixport button brings up a popup window to ask for the file to be imported. Please refer to the demoapp/metadata/demo/FMAttendee.xml for details.

It would be possible to add more export/import methods in ioService to support other file types.

Upload file from BizForm

A File upload feature is supported in OB's shared package. Check out the example metadata file in the demoapp at demoapp/metadata/shared/FMAttachment.xml and in the class file is at demoapp/bin/shared/FMAttachment.php.

To upload a file, developers needs to configure a BizCtrl with type as "File". It maps to a BizField with type as "Blob".

To download the file, users needs to configure a BizCtrl with Function as Download($record_id). Download method is implemented in FMAttachment class.

Please refer to the FMAttachement class and metadata for details.

Configuration of BizDataObj

The DTD file of the BizDataObj xml is listed in Appendix A.1

Map BizDataObj to Tables

Openbiz maps database tables to objects with BizDataObj. This section introduces the concept of mapping one or more tables with BizDataObj, the next section has full details describing how OB tackles Object Relation Mapping. At its most basic, a BizDataObj contains  parts such as table name and mapping between BizDataObj fields and table fields of SQL Functions.

  • Specify the base table: 

    <BizDataObj Name="BizDataObjName" Table="TableName" ...>

  • Map a Column to a BizField: 

    <BizField Name="FieldName" Column="ColumnName"....>
    One of BizFields must have name as "Id". This is required.
    This Id field usually maps to the primary key column of a table.

  • Map SQL Function to BizField: 

    Users can assign a BizField a SQL function provided by the database engine. The syntax is <BizField Name="FieldName" Column="" SQLExpr="FUNC([FieldName1]...[FieldName2]...)">. Make sure that the Column attribute is empty or the SQL function will not work. For example: <BizField Name="FullName" Column="" SQLExpr="CONCAT([FirstName],' ',[LastName])"...>
    Note the example SQLExpr contains query related attributes like [FirstName] and [LastName]  A [FieldName] is not evaluated to field value. [FieldName] is the syntax of query lanaguage and will instead reference the Column attribute of that BizField.

  • Specify a default value:

    <BizField Name="FieldName" Column="ColumnName" DefaultValue="default_value">. Use DefaultValue attribute to give default values to the BizField when a dataobject creates a new record.

Query Language in BizDataObj

Openbiz users won't worry about composing complicated SQL statements since BizDataObjs support a more intuitive query language at the object level. The basic syntax is "[FieldName] opr 'Value' AND/OR [fieldName] opr 'Value'..." Here "opr" is SQL operator. At runtime, OB converts [FieldName] to the column name and generates a SQL statement. OB also supports including table relationships in generated query statements.

  • Specify the default query in SearchRule
    <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" SearchRule="[Start]>'1999-10-20'" ...>

  • Specify the default sort in SortRule
    <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" SortRule="[Start] ASC" ...>

  • Specify additional SQL statement in OtherSQLRule
    <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" OtherSQLRule = "GROUP BY [EvtId] HAVING [Fee]>10" ...>

Data type and format of BizFields

BizFields support following data types and formats in their Type and Format attributes.

Type Format Syntax Format Example
Text none Text is the default type  
Number format supported by printf <BizField ... Type="Number" Format="%..." ...> %5.2f to print a float number
  "Int" - integer format according locale <BizField ... Type="Number" Format="Int" ...> If locale=enu, 12345.678 is displayed as 12,346
  "Float"- float format according locale <BizField ... Type="Number" Format="Float" ...> If locale=enu, 12345.678 is displayed as 12,345.68
Date In default read-only mode, a date can be formatted according to the Date format. <BizField ... Type="Date" Format="date format" ...> 6/21/2003 can be formatted as
%A, %b %d %Y - Saturday, Jun 21 2003 if system locale is enu
Datetime In default read-only mode, a date can be formatted according to the Date format. <BizField ... Type="Datetime" Format="datetime format" ...> 6/22/2003 9:30am can be formatted as
%m/%d/%Y %H:%M:%S - 06/22/2003 09:30:00 if system locale is enu
Currency Formatted according to locale setting <BizField ... Type="Currency" Format="Currency" ...> 1456.89 is formatted as $1,456.89 (enu)
1456.89 is formatted as F1 456,89 (fra)
Phone Formatted according to given mask # <BizField ... Type="Phone" Format="mask string" ...> 1234567890 is formatted as 
mask=(###) ###-####, 
phone=(123) 456-7890
mask=###-###-####, phone=123-456-7890
  If a phone number starting with "*", it represents international phone number, it won't be formatted   *123 4567890 is treated as international number
Blob/Clob none <BizField ... Type="Blob" ...>
<BizField ... Type="Clob" ...>
 

Data validations

Validation Type Example
Required - indicates the field can not be empty <BizField Name="Name" Required="Y" Column="NAME"/>
Validator - simple expression language  <BizField Name="Fee" Type="Currency" Format="Currency" Validator="{[Fee]>=15}" Column="FEE">
Validation Service - Use pre-made validation rules or create your own    <BizField Name="Email" Column="EMAIL" Validator="{@validate:email('[Email]')}"/>
    <BizField Name="Phone" Column="PHONE" Validator="{@validate:phone('[Phone]')}"/>

The latest 2.2.2 RC 2 demo contains several working examples. Check out demoapp/metadata/demo/BOAttendee.xml

 

Object Relational (O/R) Mapping

 o support O/R mapping, TableJoin and ObjectReference are introduced to BizDataObj metadata file.

To understand the O/R mapping, a sample is listed below:

attendee:regist = 1:M (one to many), regist:attendee = M:1 (many to one)

events:regist = 1:M (one to many), regist:events = M:1 (many to one)

attendee:events = M:M (many to many)

Map a table to a BizDataObj

To map a table to a BizDataObj, users only need to configure the BizFieldList part in the metadata. 

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
</BizDataObj>

Primary key (Id) generation

From Openbiz 2.1RC, BizDataObj supports multiple id generation algorithms. Add a BizDataObj attribute IdGeneration="Openbiz|Identity|Sequence:seqname|GUID|UUID|Other...".

IdGeneration how id (Primary Key column) is generated Supported database types
Openbiz (default) Id is generated using "ob_sysids" table which stores SYSID information for all tables who have SYSID column Apply to all database types
Identity Primary key column is generated by database engine.
Id is called "Identity" column in SQL Server, also called "auto-increment" column in MySQL.
MySQL, SQL Server, Sybase, DB2
Sequence:seqname Primary key column is generated by database sequence. "seqname" is the sequence name used to generate PK. Oracle, PostgreSQL, DB2
GUID Primary key column is database-generated GUID MySQL, SQL Server, Oracle
UUID Primary key column is generated with php uuid function Apply to all database types
Other Developers can write customer specific Id generation algorithm by modifying function GetNewID(...) in genIdService class under openbiz/bin/service/genIdService.php decided by customer 

Composite key support

In Openbiz 2.1, BizDataObj supports composite key. This feature would be useful when working with legacy database tables who does not have single primary key column. The syntax of BizDataObj whose Id field maps >2 primary key columns is:

<BizDataObj Name="" Package="" Class="" ... IdGeneration="None">
<BizField Name="fpk1" Column="PK1"/>
<BizField Name="fpk2" Column="PK2"/>
<BizField Name="Id" Column="PK1,PK2" />
...

Map multiple tables to a BizdataObj

User can map multiple tables to a BizDataObj through Join. Joined table is referred by a foreign key column in the base table of the BizDataObj, that says the base table has a foreign key points to joined table's column.

<BizObj Name="BORegist" Package="demo" Class="BizObj" Table="regist" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="EvtId" Column="EVENT_ID"/>
  <BizField Name="AttendeeId" Column="ATTENDEE_ID"/>
  <BizField Name="AttdLName" Join="attendee" Column="LASTNAME"/>
  <BizField Name="AttdFName" Join="attendee" Column="FIRSTNAME"/>
</BizFieldList>
<TableJoins>
  <Join Name="attendee" Table="attendee" Column="SYSID" ColumnRef="ATTENDEE_ID" JoinType="INNER JOIN"/>
</TableJoins>

Join Attribute Description
Name The name of the join. It is referred in the Join attribute of BizField
Table The joined table name
Column The joined column name
JoinRef If JoinRef is empty, the joined table joins to the base table. User can specify the JoinRef in the 2-level join.
ColumnRef ColumnRef refers to the column of the base table (or the JoinRef table). It contains the foreign key of the Join column.
JoinType INNER JOIN, LEFT JOIN, RIGHT JOIN, or FULL OUTER JOIN.

The query SQL is like "SELECT ... FROM BaseTable INNER JOIN JoinedTable ON BaseTable.ColumnRef=JoinedTable.JoinedColumn ...". In the above example, the SQL is 

SELECT T0.SYSID, T0.EVENT_ID, T0.ATTENDEE_ID, T1.LASTNAME, T1.FIRSTNAME 
FROM regist as T0
         INNER JOIN attendee as T1 ON T0.ATTENDEE_ID = T1.SYSID

- More explanation about the JoinRef

JoinRef is to support cascade-join. For example, in a query, table A joins B and table B joins C. Table A and C is joined through table B. User can use the following part to link C and A together.

<TableJoins>
<Join Name="join_b" Table="B" Column="B_PK" ColumnRef="A_FK_B" JoinType="LEFT OUTER JOIN"/>
<Join Name="join_c" Table="C" JoinRef="join_b" Column="C_PK" ColumnRef="B_FK_C" JoinType="LEFT OUTER JOIN"/>
</TableJoins>

Many to one relationship between BizDataObjs

Many to one relationship between two tables means table 1 has a column that contains the foreign key pointing to a key/unique column in table 2. To map such relationship between two BizDataObjs, use an Object in ObjectReference section.

<BizObj Name="BORegist" Package="demo" Class="BizObj" Table="regist" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="EvtId" Column="EVENT_ID"/>
  <BizField Name="AttendeeId" Column="ATTENDEE_ID"/>
  <BizField Name="AttdLName" Join="attendee" Column="LASTNAME"/>
  <BizField Name="AttdFName" Join="attendee" Column="FIRSTNAME"/>
</BizFieldList>
<TableJoins>
  <Join Name="attendee" Table="attendee" Column="SYSID" ColumnRef="ATTENDEE_ID" JoinType="INNER JOIN"/>
</TableJoins>
<ObjReferences>
  <Object Name="BOEvent" Description="" Relationship="M-1" Table="events" Column="SYSID" FieldRef="EvtId"/>
</ObjReferences>
</BizObj>

Object Attribute Description
Name The name of the referred BizDataObj
Description  
Relationship Relationship between this dataobj and the referred dataobj
Table The table of the referred dataobj
Column The column of the referred dataobj's table
FieldRef The field mapping to the foreign key column in base table

To get the referred dataobj (child dataobj), call GetRefObject($objame) method from parent dataobj. The referred dataobj instance will have the restriction according to the parent dataobj.

One to many relationship between BizDataObjs

One to many relationship between two tables means table 2 has a column that contains the foreign key pointing to a key/unique column in table 1. To map such relationship between two BizDataObjs, use an Object in ObjectReference section.

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
<ObjReferences>
  <Object Name="BORegist" Description="" Relationship="1-M" Table="regist" Column="EVENT_ID" FieldRef="Id" CascadeDelete="Y"/>
</ObjReferences>

</BizDataObj>

Object Attribute Description
Name The name of the referred BizDataObj
Description  
Relationship Relationship between this dataobj and the referred dataobj
Table The table of the referred dataobj
Column The column of the referred dataobj's table. This column contains the foreign key to the base table
FieldRef The field mapping to the column in base table
CascadeDelete Indicate whether deleting a record in base table will cause the deletion of all related record in referred table.

To get the referred dataobj (child dataobj), call GetRefObject($objame) method from parent dataobj. The referred dataobj instance will have the restriction according to the parent dataobj.

- One to one relationship between BizDataObjs

One to one relationship is a special case of many to one or one to many relationship.

Many to many relationship between BizDataObjs

Many to many relationship between two tables means an intersection table (also called cross reference table, or correlation table) contains the foreign key columns pointing to a key/unique column in table 1 and table 2. To map such relationship between two BizDataObjs, use an Object in ObjectReference section.

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
<ObjReferences>
  <Object Name="BOAttendee" Description="" Relationship="M-M" Table="attendee" Column="SYSID" FieldRef="Id" CascadeDelete="Y"
XTable="regist" XColumn1="EVENT_ID" XColumn2="ATTENDEE_ID"/>
</ObjReferences>
</BizDataObj>

Object Attribute Description
Name The name of the referred BizDataObj
Description  
Relationship Relationship between this dataobj and the referred dataobj
Table The table of the referred dataobj
Column The column of the referred dataobj's table. This column contains the foreign key to the base table
FieldRef The field mapping to the column in base table
CascadeDelete Indicate whether deleting a record in base table will cause the deletion of all related record in intersection table.
XTable The intersection table name
XColumn1 The intersection table column that has the foreign key of the base table
XColumn2 The intersection table column that has the foreign key of the referred table
XDataObj
BizDataObject whose base table is the intersection table that is XTable. When user associates one record from referred DataObject to the base DataObject, a new record is created from the XDataObj and added in the intersection table. 

To get the referred dataobj (child dataobj), call GetRefObject($objame) method from parent dataobj. The referred dataobj instance will have the restriction according to the parent dataobj.

BizView and BizForm Configuration 

BizView metadata DTD file can be found in Appendix A.2.

BizForm metadata DTD file can be found in Appendix A.3.

BizView - the HTML page container

BizView is the physical web page that contains multiple BizForms and other HTML elements. Its layout is based on smarty template enginee. BizView defines the layout of BizForms as well as the relationship between BizForms.

- Map BizDataObj relationship of BizForms

If more than one BizForm is placed in a BizView and they are linked by specifying Parent-Child relationship in BizView, the BizForms will have the relationship of their underline BizDataObj.

<BizView Name="EventView" ...>
<ControlList>
  <Control Name="fm_event" Form="FMEvent" SubCtrls="FMAttendeeChild"/>
  <Control Name="fm_attd" Form="FMAttendeeChild"/>
</ControlList>
</BizView>

SubCtrls attribute has syntax like SubCtrls="childform1_name;childform2_name;...". It tells children forms name of the parent form, which means children form data may change along the change of the parent form.

Because BOEvent and BOAttendee have many to many relationship, the event form and attendee form will take the M-M as their relationship. They present the data relationship on user interface.

- Sample Event View:

EventView (Event-Attendee as M-M)
FMEvent as BizForm
 |-- BOEvent as BizDataObj
FMAttendeeChild as BizForm
 |-- BOAttendee as BizDataObj

Basic BizForm layout: Data, Toolbar and Navigation bar

Openbiz BizForm is composed with three part - data part, toolbar and navigation bar.

  • Data part is the area showing the data. It can be shown as list, table, form, tree and so on.
  • Toolbar is a list of controls where users can invoke command on the BizForm.
  • Navigation bar is a set of controls that controls data navigation such as paging, scrolling.

Here's a sample layout of a BizForm:

Toolbar                                     Navigation bar
Data part

Present BizDataObj by BizForm

BizForm represents data from BizDataObj. BizForm defines the mapping between BizCtrls in the BizForm and the BizFields in BizDataObj. Here's an example.

<BizForm Name="FMRegist" ... BizObj="BORegist" ...>
<BizCtrlList>
  <BizCtrl Name="reg_id" FieldName="Id" DisplayName="Registration Id"/>
  <BizCtrl Name="reg_evtid" FieldName="EvtId" DisplayName="Event Id"/>
  <BizCtrl Name="reg_attdid" FieldName="AttendeeId" DisplayName="Attendee Id"/>
  <BizCtrl Name="reg_attdfn" FieldName="AttdFName" DisplayName="First Name"/>
  <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name"/>
</BizCtrlList>
</BizForm>

Openbiz Development Guide

Show openbiz views (pages)

- User URL string as controller.php?view=...&form=...&rule=...&mode=...&OtherInputs...

- Use client javascript GoToView(view, rule, loadPageTarget)

Input Description Sample
view bizview name shared.CalDetailView
form bizform name. This form must not depend on (a subform of) another bizform shared.FMCalDetail
rule the search rule of a bizform

syntax is "form.ctrl operator value".
operator can be =,>,>=,<,<=,!=. "LIKE %" SQL format is also valid rule. "AND", "OR" can be used to add more restriction.

FMSponsor.spr_exp>=12000 

FMSponsor.spr_name=\'Midas Auto\' OR FMSponsor.spr_id=\'SPSR_2\'

FMSponsor.spr_name LIKE \'S%\'

loadPageTarget the window or frame target to load the page  

Build view and form web templates

Smarty template engine is used in OpenBiz to render the HTML output. We provides some basic templates for render BizForm and BizView. You can create your own templates. Remember that an openbiz form must begin with a form tag <form id={$name} name={$name}>. For detail, please refer to http://smarty.php.net/docs.php 

Smarty engine recognizes the subdirectories under the main template directory. So you can create a fold under demoapp/templates/ and put template files there. When you give template file name in metadata file, just give Template="subdir/view.tpl".

- Draw BizForm as a html table

In BizForm xml file, you need give DataFormat as "block" and FormatStyle as table style which is given in css file.
<Mode ... TemplateFile="list.tpl" ... DataFormat="htmltable" FormatStyle="tbl"/>

In template file, {$fmttable}represents form whole html table.

Please refer to demo files FMEvent.xml and list.tpl

- Draw BizForm as a set of controls

Since the array dataformat output to smarty template is associated array, user can easily layout controls by their names. The associated array has format as fields[control_name][label] and fields[control_name][control].

Please refer to demo files FMEvent.xml and edit.tpl

Three DataFormats decide what data is passed to templates

DisplayMode DataFormat Data passed to template Controllability on template Example
array - Variable name to use in template is $fields
- associated array of single record
- array (control_name=>array ("label"=>label_text, "control"=>control_html))
Highly controllable in template edit.tpl
table - Variable name to use in template is $table
- 2D array of multiple records
- array (index=>array (control1_name=>value1, control2_name=>value2, ...))
  array[0] is column header
  array[1-n] are the 1st record to nth record
Highly controllable in template rptlist.tpl
block - Variable name to use in template is $block
- HTML string
lowly controllable in template list.tpl

Using BizDataObj functionalities

Only basic usage of BizDataObj is listed below. Please refer to the API doc for details.

Query and get results

1.x BizObj is renamed as BizDataObj in 2.0, because it mainly acts as business data unit. 

1.x use GetField and SetField to do get and set field values. In 2.0, no field level methods, but using GetRecord() and UpdateRecord() method to do record level operations. The idea behind is to make easier coding to retrieve query results and provide coarse-grained interfaces between 2 layers.

1.x way to query and get records

$bizobj->SetSearchRule("...");    // set search rule
$bizobj->RunSearch(-1);    // run query against the database tables. 
$bizobj->Home();    // reset the result record set
$hasVal = $bizobj->MoveFirst();    // move cursor to first record
while ($hasVal)
{
    foreach ($fieldlist as $field)
        $field_val[] = $bizobj->GetField($field);
   
// user logic code can be put here. 
    $hasVal = $bizobj->MoveNext();    // move cursor to next record
}

2.0 way to query and get records - option 1

$bizobj->SetSearchRule("...");    // set search rule
$bizobj->RunSearch(-1);    // run query against the database tables. query results can be cached
while ($recArray = $bizobj->GetRecord(1))    // get current record and move the cursor to the next record 
{
    // user logic code can be put here. recArray is an associated array whose key is "fieldname" and value is value of the field
}

2.0 way to query and get records - option 2

$bizobj->FetchRecords ($searchRule, $resultSet, $numRecords);    // get the whole recordset (list of recArray), query results won't be cached

Insert, Update and Delete a record 

// Insert Record
$recArr = $boUser->NewRecord();    // NewRecord returns an empty record array with a generate Id field
$recArr["LastName"] = "Test";
$recArr["FirstName"] = "Add";
$ok = $boUser->InsertRecord($recArr);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

// Update a record
$boUser->SetSearchRule("[Id]='USER-1006'");
$boUser->RunSearch();
$recArray = $bizobj->GetRecord(0);
$recArray["FirstName"] = "Update";
$ok = $boUser->UpdateRecord($recArray);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

// Delete a record
$boUser->SetSearchRule("[Id]='USER-1006'");
$boUser->RunSearch();
$recArray = $bizobj->GetRecord(0);
$ok = $boUser->DeleteRecord($recArray);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

Using BizForm functionalities

User can configure function in BizForm metadata file to invoke appropriate action on server side. The commonly used BizForm methods are listed below. Please refer to the API doc for details.

Query and show results

  • SearchRecord - show the query record mode
  • RearchRecord - Issue the query with user input in query mode and return to read mode

Insert a new record

  • NewRecord - show the new record mode
  • SaveRecord - Save current edited record with user input in query mode and return to read mode

Update a record

  • EditRecord - show the edit record mode on current focus record
  • SaveRecord - Save current edited record with user input in query mode and return to read mode

Delete a record

  • DeleteRecord - delete the current focus record

Copy a record

  • CopyRecord - copy the current focus record to new record

Page Navigation

  • MoveNext - show next page records
  • MovePrev - show previous page records

User input validation

According the topic at http://www.boringguys.com/?p=30, there are 3 different types of data validation checks one can do:

  • Syntactic validation - check data syntax 
  • Semantic validation - check one piece of data makes sense in regards to other incoming data
  • Domain or model validation - check data against another source of acceptable values

Syntactic and semantic validation can be implemented on client side and service side. Domain validation involves query data source, it is usually done in service code that connects to database.

Client side form validation

Openbiz does input validation using jsval library (LGPL, http://jsval.fantastic-bits.de/). To configure a validation rules for an openbiz HTMLControl, developers can use jsVal's "Inline initialization" to add validation attributes to HTMLAttr part of HTMLcontrol and FieldControl.

<Control Name="" Type="" HTMLAttr="jsval validation attributes here" ... /> 

Example: <BizCtr Name="email" Type="Text" HTMLAttr="regexp='JSVAL_RX_EMAIL' minlength=5..." ... /> 

In addition, HTMLControl has a Required (=Y|N) attribute. It is passed to pass as $fields['required'] (along with $fields['label'] and $fields['control']) to smarty template. In smarty template (edit.tpl), has code {if $item.required=="Y"} <span class='required'>*</span>{/if} to append a * to the label. Then the required control's label looks as "Email *"

Server side input validation

Openbiz mainly support validation on BizDataObj. In BizField, Required and Validator attributes are used for such purpose. Please see the BizDataObj configuration chapter for explanation of these two attributes.

Developers can use customer class to override DataObj::ValidateInput() method or Field::Validate() method achieve their own validation rules.

BizForm has an empty ValidateForm method which may be overridden by customer classes to implment special validation logic.

Extend OpenBiz classes

OpenBiz provide many functionalities to building a complicated web application. But different application has different requirement, so you may extend OpenBiz packages to build customer applications.

Extend server side classes

Because OpenBiz packages are based on object-oriented design, you can easily build up your own object by extending these packages and inherit all useful functions provided by them.

Extended classes are automatically loaded on demand. Extended class  must be included in a file with format as ClassName.php.

Use can specify class name for BizDataObj, BizField, BizView, BizForm, BizCtrl, Control and PluginService by filling the "Class" attribute of in metadata file

Base Class Where to specify the extend class
BizDataObj <BizDataObj ... Class="" ...>
BizField <BizField ... Class="" ...>
BizView <BizView ... Class="" ...>
BizForm <BizForm ... Class="" ...>
FieldControl <BizCtrl ... Class="" ...>
HTMLControl <Control ... Class="" ...>

Example: Extend BizDataObj and BizForm

/**
* class BOUser is the BizDataObj class to implement USER logic object
*/

class BOUser extends BizDataObj 
{
    function BOUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

/**
* class FMUser is the BizForm class to implement USER UI object
*/

class FMUser extends BizForm 
{
    function FMUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

      function Render() {}    // override Render()
}

Extend client side classes

BizForm is the main server side presentation class, it has its counterpart class on client browser side. In the BizForm metadata, users can specify client side class in jsClass attribute of BizForm element. For example.

<BizForm Name="FMEvent" ... Class="BizForm" jsClass="jbForm"...>

Openbiz provides two client side classes AjaxForm and jbForm that is a subclass of AjaxForm.

AjaxForm methods:

  • CallFunction(method, params_array) - convert function to request and send it to server. A server side BizForm method is invoked by this method if there's no specific method implemented in the client class. For example, a BizForm, whose jsClass=jbForm, has a method named "SelectRecord". Openbiz will check if "SelectRecord" method is defined in jbForm class. If yes, it calls jbForm's SelectRecord(params_array), otherwise it calls CallFunction(method, params_array).
  • CallbackFunction(retContent) - Ajax callback function. It passes the returned content to Show().
  • CollectFormData() - collect form data into a message in Ajax call
  • Show(retContent) - called by callback function to show Ajax returned content in the form

jbForm methods:

  • CollectFormData() - overriding AjaxForm CollectFromData(), add additional "selected row" in the form data
  • SelectRecord(params_array) - special logic on select record call
  • SortRecord(params_array) - special logic on sort record call
  • DeleteRecord(params_array) - special logic on delete record call

To implement UI logic on client side, developers need to create their own client side class like jbForm and give the class name to jsClass attribute of BizForm element. If you need special logic in some methods, add these methods in the client class, which can be subclass of either AjaxForm or jbForm. These methods can be pure client code or it can this.CallFunction(...) to send the request to server.

An example:

Form metadata file is like:

<BizForm ... Class="MyForm" jsClass="MyjbForm"...>
...
   <BizCtrl Name="mybutton" ...>
      <EventHandler Name="onclick" Event="onclick" Function="server_MyButtonClick"/>
      <EventHandler Name="onblur" Event="onblur" Function="js_MyButtonBlur"/>
...
</BizForm>

In server side MyForm class, server_MyButtonClick() needs to be defined.

In client side MyjbForm class, js_MyButtonBlur() needs to be defined. Of course, if server_MyButtonClick() is defined in client class, server_MyButtonClick() needs to call this.CallFunction("server_MyButtonClick", params_array) at the end of the method to send the request to server MyForm server_MyButtonClick() method. The client side code will be like:

function MyjbForm(name) {}
MyjbForm.inheritsFrom(jbForm); //set inheritance
MyjbForm.prototype.js_MyButtonBlur = function (params_array)
{
    // put client logic here
    ...
}
MyjbForm.prototype.server_MyButtonClick= function (params_array)
{
    // put client logic here
    ...
    // send request to server side at the end
    this.CallFunction("server_MyButtonClick", params_array);
}

Implement Plug-in Service

Openbiz customer can write their special logic by implement Plug-in Service. Plugin services are also metadata-driven objects. Service code is under bin/service and metadata is under /metadata/service. The plugin service metadata only gives the service name, package and implementing class. Any xml elements can be child of the root PluginService element. This is because different services may have different metadata configuration. Please refer to the Appendix to see the DTD of plugin service metadata xml file.

Openbiz core library includes services under openbiz/bin/service/ and their metadata files under openbiz/metadata/service/.

  • excelService.php - print Excel output with HTML or CSV formats
  • authService.php - authentication service, please refer to next chapter for usage
  • accessService.php - view access control service, please refer to next chapter for usage
  • profileService.php - user profile service, please refer to next chapter for usage
  • logService.php - write log to file
  • ioService - data winput/output service
  • pdfService.php -  prints PDF report
  • emailService.php - integrated with PHPMailer to send emails through smtp mail server.
  • doTriggerService - BizDataObj trigger service
  • auditService - audit trail service to trace data change

In the application, you can specify your own plugin service implementation with following methods.

  1. Change the service metadata content under your_app/metadata/service/, still use the core service. For example, you can write different accessService.xml to control the view access rule, but the implementing class is accessService.php in core library. The accessService.xml is like 
    <PluginService Name="accessService" Package="service" Class="accessService">
       application specific view access definition
    </PluginService>
  2. Specify the service implementing class. For example, different applications have different profile service. The profileService.xml is like 
    <PluginService Name="profileService" Package="service" Class="your_own_service_class">
    </PluginService>
  3. Combine the above 2 methods.

Write a plug-in service

Implement the class and method in the ClassName.php
A input argument of the method are the caller's object name (a BizForm name) and the input data string (a collection of form values from client browser). It implements the user-specific business logic and returns void. See the following code snippet.

class pdfService
{
 function pdfService() {}

 function renderView($viewName)
 {
  global $g_BizSystem;
  // get the view object and render the view to a html string
  $viewobj = $g_BizSystem->GetObjectFactory()->GetObject($viewName);
  if($viewobj) {
    $viewobj->SetConsoleOutput(false);
  $sHTML = $viewobj->Render();
  // convert HTML to PDF
  // ... customer code to do the convert 
 }
}

Call a plug-in service method

  • Call service in form. Define the caller function in BizForm metadata file
    <... Function="CallService(ClassName,MethodName)"...> is to call a method "MethodName" of the service "ClassName". ClassName is a class which defined in ClassName.php under bin/usrlib/ directory
  • Call service with url. Use url like bin/BizController.php?F=Invoke&P0=[servicename]&P1=[methodname]&P2=[parameter1]... The example is bin/BizController.php?F=Invoke&P0=[pdfService]&P1=[renderView]&P2=[demo.ReportView]
  • Call service in code. 
    global $g_BizSystem;
    $svcobj = $g_BizSystem->GetService($class);
    $svcobj->$method($this->m_Name);

Implement authentication, view and data access control

User authentication

Openbiz uses authentication service (usrlib/authService.php) to authenticate username and password

public function AuthenticateUser ($userid, $password) is called to authenticate user. 

  • AuthenticateUser by default querys on "User Id" and "Password" fields defined in metadata/shared/BOAuth.xml. If input user id and password is found in in BOAuth, AuthenticateUser returns true. AuthenticateUser method is to be modified to fit customer logic.
  • metadata/shared/SignupView.xml is the default login view. This view can be configured for change the login look and feel.

Role-based view access control

View access control depended on the AccessControl attribute in view metadata file in Openbiz 1.x. From Openbiz RC1, openbiz implements role-based view access control in its new security architecture. 

Openbiz uses profile service (usrlib/profileService.php) to get user profile that includes "role". Then match this role to access service (usrlib/accessService.php) to determine the users' accessibility to the view

public function GetProfile ($userid=null) is called to get user profile array which is an associated array with profile key and profile value pairs.

  • Customer must replace the default GetProfile method in openbiz package, because the default GetProfile method returns some randomly made array.

public function AllowViewAccess ($viewName, $role=null) is called to check the accessibility of a view

  • accessService has a configuration file (accessService.xml) that defines the view access permission. Please see an example below.

  • The xml configuration file is easy to understand. Customer needs to put their own logic in the accessService.xml.

Attribute-based data access control

Openbiz uses profile service (usrlib/profileService.php) to get user profile that includes attributes. Then based on these attributes to determine browse/update/delete permission of data record. The data access permissions are controlled in BizDataObj.

User can refer to attributes by @profile:attribute in BizDataObj metadata files. Profile attributes are all from profileService. When user first login, profileService returns a profile array that is saved in session. If an attribute is found in the profile array, the attribute value is returned. If the profile array doesn't contain such attribute, profileService method GetAttribute ($userid, $attr) is called to return the attribute value. Customer must implement GetAttribute method with their own logic.

- Data browse permission. A typical access control requirement is to limit the accessibility of table record to different users. This feature can be achieved by configuring AccessRule in BizDataObj metadata file. We do the configuration with the following two scenario.

Scenario  Configuration
Event can be only accessed by the owner

(personal access control)

<BizDataObj Name="Event" ... AccessRule="[OwnerId]='@profile:ORGID'" ...>

<BizField Name="OwnerId" Column="OWNER_ID"/>

Event can be accessed by all invited attendees 

(if the login user is one of the attendees, he can access the event)

<BizDataObj Name="Event" ... AccessRule="[AttendeeId]='@profile:USERID'" ...>

<BizField Name="AttendeeId" Column="ATTD_ID" Join="Attendee"/>

<Join Name="Attendee" Table="evts_attds" Column="EVT_ID" ColumnRef="SYSID" JoinType="LEFT JOIN"/>

- Data update permission. UpdateCondition is to control the record update permission. UpdateCondition expects true or false. A sample is UpdateCondition = "[OrgId]=={@profile:ORGID}". {} is the evaluated as simple expression.

- Data delete permission. DeleteCondition is to control the record delete permission. DeleteCondition expects true or false. A sample is DeleteCondition = "'admin'=={@profile:ROLEID}"

Build a multi-step wizard view

Wizard is a sequence of forms (questionnaires) which guide users to complete a complicated task. An example is filling an expense report which include different types (hotel, airfare, other activities...) of expenses.

Openbiz support wizard by easy metadata configuration. Openbiz wizard has following features:

  • Each form has "Next", "Back", "Cancel" and "Finish" navigation buttons.
  • If user clicks cancel button, user input data is not saved to database.
  • User input data won't to commit to database until user clicks finish button.

To see sample of wizards, go to Test view, click on "Wizard tests +" submenus. As you can see from the demo, wizard can be accessed with an url. 

As shown in the 2nd link, developer can give the parameter on the fly to run the wizard against given record

Configuration of wizard view

Openbiz wizard is a regular view that contains several wizard forms. So configuring a wizard in openbiz is no harder than  configuring a BizView. The difference between a wizard view and regular view is wizard view show the wizard forms one by one based on the their sequence in view metadata file, but regular view show all forms in one page. Below is an example of a wizard view metadata file.

<?xml version="1.0" standalone="no"?>
<BizView Name="EventWizardView" Description="" Package="demo" Class="BizViewWizard" Template="view.tpl">
   <ControlList>
      <Control Name="wizardForm1" Form="FMEventWzd1"/>
      <Control Name="wizardForm2" Form="FMEventWzd2"/>
   </ControlList>
   <Parameters>
      <Parameter Name="Evt_Id" Value="" />
   </Parameters>
</BizView>

Configuration of wizard forms

A wizard form is a regular form with class as BizFormWizard or BizFormNewWizard (or their subclasses).

  • BizFormWizard - to edit a record
  • BizFormNewWizard - to create a record

This is a typical wizard form metadata file.

<?xml version="1.0" standalone="no"?>
<BizForm Name="FMNewEventWzd1" Package="demo" Class="BizFormNewWizard" jsClass="jbForm" Title="Enter event information:" SearchRule="" Description="Event BizForm" BizDataObj="BOEvent">
  <DisplayModes>
    <Mode Name="EDIT" TemplateFile="edit.tpl" DataFormat="array" FormatStyle="" />
  </DisplayModes>
  <BizCtrlList>
    <BizCtrl Name="evt_id" FieldName="Id" DisplayName="Event Id" />
    <BizCtrl Name="evt_name" FieldName="Name" DisplayName="Name" Type="" Width="250" />
    <BizCtrl Name="evt_desc" FieldName="Description" DisplayName="Description" Type="Textarea" />
    <BizCtrl Name="evt_host" FieldName="Host" DisplayName="Host" />
  </BizCtrlList>
  <Toolbar>
    <Control Name="btn_back" Image="" Caption="&lt; Back" Type="Button" Function="GoPrev()" />
    <Control Name="btn_next" Image="" Caption="Next &gt;" Type="Button" Function="GoNext()" />
    <Control Name="btn_cancel" Image="" Caption="Cancel" Type="Button" Function="DoCancel()" PostAction="view:demo.EventView"/>
    <Control Name="btn_finish" Image="" Caption="Finish" Type="Button" Function="DoFinish()" PostAction="view:demo.EventView"/>
  </Toolbar> 
  <Navbar>
  </Navbar> 
</BizForm>

Extend wizard with customer wizard class

If application has speical logic, Openbiz suggest developers to write their own wizard form class drived from BizWizardForm. By overriding GoPrev(), GoNext(), DoCancel() and DoFinish() methods, developers can do different handling on navigation buttons events.

Openbiz wizard view play the role as a form controller where wizard form can set/get input data, cancel/finish the whole wizard process and render wizard forms. Please see the API document for details.

Implement dataobject events trigger

Upon dataobjects update/delete operations, openbiz allows triggering different alerts and action requests based on boolean results from search criteria for specific object. Briefly it is called DO Trigger which executes in a response to a change in the values stored in the database. DO trigger has two parts - trigger events and trigger actions. These information are defined in DOTrigger plugin service metadata files. At runtime when user update/delete a BizDataObj record, openbiz searches for this dataobj's trigger by looking for its trigger metadata file with name DataObjName_trigger.xml under the same directory. For example, demo/BOEvent's dataobj trigger metadata file is demo/BOEvent_trigger.xml.

Define a dataobject trigger metadata

<PluginService Name="BOEvent_Trigger" Description="" Package="demo" Class="service.doTriggerService" DataObjectName="BOEvent">
<DOTrigger TriggerType="UPDATE|DELETE">*
  <TriggerCondition Expression="" ExtraSearchRule="" />
  <TriggerActions>
    <TriggerAction Action="Method_Name" Immediate="Y|N" DelayMinutes="" RepeatMinutes="">
      <ActionArgument Name="" Value="" /> *
    </TriggerAction>
  </TriggerActions>
</DOTrigger>
</PluginService>

Trigger conditions Description Sample
trigger type Update or Delete record  
expression any expression supported by openbiz {[Expense]}>100. Check if current record's Expense field > 100
extra search rule search rule added on the current dataobj search rules {[AlertFlag]}='Y'. Check if there's at least one record whose AlertFlag is 'Y'
Trigger action methods Description Parameters
ExecuteSQL ExecuteSQL method executes SQL statement Name="DBName" Value="Default"
Name="SQL" Value="select * from regist where EVENT_ID='{[Id]}'"
ExecuteShell ExecuteShell method executes external application Name="Script" Value="dir"
Name="Inputs" Value=" > d:\temp\out.txt"
SendEmail SenEmail method sends outbound emails. 

It calls emailService's sendEmail method

Name="EmailService" Value="service.emailService"
Name="Account" Value="MyPhpopenbiz"
Name="TOs" Value="rockyswen@gmail.com; rockyswen@phpopenbiz.org"
Name="CCs" Value=""
Name="BCCs" Value=""
Name="Subject" Value="alert message"
Name="Body" Value="This is an alert message. \nPlease notice that the record with {[Id]} was updated."
Name="Attachments" Value="" 
AuditTrail Trace record field change

It calls auditService Audit method

Name="AuditService" Value="service.auditService"
Name="DataObjectName" Value="{@:Name}"
any method in doTriggerService The method of doTriggerService is called  Parameters needed to the method

Make customer specific UI components

Due to the extensibility nature of metadata xml files, developers can create their own metadata file, which does not comply with openbiz metadata DTD, to describe the behavior of objects. Openbiz converts xml file to a php array and pass it to the class constructor to save developers' parsing work. Developers need to write their own code to extend from MetaObject class and read in the array by overriding ReadMetadata(&$xmlArr) method.

Tabs component

This is the good example of using customer metadata xml file. Openbiz 2.1 supports tabs UI component. The metadata file (demo/tabs.xml) is like

<?xml version="1.0" standalone="no"?>
<BizForm Name="Tabs" Package="demo" Class="HTMLTabs">
  <TabViews>
    <View Name="demo.AttendeeView" URL="" Caption="Attendees"/>
    <View Name="demo.EventView" URL="" Caption="Events"/>
  </TabViews>
</BizForm>

The class code is under openbiz/bin/HTMLTabs.php. Its css file is in openbiz.css.

Developer can draw more UI widgets like tree, menu using the same approach. 

Menu component 

Openbiz 2.1 supports menu UI component. The metadata file of a menu (i.e. demo/Menus.xml) is like

<?xml version="1.0" standalone="no"?>
<Menu Name="Menus" Package="demo" Class="HTMLMenus">
  <MenuItem URL="" Caption="" Target=""> *
    <MenuItem URL="" Caption="" Target=""/> *

The class code is under openbiz/bin/HTMLMenus.php. Its css file is /css/menu.css

The menu provided in the demo application can be seen in "Test" view. This menu is a horizontal dropdown menu. It is a pure css menu. The idea is copied from http://solardreamstudios.com/learn/css/cssmenus. The output html (<ul><li>...) has same format of the output of well-known DynarchMenu http://www.dynarch.com/products/dhtml-menu/. So integration with DynarchMenu is an easy job. Of course, developers are free to modify the HTMLMenus class to work with other menu libraries. Same principle will apply to other customer UI components.

Tree component

Openbiz 2.1 supports tree UI component. The metadata file of a tree (i.e. demo/Tree.xml) is like

<?xml version="1.0" standalone="no"?>
<Tree Name="Tree" Package="demo" Class="HTMLTree">
  <Node URL="" Caption="" Target=""> *
    <Node URL="" Caption="" Target=""/> *

The class code is under openbiz/bin/HTMLTree.php. Its css file is in openbiz.css

The tree provided in the demo application can be seen in "Test" view. The technique of drawing tree is same as the tree of Eclipse help system http://help.eclipse.org/help30/index.jsp. Again, developers are free to modify the HTMLTree class to work with other tree libraries.

Control the look and feel with css files

The openbiz look and feel is controlled by stylesheet css files. The main css file is /css/openbiz.css

Control BizForm table style

In case of using Format="block" in the BizForm's displayMode, users can modify the following section in css/openbiz.css file.

/* -------- table style -------- */
.tbl {...}
.tbl .head {...}
.tbl .rowodd {...}
.tbl .roweven {...}
.tbl .rowsel {...}
.tbl .cell {...}

Control tabs style

In order to give user specific tab styles, users can modify the following section in css/openbiz.css file.

/* -------- tabs style -------- */
.tabmenu {...}
.tabmenu li {...}
.tabmenu a, a.active {...}
.tabmenu a.active {...}
.tabmenu a:hover {...}
.tabmenu a:visited {...}
.tabmenu a.active:hover {...}

Control menu style

In order to give user specific tab styles, users can modify the following section in css/menu.css file.

Control tree style

In order to give user specific tree styles, users can modify the following section in css/openbiz.css file.

/* ----- tree style ----- */
UL.expanded {...}
UL.collapsed {...}
LI.tree {...}

Control rich text editor (RTE) style

In order to give user specific RTE styles, users can modify the following section in pages/rte/rte.css file.

Date and Datetime picker

The DHTML calendar is well documented at  http://www.dynarch.com/demos/jscalendar/doc/html/reference.html. The javascript file is under demoapp/js/jscalendar.

Debug strategies

- Logging. BizSystem::log() method  can be called to log 4 priority levels LOG_EMERG, LOG_ERR, LOG_WARNING and LOG_DEBUG. Also a subject can be specified to give log messages different categories. The error is logged under /log/log_error.html, open it and you may find out what's wrong

- Debugging. Other than the DEBUG flag in 1.1.x is still valid, developers can turn on other 2 debug flags.
  1) Open the sysheader.inc under /bin, turn on debug log by changing define("DEBUG", 1); Then you'll see some debug information in /log/log_debug.html. This debug file records mainly the database calls and other operations
  2) Turn on SQL debug flag. Uncomment //$this->m_DbConnection[$rDBName]->debug = true; in BizSystem::GetDBConnection().
  3) Turn on RPC debug flag, each RPC response is printed in a separate window. Set var RPC_DEBUG = true; in clientUtil.js.

Other

2.2.2 API

Appendix A - Third Party Libraries

Appendix B - Metadata DTD Files

Appendix A - third party libraries

Appendix  A - third party libraries

Library URL Description License
Smarty  http://smarty.php.net template engine LGPL
Adodb http://adodb.sourceforge.net  database abstraction library BSD
PHPMailer http://phpmailer.sourceforge.net  email library LGPL
jsval http://jsval.fantastic-bits.de  client side data validation LGPL
jscalendar http://www.dynarch.com/projects/calendar  DHTML calendar LGPL
RTE http://www.kevinroth.com/rte/demo.htm  Cross browser rich text editor free
dompdf http://www.digitaljunkies.ca/dompdf  html to pdf convertor free

 

Appendix B - metadata DTD files

BizDataObj metadata DTD file

<!--OpenBiz BizObj metadata DTD-->

<!ELEMENT BizObj (BizFieldList, TableJoins, ObjRefernces, Parameters) >
<!ATTLIST BizObj Name CDATA #REQUIRED >
<!ATTLIST BizObj Description CDATA #REQUIRED >
<!ATTLIST BizObj Package CDATA #IMPLIED >
<!ATTLIST BizObj Class CDATA #REQUIRED >
<!ATTLIST BizObj InheritFrom CDATA #IMPLIED >
<!ATTLIST BizObj DBName CDATA #IMPLIED >
<!ATTLIST BizObj Table CDATA #REQUIRED >
<!ATTLIST BizObj SearchRule CDATA #IMPLIED >
<!ATTLIST BizObj SortRule CDATA #IMPLIED >
<!ATTLIST BizObj OtherSQLRule CDATA #IMPLIED >
<!ATTLIST BizObj AccessRule CDATA #IMPLIED >
<!ATTLIST BizObj UpdateCondition CDATA #IMPLIED >
<!ATTLIST BizObj DeleteCondition CDATA #IMPLIED >

<!ATTLIST BizObj CacheMode CDATA #IMPLIED >

<!ELEMENT BizFieldList (BizField+) >
<!ELEMENT BizField EMPTY >
<!ATTLIST BizField Name CDATA #REQUIRED >
<!ATTLIST BizField Class CDATA #IMPLIED >
<!ATTLIST BizField Join CDATA #IMPLIED >
<!ATTLIST BizField Column CDATA #REQUIRED >
<!ATTLIST BizField SQLExpr CDATA #IMPLIED >
<!ATTLIST BizField Type CDATA #IMPLIED >
<!ATTLIST BizField Format CDATA #IMPLIED >
<!ATTLIST BizField Required CDATA #IMPLIED >
<!ATTLIST BizField Validator CDATA #IMPLIED >
<!ATTLIST BizField DefaulValue CDATA #IMPLIED >
<!ATTLIST BizField Value CDATA #IMPLIED >
<!ATTLIST BizField OnAudit CDATA #IMPLIED >
<!ELEMENT TableJoins (Join+) >
<!ELEMENT Join EMPTY >
<!ATTLIST Join Name CDATA #REQUIRED >
<!ATTLIST Join Table CDATA #REQUIRED >
<!ATTLIST Join Column CDATA #REQUIRED >
<!ATTLIST Join JoinRef CDATA #IMPLIED >
<!ATTLIST Join ColumnRef CDATA #REQUIRED >
<!ATTLIST Join JoinType CDATA #REQUIRED >

<!ELEMENT ObjReferences (Object+) >
<!ELEMENT Object EMPTY >
<!ATTLIST Object Name CDATA #REQUIRED >
<!ATTLIST Object Description CDATA #IMPLIED >
<!ATTLIST Object Relationship CDATA #REQUIRED >
<!ATTLIST Object Table CDATA #REQUIRED >
<!ATTLIST Object Column CDATA #REQUIRED >
<!ATTLIST Object FieldRef CDATA #REQUIRED >
<!ATTLIST Object CascadeDelete CDATA #IMPLIED >
<!ATTLIST Object XTable CDATA #IMPLIED >
<!ATTLIST Object XColumn1 CDATA #IMPLIED >
<!ATTLIST Object XColumn2 CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizView metadata DTD file.

<!--OpenBiz BizView metadata DTD-->

<!ELEMENT BizView (ControlList, Parameters) >
<!ATTLIST BizView Name CDATA #REQUIRED >
<!ATTLIST BizView Description CDATA #REQUIRED >
<!ATTLIST BizView Package CDATA #IMPLIED >
<!ATTLIST BizView Class CDATA #IMPLIED >
<!ATTLIST BizView Template CDATA #IMPLIED >

<!ELEMENT ControlList (Control+) >
<!ELEMENT Control EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Form CDATA #REQUIRED >
<!ATTLIST Control SubCtrls CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizForm metadata DTD file.

<!--OpenBiz BizForm metadata DTD-->

<!ELEMENT BizForm (BizCtrlList, DisplayModes, Toolbar, Navbar, Parameters) >
<!ATTLIST BizForm Name CDATA #REQUIRED >
<!ATTLIST BizForm Description CDATA #REQUIRED >
<!ATTLIST BizForm Package CDATA #IMPLIED >
<!ATTLIST BizForm Class CDATA #REQUIRED >
<!ATTLIST BizForm InheritFrom CDATA #IMPLIED >
<!ATTLIST BizForm jsClass CDATA #REQUIRED >
<!ATTLIST BizForm Title CDATA #REQUIRED >
<!ATTLIST BizForm BizDataObj CDATA #REQUIRED >
<!ATTLIST BizForm PageSize CDATA #REQUIRED >
<!ATTLIST BizForm SearchRule CDATA #IMPLIED >

<!ELEMENT BizCtrlList (BizCtrl+) >
<!ELEMENT BizCtrl (EventHandler+) >
<!ATTLIST BizCtrl Name CDATA #REQUIRED >
<!ATTLIST BizCtrl Class CDATA #IMPLIED >
<!ATTLIST BizCtrl FieldName CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayName CDATA #IMPLIED
>
<!ATTLIST BizCtrl Type CDATA #IMPLIED >
<!ATTLIST BizCtrl Width CDATA #IMPLIED >
<!ATTLIST BizCtrl Height CDATA #IMPLIED >
<!ATTLIST BizCtrl HTMLAttr CDATA #IMPLIED >
<!ATTLIST BizCtrl Link CDATA #IMPLIED >
<!ATTLIST BizCtrl Image CDATA #IMPLIED >
<!ATTLIST BizCtrl Hidden CDATA #IMPLIED >
<!ATTLIST BizCtrl Enabled CDATA #IMPLIED >

<!ATTLIST BizCtrl Sortable (Y|N) "" >
<!ATTLIST BizCtrl Order CDATA #IMPLIED >
<!ATTLIST BizCtrl Style CDATA #IMPLIED >
<!ATTLIST BizCtrl ValuePicker CDATA #IMPLIED >
<!ATTLIST BizCtrl SelectFrom CDATA #IMPLIED >
<!ATTLIST BizCtrl DrillDownLink CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayMode CDATA #IMPLIED >

<!ELEMENT Toolbar (Control+) >
<!ELEMENT Navbar (Control+) >
<!ELEMENT Control (EventHandler+) >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Class CDATA #IMPLIED >
<!ATTLIST Control Image CDATA #IMPLIED >
<!ATTLIST Control Caption CDATA #IMPLIED >
<!ATTLIST Control Type CDATA #IMPLIED >
<!ATTLIST Control Width CDATA #IMPLIED >
<!ATTLIST Control Height CDATA #IMPLIED >
<!ATTLIST Control HTMLAttr CDATA #IMPLIED >
<!ATTLIST Control Style CDATA #IMPLIED >
<!ATTLIST Control Hidden CDATA #IMPLIED >
<!ATTLIST Control Enabled CDATA #IMPLIED >
<!ATTLIST Control SelectFrom CDATA #IMPLIED >

<!ATTLIST Control DisplayMode CDATA #IMPLIED >

<!ELEMENT EventHandler EMPTY >
<!ATTLIST EventHandler Name CDATA #REQUIRED >
<!ATTLIST EventHandler Event CDATA #REQUIRED >
<!ATTLIST EventHandler Function CDATA #REQUIRED >
<!ATTLIST EventHandler FunctionType CDATA #IMPLIED >
<!ATTLIST EventHandler ShortcutKey CDATA #IMPLIED >
<!ATTLIST EventHandler PostAction CDATA #IMPLIED >
<!ELEMENT DisplayModes (Mode+) >
<!ELEMENT Mode EMPTY >
<!ATTLIST Mode Name CDATA #REQUIRED >
<!ATTLIST Mode TemplateFile CDATA #REQUIRED >
<!ATTLIST Mode DataFormat CDATA #REQUIRED >
<!ATTLIST Mode FormatStyle CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

Plugin service metadata DTD file.

<!--OpenBiz Plugin service metadata DTD-->

<!ELEMENT PluginService ANY >
<!ATTLIST PluginService Name CDATA #REQUIRED >
<!ATTLIST PluginService Description CDATA #IMPLIED >
<!ATTLIST PluginService Package CDATA #REQUIRED >
<!ATTLIST PluginService Class CDATA #REQUIRED >

 

2.0 OpenBiz Manual

This document is OpenBiz 2.0 manual. You can access OpenBiz 1.x manual at manual11.html

Other links: Openbiz Eclipse plug-in designer manual, Openbiz best practice

Overview of Openbiz 2.0

Openbiz Installation

Build Applications with Openbiz

Openbiz Configuration Guide

Openbiz Development Guide

Appendix A - third party libraries

Appendix B - metadata DTD files


Overview of Openbiz 2.0

Openbiz 2.0 is a metadata-driven framework. All openbiz objects are declared in their own metadata files. Openbiz 2.0 architecture follows Model-View-Controller (MVC) design pattern, it also implements Object/Relational Mapping.

Openbiz 2.0 architecture

Metadata-driver framework

The goal of Openbiz framework is to make design, development and maintenance of software applications easy. Openbiz is XML metadata-driven framework, which means openbiz objects are constructed based on description in their metadata files. Building an application means design and development of metadata files. Due to the self-explanation nature of XML language, the application is easy to maintain. Meanwhile Openbiz is an extensible framework due to the extensible nature of XML.

The diagram below shows metadata based objects in Openbiz framework. These objects cover most functional needs of web application development.

Openbiz's implementation of MVC

One of the key advantages of Openbiz is that it is a framework that follows the Model-View-Controller (MVC) design pattern. This makes Openbiz applications much more manageable because the presentation code (View) is cleanly separated from the application data and logic (Model). All user interactions with the application are handled by a front-end controller.

Comparing Openbiz MVC with existing MVC frameworks in market such as JSF and Struts, Openbiz is more close to JSF because both are component based architecture. Openbiz's View layer comprises components of BizView, BizForm and ojects within BizForm. These components are accessible during request processing. The following table lists the openbiz implementation of top 6 advantages of Top Ten Reasons to Prefer JSF over Struts

JSF's advantages 
over Struts
Openbiz implementation
Components BizView and BizForm as persistent UI objects 
Render Kits Associate different templates to UI objects
Renderers Customer class to implement Render() method
Value Binding Support static and dynamic value bindings
Event Model Associate client event to server function
Extensibility Developers can link their own class to openbiz object
other four .... Not applicable

Openbiz's implementation of persistent object and ORM

Similar with popular Hibernate approach, Openbiz uses session to maintain the persistency of objects. Unlike J2EE web container who has objects pool in memory, PHP objects are be constructed and released for each request (this is called shared-nothing architecture). To keep the persistency of objects, openbiz persistent objects (BizDataObj, BizForm ...) save a set of states in session, then reconstruct the object with these states. Also to avoid multiple object instances of same class in the same session, openbiz use ObjectFactory to ensure object singleton.

Openbiz implements necessary object/relational mapping (ORM) features to allow BizDataObj represents the data and relationships of database tables. The following table list the features of Openbiz ORM.

Flexible mapping table-per-class, N table to 1 class
Many to one, one to many, many to many, one to one
Query facilities SQL like query language - support SQL functions and operators, support SQL aggregate functions, support group by, having and order by
Metadata facilities XML metadata describe the mapping

Openbiz security model

Openbiz supports web security in three ways - user authentication, view access control and data access control. Openbiz mainly uses plugin services to control security. This implementation allows customers to plugin their own logic to the services. The details will discussed in the developer guide - Implement authentication, view and data access control.

User authentication flow:

View access control flow:

Security concept Openbiz implementation with plugin services
User authentication Openbiz uses authentication service (bin/service/authService.php) to authenticate username and password
Role-based view access control  Openbiz uses profile service (bin/service/profileService.php) to get user profile that includes "role". 
Then match this role to access service (bin/service/accessService.php) to determine the users' accessibility to the view
Attribute-based data access control Openbiz uses profile service (bin/service/profileService.php) to get user profile that includes attributes. 
Then based on these attributes to determine browser/update/delete permission of data record. The data access permissions are controlled in BizDataObj.

Openbiz 2.0 package organization

OpenBiz provides a PHP framework that assists you to build complicated web application in an easy way. 

OpenBiz is designed as a multi-layer architecture as the figure below.

Usually a business application can be modulated to 3 layers - Data layer, Business Logic layer and Presentation layer. In OpenBiz architecture, these 3 layers map to 3 packages, Presentation layer is refined to logic which is implemented by BizView package and GUI layers which is implemented by jbForm javascript package. Business Logic layer is implemented by BizDataObj package. 3rd party package ADODB handles Database layer. Plugin services provide functional service components that can be invoked by both presentation and data layer objects.

Package Class
BizSystem BizSystem
- Provide a global variable accessed anywhere in openbiz application
- Provide the Get method for ObjectFactory, SessionContext, TypeManager, ClientProxy and Configuration
- Provide static methods for accessing XML metadata, logging and error reporting.
ObjectFactory 
- It's a factory class to get metadata-driven objects (BizView, BizForm, BizdataObj and their extended classes) 
SessionContext
- Session management class that has additional methods to save/get session variables of metadata-driven stateful objects through their GetSessionVars|SetSessionVars interfaces
TypeManager
- Type management class that has help methods to format data to UI and unformat UI input to data
ClientProxy
- It's a class that is treated as the bi-direction proxy of client. Through this class, others can get client form inputs, redraw client form or call client javascript functions.
Configuration
- A class that has help methods to get data from config.xml
BizDataObj BizDataObj
- It's the base class of all data object classes. Before Openbiz 1.2, BizDataObj was called BizObj. Since BizObj means Business Object, but it acts as business data unit, in 1.2 it is changed as BizDataObj.
BizRecord
- BizRecord class implements basic function of handling record
BizField
- BizField is the class of a logic field which mapps to a table column
BizDataSql
- BizObjSql is the class to construct SQL statement for BizDataObj
CacheRecordList
- CacheRecordList implements the cache for BizDataObj
ObjRefernces
- ObjReferences contains a list of BizDataObj whose relationship to this object is defined in the ObjReference
TableJoins
- Table Joins contains a list of table joins to the main table of this object
BizView BizView
- BizView is the class that contains list of forms. View is same as html page.
BizForm
- BizForm is the base class that contains UI controls. BizForm is a html form that is included in a BizView which is a html page.
RecordRow
- RecordRow is the class that contains FieldControls
ToolBar
- ToolBar is the class that contains HTMLControls
NavBar
- NavBar is the class that contains navigation buttons
HTMLControl
- HTMLControl is the base class of HTML controls
FieldControl
- FieldControl is the base class of field control who binds with a bizfield
DisplayMode
- contains the BizForm display mode information
jbForm  jbForm (javascript bizForm) 
- the base class that handles RPC function call and callback
ADODB This is an abstract database connection package which can connects to all major databases from different vendors. It can be downloaded from http://php.weblogs.com/ADODB

Class diagram of multi-layer architecture

Sequence diagram of a typical RPC call

Openbiz client browser communicates with server through AJAX JS-based RPC invocation.


Openbiz Installation

Running environment

OpenBiz (2.0 or later) is written by PHP5 scripts, it won't work in PHP4.x web server. We recommend platforms as

Installation directory is openbiz, or you can configure apache using Alias.

Windows installer is not in Openbiz 2.0 so far.

Support web browsers - IE5.x, Netscape 7.x and Mozillar/FireFox 1.x

Install OpenBiz

Download the zip file and unzip it to a directory under your web access root.

Please read through the sysheader.inc under openbiz/bin directory and app.inc under demoapp/bin.

Source tree structure:

From Openbiz 2.0 RC2, two main directories are included in the package. They are Openbiz core library and demo application. 

The demo application is an openbiz-based web application. Because openbiz provides metadata-driven framework, bin and metadata directories are required. The rest of the directories are suggested structure, not required. Users may have their own way to arrange the web application structure. Please modify demoapp/bin/app.inc to change constant definition.

As you observe from the bin and metadata structures, each subdirectory under bin has a matching subdirectory under metadata. This is code/metadata match-up rule, say if you have an object's metadata under /metadata/aaa/ directory, if the object implementing code is a user-defined class (not openbiz core class), the class code file must be under /bin/aaa/ directory.

Openbiz core library
openbiz_root/ 
---bin/        
(openbiz core php source - required)
------service/     
(openbiz core service library directory)
---document/    (openbiz documents - optional)
------apidoc/     
(openbiz core API)
---medata/     
(openbiz metadata files - required)
------service/     
(service package)
---others/      (third party libraries - optional)
------adodb/      
(adodb package)
------Smarty/     
(smarty package)

 

demo application
demoapp/     (demoapp web pages)
---bin/         (demoapp php source)
------demo/        
(demapp demo library)
------shared/      
(demoapp shared library)
------service/     
(demoapp service library)
---js/
          (demoapp javascript files)
---pages/       (demoapp HTML files)
---css/        
(demoapp style sheets)
---images/     
(demoapp images)
---log/        
(demoapp logs)
---medata/     
(demoapp metadata files)
------demo/       
(demoapp demo package)
------shared/      
(demoapp shared package)
------service/     
(demoapp service package)
---session     
(demoapp session files)
---templates    (demoapp smarty templates files)
------cpl          (demoapp smarty compiled templates)
------cfg          (demoapp smarty configuration files)
---tmpfiles     (temporary files)

In Unix or Linux box, you need to give write permission to web users on log, metadata, session, tmpfiles and templates directories.

Install necessary third party packages

The following package are necessary - they are included in openbiz package.

We recommend you install PHP optimization packages.

Start demo application

Populate the demo database. Find gendb.sql under openbiz root directory, apply it against your database. Notes this gendb.sql is for mysql database, please adjust the syntax according to different database type.

Open demoapp/clientUtil.js. Change the var binPath = "/demoapp/bin/"; to the appropriate bin directory under demoapp installation root. Remember the should be absolute path which begins with "/".

Open demoapp/metadata/config.xml, verify the default database entry has the correct attributes (such as username and password).

Then start a browser, open url http://localhost/demoapp/demo.html

Upgrade guide

Metadata-driven framework gives customers full flexibility to configure application as the way they like. From a version to higher version, metadata schema may be changed to fit the new features. Move from one version to a higher version usually include code and metadata upgrade. We here discuss metadata upgrade.

Upgrade from 2.0 to 2.1

- Application tree structure. In 2.1, javascript files are under app_root/js. Therefore all view templates must be changed to have correct path of javascript files. 
<script language="javascript" src="../js/clientUtil.js"></script>

- In clientUtil.js, developers must change the bin path to point to the application root directory. 
var binPath = "/application_root/bin/";

- Metadata file change

Metadata change 2.0 2.1
Control event handlers Function, FunctionType, PostAction are attributes of Control element Function, FunctionType, PostAction are attibutes of EventHandler element who is child of Control element
Id generation option BizDataObj Id field value is implicitly generated. Support generating ID with openbiz id table or auto-increment column (MySQL)  User controls BizDataObj Id field value generation with IdGeneration attribute in BizDataObj element. Support native database Id generation.

If your original Id maps on auto-increment column, you need to specify IdGeneration="Identiry"

BizField on audit NA New OnAudit attribute in BizField element to enable audit trail

Control element syntax in 2.0

<Control Name="ControlName" Type="ControlType" Function="..." FunctionType="..." PostAction=""/>

Control element syntax in 2.1

<Control Name="ControlName" Type="ControlType">
   <EventHandler Name="ehName" Event="eventName" Function="..." FunctionType="..." PostAction=""/> +
</Control>

More than one event handlers can be associated to a control. In Openbiz 2.0, one control can have only one event handling function. In 2.1, Function and FunctionType attributes are moved from Control Element (2.0 way) to EventHandler element under Control element (2.1 way). Even though the 2.1 code still work with 2.0 metadata file, such conversion is recommended when upgrading to 2.1. 

Access latest source code with SVN

Developers can access and contribute to openbiz source code with SVN client. The SVN url is at https://svn.sourceforge.net/svnroot/bigchef/trunk/, 2 modules openbiz and demoapp are in the repository. 

You can do anonymous checkouts from the svn repository. The anonymous user has only read-access to the repository. If you don't have SVN client installed on your machine, these 2 links can help you. http://sourceforge.net/docman/display_doc.php?docid=31178&group_id=1 and http://sourceforge.net/docman/display_doc.php?docid=31165&group_id=1.

If you want to contribute (add features or fix bugs) to SVN repository, you need to have a sourceforge account. To apply for sourceforge account, go to http://sourceforge.net/account/newuser_emailverify.php . Email your account to rockyswen@phpopenbiz.org, your account will be added to openbiz project. Then you should be able to check in/out openbiz SVN repository.  


Build Applications with Openbiz

Specify requirement of your application

OpenBiz is a perfect tool that help you develop your complicated web application easily and comprehensively. Based on its 3-layer architecture, your application will be on a clear logic model. It takes care the basic and advanced features of the data-oriented application. In order to tell whether OpenBiz can help building your application, you need ask these questions:

If the answers are YES, OpenBiz is the right framework for developing your application!

Plan your web applications

When you install the Openbiz package, you would notice there are two main directories "openbiz" and "demoapp" in the zip file. "openbiz" directory contains the openbiz core library and metadata. "demo" directory contains the source for a demo application (event management  and calendar demo). 

The above structure is different with that of Openbiz 2.0 RC1 and prior version where you can see demo application was in the openbiz directory. Why does Openbiz has this change? 

Develop web application with your own directory

Your own development Where to put
Your source code your_app_root/bin/
Your metadata files your_app_root/metadata/your_package/
Your web templates your_app_root/templates/
Your web pages your_app_root/
Your style sheet files your_app_root/css/
You image files your_app_root/images/
Your log files your_app_root/log/
Your session files your_app_root/session/
Your temporary files your_app_root/tmpfiles/

This is a more organized way to develop an openbiz-based web application. Your application specific files are in a separate directory, not mixed with openbiz core files. You can build multiple web applications based on single openbiz core. You need to do some extra steps to set up your own application directory. The following steps are suggested.

  1. Copy demoapp directory and rename it to your application name, say "testapp"
  2. Open testapp/bin/app.inc, change the constants appropriately. If the default values may work for you, no change is needed.
  3. Open testapp/bin/login.php, change the $application_homepage to the first web page shown to users after they login.

In the app.inc file, OPENBIZ_HOME has to be define to point to the installed path of openbiz core library. Your applications will use the openbiz core library as well as core objects defined in metadata directory.

Another important change from RC2 is that metadata and code have to match up under /metadata and /bin directories. If you have an object's metadata under /metadata/aaa/ directory, if the object implementing code is a user-defined class (not openbiz core class), the class code file must be under /bin/aaa/ directory. For example, /metadata/shared/FMCalendar.xml has a special implementing class "FMCalendar", this FMCalendar class must be located in /bin/shared/FMCalendar.php. If the object's implementing class is openbiz core class, no special code is needed, thus there's no matching code under /bin. This match-up rule is to give a clear view of the metadata and code.  

How to upgrade to the new structure if you are using the structure in RC1 or prior version? In Openbiz RC1 and prior version, application code is under bin/usrlib/ directory. Based on the metadata/code match-up rule, you need to create subdirectories with the same names of the metadata packages under /bin directory and move the code under /bin/usrlib to those subdirectories.

Create your database model

Modeling your business data with Relational database tables is the necessary base for building your whole application.

Create a new database

Use existing database

Fit your system design in Openbiz

Fit your design in Openbiz framework, you leverage the power of the framework. Your design will have

Build new application

Business requirement -> UI design + data modeling + objects design

User Interface: Pages, forms, interactivities

Data Modeling: Database table schema

Objects Design:

Convert existing application

Convert existing UI to BizViews, BizForms

Map existing database tables to BizDataObjs

Port existing business functionalities to plugin services

Sample implementation - Calendar

Requirement:

Step 1. Data Modeling with table schemas

Step 2. Map tables to BizDataObjs

Step 3. Bind UI controls with data

Step 4. User Interactions

Step 5. Implement special logic by extending openbiz

Calendar view: event navigation

User Interface Objects Calendar form
  - day, week, month and all events display modes
  - FieldControls: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd
Data Objects Calendar data object
  - Fields: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd
Tables calevts table
  - Columns: SYSID, SUBJECT, LOCATION, TYPE, NOTES, STARTTIME. ENDTIME, REPEATCYCLE, REPEATEND

Calendar Detail view: event editing and invite attendees

User Interface Objects Calendar Detail form
  - SubForm is Event Attendee form
  - New, Edit modes
  - FieldControls: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd, AttendeeId, AttendeeName
Event Attendee form
  - Parent form is "Calendar Detail form"
  - List and Schedule modes
  - FieldControls: Id, LastName, FirstName, ...
Data Objects Calendar detail data object
  - Fields: Id, Subject, Location, Type, Notes, Start, End, RepeatCycle, RepeatEnd
  - ObjReference: Calendar Attendee data object
  - Joined Fields: Attendee Id, AttendeeName (from calattds table)
Calendar Attendee data object
  Fields: Id, LName, FName, ...
Table calevts table
  - Columns: SYSID, SUBJECT, LOCATION, TYPE, NOTES, STARTTIME. ENDTIME, REPEATCYCLE, REPEATEND

calevts_attds table (intersection table of calevts and calattds)

calattds table
  Columns: SYSID, LASTNAME, FIRSTNAME, ...

Class Diagram:

Note: Calendar Form and Calendar Detail Form have special rendering logic, they are based on FMCalendar and FMCalAttendee classes which are extended from BizForm base class.

User interaction - UI controls maps to server functions

User action UI Control Function Method implementation
Show Day calendar: switch to day mode, draw the day calendar Day button ShowDay() class FMCalendar
public function ShowDay()
Show Week calendar: switch to week mode, draw the week calendar Week button ShowWeek() class FMCalendar
public function ShowWeek()
Show Month calendar: switch to month mode, draw the month calendar Month button ShowMonth() class FMCalendar
public function ShowMonth()
Show all calendar events: switch to list mode, list all events page by page All Events button ShowList() class FMCalendar
public function ShowList()
New a calendar event: Click New button on Calendar View, jump to Calendar Detail View with new mode New Event button NewEvent() class FMCalendar
public function NewEvent()
Delete a calendar event: In Calendar Detail View, click Delete button to delete an event Delete button DeleteRecord() class BizForm
public function DeleteRecord()
Edit a calendar event: Click an event link on the Calendar view, jump to Calendar Detail with edit mode Drill down link URL = "bizController.php? view=shared.CalDetailView &amp;form=shared.FMCalDetail &amp;mode=NEW"  
Add event attendees: In Calendar Detail View, click Add button on the Calendar Attendee form to pick an attendee Add button ShowPopup (shared.FMAttendeePopup) class BizForm
public function ShowPopup()
Remove event attendees: In Calendar Detail View, click Remove button on the Calendar Attendee form to remove an attendee Delete button RemoveRecord() class BizForm
public function RemoveRecord()
Show attendees' schedule: In Calendar Detail View, click Show Schedule button to switch to schedule mode Schedule button ShowSchedule() class FMCalAttendee
public function ShowSchedule()

To see the sample calendar, open http://localhost/openbiz/bin/BizController.php?view=shared.CalendarView in your browser.


Openbiz Configuration Guide

Developers can choose use XML editor to edit metadata files. Openbiz Eclipse Plug-in is recommended to be used as a design and configuration tool. Please refer to Openbiz Eclipse plug-in designer manual.

Organize metadata by package

In a big application, user may need to build lots of objects, therefore they have big metadata file list. If they put these files under a single metadata directory, managing the metadata files is a painful thing. From openbiz 1.1, metadata files can be organized by package name. Bear in mind, metadata package is different with the (BizObj, BizView ...) packages which are the code units. Metadata package is a naming system, different package maps to different directory. It is like the package concept used in Java. 

PackageX.PackageY.metaA.xml refers to the metaA.xml under META_PATH/PackageA/PackageB directory. Where META_PATH is the root metadata directory. This macro is defined in sysheader.inc and app.inc. 

How to configure  package in metadata files?

Let's explain it with the demo example. After you unzip the source, find the demo directory under metadata directory. Open FMRegist.xml file with a text editor. You'll see a Package="demo" attribute in the BizForm element. This attribute is to say the default package of any type of openbiz object is under "demo" package. Here the openbiz objects refer to the following object types.

Object Type Referred as attributes in metadata files
BizObj BizForm[BizObj]
BizObj->BizFieldList->BizField[SelectBizObj]
BizForm BizView->ControlList->Control[Form]
BizView->ControlList->Control[SubCtrl]
BizForm->BizCtrlList->BizCtrl[SelectFrom]
BizView  
BizPopup BizForm->BizCtrlList->BizCtrl[SelectBizForm]
BizFormTree Same as BizForm

If an object name doesn't contain dot symbol ("."), the system uses the package attribute defined in the object root element as its package. Otherwise, if an object name has format as aaa.objectname, the system thinks such object under package "aaa" and will locate such object under aaa directory.

Go back to the example, you can find <BizForm Name="FMRegist" Package="demo" ... BizObj="BORegist"...>, <BizCtrl Name="reg_attdln" ...  SelectBizForm="AttendeePopup"...> and <BizCtrl Name="reg_fee" ... SelectFrom="Selection(Fee)"...>. They all use default package, so the system will try to locate the metadata files as demo/BORegist.xml, demo/AttendeePopup.xml and demo/Selection.xml.

If you want to refer to an object under other package, just add the package name as the prefix of the object name. Notice, there're a Selection.xml under /demo directory and another Selection.xml under /design directory, they belong to different packages. In FMRegist, whose package is "demo", you can use <BizCtrl ...  SelectFrom="design.Selection(Mode)" ...> to configure a comboBox whose values are from the "Mode" element of "design/Selection.xml".

You cannot refer to an object in different application. But you can refer to any object in openbiz core application. For example, the core application has refer to objects under metadata/shared/ directory. Openbiz tries to locate objects in same application and then in core application. If no object is found, it reports an error.

Use object metadata inheritance

If you have a complex application, you want to reuse the existing object to different places, but you want the object behave a little differently in different scenarios. Object inheritance will solve the above problem. Since in openbiz framework objects maps to metadata file, object inheritance becomes metadata file inheritance.

How to specify inheritance between metadata files?

Specify an object attribute, InheritFrom = "parent object name". For example, in demo application, BOEventX has <BizObj Name="BOEventX" Description="Event BizObj Extended from BOEvent" Package="demo" Class="BizObj" InheritFrom="demo.BOEvent"...>. This indicates that is BOEventX is inherited from BOEvent. 

Metadata file inheritance is similar with class inheritance in programming languages, child object can inherit (if not defined in child object, but defined in parent object)  or override (if same attribute defined in both child object and parent object) the parent object attributes.

Object Type which can has inheritance What CAN be inherited or overridden What CANNOT be inherited - must be specified in child metadata file
BizObj Object Attributes: Description, DBName, Table, SearchRule, SortRule, OtherSQLRule, CacheMode

Object BizFieldList: BizField

Object Attributes: Name, Package, Class, InheritFrom
BizForm Object Attributes: Description, jsClass, Title, BizObj, PageSize, Width, Height, SearchRule

Object BizCtrlList: BizCtrl
Object DisplayModes: Mode
Object Toolbar: Control
Object Navbar: Control

Object Attributes: Name, Package, Class, InheritFrom

Simple Expression Language

In order to adding flexibility of metadata configuration, Openbiz accepts simple expression language in metadata files. If a statement has {expr} pattern, expr will be evaluated as simple expression. Basically, the simple expression is a single PHP statement which returns a value. If users need more complicated logic which can't be put in a simple expression, they can associate an object with user-defined class where they put special code.

Using Expressions

Simple expression is to support dynamic value binding of metadata attributes. Users can use simple expression in the following place in metadata files.

Literals

The simple expression language defines the following literals:

Operators

The simple expression language provides the following operators:

Variables

Syntax to get metadata object variables Meaning Implementation Sample usage
@object_name:property_name get the given property of the given object. Call object->GetProperty ($propname) @BOEvent:Name
@FMEvent:Title
@object_name:*[child_name].property_name get the given property of the given object's child element Call object->GetProperty ($propname), where $propname="*[child_name]", to get the child object. 
Then call child_object->GetProperty($propname)
@BOEvent:Field[Id].Value
@FMEvent:Control[evt_id].Value
@:property_name or 
@this:property_name
get the given property of this object ("this" object is the object defined in the metadata file) Call this->GetProperty ($propname) In BOEvent, @:Name or @this:Name means getting the "Name" property of BOEvent.
@:*[child_name].property_name or
@this:*[child_name].property_name
get the given property of this object's child element Call this->GetProperty ($propname), where $propname="*[child_name]", to get the child object. 
Then call child_object->GetProperty($propname)
In BOEvent, @:Field[Id].Value or @this:Field[Id].Value means getting the "Id" field value of BOEvent.
[field_name] get the value of a given BizField of this BizDataObj. 
It is evaluated to field value only if it is used in BizField element
Call object->GetProperty ($field_name) to get the child BizField object. 
Then call field_object->GetProperty("Value")
In BOEvent, [Id] means getting the "Id" field value of BOEvent.
@object_name:param[param_name] or
@:param[param_name]
get the given parameter's value of this object Call object->GetProperty ($propname), where $propname="param[param_name]" @:param[Evt_Id]
@profile:property_name get the user profile property.  User profile is provided with ProfileService. @profile:ROLEID

As implied from the implementation, developers can add more property support by modifying/overriding GetProperty() method. The input of GetProperty() can be either "property_name" or "*[child_name]" or something new that supported by customer code.

Functions

Developers can invoke any PHP functions in simple expression. A user defined functions can be invoked if the file that contains such function is included. For example, if the metadata object A is based on a customer class, the class file is A.php that includes another A_help.inc. In this case, you can invoke functions defined in A_help.inc in simple expression.

Examples

Configuration of BizDataObj

The DTD file of the BizDataObj xml is listed in Appendix A.1

Map BizDataObj to Tables

Openbiz maps database tables to object with BizDataObj. This chapter introduce the concept of mapping tables with BizDataObj, the next chapter "ORM" has full details of the mapping configuration. A BizDataObj must have table name and mapping between table columns to BizDataObj fields.

Query Language in BizDataObj

Openbiz users won't worry about the composing complicated SQL statements. BizDataObj support more intuitive query language at the object level. The basic syntax is "[FieldName] opr 'Value' AND/OR [fieldName] opr 'Value'..." Here "opr" is SQL operator. At runtime, openbiz convert [FieldName] to column name and generate SQL statement. Openbiz also put table relationship in generated query statements.

Data type and format of BizFields

BizField supports following data types and formats in its Type and Format attributes.

Type Format Syntax Format Example
Text none Text is the default type  
Number format supported by printf <BizField ... Type="Number" Format="%..." ...> %5.2f to print a float number
  "Int" - integer format according locale <BizField ... Type="Number" Format="Int" ...> If locale=enu, 12345.678 is displayed as 12,346
  "Float"- float format according locale <BizField ... Type="Number" Format="Float" ...> If locale=enu, 12345.678 is displayed as 12,345.68
Date In default read-only mode, a date can be formatted according to the Date format. <BizField ... Type="Date" Format="date format" ...> 6/21/2003 can be formatted as
%A, %b %d %Y - Saturday, Jun 21 2003 if system locale is enu
Datetime In default read-only mode, a date can be formatted according to the Date format. <BizField ... Type="Datetime" Format="datetime format" ...> 6/22/2003 9:30am can be formatted as
%m/%d/%Y %H:%M:%S - 06/22/2003 09:30:00 if system locale is enu
Currency Formatted according to locale setting <BizField ... Type="Currency" Format="Currency" ...> 1456.89 is formatted as $1,456.89 (enu)
1456.89 is formatted as F1 456,89 (fra)
Phone Formatted according to given mask # <BizField ... Type="Phone" Format="mask string" ...> 1234567890 is formatted as 
mask=(###) ###-####, 
phone=(123) 456-7890
mask=###-###-####, phone=123-456-7890
  If a phone number starting with "*", it represents international phone number, it won't be formatted   *123 4567890 is treated as international number
Blob/Clob none <BizField ... Type="Blob" ...>
<BizField ... Type="Clob" ...>
 

Data validations

Validation Type Example
Required - indicates the field can not be empty <BizField Name="Name" Required="Y" Column="NAME"/>
Validator - simple expression language  <BizField Name="Fee" Type="Currency" Format="Currency" Validator="{[Fee]>=15}" Column="FEE">

Object Relational (O/R) Mapping

To support O/R mapping, TableJoin and ObjectReference are introduced to BizDataObj metadata file.

To understand the O/R mapping, a sample is listed below:

attendee:regist = 1:M (one to many), regist:attendee = M:1 (many to one)

events:regist = 1:M (one to many), regist:events = M:1 (many to one)

attendee:events = M:M (many to many)

Map a table to a BizDataObj

To map a table to a BizDataObj, users only need to configure the BizFieldList part in the metadata. 

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
</BizDataObj>

Primary key (Id) generation

From Openbiz 2.1RC, BizDataObj supports multiple id generation algorithms. Add a BizDataObj attribute IdGeneration="Openbiz|Identity|Sequence:seqname|GUID|UUID|Other...".

IdGeneration how id (Primary Key column) is generated Supported database types
Openbiz (default) Id is generated using "ob_sysids" table which stores SYSID information for all tables who have SYSID column Apply to all database types
Identity Primary key column is generated by database engine.
Id is called "Identity" column in SQL Server, also called "auto-increment" column in MySQL.
MySQL, SQL Server, Sybase, DB2
Sequence:seqname Primary key column is generated by database sequence. "seqname" is the sequence name used to generate PK. Oracle, PostgreSQL, DB2
GUID Primary key column is database-generated GUID MySQL, SQL Server, Oracle
UUID Primary key column is generated with php uuid function Apply to all database types
Other Developers can write customer specific Id generation algorithm by modifying function GetNewID(...) in genIdService class under openbiz/bin/service/genIdService.php decided by customer 

Composite key support

In Openbiz 2.1, BizDataObj supports composite key. This feature would be useful when working with legacy database tables who does not have single primary key column. The syntax of BizDataObj whose Id field maps >2 primary key columns is:

<BizDataObj Name="" Package="" Class="" ... IdGeneration="None">
<BizField Name="fpk1" Column="PK1"/>
<BizField Name="fpk2" Column="PK2"/>
<BizField Name="Id" Column="PK1,PK2" />
...

Map multiple tables to a BizdataObj

User can map multiple tables to a BizDataObj through Join. Joined table is referred by a foreign key column in the base table of the BizDataObj, that says the base table has a foreign key points to joined table's column.

<BizObj Name="BORegist" Package="demo" Class="BizObj" Table="regist" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="EvtId" Column="EVENT_ID"/>
  <BizField Name="AttendeeId" Column="ATTENDEE_ID"/>
  <BizField Name="AttdLName" Join="attendee" Column="LASTNAME"/>
  <BizField Name="AttdFName" Join="attendee" Column="FIRSTNAME"/>
</BizFieldList>
<TableJoins>
  <Join Name="attendee" Table="attendee" Column="SYSID" ColumnRef="ATTENDEE_ID" JoinType="INNER JOIN"/>
</TableJoins>

Join Attribute Description
Name The name of the join. It is referred in the Join attribute of BizField
Table The joined table name
Column The joined column name
JoinRef If JoinRef is empty, the joined table joins to the base table. User can specify the JoinRef in the 2-level join.
ColumnRef ColumnRef refers to the column of the base table (or the JoinRef table). It contains the foreign key of the Join column.
JoinType INNER JOIN, LEFT JOIN, RIGHT JOIN, or FULL OUTER JOIN.

The query SQL is like "SELECT ... FROM BaseTable INNER JOIN JoinedTable ON BaseTable.ColumnRef=JoinedTable.JoinedColumn ...". In the above example, the SQL is 

SELECT T0.SYSID, T0.EVENT_ID, T0.ATTENDEE_ID, T1.LASTNAME, T1.FIRSTNAME 
FROM regist as T0
         INNER JOIN attendee as T1 ON T0.ATTENDEE_ID = T1.SYSID

- More explanation about the JoinRef

JoinRef is to support cascade-join. For example, in a query, table A joins B and table B joins C. Table A and C is joined through table B. User can use the following part to link C and A together.

<TableJoins>
<Join Name="join_b" Table="B" Column="B_PK" ColumnRef="A_FK_B" JoinType="LEFT OUTER JOIN"/>
<Join Name="join_c" Table="C" JoinRef="join_b" Column="C_PK" ColumnRef="B_FK_C" JoinType="LEFT OUTER JOIN"/>
</TableJoins>

Many to one relationship between BizDataObjs

Many to one relationship between two tables means table 1 has a column that contains the foreign key pointing to a key/unique column in table 2. To map such relationship between two BizDataObjs, use an Object in ObjectReference section.

<BizObj Name="BORegist" Package="demo" Class="BizObj" Table="regist" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="EvtId" Column="EVENT_ID"/>
  <BizField Name="AttendeeId" Column="ATTENDEE_ID"/>
  <BizField Name="AttdLName" Join="attendee" Column="LASTNAME"/>
  <BizField Name="AttdFName" Join="attendee" Column="FIRSTNAME"/>
</BizFieldList>
<TableJoins>
  <Join Name="attendee" Table="attendee" Column="SYSID" ColumnRef="ATTENDEE_ID" JoinType="INNER JOIN"/>
</TableJoins>
<ObjReferences>
  <Object Name="BOEvent" Description="" Relationship="M-1" Table="events" Column="SYSID" FieldRef="EvtId"/>
</ObjReferences>

</BizObj>

Object Attribute Description
Name The name of the referred BizDataObj
Description  
Relationship Relationship between this dataobj and the referred dataobj
Table The table of the referred dataobj
Column The column of the referred dataobj's table
FieldRef The field mapping to the foreign key column in base table

To get the referred dataobj (child dataobj), call GetRefObject($objame) method from parent dataobj. The referred dataobj instance will have the restriction according to the parent dataobj.

One to many relationship between BizDataObjs

One to many relationship between two tables means table 2 has a column that contains the foreign key pointing to a key/unique column in table 1. To map such relationship between two BizDataObjs, use an Object in ObjectReference section.

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
<ObjReferences>
  <Object Name="BORegist" Description="" Relationship="1-M" Table="regist" Column="EVENT_ID" FieldRef="Id" CascadeDelete="Y"/>
</ObjReferences>

</BizDataObj>

Object Attribute Description
Name The name of the referred BizDataObj
Description  
Relationship Relationship between this dataobj and the referred dataobj
Table The table of the referred dataobj
Column The column of the referred dataobj's table. This column contains the foreign key to the base table
FieldRef The field mapping to the column in base table
CascadeDelete Indicate whether deleting a record in base table will cause the deletion of all related record in referred table.

To get the referred dataobj (child dataobj), call GetRefObject($objame) method from parent dataobj. The referred dataobj instance will have the restriction according to the parent dataobj.

- One to one relationship between BizDataObjs

One to one relationship is a special case of many to one or one to many relationship.

Many to many relationship between BizDataObjs

Many to many relationship between two tables means an intersection table (also called cross reference table, or correlation table) contains the foreign key columns pointing to a key/unique column in table 1 and table 2. To map such relationship between two BizDataObjs, use an Object in ObjectReference section.

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
<ObjReferences>
  <Object Name="BOAttendee" Description="" Relationship="M-M" Table="attendee" Column="SYSID" FieldRef="Id" CascadeDelete="Y"
XTable="regist" XColumn1="EVENT_ID" XColumn2="ATTENDEE_ID"/>
</ObjReferences>

</BizDataObj>

Object Attribute Description
Name The name of the referred BizDataObj
Description  
Relationship Relationship between this dataobj and the referred dataobj
Table The table of the referred dataobj
Column The column of the referred dataobj's table. This column contains the foreign key to the base table
FieldRef The field mapping to the column in base table
CascadeDelete Indicate whether deleting a record in base table will cause the deletion of all related record in intersection table.
XTable The intersection table name
XColumn1 The intersection table column that has the foreign key of the base table
XColumn2 The intersection table column that has the foreign key of the referred table
XKeyColumn (No longer valid in 2.1) The primary key column name of the intersection table. 
If this attribute doesn't have value, openbiz won't generate the ID column in the table. In this case, the intersection table should auto-generate the ID column or there's no such ID column in the table.
 
XDataObj (New in 2.1) BizDataObject whose base table is the intersection table that is XTable. When user associates one record from referred DataObject to the base DataObject, a new record is created from the XDataObj and added in the intersection table. 

To get the referred dataobj (child dataobj), call GetRefObject($objame) method from parent dataobj. The referred dataobj instance will have the restriction according to the parent dataobj.

BizView and BizForm Configuration 

BizView metadata DTD file can be found in Appendix A.2.

BizForm metadata DTD file can be found in Appendix A.3.

BizView - the HTML page container

BizView is the physical web page that contains multiple BizForms and other HTML elements. Its layout is based on smarty template enginee. BizView defines the layout of BizForms as well as the relationship between BizForms.

- Map BizDataObj relationship of BizForms

If more than one BizForm is placed in a BizView and they are linked by specifying Parent-Child relationship in BizView, the BizForms will have the relationship of their underline BizDataObj.

<BizView Name="EventView" ...>
<ControlList>
  <Control Name="fm_event" Form="FMEvent" SubCtrls="FMAttendeeChild"/>
  <Control Name="fm_attd" Form="FMAttendeeChild"/>
</ControlList>
</BizView>

SubCtrls attribute has syntax like SubCtrls="childform1_name;childform2_name;...". It tells children forms name of the parent form, which means children form data may change along the change of the parent form.

Because BOEvent and BOAttendee have many to many relationship, the event form and attendee form will take the M-M as their relationship. They present the data relationship on user interface.

- Sample Event View:

EventView (Event-Attendee as M-M)

FMEvent as BizForm
 |-- BOEvent as BizDataObj
FMAttendeeChild as BizForm
 |-- BOAttendee as BizDataObj

Basic BizForm layout: Data, Toolbar and Navigation bar

Openbiz BizForm is composed with three part - data part, toolbar and navigation bar.

Here's a sample layout of a BizForm:

Toolbar                                     Navigation bar

Data part

Present BizDataObj by BizForm

BizForm represents data from BizDataObj. BizForm defines the mapping between BizCtrls in the BizForm and the BizFields in BizDataObj. Here's an example.

<BizForm Name="FMRegist" ... BizObj="BORegist" ...>
<BizCtrlList>
  <BizCtrl Name="reg_id" FieldName="Id" DisplayName="Registration Id"/>
  <BizCtrl Name="reg_evtid" FieldName="EvtId" DisplayName="Event Id"/>
  <BizCtrl Name="reg_attdid" FieldName="AttendeeId" DisplayName="Attendee Id"/>
  <BizCtrl Name="reg_attdfn" FieldName="AttdFName" DisplayName="First Name"/>
  <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name"/>
</BizCtrlList>
</BizForm>

Present data with various HTML elements

HTMLControl or BizCtrl can present its data with various HTML elements by specifying element type and attributes. HTML elements are displayed in edit/query modes

Attributes of HTMLControl element in BizForm

Type Width Height HTMLAttr* Style** SeclectFrom Caption Image Comments
Text x x x
Limit the input length
x       Single line text input. Default type
Textarea x x x x       Multi-line Text input
RichText x x x x       Rich text editor edit HTML source
ListBox x x x
Show ListBox or ComboBox
x x
Set list of values
    ListBox or ComboBox
CheckBox x x x x x
Set True value
    CheckBox
Radio x
Arrange radio list 
x x x x
Set list of values
    Radio buttons
HTMLButton x x x x   x   Standard HTML Button
SubmitButton x x x x   x   Standard HTML Submit Button
ResetButton x x x x   x   Standard HTML Reset Button
Password x x x x       HTML password
Button x x x x   x x OpenBiz image button
Date x x x x       Textbox with date picker icon
Datetime x x x x       Textbox with datetime picker icon
HTMLBlock x x   x   x
Special Characters
  Caption is treated as HTML block
File x x x x       File control to upload file
FunctionColumn x x x x     x This type doesn't map to a data field

* HTMLAttr field can contain any valid additional HTML attribute applied on the HTML element type

** Style field can contain any valid style properties (css)

Limit the input length: 

HTMLAttr="maxlength=N" to limit the maximum number of characters that the user can enter in a text control. 

Show ListBox or ComboBox: 

By default show comboBox. If HTMLAttr="size=N", show N-row listbox.

Set list of values: 

SelectFrom="XmlFile(Key)" means this field control is a listbox or radio buttons whose data is from the "Key" elements in XmlFile.

Set True value: 

SelectFrom="Value" means this checkbox returns the Value when user check the checkbox.

Arrange radio list: 

By default the radion buttons are arranged horiztionally. If Width="1", you can force them arranged vertically.

Special characters:

"<" and ">" used in HTML block have to be replaced by "&lt;" and "&gt;". Please refer to http://www.w3schools.com/html/html_entities.asp for more details.

Rich text editor

Openbiz rich text editor primarily uses the code (LGPL license) from Kevin Roth http://www.kevinroth.com/rte/demo.htm. Thanks Kevin for his excellent work. It supports IE5.5+ and Firfox 1.x. Below is a screenshot.

Date/Datetime picker

Openbiz 2.1 uses the open source DHTML calendar 1.0 (LGPL license) provided by dynarch.com. The DHTML calendar is well documented at  http://www.dynarch.com/demos/jscalendar/doc/html/reference.html. Many thanks to Nik Chankov for his help on integrating openbiz with DHTML calendar. Openbiz by default uses system style for the calenar.

Additional attributes of BizCtrl

Event handling in BizForm 

As a html element can trigger events like onclick and onblur, each html Control or BizCtrl may have event handling functions associating to events. Event handling is defined in following syntax.

<Control Name="ControlName" Type="ControlType">
   <EventHandler Name="ehName" Event="eventName" Function="..." FunctionType="..." PostAction=""/> +
</Control>

More than event handlers can be associated to a control. This is a new feature in 2.1 release. In Openbiz 2.0, one control can have only one event handling function. In 2.1, Function and FunctionType attributes are moved from Control Element (2.0 way) to EventHandler element under Control element (2.1 way).

- Event is the html element event name. Please refer to http://www.w3.org/TR/REC-html40/interact/scripts.html, 18.2.3 Intrinsic events.

- Function gives a BizForm method name and arguments. Server side should have a corresponding BizForm method. When the request hits BizController, it is routed to the BizForm method. If the method doesn't exist, an error is returned. Function with syntax of 

  <EventHandler ... Function="objectName.methodName(arg1, arg2...)" .../>. 

The objectName can be empty, this means it calls method of current BizForm. For example, <EventHandler ... Function="SaveRecord()" .../>. User can only invoke method of objects whose have metadata files. These objects include BizForm, BizDataObj, BizView and PluginService. BizForm methods and PluginService methods are recommended to be callable from client side.

- FunctionType can be either RPC or Page or Form or Popup.

FunctionType Explanation Example
RPC the function is invoked on server side by HTTPRequest (AJAX). RPC is default value New record button:
<Control Name="btn_new" Function="NewRecord()" FunctionType="RPC"/>
Page the function is invoked on server side with page reload, form data is not passed to server Export button to bring up a file save dialog in the page
<Control Name="btn_export" Function="CallService(ioService,exportXML)" FunctionType="Page"/>
Form the function is invoked on server side by form submission Save button when there's file to upload in the form:
<Control Name="btn_save" Function="SaveRecord()" FunctionType="Form"/>
Popup the function is invoked on server side targeting to a new popup window Excel output button to show excel format in a popup:
<Control Name="btn_excel" Function="CallService(excelService,renderHTML)" FunctionType="Popup"/>

- ShortcutKey associates a shortcut key to the function. It is explained in "Keyboard navigation on BizForm".

- PostAction is the redirected page/view after an action is taken. It is explained in "Controlling page navigation".

Keyboard navigation on BizForm

Openbiz 2.1RC adds a very important feature - keyboard navigation support on BizForm. Once shortcut keys are defined on BizForm, users are able to use keyboard to to navigate records and pages, create/edit/delete record. Users can have the rich client experience on browser. 

Shortcut keys are defined in BizForm metadata files. EventHandler of controls can have a ShortcutKey attribute to associate the shortcut key to a function. The syntax is <Control Name="" Function="" ShortcutKey="key_combination".../>. BizForm only recognizes shortcut keys defined in controls of its Toolbar and Navbar.

Openbiz recognizes keys including:

Key input key text to use in ShortcutKey attribute
0,1,...9 0,1,...9
a,b,...z or A,B,...Z A,B,...Z
Ctrl key Ctrl
Shift key Shift
Alt key Alt
Enter key Enter 
Escape key Escape
Page up key PageUp
Page down key PageDown
Left arrow key Left
Right arrow key Right
Up arrow key Left
Down arrow key Down
Insert key Insert
Delete key Delete

Developers can configure combination of Ctrl and/or Shift and/or Alt with other key, just use "+" to link them together. Be aware of not conflicting with default shortcut keys of browsers. Please refer to http://www.mozilla.org/support/firefox/keyboard for shortcut key for different browsers.

See shortcut key sample in demoapp/metadata/demo/FMEvent.xml. This BizForm supports following shortcut keys:

Shortcut key Command to execute
Ctrl+Shift+Right go to next page
Ctrl+Shift+Left go to previous page
Ctrl+Shift+Down go to next record
Ctrl+Shift+Up go to previous record
Ctrl+Shift+N create a new record
Ctrl+Shift+E edit the selected record
Delete delete the selected record
Ctrl+Shift+Q switch to search record mode
Enter run search, or save record
Escape cancel search or cancel editing
Ctrl+Shift+C copy the selected record
Ctrl+Shift+R refresh form with default query

Form controls dependency

In a complex form, there's usually some controls depending the values of other controls. When the driving control changes, its children controls change accordingly. This is so called form controls dependency.

With the help of expression language, controls relationship can specified in BizForm metadata file. With the help of event handlers, events on driving control will cause the dynamical changes on its children controls.

A sample form is delivered  under demoapp/metadata/demo/FMFieldDepTest.xml

The first combobox is the driving control. Based on its value,
- 2nd control will be enabled or disabled (BizForm configuration)
- 3rd control will be hidden or shown (BizForm configuration)
- 4th control will have different lists (BizForm configuration)
- 5th control will change value and color when monuseover the 1st control (customer js class extending from jbForm)

Configuration of record-selecting popup BizForm 

Users can pick record from a different form on the following cases:

Note: Openbiz keeps only one instance of a metadata object (of BizDataObj, BizForm, BizView) in a user session, so always configure a different object when two instances of same entity needed in one view. For example, on an Event form (FMEvent / BOEvent), we usually configure an event popup as (FMEventPopup / BOEventX). There're two ways to configure a record-selecting popup BizForm.

To configure a html control to show popup form, users can set "ShowPopup($popupFormName)" in the control Function attribute and set FunctionTarget="Popup". This configuration can be used in picking a child record (M-1 or M-M) in the child form.

<Control Name="btn_new" Caption="Add" Type="Button" Function="ShowPopup(demo.FMAttendeePopup)" FunctionTarget="Popup"/>

On the popup form, add a button to call AddToParent() to add the current selected record to the parent form (the form trigger the popup). 

To configure a BizCtrl to show popup from, user ValuePicker attribute.

<BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup"/>

On the popup form, add a button to call JoinToParent() to join the current selected record to the parent form (the form trigger the popup).

You can user ValuePicker attribute to allow users to click the icon to show the picker popup window. Users may want to type in the value in the control and system will automatically pick the right record according to the user input. Openbiz supports this feature by BizForm's AutoPickValue($ctrlname) method. To configure auto picker.

<BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup">
   <EventHandler Name="onchange" Event="onchange" Function="AutoPickValue(reg_attdln)" />
</BizCtrl>

According to the user input, the behavior is described in the following table:

Case User input Behavior
1 empty delete all related controls values
2 not empty query the DataObj of valuepicker BizForm with searchRule as [field] LIKE 'input_value%'. Based on the query results:

  • if single record returned, auto fill all related controls values with returned value
  • if no record returned, show value picker popup with no searchRule
  • if multiple records returned, show value picker popup with the searchRule

Configure drilldown link to another view

You can configure a BizCtrl associated with a hyperlink (drilldown link) which changes current view to another view who has the detailed information of that BizCtrl.

In a BizForm, set a DillDownLink attribute of a BizCtrl. The syntax is

DrillDownLink="OtherView,OtherBizForm.OtherBizCtrl=MyBizCtrl".
OtherView - a view name the link takes to;
OtherBizForm - an independent BizForm, which is not a subforml of any other BizForm, in OtherView;
OtherBizCtrl - a BizCtrl of OtherBizForm
MyBizCtrl - a BizCtrl in current BizForm 

Here's an example: <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup" DrillDownLink="AttendeeView,FMAttendee.attd_id=reg_attdid"/>.

Select field data from comboBox or ListBox

- Bind static list to comboBox

In your BizForm, you assign SelectFrom="Selection(Fee)" for a BizCtrl, which means this field control is a comboBox whose data is from the "Fee" elements in Selection.xml file. Please see example in demo FMRegist.xml where BizCtrl reg_fee is defined as a comboBox.
<Selection>
  <Fee Value=""/>
  <Fee Value="15"/>
  <Fee Value="20"/>
</Selection>

Also, you can give both value and text. If only give value, openbiz uses the value as the display text.
<Selection>
   <ChartOption Value="AAA" Text="BarLine Chart"/>
   <ChartOption Value="BBB" Text="Pie Chart"/>
   <ChartOption Value="CCC" Text="GroupBar Chart"/>
</Selection>
You can make up your own xml file that has list of values for selection.

- Bind dynamic list (Table column) to comboBox

In your BizForm, you assign SelectFrom="BizDataObjName[BizFieldName]" for a BizCtrl, which means this field control is a comboBox whose data is from the table column mapping to the BizFieldName of the BizObjName. To avoid same values appear in the comboBox, you need to make sure the BizObj query returns an unique list.

Format SelectFrom="BizDataObjName[BizFieldName4Text:BizFieldName4Value]" is supported too. So users can show BizFieldName4Text field in comboBox and set BizFieldName4Value for value.

A SearchRule can be applied on the SelectFrom with syntax as SelectFrom="BizDataObjName[BizFieldName4Text:BizFieldName4Value], SearchRule_of_the_BizDataObj". For example, <BizCtrl Name="" ... SelectFrom="BOEvent[Name], [Name] LIKE '%Soc%'"/>.

Controlling page navigation

Openbiz has an unique concept of display mode. BizForm can have more than one display modes. Basically each display mode is a rendering mode of the BizForm. A Bizform presents a BizDataObj data to UI, the same data set can be rendered in different modes which is called "display modes".

- Display modes in a BizForm

Display modes are specified in <DisplayModes> section of BizForm metadata file. You can associate smarty template with each mode. For detail please refer to build view and form web templates.

Usually a BizForm can have READ, NEW, EDIT, QUERY display modes. But no limit to associate any display mode to the BizForm. An example is under /demoapp/metadata/shared/FMCalendar.xml. It has display modes as "LIST", "DAY", "WEEK", "MONTH".

Switching between display modes in a BizForm is done in code by calling BizForm method SetDisplayMode($mode). Code may be applied to each display mode to implement special logic.

Each control or BizCtrl has DisplayMode attribute. You can set DisplayMode = "MODE1|MODE2|...". For example, <BizCtrl Name="LastName" ... DisplayMode="EDIT|NEW"/>, then LastName only shown on EDIT and NEW modes.

- Page redirection after an action is finished

It's very common that users click on a button to trigger an action on server side and after the action is finished the page is redirected to another page. Page redirection can be specified as a post action in BizForm metadata file. The syntax is

<EventHandler Name="..." Function="..." PostAction="url|view"/> PostAction can accept url:url_string or view:view_name.

An example is the login form demoapp/metadata/shared/FMAuth.xml

<Control Name="btn_submit" Image="" Caption="Submit" Type="HTMLButton" Function="Login()" PostAction="url:login.php?login=success"/>

- Error page and error message

If the action errors out, application should return error page or error popup to browser.

Import and export from BizForm

Data import and export support is important feature for off-line users. Off-line users usually run the application (web application also can be run in local box) locally on their laptops and take the work back to synchronize with server database. Openbiz provides import and export support in the following ways:

Data export - implemented in exportXML method of ioService. The exported xml file has format as 

<BizDataObj Name="demo.BOAttendeeX">
  <Record>
   <Field Name="field name" Value="field value" /> *
  </Record>
</BizDataObj>

Data import - implemented in importXML method of ioService. The xml file to import has the same format as described above.

Import and Export buttons are configured in FMAttendee form. Import button invokes ioService's exportXML method directly, while export button brings up a popup window to ask for the file to be imported. Please refer to the demoapp/metadata/demo/FMAttendee.xml for details.

It would be possible to add more export/import methods in ioService to support other file types.

Upload file from BizForm

File upload is supported in openbiz shared package. Metadata file is at demoapp/metadata/shared/FMAttachment.xml and class file is at demoapp/bin/shared/FMAttachment.php.

To upload the file, user needs to configure a BizCtrl with type as "File". It maps to a BizField with type as "Blob".

To download the file, users needs to configure a BizCtrl with Function as Download($record_id). Download method is implemented in FMAttachment class.

Please refer to the FMAttachement class and metadata for details.


Openbiz Development Guide

Show openbiz views (pages)

- User URL string as controller.php?view=...&form=...&rule=...&mode=...&OtherInputs...

- Use client javascript GoToView(view, rule, loadPageTarget)

Input Description Sample
view bizview name shared.CalDetailView
form bizform name. This form must not depend on (a subform of) another bizform shared.FMCalDetail
rule the search rule of a bizform

syntax is "form.ctrl operator value".
operator can be =,>,>=,<,<=,!=. "LIKE %" SQL format is also valid rule. "AND", "OR" can be used to add more restriction.

FMSponsor.spr_exp>=12000 

FMSponsor.spr_name=\'Midas Auto\' OR FMSponsor.spr_id=\'SPSR_2\'

FMSponsor.spr_name LIKE \'S%\'

loadPageTarget the window or frame target to load the page  

Build view and form web templates

Smarty template engine is used in OpenBiz to render the HTML output. We provides some basic templates for render BizForm and BizView. You can create your own templates. Remember that an openbiz form must begin with a form tag <form id={$name} name={$name}>. For detail, please refer to http://smarty.php.net/docs.php 

Smarty engine recognizes the subdirectories under the main template directory. So you can create a fold under demoapp/templates/ and put template files there. When you give template file name in metadata file, just give Template="subdir/view.tpl".

- Draw BizForm as a html table

In BizForm xml file, you need give DataFormat as "block" and FormatStyle as table style which is given in css file.
<Mode ... TemplateFile="list.tpl" ... DataFormat="htmltable" FormatStyle="tbl"/>

In template file, {$fmttable}represents form whole html table.

Please refer to demo files FMEvent.xml and list.tpl

- Draw BizForm as a set of controls

Since the array dataformat output to smarty template is associated array, user can easily layout controls by their names. The associated array has format as fields[control_name][label] and fields[control_name][control].

Please refer to demo files FMEvent.xml and edit.tpl

Three DataFormats decide what data is passed to templates

DisplayMode DataFormat Data passed to template Controllability on template Example
array - Variable name to use in template is $fields
- associated array of single record
- array (control_name=>array ("label"=>label_text, "control"=>control_html))
Highly controllable in template edit.tpl
table - Variable name to use in template is $table
- 2D array of multiple records
- array (index=>array (control1_name=>value1, control2_name=>value2, ...))
  array[0] is column header
  array[1-n] are the 1st record to nth record
Highly controllable in template rptlist.tpl
block - Variable name to use in template is $block
- HTML string
lowly controllable in template list.tpl

Using BizDataObj functionalities

Only basic usage of BizDataObj is listed below. Please refer to the API doc for details.

Query and get results

1.x BizObj is renamed as BizDataObj in 2.0, because it mainly acts as business data unit. 

1.x use GetField and SetField to do get and set field values. In 2.0, no field level methods, but using GetRecord() and UpdateRecord() method to do record level operations. The idea behind is to make easier coding to retrieve query results and provide coarse-grained interfaces between 2 layers.

1.x way to query and get records

$bizobj->SetSearchRule("...");    // set search rule
$bizobj->RunSearch(-1);    // run query against the database tables. 
$bizobj->Home();    // reset the result record set
$hasVal = $bizobj->MoveFirst();    // move cursor to first record
while ($hasVal)
{
    foreach ($fieldlist as $field)
        $field_val[] = $bizobj->GetField($field);
   
// user logic code can be put here. 
    $hasVal = $bizobj->MoveNext();    // move cursor to next record
}

2.0 way to query and get records - option 1

$bizobj->SetSearchRule("...");    // set search rule
$bizobj->RunSearch(-1);    // run query against the database tables. query results can be cached
while ($recArray = $bizobj->GetRecord(1))    // get current record and move the cursor to the next record 
{
    // user logic code can be put here. recArray is an associated array whose key is "fieldname" and value is value of the field
}

2.0 way to query and get records - option 2

$bizobj->FetchRecords ($searchRule, $resultSet, $numRecords);    // get the whole recordset (list of recArray), query results won't be cached

Insert, Update and Delete a record 

// Insert Record
$recArr = $boUser->NewRecord();    // NewRecord returns an empty record array with a generate Id field
$recArr["LastName"] = "Test";
$recArr["FirstName"] = "Add";
$ok = $boUser->InsertRecord($recArr);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

// Update a record
$boUser->SetSearchRule("[Id]='USER-1006'");
$boUser->RunSearch();
$recArray = $bizobj->GetRecord(0);
$recArray["FirstName"] = "Update";
$ok = $boUser->UpdateRecord($recArray);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

// Delete a record
$boUser->SetSearchRule("[Id]='USER-1006'");
$boUser->RunSearch();
$recArray = $bizobj->GetRecord(0);
$ok = $boUser->DeleteRecord($recArray);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

Using BizForm functionalities

User can configure function in BizForm metadata file to invoke appropriate action on server side. The commonly used BizForm methods are listed below. Please refer to the API doc for details.

Query and show results

Insert a new record

Update a record

Delete a record

Copy a record

Page Navigation

User input validation

According the topic at http://www.boringguys.com/?p=30, there are 3 different types of data validation checks one can do:

Syntactic and semantic validation can be implemented on client side and service side. Domain validation involves query data source, it is usually done in service code that connects to database.

Client side form validation

Openbiz does input validation using jsval library (LGPL, http://jsval.fantastic-bits.de/). To configure a validation rules for an openbiz HTMLControl, developers can use jsVal's "Inline initialization" to add validation attributes to HTMLAttr part of HTMLcontrol and FieldControl.

<Control Name="" Type="" HTMLAttr="jsval validation attributes here" ... /> 

Example: <BizCtr Name="email" Type="Text" HTMLAttr="regexp='JSVAL_RX_EMAIL' minlength=5..." ... /> 

In addition, HTMLControl has a Required (=Y|N) attribute. It is passed to pass as $fields['required'] (along with $fields['label'] and $fields['control']) to smarty template. In smarty template (edit.tpl), has code {if $item.required=="Y"} <span class='required'>*</span>{/if} to append a * to the label. Then the required control's label looks as "Email *"

Server side input validation

Openbiz mainly support validation on BizDataObj. In BizField, Required and Validator attributes are used for such purpose. Please see the BizDataObj configuration chapter for explanation of these two attributes.

Developers can use customer class to override DataObj::ValidateInput() method or Field::Validate() method achieve their own validation rules.

BizForm has an empty ValidateForm method which may be overridden by customer classes to implment special validation logic.

Extend OpenBiz classes

OpenBiz provide many functionalities to building a complicated web application. But different application has different requirement, so you may extend OpenBiz packages to build customer applications.

Extend server side classes

Because OpenBiz packages are based on object-oriented design, you can easily build up your own object by extending these packages and inherit all useful functions provided by them.

Extended classes are automatically loaded on demand. Extended class  must be included in a file with format as ClassName.php.

Use can specify class name for BizDataObj, BizField, BizView, BizForm, BizCtrl, Control and PluginService by filling the "Class" attribute of in metadata file

Base Class Where to specify the extend class
BizDataObj <BizDataObj ... Class="" ...>
BizField <BizField ... Class="" ...>
BizView <BizView ... Class="" ...>
BizForm <BizForm ... Class="" ...>
FieldControl <BizCtrl ... Class="" ...>
HTMLControl <Control ... Class="" ...>

Example: Extend BizDataObj and BizForm

/**
* class BOUser is the BizDataObj class to implement USER logic object
*/

class BOUser extends BizDataObj 
{
    function BOUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

/**
* class FMUser is the BizForm class to implement USER UI object
*/

class FMUser extends BizForm 
{
    function FMUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

      function Render() {}    // override Render()
}

Extend client side classes

BizForm is the main server side presentation class, it has its counterpart class on client browser side. In the BizForm metadata, users can specify client side class in jsClass attribute of BizForm element. For example.

<BizForm Name="FMEvent" ... Class="BizForm" jsClass="jbForm"...>

Openbiz provides two client side classes AjaxForm and jbForm that is a subclass of AjaxForm.

AjaxForm methods:

jbForm methods:

To implement UI logic on client side, developers need to create their own client side class like jbForm and give the class name to jsClass attribute of BizForm element. If you need special logic in some methods, add these methods in the client class, which can be subclass of either AjaxForm or jbForm. These methods can be pure client code or it can this.CallFunction(...) to send the request to server.

An example:

Form metadata file is like:

<BizForm ... Class="MyForm" jsClass="MyjbForm"...>
...
   <BizCtrl Name="mybutton" ...>
      <EventHandler Name="onclick" Event="onclick" Function="server_MyButtonClick"/>
      <EventHandler Name="onblur" Event="onblur" Function="js_MyButtonBlur"/>
...
</BizForm>

In server side MyForm class, server_MyButtonClick() needs to be defined.

In client side MyjbForm class, js_MyButtonBlur() needs to be defined. Of course, if server_MyButtonClick() is defined in client class, server_MyButtonClick() needs to call this.CallFunction("server_MyButtonClick", params_array) at the end of the method to send the request to server MyForm server_MyButtonClick() method. The client side code will be like:

function MyjbForm(name) {}
MyjbForm.inheritsFrom(jbForm); //set inheritance
MyjbForm.prototype.js_MyButtonBlur = function (params_array)
{
    // put client logic here
    ...
}
MyjbForm.prototype.server_MyButtonClick= function (params_array)
{
    // put client logic here
    ...
    // send request to server side at the end
    this.CallFunction("server_MyButtonClick", params_array);
}

Implement Plug-in Service

Openbiz customer can write their special logic by implement Plug-in Service. Plugin services are also metadata-driven objects. Service code is under bin/service and metadata is under /metadata/service. The plugin service metadata only gives the service name, package and implementing class. Any xml elements can be child of the root PluginService element. This is because different services may have different metadata configuration. Please refer to the Appendix to see the DTD of plugin service metadata xml file.

Openbiz core library includes services under openbiz/bin/service/ and their metadata files under openbiz/metadata/service/.

In the application, you can specify your own plugin service implementation with following methods.

  1. Change the service metadata content under your_app/metadata/service/, still use the core service. For example, you can write different accessService.xml to control the view access rule, but the implementing class is accessService.php in core library. The accessService.xml is like 
    <PluginService Name="accessService" Package="service" Class="accessService">
       application specific view access definition
    </PluginService>
  2. Specify the service implementing class. For example, different applications have different profile service. The profileService.xml is like 
    <PluginService Name="profileService" Package="service" Class="your_own_service_class">
    </PluginService>
  3. Combine the above 2 methods.

Write a plug-in service

Implement the class and method in the ClassName.php
A input argument of the method are the caller's object name (a BizForm name) and the input data string (a collection of form values from client browser). It implements the user-specific business logic and returns void. See the following code snippet.

class pdfService
{
 function pdfService() {}

 function renderView($viewName)
 {
  global $g_BizSystem;
  // get the view object and render the view to a html string
  $viewobj = $g_BizSystem->GetObjectFactory()->GetObject($viewName);
  if($viewobj) {
    $viewobj->SetConsoleOutput(false);
  $sHTML = $viewobj->Render();
  // convert HTML to PDF
  // ... customer code to do the convert 
 }
}

Call a plug-in service method

Implement authentication, view and data access control

User authentication

Openbiz uses authentication service (usrlib/authService.php) to authenticate username and password

public function AuthenticateUser ($userid, $password) is called to authenticate user. 

Role-based view access control

View access control depended on the AccessControl attribute in view metadata file in Openbiz 1.x. From Openbiz RC1, openbiz implements role-based view access control in its new security architecture. 

Openbiz uses profile service (usrlib/profileService.php) to get user profile that includes "role". Then match this role to access service (usrlib/accessService.php) to determine the users' accessibility to the view

public function GetProfile ($userid=null) is called to get user profile array which is an associated array with profile key and profile value pairs.

public function AllowViewAccess ($viewName, $role=null) is called to check the accessibility of a view

Attribute-based data access control

Openbiz uses profile service (usrlib/profileService.php) to get user profile that includes attributes. Then based on these attributes to determine browse/update/delete permission of data record. The data access permissions are controlled in BizDataObj.

User can refer to attributes by @profile:attribute in BizDataObj metadata files. Profile attributes are all from profileService. When user first login, profileService returns a profile array that is saved in session. If an attribute is found in the profile array, the attribute value is returned. If the profile array doesn't contain such attribute, profileService method GetAttribute ($userid, $attr) is called to return the attribute value. Customer must implement GetAttribute method with their own logic.

- Data browse permission. A typical access control requirement is to limit the accessibility of table record to different users. This feature can be achieved by configuring AccessRule in BizDataObj metadata file. We do the configuration with the following two scenario.

Scenario  Configuration
Event can be only accessed by the owner

(personal access control)

<BizDataObj Name="Event" ... AccessRule="[OwnerId]='@profile:ORGID'" ...>

<BizField Name="OwnerId" Column="OWNER_ID"/>

Event can be accessed by all invited attendees 

(if the login user is one of the attendees, he can access the event)

<BizDataObj Name="Event" ... AccessRule="[AttendeeId]='@profile:USERID'" ...>

<BizField Name="AttendeeId" Column="ATTD_ID" Join="Attendee"/>

<Join Name="Attendee" Table="evts_attds" Column="EVT_ID" ColumnRef="SYSID" JoinType="LEFT JOIN"/>

- Data update permission. UpdateCondition is to control the record update permission. UpdateCondition expects true or false. A sample is UpdateCondition = "[OrgId]=={@profile:ORGID}". {} is the evaluated as simple expression.

- Data delete permission. DeleteCondition is to control the record delete permission. DeleteCondition expects true or false. A sample is DeleteCondition = "'admin'=={@profile:ROLEID}"

Build a multi-step wizard view

Wizard is a sequence of forms (questionnaires) which guide users to complete a complicated task. An example is filling an expense report which include different types (hotel, airfare, other activities...) of expenses.

Openbiz support wizard by easy metadata configuration. Openbiz wizard has following features:

To see sample of wizards, go to Test view, click on "Wizard tests +" submenus. As you can see from the demo, wizard can be accessed with an url. 

As shown in the 2nd link, developer can give the parameter on the fly to run the wizard against given record

Configuration of wizard view

Openbiz wizard is a regular view that contains several wizard forms. So configuring a wizard in openbiz is no harder than  configuring a BizView. The difference between a wizard view and regular view is wizard view show the wizard forms one by one based on the their sequence in view metadata file, but regular view show all forms in one page. Below is an example of a wizard view metadata file.

<?xml version="1.0" standalone="no"?>
<BizView Name="EventWizardView" Description="" Package="demo" Class="BizViewWizard" Template="view.tpl">
   <ControlList>
      <Control Name="wizardForm1" Form="FMEventWzd1"/>
      <Control Name="wizardForm2" Form="FMEventWzd2"/>
   </ControlList>
   <Parameters>
      <Parameter Name="Evt_Id" Value="" />
   </Parameters>
</BizView>

Configuration of wizard forms

A wizard form is a regular form with class as BizFormWizard or BizFormNewWizard (or their subclasses).

This is a typical wizard form metadata file.

<?xml version="1.0" standalone="no"?>
<BizForm Name="FMNewEventWzd1" Package="demo" Class="BizFormNewWizard" jsClass="jbForm" Title="Enter event information:" SearchRule="" Description="Event BizForm" BizDataObj="BOEvent">
  <DisplayModes>
    <Mode Name="EDIT" TemplateFile="edit.tpl" DataFormat="array" FormatStyle="" />
  </DisplayModes>
  <BizCtrlList>
    <BizCtrl Name="evt_id" FieldName="Id" DisplayName="Event Id" />
    <BizCtrl Name="evt_name" FieldName="Name" DisplayName="Name" Type="" Width="250" />
    <BizCtrl Name="evt_desc" FieldName="Description" DisplayName="Description" Type="Textarea" />
    <BizCtrl Name="evt_host" FieldName="Host" DisplayName="Host" />
  </BizCtrlList>
  <Toolbar>
    <Control Name="btn_back" Image="" Caption="&lt; Back" Type="Button" Function="GoPrev()" />
    <Control Name="btn_next" Image="" Caption="Next &gt;" Type="Button" Function="GoNext()" />
    <Control Name="btn_cancel" Image="" Caption="Cancel" Type="Button" Function="DoCancel()" PostAction="view:demo.EventView"/>
    <Control Name="btn_finish" Image="" Caption="Finish" Type="Button" Function="DoFinish()" PostAction="view:demo.EventView"/>
  </Toolbar> 
  <Navbar>
  </Navbar> 
</BizForm>

Extend wizard with customer wizard class

If application has speical logic, Openbiz suggest developers to write their own wizard form class drived from BizWizardForm. By overriding GoPrev(), GoNext(), DoCancel() and DoFinish() methods, developers can do different handling on navigation buttons events.

Openbiz wizard view play the role as a form controller where wizard form can set/get input data, cancel/finish the whole wizard process and render wizard forms. Please see the API document for details.

Implement dataobject events trigger

Upon dataobjects update/delete operations, openbiz allows triggering different alerts and action requests based on boolean results from search criteria for specific object. Briefly it is called DO Trigger which executes in a response to a change in the values stored in the database. DO trigger has two parts - trigger events and trigger actions. These information are defined in DOTrigger plugin service metadata files. At runtime when user update/delete a BizDataObj record, openbiz searches for this dataobj's trigger by looking for its trigger metadata file with name DataObjName_trigger.xml under the same directory. For example, demo/BOEvent's dataobj trigger metadata file is demo/BOEvent_trigger.xml.

Define a dataobject trigger metadata

<PluginService Name="BOEvent_Trigger" Description="" Package="demo" Class="service.doTriggerService" DataObjectName="BOEvent">
<DOTrigger TriggerType="UPDATE|DELETE">*
  <TriggerCondition Expression="" ExtraSearchRule="" />
  <TriggerActions>
    <TriggerAction Action="Method_Name" Immediate="Y|N" DelayMinutes="" RepeatMinutes="">
      <ActionArgument Name="" Value="" /> *
    </TriggerAction>
  </TriggerActions>
</DOTrigger>
</PluginService>

Trigger conditions Description Sample
trigger type Update or Delete record  
expression any expression supported by openbiz {[Expense]}>100. Check if current record's Expense field > 100
extra search rule search rule added on the current dataobj search rules {[AlertFlag]}='Y'. Check if there's at least one record whose AlertFlag is 'Y'
Trigger action methods Description Parameters
ExecuteSQL ExecuteSQL method executes SQL statement Name="DBName" Value="Default"
Name="SQL" Value="select * from regist where EVENT_ID='{[Id]}'"
ExecuteShell ExecuteShell method executes external application Name="Script" Value="dir"
Name="Inputs" Value=" > d:\temp\out.txt"
SendEmail SenEmail method sends outbound emails. 

It calls emailService's sendEmail method

Name="EmailService" Value="service.emailService"
Name="Account" Value="MyPhpopenbiz"
Name="TOs" Value="rockyswen@gmail.com; rockyswen@phpopenbiz.org"
Name="CCs" Value=""
Name="BCCs" Value=""
Name="Subject" Value="alert message"
Name="Body" Value="This is an alert message. \nPlease notice that the record with {[Id]} was updated."
Name="Attachments" Value="" 
AuditTrail Trace record field change

It calls auditService Audit method

Name="AuditService" Value="service.auditService"
Name="DataObjectName" Value="{@:Name}"
any method in doTriggerService The method of doTriggerService is called  Parameters needed to the method

Make customer specific UI components

Due to the extensibility nature of metadata xml files, developers can create their own metadata file, which does not comply with openbiz metadata DTD, to describe the behavior of objects. Openbiz converts xml file to a php array and pass it to the class constructor to save developers' parsing work. Developers need to write their own code to extend from MetaObject class and read in the array by overriding ReadMetadata(&$xmlArr) method.

Tabs component

This is the good example of using customer metadata xml file. Openbiz 2.1 supports tabs UI component. The metadata file (demo/tabs.xml) is like

<?xml version="1.0" standalone="no"?>
<BizForm Name="Tabs" Package="demo" Class="HTMLTabs">
  <TabViews>
    <View Name="demo.AttendeeView" URL="" Caption="Attendees"/>
    <View Name="demo.EventView" URL="" Caption="Events"/>
  </TabViews>
</BizForm>

The class code is under openbiz/bin/HTMLTabs.php. Its css file is in openbiz.css.

Developer can draw more UI widgets like tree, menu using the same approach. 

Menu component 

Openbiz 2.1 supports menu UI component. The metadata file of a menu (i.e. demo/Menus.xml) is like

<?xml version="1.0" standalone="no"?>
<Menu Name="Menus" Package="demo" Class="HTMLMenus">
  <MenuItem URL="" Caption="" Target=""> *
    <MenuItem URL="" Caption="" Target=""/> *

The class code is under openbiz/bin/HTMLMenus.php. Its css file is /css/menu.css

The menu provided in the demo application can be seen in "Test" view. This menu is a horizontal dropdown menu. It is a pure css menu. The idea is copied from http://solardreamstudios.com/learn/css/cssmenus. The output html (<ul><li>...) has same format of the output of well-known DynarchMenu http://www.dynarch.com/products/dhtml-menu/. So integration with DynarchMenu is an easy job. Of course, developers are free to modify the HTMLMenus class to work with other menu libraries. Same principle will apply to other customer UI components.

Tree component

Openbiz 2.1 supports tree UI component. The metadata file of a tree (i.e. demo/Tree.xml) is like

<?xml version="1.0" standalone="no"?>
<Tree Name="Tree" Package="demo" Class="HTMLTree">
  <Node URL="" Caption="" Target=""> *
    <Node URL="" Caption="" Target=""/> *

The class code is under openbiz/bin/HTMLTree.php. Its css file is in openbiz.css

The tree provided in the demo application can be seen in "Test" view. The technique of drawing tree is same as the tree of Eclipse help system http://help.eclipse.org/help30/index.jsp. Again, developers are free to modify the HTMLTree class to work with other tree libraries.

Control the look and feel with css files

The openbiz look and feel is controlled by stylesheet css files. The main css file is /css/openbiz.css

Control BizForm table style

In case of using Format="block" in the BizForm's displayMode, users can modify the following section in css/openbiz.css file.

/* -------- table style -------- */
.tbl {...}
.tbl .head {...}
.tbl .rowodd {...}
.tbl .roweven {...}
.tbl .rowsel {...}
.tbl .cell {...}

Control tabs style

In order to give user specific tab styles, users can modify the following section in css/openbiz.css file.

/* -------- tabs style -------- */
.tabmenu {...}
.tabmenu li {...}
.tabmenu a, a.active {...}
.tabmenu a.active {...}
.tabmenu a:hover {...}
.tabmenu a:visited {...}
.tabmenu a.active:hover {...}

Control menu style

In order to give user specific tab styles, users can modify the following section in css/menu.css file.

Control tree style

In order to give user specific tree styles, users can modify the following section in css/openbiz.css file.

/* ----- tree style ----- */
UL.expanded {...}
UL.collapsed {...}
LI.tree {...}

Control rich text editor (RTE) style

In order to give user specific RTE styles, users can modify the following section in pages/rte/rte.css file.

Date and Datetime picker

The DHTML calendar is well documented at  http://www.dynarch.com/demos/jscalendar/doc/html/reference.html. The javascript file is under demoapp/js/jscalendar.

Debug strategies

- Logging. BizSystem::log() method  can be called to log 4 priority levels LOG_EMERG, LOG_ERR, LOG_WARNING and LOG_DEBUG. Also a subject can be specified to give log messages different categories. The error is logged under /log/log_error.html, open it and you may find out what's wrong

- Debugging. Other than the DEBUG flag in 1.1.x is still valid, developers can turn on other 2 debug flags.
  1) Open the sysheader.inc under /bin, turn on debug log by changing define("DEBUG", 1); Then you'll see some debug information in /log/log_debug.html. This debug file records mainly the database calls and other operations
  2) Turn on SQL debug flag. Uncomment //$this->m_DbConnection[$rDBName]->debug = true; in BizSystem::GetDBConnection().
  3) Turn on RPC debug flag, each RPC response is printed in a separate window. Set var RPC_DEBUG = true; in clientUtil.js.

API document

Openbiz 2.0 API document

Appendix  A - third party libraries

Library URL Description License
Smarty  http://smarty.php.net template engine LGPL
Adodb http://adodb.sourceforge.net  database abstraction library BSD
PHPMailer http://phpmailer.sourceforge.net  email library LGPL
jsval http://jsval.fantastic-bits.de  client side data validation LGPL
jscalendar http://www.dynarch.com/projects/calendar  DHTML calendar LGPL
RTE http://www.kevinroth.com/rte/demo.htm  Cross browser rich text editor free
dompdf http://www.digitaljunkies.ca/dompdf  html to pdf convertor free

Appendix  B - metadata DTD files

BizDataObj metadata DTD file

<!--OpenBiz BizObj metadata DTD-->

<!ELEMENT BizObj (BizFieldList, TableJoins, ObjRefernces, Parameters) >
<!ATTLIST BizObj Name CDATA #REQUIRED >
<!ATTLIST BizObj Description CDATA #REQUIRED >
<!ATTLIST BizObj Package CDATA #IMPLIED >
<!ATTLIST BizObj Class CDATA #REQUIRED >
<!ATTLIST BizObj InheritFrom CDATA #IMPLIED >
<!ATTLIST BizObj DBName CDATA #IMPLIED >
<!ATTLIST BizObj Table CDATA #REQUIRED >
<!ATTLIST BizObj SearchRule CDATA #IMPLIED >
<!ATTLIST BizObj SortRule CDATA #IMPLIED >
<!ATTLIST BizObj OtherSQLRule CDATA #IMPLIED >
<!ATTLIST BizObj AccessRule CDATA #IMPLIED >
<!ATTLIST BizObj UpdateCondition CDATA #IMPLIED >
<!ATTLIST BizObj DeleteCondition CDATA #IMPLIED >

<!ATTLIST BizObj CacheMode CDATA #IMPLIED >

<!ELEMENT BizFieldList (BizField+) >
<!ELEMENT BizField EMPTY >
<!ATTLIST BizField Name CDATA #REQUIRED >
<!ATTLIST BizField Class CDATA #IMPLIED >
<!ATTLIST BizField Join CDATA #IMPLIED >
<!ATTLIST BizField Column CDATA #REQUIRED >
<!ATTLIST BizField SQLExpr CDATA #IMPLIED >
<!ATTLIST BizField Type CDATA #IMPLIED >
<!ATTLIST BizField Format CDATA #IMPLIED >
<!ATTLIST BizField Required CDATA #IMPLIED >
<!ATTLIST BizField Validator CDATA #IMPLIED >
<!ATTLIST BizField DefaulValue CDATA #IMPLIED >
<!ATTLIST BizField Value CDATA #IMPLIED >
<!ATTLIST BizField OnAudit CDATA #IMPLIED >
<!ELEMENT TableJoins (Join+) >
<!ELEMENT Join EMPTY >
<!ATTLIST Join Name CDATA #REQUIRED >
<!ATTLIST Join Table CDATA #REQUIRED >
<!ATTLIST Join Column CDATA #REQUIRED >
<!ATTLIST Join JoinRef CDATA #IMPLIED >
<!ATTLIST Join ColumnRef CDATA #REQUIRED >
<!ATTLIST Join JoinType CDATA #REQUIRED >

<!ELEMENT ObjReferences (Object+) >
<!ELEMENT Object EMPTY >
<!ATTLIST Object Name CDATA #REQUIRED >
<!ATTLIST Object Description CDATA #IMPLIED >
<!ATTLIST Object Relationship CDATA #REQUIRED >
<!ATTLIST Object Table CDATA #REQUIRED >
<!ATTLIST Object Column CDATA #REQUIRED >
<!ATTLIST Object FieldRef CDATA #REQUIRED >
<!ATTLIST Object CascadeDelete CDATA #IMPLIED >
<!ATTLIST Object XTable CDATA #IMPLIED >
<!ATTLIST Object XColumn1 CDATA #IMPLIED >
<!ATTLIST Object XColumn2 CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizView metadata DTD file.

<!--OpenBiz BizView metadata DTD-->

<!ELEMENT BizView (ControlList, Parameters) >
<!ATTLIST BizView Name CDATA #REQUIRED >
<!ATTLIST BizView Description CDATA #REQUIRED >
<!ATTLIST BizView Package CDATA #IMPLIED >
<!ATTLIST BizView Class CDATA #IMPLIED >
<!ATTLIST BizView Template CDATA #IMPLIED >

<!ELEMENT ControlList (Control+) >
<!ELEMENT Control EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Form CDATA #REQUIRED >
<!ATTLIST Control SubCtrls CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizForm metadata DTD file.

<!--OpenBiz BizForm metadata DTD-->

<!ELEMENT BizForm (BizCtrlList, DisplayModes, Toolbar, Navbar, Parameters) >
<!ATTLIST BizForm Name CDATA #REQUIRED >
<!ATTLIST BizForm Description CDATA #REQUIRED >
<!ATTLIST BizForm Package CDATA #IMPLIED >
<!ATTLIST BizForm Class CDATA #REQUIRED >
<!ATTLIST BizForm InheritFrom CDATA #IMPLIED >
<!ATTLIST BizForm jsClass CDATA #REQUIRED >
<!ATTLIST BizForm Title CDATA #REQUIRED >
<!ATTLIST BizForm BizDataObj CDATA #REQUIRED >
<!ATTLIST BizForm PageSize CDATA #REQUIRED >
<!ATTLIST BizForm SearchRule CDATA #IMPLIED >

<!ELEMENT BizCtrlList (BizCtrl+) >
<!ELEMENT BizCtrl (EventHandler+) >
<!ATTLIST BizCtrl Name CDATA #REQUIRED >
<!ATTLIST BizCtrl Class CDATA #IMPLIED >
<!ATTLIST BizCtrl FieldName CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayName CDATA #IMPLIED
>
<!ATTLIST BizCtrl Type CDATA #IMPLIED >
<!ATTLIST BizCtrl Width CDATA #IMPLIED >
<!ATTLIST BizCtrl Height CDATA #IMPLIED >
<!ATTLIST BizCtrl HTMLAttr CDATA #IMPLIED >
<!ATTLIST BizCtrl Link CDATA #IMPLIED >
<!ATTLIST BizCtrl Image CDATA #IMPLIED >
<!ATTLIST BizCtrl Hidden CDATA #IMPLIED >
<!ATTLIST BizCtrl Enabled CDATA #IMPLIED >

<!ATTLIST BizCtrl Sortable (Y|N) "" >
<!ATTLIST BizCtrl Order CDATA #IMPLIED >
<!ATTLIST BizCtrl Style CDATA #IMPLIED >
<!ATTLIST BizCtrl ValuePicker CDATA #IMPLIED >
<!ATTLIST BizCtrl SelectFrom CDATA #IMPLIED >
<!ATTLIST BizCtrl DrillDownLink CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayMode CDATA #IMPLIED >

<!ELEMENT Toolbar (Control+) >
<!ELEMENT Navbar (Control+) >
<!ELEMENT Control (EventHandler+) >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Class CDATA #IMPLIED >
<!ATTLIST Control Image CDATA #IMPLIED >
<!ATTLIST Control Caption CDATA #IMPLIED >
<!ATTLIST Control Type CDATA #IMPLIED >
<!ATTLIST Control Width CDATA #IMPLIED >
<!ATTLIST Control Height CDATA #IMPLIED >
<!ATTLIST Control HTMLAttr CDATA #IMPLIED >
<!ATTLIST Control Style CDATA #IMPLIED >
<!ATTLIST Control Hidden CDATA #IMPLIED >
<!ATTLIST Control Enabled CDATA #IMPLIED >
<!ATTLIST Control SelectFrom CDATA #IMPLIED >

<!ATTLIST Control DisplayMode CDATA #IMPLIED >

<!ELEMENT EventHandler EMPTY >
<!ATTLIST EventHandler Name CDATA #REQUIRED >
<!ATTLIST EventHandler Event CDATA #REQUIRED >
<!ATTLIST EventHandler Function CDATA #REQUIRED >
<!ATTLIST EventHandler FunctionType CDATA #IMPLIED >
<!ATTLIST EventHandler ShortcutKey CDATA #IMPLIED >
<!ATTLIST EventHandler PostAction CDATA #IMPLIED >
<!ELEMENT DisplayModes (Mode+) >
<!ELEMENT Mode EMPTY >
<!ATTLIST Mode Name CDATA #REQUIRED >
<!ATTLIST Mode TemplateFile CDATA #REQUIRED >
<!ATTLIST Mode DataFormat CDATA #REQUIRED >
<!ATTLIST Mode FormatStyle CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

Plugin service metadata DTD file.

<!--OpenBiz Plugin service metadata DTD-->

<!ELEMENT PluginService ANY >
<!ATTLIST PluginService Name CDATA #REQUIRED >
<!ATTLIST PluginService Description CDATA #IMPLIED >
<!ATTLIST PluginService Package CDATA #REQUIRED >
<!ATTLIST PluginService Class CDATA #REQUIRED >

Openbiz Eclipse Plugin User Manual

Openbiz Eclipse Plugin User Manual

  1. Installation
  2. Work on openbiz project
    2.1 Create openbiz project
    2.2 Create and edit a BizObj
    2.3 Create and edit a BizForm
    2.4 Create and edit a BizView
    2.5 Test BizView on browser

1. Installation

Openbiz Eclipse Plugin assists openbiz users to develop openbiz application in Eclipse environment.

First remove older Openbiz Eclipse plugin installation. Download openbiz_eclipse_0.9.x.zip from openbiz sourceforge web site. Same as installation of other eclipse plugins, just unzip it to your eclipse directory. Then restart eclipse. Openbiz plugin works with Eclipse 3.x.

To make sure that openbiz plugin can connect to your database (which is required for openbiz development), please edit config.xml under ECLIPSE_ROOT/plugins/org.openbiz.metadata_0.9.x/config. A pre-configured database element in the file is to connect local MySql database using connect/j JDBC driver. Please make change on it to point to correct jdbc driver and database url.

The pre-configure database element in config.xml

<Database DriverFile="D:\java\eclipse\plugins\org.openbiz.metadata_0.9.x\lib\mysql-connector-java-3.1.10-bin.jar" DriverClass="com.mysql.jdbc.Driver" ConnectURL="jdbc:mysql://localhost:3306/demo" Schema="" User="root" Password="root"/>

To configure a database element, the following attributes must be filled correctly.

2. Work on Openbiz Project

2.1 Create openbiz project

With help of eclipse, openbiz directory can be managed under an eclipse project. User can create a project that points to the openbiz (or openbiz/metadata) directory. Then the openbiz project tree should appear on the eclipse Navigator view.

2.2 Create a BizDataObj - the object maps to database table

Click the File -> New -> Others... from the menu, or right click on the item of openbiz project, select New -> Others..., a window pops up. Select Openbiz Metadata Object -> BizDataObj metadata file.

 

Then do the following tasks in the rest pages.

  1. Type in a metadata file name
  2. Select a database from the database list that is read from config.xml
  3. Select a database table to be the BizDataObj base table
  4. Select table columns mapping to the BizFields

After you click Finish button, the new metadata file is opened in the editor area. The editor looks like eclipse Plug-in Menifest Editor. The overview page shows the information of root xml element of the metadata object, the rest pages show the second level xml elements. 

The plugin provides three wasy to edit the metadata file, 

2.3 Create a BizForm - the UI object maps to BizDataObj

Like creating a BizDataObj, click the File -> New -> Others... from the menu, or right click on the item of openbiz project, select New -> Others..., a window pops up. Select Openbiz Metadata Object -> BizForm metadata file.

Then do the following tasks in the rest pages.

  1. Type in a metadata file name
  2. Select a BizDataObj that BizForm depends on 
  3. Select BizDataObj's BizFields mapping to the BizForm's BizCtrls
  4. Create Toolbar controls and Navigation bar controls
  5. Add event handlers to controls and BizCtrls

Screenshot: right click mouse on a control, select Add EventHanlder menu item

Screenshot: edit event handler of a control

After you click Finish button, the new metadata file is opened in the editor area. 

2.4 Create a BizView - BizForm Container

Like creating a BizDataObj, click the File -> New -> Others... from the menu, or right click on the item of openbiz project, select New -> Others..., a window pops up. Select Openbiz Metadata Object -> BizView metadata file.

Then Type in a metadata file name and click Finish button.

After you click Finish button, the new metadata file is opened in the editor area.

2.5 Test BizView on browser

A BizView can be accessed with url as following format:

openbiz_root_path/bin/controller.php?view=package.viewname

For example, http://localhost/demoapp/bin/controller.php?view=shared.SignupView

Best Practices

Openbiz Best Practice

1. Work on Openbiz metadata files

Since openbiz-based applications heavily depends on metadata files, editing metadata files is as important as writing code during application development. In a  simple application, a web page includes a single data table that maps to a single database table. It is very easy to implement by configuring one BizDataObj, one BizForm and one BizView (this is covered by the simple tutorial). In case of building a complex application like CRM and school admin, database tables are related together by foreign keys, a page usually contains a driving form and multiple children forms which depends on the data of the driving form and one data object can be used in many places. Without careful design, managing metadata files becomes a tough job. This document is to discuss the best practice of managing your openbiz metadata files.

In order to discuss the topic on a concrete base, a commercial CRM database schema from sugarcrm is used here. In the schema, the relationship between accounts table and contacts table is many-to-many. The intersection table of their relationship is accounts_contacts.

accounts
id 
date_entered 
date_modified 
modified_user_id 
assigned_user_id 
created_by 
name 
parent_id 
account_type 
industry 
annual_revenue 
phone_fax 
billing_address_street 
billing_address_city 
billing_address_state 
billing_address_postalcode 
billing_address_country 
description 
rating 
phone_office 
phone_alternate 
email1 
email2 
website 
ownership 
employees 
sic_code 
ticker_symbol 
shipping_address_street 
shipping_address_city 
shipping_address_state 
shipping_address_postalcode
shipping_address_country 
deleted 
accounts_contacts
id 
contact_id 
account_id 
date_modified
deleted 
contacts
id 
deleted 
date_entered 
date_modified 
modified_user_id 
assigned_user_id 
created_by 
salutation 
first_name 
last_name 
lead_source 
title 
department 
reports_to_id 
birthdate 
do_not_call 
phone_home 
phone_mobile 
phone_work 
phone_other 
phone_fax 
email1 
email2 
assistant 
assistant_phone 
email_opt_out 
primary_address_street 
primary_address_city 
primary_address_state 
primary_address_postalcode
primary_address_country 
.... 
....
....

The requirement is to implement a contact page and and account page.

1.1 Preparation

Before starting editing the metadata files, we need to add database into openbiz eclipse plugin and openbiz application configurations. Metadata tree structure should be determined too.

1.2 Design the BizForm and BizDataObj objects

What are the objects in a view? 

A normal view with a little complexity may include a driving form and sub forms. A sub form may have a popup form to add a record into itself. Each form object has a corresponding data object behind it. We name the data object of the driving form as "main DO", the data object of a  sub form as "reference DO" because it must be one of the ObjReferences of the main DO. Then we call the data object of a popup form as "popup DO".

When a BizDataObj has joined fields (from other tables' columns), users should be able to select a record on a popup form to join it to the base form. This base form can either be driving form or sub form.

Openbiz objects hierarchy

Every database table should have a corresponding dataobj who has only fields mapping to its base table's columns. No join and object reference is in the dataobj. This dataobj is a slim dataobj that is the parent object of other fatter dataobj. If the parent dataobj includes all joins and object references, its children objects have them too. It'll hurt the performance. Other data objects (Main data object, Reference data object and Popup data object) inherit from the base data object.

A BizDataObj may be presented on UI with BizForms. Since different BizForms (even if they are based on same BizDataObj) usually have different UI layout which is rendered by smarty template, it might be easy to manage BizForms without inheritance. 

BizView is in fact a web page. Because web pages usually have different layout, inheritance is not well suitable for BizView.

Naming convention of openbiz objects

We need to have some naming convention of the objects so that we can tell the content of the objects from their names. Difference developers can different way to assigning names. In this article we uses prefix in the naming convention.

Data object (DO) DO prefix Example Form object Form prefix Example
base dataobj _DO _DOContacts      
main dataobj DO DOContacts driving form FM FMContacts
reference dataobj DORef DORefContacts sub form FMSub FMSubContacts
popup dataobj DOPop DOPopContacts popup form FMPop FMPopContacts

After knowing the objects in a view and objects hierarchy, applying the naming convention, finally we have objects chart drawn out as below.

1.3 Create Openbiz metadata files

Developers can recommended to use Openbiz Eclipse Plugin to compose Openbiz metadata files.

Openbiz eclipse plugin provides several different ways to help developers to create Openbiz metadata files.

Once the metadata file created, open it with Openbiz Metadata editor to edit it in eclipse. Please see the Openbiz eclipse plugin user manual for more details.

The the metadata file tree is shown as the following screenshot which is copied from eclipse Package Explorer view.

Other alternate metadata structure recommended by many other openbiz users separates BizDataObj, BizForm and BizView files under different directories. For example:

app_root/ 
---metadata/
------project/
------project/do   
(BizDataObj files)
------project/form 
(BizForm files)
------project/view 
(BizView files)

Change the Id generation algorithm for BizDataObj

By looking at the sugarcrm tables, you would find the id (primary key) column does not generated with native mysql algorithm. Now we need to extend genIdService (Openbiz plugin service) to use application specific ID generation algorithm.

- Create demoapp/bin/service/sugarIdService.php. Have a sugarIdService class extending from genIdService class and override GetNewID method.

include_once(OPENBIZ_HOME."/bin/service/genIdService.php");

class sugarIdService extends genIdService
{
public function __construct() {}

public function GetNewID($idGeneration, $conn, $dbtype, $table=null, $column=null)
{
if ($idGeneration == 'sugarId')
return create_guid();
// this function is used in sugarcrm source code
return parent::GetNewID($idGeneration, $conn, $dbtype, $table, $column);
}
}

- Create demoapp/metadata/service/genIdService.xml that is the metadata file of Id Generation Service plugin. Assign the class as sugarIdService.

<?xml version="1.0" standalone="no"?>
<PluginService Name="genIdService" Package="service" Class="sugarIdService">
</PluginService>

- Assign BizDataObj's IdGeneration attribute as "sugarId". This attribute is used in GetNewId method of sugarIdService class.

1.4 Test views

To verify the your design works, open a browser and type in url 

http://localhost/demoapp/bin/controller.php?view=sugar.accounts.ViewAccounts 

http://localhost/demoapp/bin/controller.php?view=sugar.contacts.ViewContacts 

Verify the basic functionalities 

1.5 Refine the metadata files

2.0 API

The 2.0 API docs are listed here:
http://www.phpopenbiz.org/document/apidoc20/index.html

Docs generated courtesy of:
http://www.phpdoc.org/

1.0 Openbiz Manual

OpenBiz Document 1.1.1

1. Introduction

Package BizObj
Package BizView
Package jbForm (javascript bizForm)
Package ADODB
2. Installation

Running Environment
Install Openbiz
Install necessary third party packages
Windows Installer with AppServ
3. Build your application

Specify requirement of your application
Create your database model
Create metadata xml files
Build template
Technical Details - Advanced Configration
4. Advanced: build your application by extending OpenBiz

Extend BizObj and BizForm
Implement Plug-in Service Interface
Implement View Access Control
5. API document
6. Debug strategies
7. Openbiz designer user manual

Introduction

OpenBiz provides a PHP framework that assists you to build complicated web application in an easy way. 

OpenBiz is designed as a multi-layer architecture as the figure below.

Usually a business application can be modulated to 3 layers - Data layer, Business Logic layer and Presentation layer. In OpenBiz architecture, these 3 layers map to 3 packages, Presentation layer is refined to logic which is implemented by BizView package and GUI layers which is implemented by jbForm javascript package. Business Logic layer is implemented by BizObj package. 3rd party package ADODB handles Database layer.

Package BizObj

Classes

Functionalities

Package BizView

Classes

Functionalities


Popup an BizForm and Select data to populate multiple fields on base BizForm

Registration BizForm depends on Player BizForm (RegForm.PlayerId = PlyForm.PlayerId)

Michael Liu is current selected player

Alan Chew is current selected player

Package jbForm (javascript bizForm)

Class

Functionalities

Package ADODB

This is an abstract database connection package which can connects to all major databases from different vendors. It can be downloaded from http://php.weblogs.com/ADODB


Installation

1. Running environment

OpenBiz is written by PHP4 scripts, it runs at web server side. The typical running environment could be Web Server + PHP 4.x. To ensure the performance and reliability, we recommend users to use latest web server and php engine. For example

If you have the administrator permission, you can configure PHP running as an Apache module. Some php performance software, such as mmcache, works under Apache module. This url http://www.thesitewizard.com/archive/php4install.shtml is the guide to setting up PHP 4 to run with Apache on Windows.

For better performance, please enable dom xml extension under PHP4. Please refer to http://us4.php.net/domxml. domxml extension is required to run Design Studio.

Support web browsers - IE5.x, Netscape 7.x and Mozillar 1.x

2. Install OpenBiz

Download the zip file and unzip it to a directory under your web access root.

Please read through the sysheader.inc under openbiz_root/ directory. Important notices:

Source tree structure:

openbiz_root/ 
---bin/        
(openbiz php source)
------adodb/      
(adodb package)
------configs/    
(smarty config dir)
------fpdf/       
(fpdf package)
------jpgraph/    
(jpgraph package)
------Smarty/     
(smarty package)
------templates/   (openbiz templates)
------templates_c/
(templates compiled code)
------tmpfiles/   
(temporary file directory)
------usrlib/     
(openbiz user library directory)
---css/        
(openbiz style sheets)
---document/   
(openbiz documents)
---images/     
(openbiz images)
---log/        
(openbiz logs)
---medata/     
(openbiz metadata files)
------demo/        
(demo package)
------design/      
(design package)
---session     
(openbiz session files)

In Unix or Linux box, you need to give write permission to web users on log, metadata, session, bin/tmpfiles and bin/templates_c directories.

3. Install necessary third party packages

The following package are necessary - they are included in openbiz package

We recommend you install PHP optimization packages.

4. Windows Installer with AppServ

For Windows users who want to install Web Server + PHP + Openbiz, an installer is available since B10110. Please follow the steps below:


Build Your Application

1. Specify requirement of your application

OpenBiz is a perfect tool that help you develop your complicated web application easily and comprehensively. Based on its 3-layer architecture, your application will be on a clear logic model. It takes care the basic and advanced feature of the data-oriented application. In order to tell whether OpenBiz can help building your application, you need ask these questions:

If the answers are YES, OpenBiz is the right framework for developing your application!

2. Create your database model

Modeling your business data with Relational database tables is the necessary base for building your whole application.

Populate the demo database to see how demo works

Create a new database

Use existing database (assume each table has single auto-generated id column)

3. Create metadata xml files

Developers can choose use XML editor to edit medata files or use Openbiz Designer to visually edit metadata files. For more detail of Openbiz designer, Please refer to Openbiz designer user manual.

3.1 Organize metadata by package

In a big application, user may need to build lots of objects, therefore they have big metadata file list. If they put these files under a single metadata directory, managing the metadata files is a painful thing. From openbiz 1.1, metadata files can be organized by package name. Bear in mind, metadata package is different with the (BizObj, BizView ...) packages which are the code units. Metadata package is a naming system, different package maps to different directory. It is like the package concept used in Java. 

PackageX.PackageY.metaA.xml refers to the metaA.xml under META_PATH/PackageA/PackageB directory. Where META_PATH is the root metadata directory. This macro is defined in sysheader.inc with define ("META_PATH", "../metadata/"). 

3.1.1 How to configure  package in metadata files?

Let's explain it with the demo example. After you unzip the source, find the demo directory under metadata directory. Open FMRegist.xml file with a text editor. You'll see a Package="demo" attribute in the BizForm element. This attribute is to say the default package of any type of openbiz object is under "demo" package. Here the openbiz objects refer to the following object types.

Object Type Referred as attributes in metadata files
BizObj BizForm[BizObj]
BizObj->BizFieldList->BizField[SelectBizObj]
BizForm BizView->ControlList->Control[Form]
BizView->ControlList->Control[SubCtrl]
BizForm->BizCtrlList->BizCtrl[SelectFrom]
BizView  
BizPopup BizForm->BizCtrlList->BizCtrl[SelectBizForm]
BizFormTree Same as BizForm

If an object name doesn't contain dot symbol ("."), the system uses the package attribute defined in the object root element as its package. Otherwise, if an object name has format as aaa.objectname, the system thinks such object under package "aaa" and will locate such object under aaa directory.

Go back to the example, you can find <BizForm Name="FMRegist" Package="demo" ... BizObj="BORegist"...>, <BizCtrl Name="reg_attdln" ...  SelectBizForm="AttendeePopup"...> and <BizCtrl Name="reg_fee" ... SelectFrom="Selection(Fee)"...>. They all use default package, so the system will try to locate the metadata files as demo/BORegist.xml, demo/AttendeePopup.xml and demo/Selection.xml.

If you want to refer to an object under other package, just add the package name as the prefix of the object name. Notice, there're a Selection.xml under /demo directory and another Selection.xml under /design directory, they belong to different packages. In FMRegist, whose package is "demo", you can use <BizCtrl ...  SelectFrom="design.Selection(Mode)" ...> to configure a comboBox whose values are from the "Mode" element of "design/Selection.xml".

3.1.2 How to configure  package with Openbiz Design Tool?

From openbiz 1.1, in the object browser view of Design Tool, user can give "Package" name for each object. If the object is not found under the directory (META_PATH/package/) mapping to the given package, a sample metadata file (copied from object type template) is created under that directory. If no package name is specified, a sample metadata file (copied from object type template) is created under META_PATH/ directory.

3.2 Use object metadata inheritance

If you have a complex application, you want to reuse the existing object to different places, but you want the object behave a little differently in different scenarios. Object inheritance will solve the above problem. Since in openbiz framework objects maps to metadata file, object inheritance becomes metadata file inheritance.

3.2.1 How to specify inheritance between metadata files?

Specify an object attribute, InheritFrom = "parent object name". For example, in demo application, BOEventX has <BizObj Name="BOEventX" Description="Event BizObj Extended from BOEvent" Package="demo" Class="BizObj" InheritFrom="demo.BOEvent"...>. This indicates that is BOEventX is inherited from BOEvent. 

Metadata file inheritance is similar with class inheritance in programming languages, child object can inherit (if not defined in child object, but defined in parent object)  or override (if same attribute defined in both child object and parent object) the parent object attributes.

Object Type which can has inheritance What CAN be inherited or overridden What CANNOT be inherited - must be specified in child metadata file
BizObj Object Attributes: Description, DBName, Table, SearchRule, SortRule, OtherSQLRule, CacheMode

Object BizFieldList: BizField

Object Attributes: Name, Package, Class, InheritFrom, DesignProfile
BizForm Object Attributes: Description, jsClass, Title, BizObj, PageSize, Width, Height, SearchRule

Object BizCtrlList: BizCtrl
Object DisplayModes: Mode
Object Toolbar: Control
Object Navbar: Control

Object Attributes: Name, Package, Class, InheritFrom, DesignProfile

3.3 Create an object record in ObjBrowse view

Open design.htm in browser to access OpenBiz Design Studio. In unix, make sure your metadata directory has write permission open for web clients. Put focus on a record, click "Design" button to modify the object xml file.

3.4 Build BizObj metadata

BizObj metadata file describes the mapping between database tables and BizObj. It's a xml file with following DTD.

<!--OpenBiz BizObj metadata DTD-->

<!ELEMENT BizObj (BizFieldList) >
<!ATTLIST BizObj Name CDATA #REQUIRED >
<!ATTLIST BizObj Description CDATA #REQUIRED >
<!ATTLIST BizObj Package CDATA #IMPLIED >
<!ATTLIST BizObj Class CDATA #REQUIRED >
<!ATTLIST BizObj InheritFrom CDATA #IMPLIED >
<!ATTLIST BizObj Table CDATA #REQUIRED >
<!ATTLIST BizObj SearchRule CDATA #IMPLIED >
<!ATTLIST BizObj SortRule CDATA #IMPLIED >
<!ATTLIST BizObj OtherSQLRule CDATA #IMPLIED >
<!ATTLIST BizObj CacheMode CDATA #IMPLIED >
<!ATTLIST BizObj DesignProfile CDATA #REQUIRED >

<!ELEMENT BizFieldList (BizField+) >
<!ELEMENT BizField EMPTY >
<!ATTLIST BizField Name CDATA #REQUIRED >
<!ATTLIST BizField BaseTable CDATA #REQUIRED >
<!ATTLIST BizField BaseColumn CDATA #REQUIRED >
<!ATTLIST BizField ForeignTable CDATA #IMPLIED >
<!ATTLIST BizField ForeignColumn CDATA #IMPLIED >
<!ATTLIST BizField ForeignPrimKey CDATA #IMPLIED >
<!ATTLIST BizField SelectBizObj CDATA #IMPLIED >
<!ATTLIST BizField SelectField CDATA #IMPLIED >
<!ATTLIST BizField Type CDATA #IMPLIED >
<!ATTLIST BizField Format CDATA #IMPLIED >
<!ATTLIST BizField Required CDATA #IMPLIED >
<!ATTLIST BizField Validator CDATA #IMPLIED >
<!ATTLIST BizField Value CDATA #IMPLIED >

Open Design Studio screenshot - BizObj Design. Click "Go Back to object browser" button to return to ObjBrowse View.

Important Notes: 

3.4.1 Composite keys support

Most database table designers recommend each table have its unique primary key column which is also called ID column. In Openbiz BizObj, Id field is a required field for all BizObj. If table has ID column, it's easy to map such column to Id BizField. But there's still many tables are given composite keys. Openbiz provide the following solution to map composite keys to Id BizField.

On the Id BizField of a BizObj, user can specify >1 column names in the BaseColumn attribute. For example, <BizField Name="Id" ... BaseColumn="key1,key2,key3" ...>. But you need to make sure all BizFields mapping to the composite keys are marked as "Required='Y'".

3.4.2 Efficiently use memory by specifying cache mode

Openbiz leverages server side BizObj cache (storing database query results temporally) to maintain the session data so that users can feel smooth interaction just as they are using desktop rich client. But many web interfaces simply provide navigation only functionality. To help openbiz use memory efficiently, BizObj cache mode can be turned off. There're two ways to control the cache mode.

1) Set CacheMode attribute in BizObj metadata file. <BizObj Name=... CacheMode = "0|1" ...>. 0 means no cache is used, 1 means query data is cached. If no value is given, default cache mode = 1.

2) Call BizObj::Home($cacheMode) to reset the ResultSet and set the cache mode. The default $cacheMode is 1.

Keep in mind, no cache mode is suggested to be used in navigation only BizForm. 

3.5 Build BizForm metadata

BizForm metadata file describes the mapping between BizObj and BizForm as well as other UI controls in BizForm. It's a xml file with following DTD.

<!--OpenBiz BizForm metadata DTD-->

<!ELEMENT BizForm (BizCtrlList, TemplateList, Toolbar, Navbar) >
<!ATTLIST BizForm Name CDATA #REQUIRED >
<!ATTLIST BizForm Description CDATA #REQUIRED >
<!ATTLIST BizForm Package CDATA #IMPLIED >
<!ATTLIST BizForm Class CDATA #REQUIRED >
<!ATTLIST BizForm InheritFrom CDATA #IMPLIED >
<!ATTLIST BizForm jsClass CDATA #REQUIRED >
<!ATTLIST BizForm Title CDATA #REQUIRED >
<!ATTLIST BizForm BizObj CDATA #REQUIRED >
<!ATTLIST BizForm PageSize CDATA #REQUIRED >
<!ATTLIST BizForm SearchRule CDATA #IMPLIED >
<!ATTLIST BizForm DesignProfile CDATA #REQUIRED >

<!ELEMENT BizCtrlList (BizCtrl+) >
<!ELEMENT BizCtrl EMPTY >
<!ATTLIST BizCtrl Name CDATA #REQUIRED >
<!ATTLIST BizCtrl FieldName CDATA #REQUIRED >
<!ATTLIST BizCtrl DisplayName CDATA #REQUIRED >
<!ATTLIST BizCtrl Type CDATA #IMPLIED >
<!ATTLIST BizCtrl Width CDATA #IMPLIED >
<!ATTLIST BizCtrl Height CDATA #IMPLIED >
<!ATTLIST BizCtrl HTMLAttr CDATA #IMPLIED >
<!ATTLIST BizCtrl Function CDATA #IMPLIED >
<!ATTLIST BizCtrl Image CDATA #IMPLIED >
<!ATTLIST BizCtrl Hidden (Y|N) "" >
<!ATTLIST BizCtrl Enabled (Y|N) "" >
<!ATTLIST BizCtrl Sortable (Y|N) "" >
<!ATTLIST BizCtrl Order CDATA #IMPLIED >
<!ATTLIST BizCtrl Style CDATA #IMPLIED >
<!ATTLIST BizCtrl SelectBizForm CDATA #IMPLIED >
<!ATTLIST BizCtrl SelectFrom CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayMode CDATA #IMPLIED >

<!ELEMENT DisplayModes (Mode+) >
<!ELEMENT Mode EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Image CDATA #IMPLIED >
<!ATTLIST Control Caption CDATA #REQUIRED >
<!ATTLIST Control Type CDATA #REQUIRED >
<!ATTLIST Control Width CDATA #IMPLIED >
<!ATTLIST Control Height CDATA #IMPLIED >
<!ATTLIST Control HTMLAttr CDATA #IMPLIED >
<!ATTLIST Control Function CDATA #IMPLIED >
<!ATTLIST Control Style CDATA #IMPLIED >
<!ATTLIST Control Enabled (Y|N) "" >
<!ATTLIST Control DisplayMode CDATA #IMPLIED >
<!ATTLIST Control Access (READ|WRITE) "" >

Open Design Studio screenshot - BizForm Design. 

3.6 Build BizView metadata

BizView metadata file describes the BizForms and their relationship in the BizView. It's a xml file with following DTD.

<!--OpenBiz BizView metadata DTD-->

<!ELEMENT BizView (ControlList) >
<!ATTLIST BizView Name CDATA #REQUIRED >
<!ATTLIST BizView Description CDATA #REQUIRED >
<!ATTLIST BizView Package CDATA #IMPLIED >
<!ATTLIST BizView Class CDATA #IMPLIED >
<!ATTLIST BizView Template CDATA #IMPLIED >
<!ATTLIST BizView AccessControl CDATA #IMPLIED >
<!ATTLIST BizView DesignProfile CDATA #REQUIRED >

<!ELEMENT ControlList (Control+) >
<!ELEMENT Control EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Form CDATA #REQUIRED >
<!ATTLIST Control SubCtrls CDATA #IMPLIED >
<!ATTLIST Control Dependency CDATA #IMPLIED >

Open Design Studio screenshot - BizView Design. 

3.7  Build BizPopup metadata

BizPopup is a special BizView. It has only one BizForm and uses BizForm.dtd file as its XML schema. Because the BizPopup is mainly used in record selection, it makes sense to provide only navigation and query for its BizForm, meanwhile only need to show most critical columns.

Open Design Studio screenshot - BizPopup Design

3.8 Build BizFormTree metadata

BizFormTree is a special BizForm. It uses BizForm.dtd file as its XML schema. BizFormTree is designed to represent the tree hierarchy relationship within a database table.

For example, event table schema: (every record has PARENT_ID and CHILD_FLAG columns which build tree hierarchy relationship between the records in the same table)

Column Comments
SYSID Primary key
NAME Event name
PARENT_ID Store the SYSID of its parent event.
CHILD_FLAG Flag that indicates whether this record has child record or not

Open Design Studio screenshot - BizFormTree Design

To build up a BizFormTree metadata, please the following xml elements are necessary

See screenshot here

3.9 Upgrade configuration xml files when openbiz xml schema changes

The main xml schema (DTD files) won't get changed, but xml element's attributes can be changed (adding a new attribute or remove an old attribute) along the OpenBiz development. To assist OpenBiz customers to update their existing xml files easily, a new button is introduced since B10105.

The button in the red circle is to update the xml element from the current xml schema, meanwhile the existing attributes data is kept. This button can only upgrade the attributes in single xml element. Put focus on an element and click the upgrade button. Then repeat it on another element.

4. Build template

Smarty template engine is used in OpenBiz to render the HTML output. We provides some basic templates for render BizForm and BizView. You can create your own templates. Remember that an openbiz form must begin with a form tag <form id={$name} name={$name}>. For detail, please refer to http://smarty.php.net/docs.php 

4.1 Draw BizForm as a html table

From B10109, draw a BizForm as a html table is easy. 

In BizForm xml file, you need give DataFormat as "htmltable" and FormatStyle as "table style, table header style, table odd row style, table even row style, table selected row style>
<Mode ... TemplateFile="list.tpl" ... DataFormat="htmltable" FormatStyle="tbl,tbl_head,tbl_rowodd,tbl_roweven,tbl_rowsel,tbl_cell"/>

In template file, {$fmttable}represents form whole html table.

Please refer to demo files FMEvent.xml and list.tpl

4.2 Draw BizForm as a set of controls

From B10109, draw a BizForm as a set of controls is more flexisible.

Since the array dataformat output to smarty template is associated array, user can easily layout controls by their names.

Please refer to demo files FMEvent.xml and edit.tpl

5. Technical Details - Advanced Configration

5.1 Link to another view

You can configure a BizCtrl associated with a hyperlink which changes current view to another view who has the detailed information of that BizCtrl.

In a BizForm, set a LinkTo attribute of a BizCtrl. Syntax is LinkTo="OtherView.OtherBizForm.OtherBizCtrl=MyBizCtrl".
OtherView - a view name the link takes to;
OtherBizForm - an independent BizForm, who is not a subctrl of any other BizForm, in OtherView;
OtherBizCtrl - a BizCtrl of OtherBizForm
MyBizCtrl - a BizCtrl in current BizForm 

Please see the example in demo xml files (FMMatch, RegistView, FMPlayer). In this example, a link is associated with player name. This link changes view to RegistView with the player's detail. Click here to see the screenshot.

5.2 Select field data from comboBox or ListBox

5.2.1 Bind static list to comboBox

In your BizForm, you assign SelectFrom="Selection(Fee)" for a BizCtrl, which means this field control is a comboBox whose data is from the "Fee" elements in Selection.xml file. Please see example in demo FMRegist.xml where BizCtrl reg_fee is defined as a comboBox.
<Selection>
  <Fee Value=""/>
  <Fee Value="15"/>
  <Fee Value="20"/>
</Selection>

Also, you can give both value and text. If only give value, openbiz uses the value as the display text.
<Selection>
   <ChartOption Value="AAA" Text="BarLine Chart"/>
   <ChartOption Value="BBB" Text="Pie Chart"/>
   <ChartOption Value="CCC" Text="GroupBar Chart"/>
</Selection>
You can make up your own xml file that has list of values for selection.

5.2.2 Bind dynamic list (Table column) to comboBox

In your BizForm, you assign SelectFrom="BizObjName[BizFieldName]" for a BizCtrl, which means this field control is a comboBox whose data is from the table column mapping to the BizFieldName of the BizObjName. To avoid same values appear in the comboBox, you need to make sure the BizObj query returns an unique list.

5.3 Select a field data Fld1 in BizForm FM1 from another popup BizForm FM2

Say you have following configuration, you want to select Ctrl_1 data from Ctrl_2 that is a bizCtrl on popup BizForm. Keep in mind, the real data is selected from BizObj fields, you need to configure base and popup BizForms as well as their corresponding BizObjs.

  BizCtrl/BizForm BizField/BizObj
Base BizForm Ctrl_1/FM_1 Fld_1/BO_1
Popup BizForm Ctrl_2/FM_2  Fld_2/BO_2

Step1: Give SelectBizObj=BO_2 and SelectField=Fld_2 for the Fld_1 in BO_1 xml file
Step2: Create a Popup_2.xml whose BizForm is FM_2
Step3: In FM_1.xml set SelectBizForm=FM_2 for Ctrl_1

Please see the example in demo xml files (BORegist, FMRegist, BOEvent, EventPopup). In this example, it is configured to select event data to populate multiple fields on FMRegist. Click here to see the screenshot.

5.4 Link 2 BizForm with dependent relationship

You can define the dependency relationship between BizForms in a same view. Records in a child BizForm  is dynamically changed along the record change on it parent BizForm. Such relationship is defined in BizView xml file.

<BizView ... >
  <ControlList>
    <Control Name="fm_1" Form="ParentForm" SubCtrls="ChildForm"/>
    <Control Name="fm_2" Form="ChildForm" Dependency="ChildBizCtrl=ParentForm.ParentBizCtrl"/>
  </ControlList>
</BizView>

Please see the exmaple in demo xml files - RegistView.xml. It defines that Registration BizForm depends on Player BizForm (RegForm.PlayerId = PlyForm.PlayerId). Click here to see the screenshot.

5.5 Data type, format and validation

5.5.1 Openbiz support following data types and formats (attributes of BizField)

Type Format Syntax Format Example
Text none    
Number format supported by printf <BizField ... Type="Number" Format="%..." ...> %5.2f to print a float number
  "Int" - integer format according locale <BizField ... Type="Number" Format="Int" ...> If locale=enu, 12345.678 is displayed as 12,346
  "Float"- float format according locale <BizField ... Type="Number" Format="Float" ...> If locale=enu, 12345.678 is displayed as 12,345.68
Date In default read-only mode, a date can be formatted according to the Date format. <BizField ... Type="Date" Format="date format" ...> 6/21/2003 can be formatted as
%A, %b %d %Y - Saturday, Jun 21 2003 if system locale is enu
  In edit/query mode, a date is formatted as YYYY-MM-DD (ISO 8601)   12/31/2003 can be formatted as 2003-12-31
Datetime In default read-only mode, a date can be formatted according to the Date format. <BizField ... Type="Datetime" Format="datetime format" ...> 6/22/2003 9:30am can be formatted as
%m/%d/%Y %H:%M:%S - 06/22/2003 09:30:00 if system locale is enu
  In edit/query mode, a date is formatted as YYYY-MM-DD hh:mm:ss (ISO 8601)   6/22/2003 9:30am can be formatted as
2003-06-22 09:30:00
Currency Formatted according to locale setting <BizField ... Type="Currency" Format="Currency" ...> 1456.89 is formatted as $1,456.89 (enu)
1456.89 is formatted as F1 456,89 (fra)
Phone Formatted according to given mask # <BizField ... Type="Phone" Format="mask string" ...> 1234567890 is formatted as 
mask=(###) ###-####, 
phone=(123) 456-7890
mask=###-###-####, phone=123-456-7890
  If a phone number starting with "*", it represents international phone number, it won't be formatted   *123 4567890 is treated as international number

5.5.2 Openbiz support following data validations

Validation Type Example
Required - indicates the field can not be empty <BizField Name="Name" Required="Y" BaseTable="players" BaseColumn="NAME"/>
Validator - php statments that returns a boolean value  <BizField Name="Fee" Type="Currency" Format="Currency" Validator="return [Fee]>=15;" BaseTable="regist" BaseColumn="FEE">

5.6 Present data with various HTML elements

From B10107, customer can present their data with various HTML elements by specifying element type and attributes in BizForm xml files. HTML elements are displayed in edit/query modes

Attributes of FieldControl element in BizForm

 
Type Width Height HTMLAttr* Style** SeclectFrom Caption Function Image Comments
Text x x x
Limit the input length
x     x
OnChange
  Single line text input. Default type
Textarea x x x x     x
OnChange
  Multi-line Text input
ListBox x x x
Show ListBox or ComboBox
x x
Set list of values
  x
OnChange
  ListBox or ComboBox
CheckBox x x x x x
Set True value
  x
OnClick
  CheckBox
Radio x
Arrange radio list 
x x x x
Set list of values
  x
OnClick
  Radio buttons
HTMLButton x x x x   x x
OnClick
  Standard HTML Button
SubmitButton x x x x   x x
OnClick
  Standard HTML Submit Button
ResetButton x x x x   x x
OnClick
  Standard HTML Reset Button
Password x x x x         HTML password
Button x x x x   x x
OnClick
x OpenBiz image button
Date x x x x         Textbox with date picker icon
Datetime x x x x         Textbox with datetime picker icon
HTMLBlock x x   x   x
Special Characters
    Caption is treated as HTML block
FunctionColumn x x x x     x x This type doesn't map to a data field

* HTMLAttr field can contain any valid additional HTML attribute applied on the HTML element type

** Style field can contain any valid style properties (css)

Limit the input length: 

HTMLAttr="maxlength=N" to limit the maximum number of characters that the user can enter in a text control. 

Show ListBox or ComboBox: 

By default show comboBox. If HTMLAttr="size=N", show N-row listbox.

Set list of values: 

SelectFrom="XmlFile(Key)" means this field control is a listbox or radio buttons whose data is from the "Key" elements in XmlFile.

Set True value: 

SelectFrom="Value" means this checkbox returns the Value when user check the checkbox.

Arrange radio list: 

By default the radion buttons are arranged horiztionally. If HTMLAttr="wide=1", you can force them arranged vertically.

Special characters: 

"<" and ">" used in HTML block have to be replaced by "&lt;" and "&gt;".

5.7 Use the aggregation SQL functions 

You can assign a BizField with SQL functions provided by the database engine. The syntax is

<BizField Name="FieldName" BaseTable="TableName" BaseColumn="FUNC(ColumnName)"...>

For example:

 <BizField Name="SumFee" BaseTable="regist" BaseColumn="SUM(FEE)"...>

5.8 Usage of SearchRule, SortRule and OtherSQLRule

  Syntax Example
SearchRule SearchRule = SQL Where clause* SearchRule = "[LastName]='Yao' OR [FirstName]='James'"
SortRule SortRule = SQL Order By clause* SortRule = "[Id] ASC" 
OtherSQLRule OtherSQLRule = any SQL clause* OtherSQLRule = "GROUP BY [EvtId] HAVING [SumFee]>10"

* Replace the Column name with BizField name.

5.9 Usage of rule in calling GoToView from client

The most useful client side javascript function is GoToView(view, rule, loadPageTarget).

Argument Description Sample
view the view name  
rule the search rule of a bizform who is not depent on (a subctrl of) another bizform

syntax is "form.ctrl operator value".
operator can be =,>,>=,<,<=,!=. "LIKE %" SQL format is also valid rule. "AND", "OR" can be used to add more restriction.

FMSponsor.spr_exp>=12000 

FMSponsor.spr_name=\'Midas Auto\' OR FMSponsor.spr_id=\'SPSR_2\'

FMSponsor.spr_name LIKE \'S%\'

loadPageTarget the window or frame target to load the page  

In the demo application, EvtMenu.htm consists of a list of hyperlinks that call GoToView functions.

5.10 Make your own calendar and timestamp picker


Advanced: build your application by extending OpenBiz

OpenBiz provide many functionalities to building a complicated web application. But different application has different requirement, so you may extend OpenBiz packages to build customer oriented application.

Because OpenBiz packages are based on object-oriented design, you can easily build up your own object by extending these packages and inherit all useful functions provided by them.

Since B10107, extended classes are automatically loaded on demand. Customers can put their library files under /bin or /bin/usrlib/. Extended class  must be included in a file with format as ClassName.php.

1. Extend BizObj and BizForm

/**
* class BOUser is the BizObj class to implement USER logic object
*/

class BOUser extends BizObj 
{
    function BOUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

/**
* class FMUser is the BizForm class to implement USER UI object
*/

class FMUser extends BizForm 
{
    function FMUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

      function Render() {}    // override Render()
}

2. Implement Plug-in Service Interface

From openbiz 1.1, customer can write their special logic by implement Plug-in Service Interface.

class chartService
{
function chartService() {}

function render($objname, $inputDataStr)
{
  $kvArray = ExtractInputToArray($inputDataStr);
  $chartName = $kvArray['__this']; // get the value of the control that issues the call 

  // get the current UI bizobj and its querySQL, create a new bizobj and search with the same sql
 
$bizform = &sys_getobj($objname); // get the existing bizform object 

  // copy to a new bizobj, not touch the bizobj belong to UI, syntax may change in PHP5
 
$bizobj = $bizform->m_BizObj;
...
}

Three examples can be found in bin/usrlib/

3. Implement View Access Control

By assigning a customer function call to the "AccessControl" attribute of BizView, access control can be added to a view. The syntax is

<BizView ... AccessControl="ClassName.MethodName"...>

Or <BizView ... AccessControl="I"...>. If I=0 access denied; if I=1 view readonly; if I=2 view is read+write. 

You can control the access level of each control by assign "Access" attribute (READ/WRITE) to a control in BizForm. If no Access attribute is given, openbiz treates it have "WRITE" permission.

<Control Name="SearchButton" ... Access="READ">
<Control Name="EditButton" ... Access="WRITE">

Then implement this function call as a class method with a input argument as view name. The function should return an integer value.

Return Value Meaning
0 Cannot access the view. System will show an error page "viewdenied.tpl"
1 View is read-only
2 View is editable

/* Example: method CanAccessView of class ViewControl.  
   BizView config as AccessControl="ViewControl.CanAccessView"  */

function CanAccessView($view)
{
//$userid = _SESSION["login"];
//check if this user can access this view
//if view is not accessible
// echo "$view is not accessible!";
// exit;
//else
// return;    // (0,1,2) - (no view, read, write)
}


API Document

OpenBiz API Document is generated by PhpDocumentor http://phpdocu.sourceforge.net/


Debug Strategies

2.0 User Contributed Guides

Members of the PHPOpenBiz community are encouraged to create additional pages in the manual and link to them here.

Custom Classess: BizDataObj

OpenBiz will use the BizDataObj php class in order to save data defined in the XML BizDataObj file.  This can be overridden by specifying another file by editing the BizDataObj XML file from:

<?xml version="1.0" encoding="UTF-8"?>
<BizDataObj AccessRule="" Class="BizDataObj" DBName="my_camp_office" DeleteCondition="" Description="Add description of BizDataObj" IdGeneration="Identity" InheritFrom="" Name="BOAccount" OtherSQLRule="" Package="account" SearchRule="" SortRule="" Table="account" UpdateCondition="">
<BizFieldList>

to

<?xml version="1.0" encoding="UTF-8"?>
<BizDataObj AccessRule="" Class="account.BOAccount" DBName="my_camp_office" DeleteCondition="" Description="Add description of BizDataObj" IdGeneration="Identity" InheritFrom="" Name="BOAccount" OtherSQLRule="" Package="account" SearchRule="" SortRule="" Table="account" UpdateCondition="">
<BizFieldList>

This new entry specifies a destination and file in realation to your application's bin folder.  Something like:

MYAPPLICATION/bin/account/BOAccount.php

That is the easy part, now we have to create a new class that we will customize for writing data to the database.   But first, a word about OpenBiz's BizDataObj class.

The BizDataObj has a couple of functions that handle your basic CRUD operations.  These are the functions that you oftern times want to override in your custom class. 

CREATE:  InsertRecord(&$recArr, $exsitingRecord=false)
READ:     Query($page)
UPDATE:  UpdateRecord(&$recArr)
DELETE:  DeleteRecord($recArr=null, $cascadeObjNames=null)

Further inspection shows that these functions follow a basic pattern.  Build the SQL query, connect to the database and run the query performing the occassional helper function along the way.   If you have complex Create/Update/Delete queries you plan to run, consider overwriting these functions in your custom class.   You can skip OpenBiz's BuildQuery function and write you own queries directly.  Heck, go crazy and write several queries and run them all from within one of these functions.  For example...

  public function UpdateRecord(&$recArr)
   {
    .......
      //$sql = $this->BuildUpdateSQL();
      $sql = "UPDATE tablex SET columna='value' where index_id = ".$recArr['id']."';";
      BizSystem::log(LOG_DEBUG, "DATAOBJ", "Update Sql = $sql");
      $db = $this->GetDBConnection();
      try {
         $db->query($sql);
      }
      catch (Exception $e) {
         $this->m_ErrorMessage = "Error in query: " . $sql . ". " . $e->getMessage();
         return null;
      }

      $sql = "UPDATE tabley SET columna='value2' where index_id = ".$recArr['id']."';";
      BizSystem::log(LOG_DEBUG, "DATAOBJ", "Update Sql = $sql");
      $db = $this->GetDBConnection();
      try {
         $db->query($sql);
      }
      catch (Exception $e) {
         $this->m_ErrorMessage = "Error in query: " . $sql . ". " . $e->getMessage();
         return null;
      }
.....

}

**Warning** Some functions in BO are set to be private and may not be called from an inheriting class.  I went into the BizDataObj class and changed them to protected.

Some developers may have only modest changes to the SQL queries generated they should consider overridding a CRUD functions BuildQuery function.

 

I've run out of time and have to go but more to come!

 

Extending Permissions In OB

**DRAFT**

A permission scheme that can be customized using OB forms.

XML is pretty cool but sometimes you want to create parts of an application that can be modfied by users from the web.  On a current project I'm working on, I need to implement a permission system that allows the following:
-Staff can be in more than one role
-Staff determine which views are accessible to which roles

I will demonstrate how to create an interface allowing your users to modify permissions and roles via ordinary BizForms and BizObjs.  The key to this setup is replacing the access XML file with a database table.  This way OB's builtin Forms/Objs can be used to modify access permissions.

  • A sequence of steps can be broken down as...
  • Create tables in database
  • Create BizForms/Objects to manipulate tables
  • Override standard Profile class
  • Override standard Access class

My permissions system uses the following tables:

staff - holds basic user information with which to hold user accounts
list -  This is a generic table that I use to store any simple lists.  For this example, we'll store a list of Roles and Views.
view - a generic list of views that match the actual views in your application
role_staff - A join table connecting multiple roles to multiple staff
role_view - Another join table that assigns a views to a roles

Getting Custom Data into SMARTY

SMARTY is a neat templating engine and a nice compliment to PHPOpenBiz. In this Guide, I'll explain how I supply SMARTY with variables that contain my own custom business logic. The end result is a was to feed SMARTY templates variables containing simple arrays, strings or even full fledged blocks of HTML code.

The advantage is that OpenBiz can handle the scripting and feed SMARTY the end results in the form of HTML code or simple arrays to loop through. This strategy makes it easier to separate logic and theme data.

The 30 second version is:
Modify BizForm and BizView to call to a new function in each respective class called GetCustomVariables(&$Smarty) within the Render() or RenderHTML() function.

Than create child classes that override the GetCustomVariables($smarty) function adding new vars as needed. Once inside your custom child class that extends either BizForm or BizView you have plenty of room to operating in creating as many custom variables as you wish. You have access to the usual OpenBiz classes including that Forms BizDataObject.

TODO: What about making this a default feature within the BizForm and BizView?

OpenBiz 2.2 Requirements

Note: These are requirements for OpenBiz 2.2, for requirements involving 2.0 check here.

This is a list of requirements in order to use PHPOpenbiz 2.2 as well as it's supporting packages.

PHPOpenBiz
APC suggested
eAccelerator is a reported alternative
PHP 5.1 or greater
 *For installs greater than 5.1.6 see this fix...

Zend Framework
PDO extension and the PDO_YOURDATABASEOFCHOICE (ie. PDO_Mysql)
PHP 5.1 or greater

Smarty template engine

F.A.Q.

Frequent Asked Questions
Please refer to Openbiz forum site form questions and answers

Can I use wildchar in query?
  Yes you can. "*" are supported.
 
Can I use comparison operator in query?
  Yes you can. User can query using ">", ">=", "<", "<=", "!=", "=".
 
How do I issue a query with OR logic?
  "OR" and "AND" are valid query symbol in the bizForm query. Please see the sample below

 
Can I use SQL function in a BizField?
 

Yes, you can use SQL functions provided by the database engine. 
For example, <BizField Name="FullName" Column="" SQLExpr="CONCAT([FirstName],' ',[LastName])"...>
 

Can I use aggregate SQL result in a BizObj?
  Besides "SearchRule" and "SortRule", you can add any SQL clause into "OtherSQLRule" in the BizObj element.
For example, <BizObj ... OtherSQLRule="GROUP BY [EvtId] HAVING [SumFee]>10"...>
 
Is it possible to define the menu and links to views?
  As Openbiz is a generic package, you can build any UI based on it. The most useful client javascript function is GoToView(...). Read more in manual 5.9
/*
function GoToView(view, rule, loadPageTarget) 
- view is the BizView name
- rule is the search rule on a view.
- loadPageTarget is the target frame.
*/
 
Does openbiz provide authentication functionality?
  Openbiz is a generic package, but different customers might have different authentication requirements. So openbiz only provides a simple authentication functionality.
Go to bin/sysheader.inc, change define("CHECKUSER", "Y"); define("TIMEOUT", 1200); Then the demo application will check whether user has logged in or his session is timed out. Since openbiz 2.0, user authentication is implemented in plugin service.
 
How does openbiz provide access control?
  Please read the openbiz manual "Implement View and Data Access Control".
 
I need to build cross database application, can I use more than one databases with openbiz?
  In the Config.xml, define several Databases as Datasources, then assign the Datasource name as the DBName to BizObj. If the DBName is empty, openbiz will use "Default" Datasource as database connection.
 
Does Openbiz support report functionality?
  PDF report and Excel output are supported from version 1.1 as plug-in services. Also with proper template design, you can create HTML reports too.

Openbiz 2.4 Manual PDF

Openbiz 2.4 Manual PDF

Openbiz 2.x 中文手册

Openbiz 2.x 手册中文版, 中文Powerpoint 教程, Openbiz 中文论坛

Openbiz 宣传册

当你期望用最好的用户界面开发, 在一个出类拔萃的应用程序框架之上, 并且最大限度地降低开发和技术支持成本… 你会发现所有这一切都在OPENBIZ - 使应用开发不同于编程!


系统简介

Openbiz提供了一个PHP 应用程序框架。它可以帮助专业软件开发人员和技术咨询家来构建网络上企业级应用。由于企业级应用的高复杂性,系统开发通常会包括巨大投资和冗长的时间去进行工程计划,系统设计,原型设计,组件编码,功能测试,产品部署以及维护。

Openbiz框架的目标是节省复杂应用的开发投入和缩短开发时间。借助于Openbiz的帮助,应用程序的开发将建立于一个拥有完全互联网(Web)层面的,以Metadata驱动为核心的,并且有Eclipse插件作为图形化编写工具的平台。

技术优势

Metadata驱动

Openbiz是一个Metadata驱动的框架。这意味着Openbiz对象(Objects)的创立是基于Metadata的文字描述。构建一个应用意味着设计和编写XML格式的Metadata文件。因此,基于Openbiz的应用软件包是完全可客户化的,而且是极其容易开发和维护的。

完全互联网(Web)层面

Openbiz被设计成一个多层面的结构。以下的图表说明了这一点。它涵盖了完全互联网(Web)层面,从网页流览器作为客户机到服务器这边的数据整合层面。使用Openbiz,软件开发者可以节省花在与其他软件库接口的工作。

MVC(模型-视图-控制器)模式

Openbiz框架内部继承了MVC(模型-视图-控制器)的设计模式。这使得基于Openbiz的应用非常容易来开发和管理,因为表述层的程序与商业数据和逻辑清楚地分离开来。

ORM(对象关系映射)

Openbiz的内核实现了对象关系映射功能。Openbiz以BizDataObj对象来表述数据库表格和它们之间的逻辑关系。Openbiz支持的映射包括一对多,多对一,一对一和多对多的对象逻辑关系,并且支持与标准结构化查询语言(SQL)相似的查询语言。

安全模型

安全性是现今商业应用环境中必不可少的组成部分。Openbiz的安全模型可用来创建用户身份验证,基于角色的视图许可控制以及基于属性的数据许可控制。

与Eclipse集成的编辑工具

Openbiz的编辑工具与当前最流行的Eclipse开发环境集成在一起。Openbiz的编辑工具是一个Eclipse的插件。它提供几种不同的向导来帮助开发人员创建新的Metadata文件,并提供图形用户界面来编辑这些文件。与此同时开发人员可以利用Eclipse的其他强大功能。

提升效率

  • Openbiz框架的Metadata特性保证了开发可以迅速因需求而变化,也使得应用更容易升级和维护。
  • Openbiz提供了一个强大的武器给软件咨询公司,开发人员,甚至管理者去快速满足他们商业客户的需求。
  • 由于Openbiz的授权许可证是完全免费的(BSD),而且允许被发布于商业软件中,这也是选择Openbiz的另一个理由。

投资回报

  • 低成本。由于Openbiz的免费许可证和短时的开发过程,你将花极少的费用在购买软件和雇佣咨询公司上,而且得到更好的产品。
  • 迅速部署。基于Openbiz的应用是完全可重配置的,这样它能够迅速因需求而变化。你将很快看到回报。
  • 低维护费用。管理Openbiz的Metadata比起管理程序要简单得多。

用户经验

  • “我们正在想办法来代替公司以有的过时的用Visual Basic编写的程序。Openbiz是我们发现的最好的开发框架。”-Andrew, 美国
  • “我们花了两个月来研究不同的应用框架,Openbiz是唯一的系统,它能创建Web应用而不需要了解PHP编程。”-Nik, 保加利亚
  • “我高兴地给出A+,因为我对Openbiz的问题得到了迅速而且完美的解答。Openbiz框架的确厉害!”-Douglas, 法国

Openbiz 2.2 中文手册

Openbiz 2.2 概要

Openbiz 2.2 安装

  • 下载和安装 
  • 演示应用

Openbiz 2.2 新特点

  • 建造在Zend 框架上
  • 用APC 提高性能
  • Openbiz 对象的改进
    • BizDataObj 改进
    • BizForm 改进
    • BizView 改进
  • 与BIRT 报表集成
  • 支持tabs and sub tabs
  • 新的界面
  • 树状结构的解决方案 - BizFormTree

附录- metadata DTD 文件


这个文件介绍Openbiz 2.2 在版本2.1之上的新改进的特点 。Openbiz 2.1 指南仍然可在版本2.2使用 。

Openbiz 2.2安装

下载和安装Openbiz 2.2

NOTE: 从Openbiz 2.2.1.1, 强力推荐使用Web Installer. 将Openbiz 下载后解压缩到某一个目录. 在浏览其中键入 http://localhost/openbiz_install_dir/demoapp/index.php. 然后沿着提示走下去.

Openbiz 2.2.1.1之前的版本用下面的步骤.

1. 下载 Openbiz 2.2 source, 下载 Zend Framework source。为得到更高的性能, 推荐使用APC extension。 A topic on apachelounge介绍了在windows安装APC 。

2. 在openbiz_home/bin/sysheader.inc 配置Zend framework 路径。例如, 如果Zend framework library 是在/htdocs/zf015/, 需在sysheader.inc 增加以下的定义。

// defined Zend framework library home as ZEND_FRWK_HOME
define('ZEND_FRWK_HOME',$_SERVER['DOCUMENT_ROOT']."/zf015/library");
// add zend framework to include path
set_include_path(get_include_path() . PATH_SEPARATOR . ZEND_FRWK_HOME);

Openbiz 2.2 演示应用

1. 改变Config.xml Database Driver属性。 http://us2.php.net/manual/en/ref.pdo.php#pdo.drivers 给除了支持的PDO Driver名单。

2. 启动Openbiz dempapp, 在浏览器中键入 http://localhost/ob22/demoapp/demo.html。演示中事件管理应用的home 被改变到 http://localhost/ob22/demoapp/bin/home.php, 而不是在2.1 版本的 http://localhost/ob22/demoapp/pages/EventMgr.htm

Openbiz 2.2 新特点

建造在Zend 框架之上

  • 用Zend_Db (基于PDO) 替换ADODB 数据库抽象库 。好处包括更高的性能和更低的 memory footprint。
  • Zend 框架提供许多有用的功能
  • Zend 框架是正式官方的php 框架, 但这是仍然一个底层的工具库。Openbiz 应用框架着重于应用层。

用APC 提高性能

与BIRT 报表集成

产生报表是商业应用一个非常重要特点。通过利用 BIRT 报表服务器, Openbiz 应用从BizForm/BizDataObj 中产生报表。

BIRT 是一个基于Eclipse的报表系统, 它集成以您的Java/J2.EE 应用产生高质量报表。在开源之报表工具中, BIRT 是最佳的一个。它的Eclipse报表设计师让您从数据库桌和其它数据源(即xml 和csv 文件) 创造漂亮的报表。 

BIRT 服务器的最简单的设施是使用BIRT 观察者。好参考可能被发现在The simplest installation of BIRT server is using BIRT viewer. A good reference can be found at Installing the BIRT Viewer in Tomcat.

Openbiz 使用它的reportService 与BIRT viewer 服务器集成。创造BIRT 报告模板和用BIRT viewer 显示报告的步骤:

  1. 确定Openbiz 代码可能访问BIRT viewer 服务器目录。Openbiz reportService 将生成一个BIRT 报表设计并将其复制到BIRT viewer 报表目录。
  2. 用Eclipse设计师创造一个BIRT 报告。使用csv 文件作为它的数据源和数据集。假设现在我们有一个BIRT 报告设计文件叫做abc.rptdesign 。
  3. 以smarty 模板句法转换上述rptdesign 文件成模板。例如, 替换resultset 结构用{foreach} 。abc.rptdesign 成为abc.rptdesign.tpl 。下表是转换设计成模板的例子。
    resultset in .rptdesign resultset in template
    <list-property name="resultSet">
    <structure>
    <property name="position">1</property>
    <property name="name">AttendeeId</property>
    <property name="nativeName">AttendeeId</property>
    <property name="dataType">string</property>
    <property name="nativeDataType">12</property>
    </structure>
    <structure>
    <property name="position">2</property>
    <property name="name">Income</property>
    <property name="nativeName">Income</property>
    <property name="dataType">string</property>
    <property name="nativeDataType">12</property>
    </structure>
    </list-property>
    <list-property name="resultSet">
    {foreach item=fld from=$rpt_fields}<structure>
    <property name="name">{$fld.name}</property>
    <property name="nativeName">{$fld.name}</property>
    <property name="dataType">{$fld.type}</property>
    <property name="nativeDataType">12</property>
    </structure>
    {/foreach}
    </list-property>
  4. 复制模板文件到Openbiz 应用的template 目录之下。Openbiz demoapp 有缺省BIRT 设计模板文件"dataobj.rptdesign.tpl" 在它的模板目录之下。
  5. 创造reportService metadata, 它指定TargetReportPath 、ReportTemplate 和BIRTViewer url。您能在openbiz/metadata/service/reportService.xml发现reportService metadata 的例子
  6. 在BizForm增加一个按钮来调用reportService render 方法。Openbiz demoapp Attendee BizForm (在Attendee tab) 有一个报表按钮。相似的按钮可能被创造在任一BizForm 界面 。
  7. 当用户点击报表按钮, 他或她将得到显示报表的一些选择。

支持 tabs and sub tabs

Tabs 非常普遍地被使用在企业应用和消费者网站。在许多商业应用, subtabs 是常见的widgets 用来组织界面元件之间父子关系。

Openbiz 2.2 以BizView HTMLTab 类的一个新属性和ViewSet 属性的组合来支持tabs and subtabs 。

HTMLTab 类样品metadata xml 文件是在demoapp/metadata/demo/Tabs.xml 和demoapp/metadata/demo/EventTabs.xml 。

demo/Tabs.xml
<?xml version="1.0" standalone="no"?>
<Tabs Name="Tabs" Package="demo" Class="HTMLTabs" TemplateFile="tabs.tpl">
<TabViews>
<View Name="home" URL="./home.php" Caption="Home"/>
<View Name="event" URL="" View="demo.EventView" ViewSet="EventSet" Caption="Events" Icon=""/>
<View Name="regist" URL="" View="demo.RegistView" Caption="Registration" Icon=""/>
<View Name="attendee" URL="" View="demo.AttendeeView" Caption="Attendees" Icon=""/>
<View Name="reports" URL="./report.php" Caption="Reports" Icon=""/>
<View Name="test" URL="" View="demo.FieldDepTestView" Caption="Test 2.1 Features" Icon=""/>
</TabViews>
</Tabs>
demo/EventTabs.xml
<?xml version="1.0" standalone="no"?>
<Tabs Name="EventTabs" Package="demo" Class="HTMLTabs" TemplateFile="subtabs.tpl">
<TabViews>
<View Name="EventAttendee" URL="" View="demo.EventView" Target="" Caption="Attendees" Icon=""/>
<View Name="EventRegist" URL="" View="demo.EventRegistView" Target="" Caption="Registration" Icon=""/>
</TabViews>
</Tabs>

有一样的ViewSet = "EventSet " 的对应的视图(view)

demo/EventView.xml demo/EventRegistView.xml
<?xml version="1.0" standalone="no"?>
<BizView Name="EventView" ViewSet="EventSet"
Description="Event BizView" Package="demo"
Class="BizView" Template="view.tpl">
<ControlList>
<Control Name="_tabs" Form="Tabs"/>
<Control Name="fm_event" Form="FMEvent" SubCtrls="FMAttendeeChild"/>
<Control Name="_subtabs" Form="EventTabs"/>
<Control Name="fm_attd" Form="FMAttendeeChild"/>
</ControlList>
</BizView>
<?xml version="1.0" standalone="no"?>
<BizView Name="EventRegistView" ViewSet="EventSet"
Description="Event BizView" Package="demo"
Class="BizView" Template="view.tpl">
<ControlList>
<Control Name="_tabs" Form="Tabs"/>
<Control Name="fm_event" Form="FMEvent" SubCtrls="FMRegistChild"/>
<Control Name="_subtabs" Form="EventTabs"/>
<Control Name="fm_regist" Form="FMRegistChild" />
</ControlList>
</BizView>

由于EventView 和EvenrRegistView 分享同样ViewSet, 在他们之间互换将保留对FMEvent 和它的BOEvent 同样对象的上下文。例如, 在EventView 用户在上面的form 查询"*Tennis*" , 当他点击Registration sub tab, 换到EventRegistView, 同样的查询结果被保留在新视图。 

新的界面

以优秀品质设计企业网应用通常需要web 设计师。Openbiz 2.2 demoapp 带来新的界面样式:

  • Tabs 和subtabs
  • BizForm 标题bar
  • Table column hearder 和 selected row
  • 3D 样式按钮

当然开发商可以改变在demoapp/css 之下德css 文件来应用他们自己的样式。

树状结构的解决方案 - BizFormTree

Openbiz 2.2 中的一个新类是BizFormTree (Openbiz 1.1 有相似的类). 这个类是为了解决一个共同的问题, 树状结构保存在一个数据库表中. 这个表包含ID 和ParentID columns. BizFormTree 允许用户浏览树,并添加/删除/编辑树节点.

BizFormTree 是一个特殊BizForm.它利用BizForm.dtd文件作为其xml schema. BizFormTree 目的是表现在一个数据库表中的树的层次关系.

举例来说, event table schema: (every record has PARENT_ID column which builds tree hierarchy relationship between the records in the same table)

Column Comments
SYSID Primary key
NAME Event name
PARENT_ID Store the SYSID of its parent event.

BizFormTree 需要映射BizDataObj 中的两个BizFields "Id" 和 "PId".  "PId" 对应于table column parent id. 这个类提供两个新的方法

  • ListChildren($id) - 列出某一纪录的所有子记录
  • ListSiblings($id) - 列出某一纪录的所有兄弟记录

该类将 parent object array 输出的 smarty template. 以parent array, 开发者可显示当前纪录的父结构. BizFormTree metadata 的例子是

<BizCtrlList>
   <BizCtrl Name="bctrl_Id" FieldName="Id" DisplayName="Id"/>
   <BizCtrl Name="bctrl_name" FieldName="Name" DisplayName="Name" Link="javascript:CallFunction('{@:Name}.ListChildren({@:Control[bctrl_Id].Value})')"/>
   <BizCtrl Name="bctrl_pid" FieldName="PId" DisplayName="PId"/>
</BizCtrlList>

The template is like

{section name=i loop=$parents}
{if $smarty.section.i.index != 0} > {/if}<a href="javascript:CallFunction('demo.FMEventTree.ListSiblings({$parents[i].Id}))')">{$parents[i].Name}</a>
{sectionelse} {/section}

下图显示了应用BizFormTree 和 list_tree.tpl 的一个例子.


附录- metadata DTD 文件

蓝色文字表示Openbiz 2.2 中新的元素

BizDataObj metadata DTD 文件

<!--OpenBiz BizObj metadata DTD-->

<!ELEMENT BizObj (BizFieldList, TableJoins, ObjRefernces, Parameters) >
<!ATTLIST BizObj Name CDATA #REQUIRED >
<!ATTLIST BizObj Description CDATA #REQUIRED >
<!ATTLIST BizObj Package CDATA #IMPLIED >
<!ATTLIST BizObj Class CDATA #REQUIRED >
<!ATTLIST BizObj InheritFrom CDATA #IMPLIED >
<!ATTLIST BizObj DBName CDATA #IMPLIED >
<!ATTLIST BizObj Table CDATA #REQUIRED >
<!ATTLIST BizObj SearchRule CDATA #IMPLIED >
<!ATTLIST BizObj SortRule CDATA #IMPLIED >
<!ATTLIST BizObj OtherSQLRule CDATA #IMPLIED >
<!ATTLIST BizObj AccessRule CDATA #IMPLIED >
<!ATTLIST BizObj UpdateCondition CDATA #IMPLIED >
<!ATTLIST BizObj DeleteCondition CDATA #IMPLIED >

<!ATTLIST BizObj Stateless CDATA #IMPLIED >

<!ELEMENT BizFieldList (BizField+) >
<!ELEMENT BizField EMPTY >
<!ATTLIST BizField Name CDATA #REQUIRED >
<!ATTLIST BizField Class CDATA #IMPLIED >
<!ATTLIST BizField Join CDATA #IMPLIED >
<!ATTLIST BizField Column CDATA #REQUIRED >
<!ATTLIST BizField SQLExpr CDATA #IMPLIED >
<!ATTLIST BizField Type CDATA #IMPLIED >
<!ATTLIST BizField Format CDATA #IMPLIED >
<!ATTLIST BizField Required CDATA #IMPLIED >
<!ATTLIST BizField Validator CDATA #IMPLIED >
<!ATTLIST BizField DefaulValue CDATA #IMPLIED >
<!ATTLIST BizField Value CDATA #IMPLIED >
<!ATTLIST BizField OnAudit CDATA #IMPLIED >
<!ELEMENT TableJoins (Join+) >
<!ELEMENT Join EMPTY >
<!ATTLIST Join Name CDATA #REQUIRED >
<!ATTLIST Join Table CDATA #REQUIRED >
<!ATTLIST Join Column CDATA #REQUIRED >
<!ATTLIST Join JoinRef CDATA #IMPLIED >
<!ATTLIST Join ColumnRef CDATA #REQUIRED >
<!ATTLIST Join JoinType CDATA #REQUIRED >

<!ELEMENT ObjReferences (Object+) >
<!ELEMENT Object EMPTY >
<!ATTLIST Object Name CDATA #REQUIRED >
<!ATTLIST Object Description CDATA #IMPLIED >
<!ATTLIST Object Relationship CDATA #REQUIRED >
<!ATTLIST Object Table CDATA #REQUIRED >
<!ATTLIST Object Column CDATA #REQUIRED >
<!ATTLIST Object FieldRef CDATA #REQUIRED >
<!ATTLIST Object CascadeDelete CDATA #IMPLIED >
<!ATTLIST Object XTable CDATA #IMPLIED >
<!ATTLIST Object XColumn1 CDATA #IMPLIED >
<!ATTLIST Object XColumn2 CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizView metadata DTD 文件

<!--OpenBiz BizView metadata DTD-->

<!ELEMENT BizView (ControlList, Parameters) >
<!ATTLIST BizView Name CDATA #REQUIRED >
<!ATTLIST BizView Description CDATA #REQUIRED >
<!ATTLIST BizView ViewSet CDATA #IMPLIED >
<!ATTLIST BizView Package CDATA #IMPLIED >
<!ATTLIST BizView Class CDATA #IMPLIED >
<!ATTLIST BizView Template CDATA #IMPLIED >

<!ELEMENT ControlList (Control+) >
<!ELEMENT Control EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Form CDATA #REQUIRED >
<!ATTLIST Control SubCtrls CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizForm metadata DTD 文件

<!--OpenBiz BizForm metadata DTD-->

<!ELEMENT BizForm (BizCtrlList, DisplayModes, Toolbar, Navbar, Parameters) >
<!ATTLIST BizForm Name CDATA #REQUIRED >
<!ATTLIST BizForm Description CDATA #REQUIRED >
<!ATTLIST BizForm Package CDATA #IMPLIED >
<!ATTLIST BizForm Class CDATA #REQUIRED >
<!ATTLIST BizForm InheritFrom CDATA #IMPLIED >
<!ATTLIST BizForm jsClass CDATA #REQUIRED >
<!ATTLIST BizForm Title CDATA #REQUIRED >
<!ATTLIST BizForm BizDataObj CDATA #REQUIRED >
<!ATTLIST BizForm PageSize CDATA #REQUIRED >
<!ATTLIST BizForm SearchRule CDATA #IMPLIED >
<!ATTLIST BizFomr Stateless CDATA #IMPLIED >

<!ELEMENT BizCtrlList (BizCtrl+) >
<!ELEMENT BizCtrl (EventHandler+) >
<!ATTLIST BizCtrl Name CDATA #REQUIRED >
<!ATTLIST BizCtrl Class CDATA #IMPLIED >
<!ATTLIST BizCtrl FieldName CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayName CDATA #IMPLIED >
<!ATTLIST BizCtrl Type CDATA #IMPLIED >
<!ATTLIST BizCtrl Width CDATA #IMPLIED >
<!ATTLIST BizCtrl Height CDATA #IMPLIED >
<!ATTLIST BizCtrl HTMLAttr CDATA #IMPLIED >
<!ATTLIST BizCtrl Link CDATA #IMPLIED >
<!ATTLIST BizCtrl Image CDATA #IMPLIED >
<!ATTLIST BizCtrl Hidden CDATA #IMPLIED >
<!ATTLIST BizCtrl Enabled CDATA #IMPLIED >

<!ATTLIST BizCtrl Sortable (Y|N) "" >
<!ATTLIST BizCtrl Order CDATA #IMPLIED >
<!ATTLIST BizCtrl Style CDATA #IMPLIED >
<!ATTLIST BizCtrl ValuePicker CDATA #IMPLIED >
<!ATTLIST BizCtrl PickerMap CDATA #IMPLIED >
<!ATTLIST BizCtrl DefaultValue CDATA #IMPLIED >
<!ATTLIST BizCtrl SelectFrom CDATA #IMPLIED >
<!ATTLIST BizCtrl DrillDownLink CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayMode CDATA #IMPLIED >

<!ELEMENT Toolbar (Control+) >
<!ELEMENT Navbar (Control+) >
<!ELEMENT Control (EventHandler+) >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Class CDATA #IMPLIED >
<!ATTLIST Control Image CDATA #IMPLIED >
<!ATTLIST Control Caption CDATA #IMPLIED >
<!ATTLIST Control Type CDATA #IMPLIED >
<!ATTLIST Control Width CDATA #IMPLIED >
<!ATTLIST Control Height CDATA #IMPLIED >
<!ATTLIST Control HTMLAttr CDATA #IMPLIED >
<!ATTLIST Control Style CDATA #IMPLIED >
<!ATTLIST Control Hidden CDATA #IMPLIED >
<!ATTLIST Control Enabled CDATA #IMPLIED >
<!ATTLIST Control SelectFrom CDATA #IMPLIED >

<!ATTLIST Control DisplayMode CDATA #IMPLIED >

<!ELEMENT EventHandler EMPTY >
<!ATTLIST EventHandler Name CDATA #REQUIRED >
<!ATTLIST EventHandler Event CDATA #REQUIRED >
<!ATTLIST EventHandler Function CDATA #REQUIRED >
<!ATTLIST EventHandler FunctionType CDATA #IMPLIED >
<!ATTLIST EventHandler ShortcutKey CDATA #IMPLIED >
<!ATTLIST EventHandler PostAction CDATA #IMPLIED >
<!ELEMENT DisplayModes (Mode+) >
<!ELEMENT Mode EMPTY >
<!ATTLIST Mode Name CDATA #REQUIRED >
<!ATTLIST Mode TemplateFile CDATA #REQUIRED >
<!ATTLIST Mode DataFormat CDATA #REQUIRED >
<!ATTLIST Mode FormatStyle CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

Plugin service metadata DTD 文件

<!--OpenBiz Plugin service metadata DTD-->

<!ELEMENT PluginService ANY >
<!ATTLIST PluginService Name CDATA #REQUIRED >
<!ATTLIST PluginService Description CDATA #IMPLIED >
<!ATTLIST PluginService Package CDATA #REQUIRED >
<!ATTLIST PluginService Class CDATA #REQUIRED >

Openbiz 2.0 中文手册(一)

这份文件是openbiz2.0手册. Openbiz1.x的手册在manual11.html

其他链接:openbizeclipse插件设计师手册, openbiz最佳做法

Openbiz 2.0概况

Openbiz 安装

构建openbiz应用

Openbiz 配置指南

  • 层次管理Metadata
  • 使用对象数据继承
  • 简单的表达语言
    • 使用表达式
    • 字符
    • 操作符
    • 变量
    • 函数
    • 实例
  • 配置Bizdataobj
    • 映射Bizdataobj到数据表格
    • Bizdataobj的查询语言
    • Bizfields的数据类型和格式
    • 数据验证
  • 对象关系(O/R)的映射
    • 映射一个表格到一个Bizdataobj
    • 主键(ID)的生成
    • 复合主键的支持
    • 映射多个表格到一个Bizdataobj
    • BizDataObjs中多对一的关系
    • BizDataObjs中一对多的关系
    • BizDataObjs中多对多的关系
  • 配置BizView 和 BizForm
    • BizView - the HTML 网页容器
    • BizForm的基本布局:数据,工具栏及导航栏
    • 映射Bizdataobj到Bizform
    • 以各种不同类型的html元素来表现数据
    • BizForm的事件处理
    • BizForm键盘处理功能
    • BizForm中html元素的互相依赖
    • 配置drilldown连接到另一视图
    • 从组合或列表选择Field数据
    • 控制页面导航
    • 从BizForm导入和导出数据
    • 从BizForm上传文件

Openbiz 开发指南 (另文档)

附录一:第三方库

附录二:Metadata的文档类型定义DTD


Openbiz 2.0概况

Openbiz 2.0是一个metadata驱动的框架. 所有openbiz对象都有自己的metadata文档. Openbiz2.0建筑架构遵循模型-视图-控制器(MVC)的设计模式,它也实现了对象/关系映射.

Openbiz 2.0 架构

Metadata驱动框架

Openbiz的目标是使设计,开发和维护应用软件容易. Openbiz是xml数据驱动框架,即openbiz对象建基于描述他们的数据档案. 建立一个应用意味着设计和开发数metadata文档. 由于自我阐释性标示语言, 应用易于维护. 与此同时由于XML的可扩展性, openbiz是一个可扩展的框架.

下面的图表显示了基于metadata 对象的openbiz框架. 这些对象涵盖大部分功能需求的Web应用开发.

Openbiz对MVC的实施

Openbiz其中一个关键的优势是,它是一个遵循模型-视图-控制器(MVC)的设计模式的框架. This makes Openbiz applications much more manageable because the presentation code (View) is cleanly separated from the application data and logic (Model).这使得Openbiz应用更为可控,因为表现编码(视图)与应用和数据逻辑(模型)分离得十分干净. 所有使用者介面与应用处理都由一个前端控制器控制.

比较Openbiz MVC设计与市场上现有的MVC框架, 如JSF和Struts, Openbiz是比较接近JSF, 因为两者都是基于组件的架构. Openbiz的表述层由bizview, bizform和bizform内部的元件组成. 下表中列出Openbiz实施六大优点(参见相对于Struts, 十大喜欢JSF的理由).

JSF相对于Struts的优势 Openbiz 的实现
Components(部件) BizView 和 BizForm 作为持久的界面对象
Render Kits(渲染包) 连接不同模板到界面对象
Renderers(渲染) 客户类实施Render()方法
Value Binding(值绑定) 支持静态和动态值绑定
Event Model(事件模型) 连接客户端事件到服务器功能
Extensibility(延展性) 开发商可以把自己的类连接到openbiz对象
其他四个.... 不适用

Openbiz实现持久对象和ORM

类似流行的Hibernate的做法, openbiz利用会话(session)来保持对象的持久性. 不像j2ee的web容器有对象池内存, php每个请求对象兴建和释放(这称为不共享架构). 要保持对象的持久性, openbiz持久对象(bizdataobj,bizform...)将对象状态存入session, 然后重建对象. Also to avoid multiple object instances of same class in the same session, openbiz use ObjectFactory to ensure object singleton. 为防止同一类的对象实例在同一session中出现, openbiz使用ObjectFactory以确保对象的单独性.

Openbiz实现了必要的对象/关系映射(ORM)的功能, 允许Bizdataobj代表数据库表和数据库表间的关系. 下表列出Openbiz ORM的特点

灵活的映射 每表有一个对象, 或多表一个对象
多对一, 一对多, 多对多, 一对一
查询设施 象SQL一样的l查询语言, 支持SQL函数和操作符, 支持SQL总计功能,和group by, having and order by
Metadata 设施 XML metadata 描述映射

Openbiz 安全模式

Openbiz支持三种网络安全 - 用户认证, 视图控制和数据访问控制. Openbiz主要用途插件服务以控制安全. 这种方案允许用户插入自己的逻辑来服务. 详情将讨论在开发指南-实施认证,视图和数据存取控制.

用户认证流程:

视图准入控制流程:

安全 openbiz执行插件服务
用户认证 Openbiz利用认证服务(bin/service/authservice.php)认证的用户名和密码
 基于角色的视图出入管制 Openbiz用Profile服务(bin/service/profileservice.php)取得用户信息, 其中包括"角色".
然后用access服务(bin/service/accessservice.php)去查询该角色, 以确定用户的视图权限
基于属性数据存取控制 Openbiz用Profile服务(bin/service/profileservice.php),以取得用户的概况,包括属性.
然后,基于这些属性,以确定对数据记录浏览/更新/删除的许可. 数据访问权限控制在Bizdataobj.

Openbiz 2.0 的结构组织

Openbiz提供一个PHP框架助你建立复杂的网络应用.

OpenBiz设计作为一个多层结构如下图下文.

通常商业应用可分为3层 - 数据层, 商业逻辑层和表现层. 在openbiz结构中, 其中3层映射到3个软件包. 表现层是执行bizview软件包, GUI层是执行jbform的javascript的软件包. 商业逻辑层是执行Bizdataobj软件包. 数据库处理层是通过第三方的包来实现. 插件服务功能,提供服务组件,可援引双方陈述和数据层对象.

Package (包) Class (类)
BizSystem BizSystem
- 提供一个全局变量
- 提供get方法为 ObjectFactory, SessionContext, TypeManager, ClientProxy 和 Configuration类
- 提供静态方法访问xml数据,日志和错误报告.
    
SessionContext
- Session管理类提供更多方法从session中保存/获得metadata驱动对象的状态, 通过其GetsessionVars|SetsessionVars接口
TypeManager
- 格式式管理类提供帮助方法格式化数据到用户界面以及解悉界面的输入数据
ClientProxy
- 它是当作双向代理客户的类. 通过这个类, 其他人可以得到客户输入, 重画客户端或执行客户端的javascript功能.
Configuration
- 这个类提供方法来从config.xml获取数据
BizDataObj BizDataObj
- 它是所有数据对象类的基类. 在openbiz1.2之前它被称为BizObj. 因为bizobj指商务对象,但它作为业务数据单元,所以将它改变为BizDataObj.
BizRecord
- BizRecord类实现对记录的基本功能
BizField
- BizField类是映射到表格column的逻辑单元
BizDataSql
- BizObjSql类为Bizdataobj构建sql语句
ObjRefernces
- ObjReferences包含一组与本BizDataObj相关的其他Bizdataobj
TableJoins
- TableJoins包含一组与本对象连接(join)表格
BizView BizView
- BizView是表单的容器类. 它可被视作html网页.
BizForm
- BizForm是表单的基类. 它是一个html表单, 即包含在一个bizview中.
RecordRow
- RecordRow是FieldControl的容器类
ToolBar
- ToolBar工具条类. 它包含htmlcontrols
NavBar
- NavBar是导航条类. 它包含按钮
HTMLControl
- HTMLControl是html元素的基类
FieldControl
- FieldControl是与bizfield相关的html元素的基类
DisplayMode
- DisplayMode包含bizform显示模式信息
jbForm jbForm (javascript bizForm)
- 客户端处理AJAX的函数调用和回调的基类
ZEND_DB 这是一个抽象的数据库连接方案,可以连接到不同的供应商的所有主要数据库. 它包含于Zend Framework包内.

类图的多层结构

序列图的一个典型AJAX的调用

Openbiz客户端浏览器与服务器通过AJAX调用.


安装Openbiz

运行环境

Openbiz(2.0或更新版本)是基于php5脚本. 我们推荐平台

  • Apache HTTP Server 1.3.x or 2.x + PHP 5.x
  • Internet Information Server (IIS) 5.x + PHP 5.x

安装目录是openbiz,或者你可以配置apache使用别名.

支持浏览器 - IE5.x (或更新版本), Netscape 7.x and Mozillar/FireFox 1.x (或更新版本)

安装openbiz

下载zip文件并解压缩到一个目录下 (under web root).

请翻阅openbiz/bin目录下的sysheader.inc, 和demoapp/bin下的 app.inc.

  • Openbiz 核心路径 " OPENBIZ_HOME " 可被设置于 syshearder.inc 和 app.inc文件中. app.inc中的值先于sysheader.inc中的值.
  • sysheader.inc定义路径第三方php软件包包括 Smarty " SMARTY_DIR ", 和 Adodb " ADODB_DIR " 等等.
  • 应用 home 路径" APP_HOME ", metadata 文件路径 " META_PATH ", 日志文件路径 " LOG_PATH ", session 文件路径 " SESSION_PATH " 和 smarty 模板文件路径 " SMARTY_TPL_PATH " 在app.inc中指明.
  • " DEBUG " 显示是否打印调试信息
  • " CHECKUSER " 检查用户是否登录
  • " TIMEOUT " 是会话超时秒

源代码树结构:

从openbiz2.0rc2中,两个主要的目录包括在软件包. 他们是openbiz核心库和应用演示.

演示应用是一个openbiz的web应用. 因为openbiz提供metadata 驱动架构, bin和metadata 目录是必须的. 其余的目录结构建议,而不是要求. 用户可能有自己的方式来安排web应用结构. 请修改demoapp/bin/app.inc改变常数定义.

正如你观察的bin及metadata结构, 每个bin的子目录下有一个匹配的metadata子目录. 这是代码/metadata匹配原则, 如果你有一个对象的 metadata 在 /metadata/aaa/, 而且对象执行代码是一个用户定义类(不是openbiz核心类), 类代码文件必须在/bin/aaa/目录.

Openbiz 核心库
openbiz_root/ openbiz_root/
---bin/         (openbiz core php source - required)
------service/      (openbiz core service library directory)
---document/     (openbiz documents - optional)
------apidoc/      (openbiz core API)
---medata/      (openbiz metadata files - required)
------service/      (service package)
---others/       (third party libraries - optional)
------adodb/       (adodb package)
------Smarty/      (smarty package)

 

演示应用
demoapp/      (demoapp web pages)
---bin/         (demoapp php source)
------demo/         (demapp demo library)
------shared/       (demoapp shared library)
------service/      (demoapp service library)
---js/           (demoapp javascript files)
---pages/        (demoapp HTML files)
---css/         (demoapp style sheets)
---images/      (demoapp images)
---log/         (demoapp logs)
---medata/      (demoapp metadata files)
------demo/        (demoapp demo package)
------shared/       (demoapp shared package)
------service/      (demoapp service package)
---session      (demoapp session files)
---templates    (demoapp smarty templates files)
------cpl          (demoapp smarty compiled templates)
--- ---cfg          (demoapp smarty configuration files)
---tmpfiles     (temporary files)

In Unix or Linux box, you need to give write permission to web users on log, metadata, session, tmpfiles and templates directories.在unix或linux里, 你需要将可写权限赋予网络用户对日志, 数据, session, tmpfiles和模板目录.

安装必要的第三方软件包

以下软件包是必要的,他们包括在openbiz软件包

我们建议你安装php优化软件包.

开始演示应用

填充演示数据库. 在openbiz根目录寻找gendb.sql, 将它应用到你的数据库.  注意gendb.sql是为mysql数据库的脚本, 请根据不同的数据库类型调整语法.

打开demoapp/clientutil.js. 改变 var binPath = "/demoapp/bin/" ; 到适当的demoapp根下的bin目录. 记得应该是绝对路径, 因此用"/".

打开demoapp/metadata/config.xml, 核实默认数据库正确的属性(如用户名和密码).

然后启动浏览器, 打开http://localhost/demoapp/demo.html

Upgrade guide升级指南

请参阅 http://phpopenbiz.org/document/manual.html#upgrade 

通过SVN获取最新的源代码

请参阅 http://phpopenbiz.org/document/manual.html#svn


构建Openbiz应用

为你的应用提出具体要求

OpenBiz是一个完美的工具来帮助你轻松和全面地开发复杂web应用. 基于其3层结构, 你的应用将有一个很清晰的逻辑模式. 它顾及到了面向数据的应用的基本和先进功能. 为了分辨openbiz是否可以帮助建立你的应用程序, 你需要问这些问题:

  • 你的应用是web基于的应用程序或可转换成基于web的应用?
  • 你的应用是否需要用数据库操纵不同类型的数据?

如果答案是的话, Openbiz就是正确的开发你的应用得的框架,!

计划你的web应用

当你安装Openbiz软件包时, 你会发现在zip文件有两个主要目录"openbiz"和"demoapp". "openbiz"目录包含了核心openbiz程序和metadata.  "demo"目录包含源演示应用(事件管理和日历演示).

上述结构不同于Openbiz RC2.0之前的版本, 在那里你会看到演示应用在openbiz目录里. 为什么openbiz进行了这一转变?

  • 它给开发人员带来了一个清晰的逻辑结构 - openbiz核心库和应用程序代码在不同的目录.
  • Openbiz核心库比openbiz应用更便携式, 它可以被多种应用分享.
  • 如果openbiz核心更新版本, 应用很容易的升级.

在你的目录开发web应用

自己的开发项目 目录
你的源代码 your_app_root/bin/
你的metadata档案 your_app_root/metadata/your_package/
你的网站模板 your_app_root/templates/
你的网页 your_app_root/, your_app_root/pages
你的style sheet文件 your_app_root/css/
你的图像文件 your_app_root/images/
你的日志文件 your_app_root/log/
你们的session档案 your_app_root/session/
你的临时文件 your_app_root/tmpfiles/

这个结构可以帮助你更有组织地开发openbiz web应用. 你的应用的特定文件都是在一个单独的目录,而不是混在openbiz核心档案. 你可以建立多个web应用基于单个openbiz核心. 你需要做一些额外的步骤, 建立了自己的应用程序目录. 我们建议下列步骤.

  1. 拷贝demoapp目录,并命名为你的应用的名字, 比如说"testapp"
  2. 打开 testapp/bin/app.inc, 恰当地改变常量. 如果你可以接受默认值, 不需要改变.
  3. 打开 testapp/bin/login.php, 改变 $application_homepage 到用户登录后显示给用户的首页.

在app.inc档案, OPENBIZ_HOME已被确定为openbiz核心库的安装路径. 你的应用程序将使用openbiz核心库以及在metadata目录的核心对象.

RC2的另一个重要变化是metadata和代码必须分别放在对应的/metadata 和 /bin 目录下. 这是代码/metadata匹配原则, 如果你有一个对象的 metadata 在 /metadata/aaa/, 而且对象执行代码是一个用户定义类(不是openbiz核心类), 类代码文件必须在/bin/aaa/目录. 举例来说, /metadata/shared/FMCalendar.xml具有特殊类"FMCalendar", 这"FMCalendar"类的代码必须位于/bin/shared/FMCalendar.php. 如果对象的执行类是openbiz核心类, 没有特别码, 因此就不用在/bin 下写代码. 这个代码/metadata匹配原则给metadata 和代码一个明确结构.

创建数据库模式

为你的业务数据与关系数据库表建模是你的整个开发的必需的基础建设.

创造一个新的数据库

  • 指定新的数据库为metadata/config.xml的默认数据库
  • 创造"ob_users"表中存储用户名和密码. Since 2.0, openbiz counts on authentication service to authentiate user and password, so the user id and password can be stored in the storage that is queried by the authentication service.自2.0openbiz用认证服务类验证用户名和密码, 所以用户名和密码,可以储存在认证服务查询的数据库里. 
  • 创造"ob_sysids"表, 其中sysid栏为各表的ID栏
  • 每个表必须有一个ID栏, 并在ob_sysids表加上一条纪录(TABLE=你的表的名字, PREFIX=ID的前缀, IDBODY=起始整数)

Use existing database使用现有数据库

  • 指定新的数据库为metadata/config.xml的默认数据库
  • 创造"ob_users"表或重用现有含有用户名和密码栏的表. Ensure that authentication service queries the user id and password on the right table (or source).确保认证服务从正确的表(或来源)查询用户名和密码.
  • 设定IdGeneration 属性为现有ID生成算法. 例如, 如果你的oracle数据库的使用顺序来创造 PK column (主键栏), IdGeneration应为"Sequence:seqname". 细节请参阅本主键栏(ID)生成的章节.

用Openbiz来进行系统设计

用Openbiz的强大功能来进行系统设计. 你的设计将有

  • 明确三层结构栈
  • XML metadata驱动应用
  • MVC (模型-视图-控制器)设计模式
  • 一套丰富的库
  • 常见的应用功能

建立新的应用

业务需求 -> 界面设计+数据建模+对象设计

用户界面:页面, 表单, 人机互动

数据模型:数据库结构设计

对象设计:

  • 界面对象 - Bizview, Bizform
  • 数据对象 - Bizdataobj与对象/关系映射
  • 功能对象-插件服务

转换现有的应用

将现有的界面转换为bizviews, bizforms

将现有的数据库表映射到Bizdataobjs

将现有的业务功能变为插件服务

样本实例 - 日历

请参阅 http://phpopenbiz.org/document/manual.html#bld_sample 


Openbiz配置指南

开发商能选择用XML编辑器编辑metadata文件。Openbiz Eclipse插间被推荐为设计和配置工具。参见Openbiz Eclipse插入设计师指南

由包裹组织metadata

在复杂的应用, 用户也许需要建立许多对象, 因此他们有很长的metadata文件名单。如果他们将这些文件放在一个metadata目录之下, 处理metadata文件是一件痛苦的事。从openbiz 1.1, metadata文件可能由包裹名字组织。记住, metadata包裹是不同的以是代码单位的(BizObj, BizView...)包裹。Metadata包裹是一个命名系统, 不同的包裹地对映于\不同的目录。它是象被使用在Java中的包裹概念。

PackageX.PackageY.metaA.xml 指在META_PATH/PackageA/PackageB目录之下的metaA.xmlMETA_PATH是metadata根目录。这个宏变量被定义在sysheader.inc 和app.inc 。

怎么配置在metadata文件的包裹?

我们解释它以演示例子。在您unzip源码之后, 找到在metadata 目录之下演示目录。用文本编辑程序打开FMRegist.xml 文件。您将看见Package="demo" 属性在BizForm 元素。这个属性将说任一类型缺省包裹openbiz 对象是在"demo" 包裹之下。这里openbiz 对象提到以下对象类型。

目标类型

提到作为属性在metadata文件

BizObj

BizForm[BizObj ]
BizObj->BizFieldList->BizField[SelectBizObj ]

BizForm

BizView->ControlList->Control[Form ]
BizView->ControlList->Control[SubCtrl ]
BizForm->BizCtrlList->BizCtrl[SelectFrom ]

BizView

 

BizPopup

BizForm->BizCtrlList->BizCtrl[SelectBizForm ]

BizFormTree

同BizForm一样

如果对象名不包含小点标志("."), 系统使用定义了在对象根元素包裹属性作为它的包裹。否则, 如果对象名有格式作为aaa.objectname, 系统认为这样的对象在包裹之下"aaa" 并会在aaa 目录之下查找这样的对象。

去回到例子, 您能发现< BizForm Name="FMRegist" Package="demo"... BizObj="BORegist"... >, < BizCtrl Name="reg_attdln"...  SelectBizForm="AttendeePopup"... > 和< BizCtrl Name="reg_fee"... SelectFrom="Selection(Fee)"... > 。他们全都个用途缺省包裹, 因此系统将设法寻找metadata 文件作为 demo/BORegist.xml demo/AttendeePopup.xml demo/Selection.xml

如果您想要提到对象在其它包裹之下, 请增加包裹名字作为对象名的前缀。通知, 有Selection.xml 在/demo 目录之下并且其它Selection.xml 在/design 目录之下, 他们属于不同的包裹。在FMRegist, 包裹是"演示", 您能使用< BizCtrl...  SelectFrom="design.Selection(Mode)" ... > 配置价值是从"design/Selection.xml 的" "方式" 元素的comboBox 。

您无法提到一个对象在另外应用。但您能提到任一个对象在openbiz 核心应用。例如, 核心应用有提到对象在metadata/shared/ 目录之下。Openbiz 设法找出对象同样应用和然后核心应用。如果对象不被发现, 它报告错误。

使用对象metadata继承

如果你有一个非常复杂的应用,你要重用现有对象,以不同的地方,但是你要表现的对象在不同的情况下回有不同,. 继承对象将解决以上问题. 由于openbiz框架的对象映射到metadata数据文件, 继承对象就成为数据文件继承.

怎么指定在metadata 文件之间继承呢?

指定对象属性, InheritFrom = "父母对象名" 。例如, 在演示应用, BOEventX 有< BizObj Name="BOEventX" Description="Event BizObj Extended BOEvent" Package="demo" Class="BizObj" InheritFrom="demo.BOEvent"... > 。这表明是BOEventX 被继承从BOEvent 。 

Metadata 文件继承类似于以类继承在编程语言, 子对象可能继承(如果没定义在子对象, 而且定义在父对象)  或覆盖(如果同样属性被定义在子对象和父对象) 父对象的属性。

能有继承的对象类型 什么可能被继承或覆盖 什么无法被继承- 必须被指定在子metadata 文件中
BizObj 对象属性: 描述, DBName, Table, SearchRule, SortRule, OtherSQLRule, CacheMode

对象BizFieldList: BizField

对象属性: Name, Package, Class, InheritFrom
BizForm 对象属性: Description, jsClass, Title, BizObj, PageSize, Width, Height, SearchRule

Object BizCtrlList: BizCtrl
Object DisplayModes: Mode
Object Toolbar: Control
Object Navbar: Control

对象属性: Name, Package, Class, InheritFrom

简单表达式语言

为了增加metadata 配置的灵活性, Openbiz 在metadata 文件接受简单表达式语言。如果声明有 {expr} 样式, expr 将被评估作为简单的表示。 基本上, 简单表达式是返回值的一个PHP 语句。如果用户需要的复杂逻辑无法被一个简单表达式表示, 他们可将特别代码写在用户定义的类里。

使用表达式

简单表达式将支持metadata 属性动态值捆绑。在metadata 文件中用户能在以下地方使用简单表示。

  • BizDataObj
    SearchRule, SortRule, OtherSQLRule, AccessRule, UpdateCondition, DeleteCondition 。这些属性是询问BizDataObj 元素相关的属性. [ field_name ] 是询问语言的语法, 它将由表格的column 名字替换。请参见 在BizDataObj查询语言 为细节。
  • BizDataObj.BizField
    Required, Validator, Value, DefaultValue 
  • BizForm
    Link, Style, Hidden, Enabled, SelectFrom
  • BizForm.EventHandler
    Function, PostAction

字符

简单表达式语言定义以下字符:

  • 布尔: true, false
  • 整数: 和PHP一样
  • 浮点: 和PHP一样
  • 串: 用单引号和双引号; "是\", ' 是\ ', 并且\ 是\ \ 
  • Null: null

操作

简单表达式语言提供以下操作符:

  • 算术: +, - (binary), *, / 和 div, % 和 mod, - (一元)
  • 逻辑: and, &&, or, ||, not, !
  • 关系: ==,! =, <, >, < =, > = 。
  • 有条件: A? B: C. 根据A 的评估的结果, 评估B 或C。 

变量

  • 简单表达式允许开发商使用openbiz metadata 对象的变量:
得到metadata 对象变量的句法 变量 实现 例子
@object_name:property_name 得到指定的对象的指定的内容 Call object->GetProperty ($propname) @BOEvent:Name
@FMEvent:Title
@object_name:*[child_name].property_name 得到指定的对象的指定的子元素的内容 Call object->GetProperty ($propname), where $propname="*[child_name]", to get the child object. 
Then call child_object->GetProperty($propname)
@BOEvent:Field[Id].Value
@FMEvent:Control[evt_id].Value
@:property_name or 
@this:property_name
得到对象指定的内容 ("本" 对象是被定义在metadata 文件中的对象) Call this->GetProperty ($propname) In BOEvent, @:Name or @this:Name means getting the "Name" property of BOEvent.
@:*[child_name].property_name or
@this:*[child_name].property_name
得到对象的指定的子元素的内容 Call this->GetProperty ($propname), where $propname="*[child_name]", to get the child object. 
Then call child_object->GetProperty($propname)
In BOEvent, @:Field[Id].Value or @this:Field[Id].Value means getting the "Id" field value of BOEvent.
[field_name] 得到BizDataObj 指定的BizField 的值 。  Call object->GetProperty ($field_name) to get the child BizField object. 
Then call field_object->GetProperty("Value")
In BOEvent, [Id] means getting the "Id" field value of BOEvent.
@object_name:param[param_name] or
@:param[param_name]
得到这个对象的指定的参数值 Call object->GetProperty ($propname), where $propname="param[param_name]" @:param[Evt_Id]
@profile:property_name  得到用户概况属性 User profile is provided with ProfileService. @profile:ROLEID

从上述的实现可看出, 如果重写 GetProperty() 方法, 开发商可能增加支持更多属性。GetProperty() 的输入可能是支持由顾客代码的"property_name" 或"* [ child_name ]" 或其他。

简单的表示语言并且允许开发商使用所有全局变量由PHP 支持。请阅读 http://us2.php.net/manual/en/reserved.variables.php 

函数

开发商可以在简单表达式中调用所有PHP 函数。如果包含函数的文件被包括了, 用户定义的函数可能被调用。例如, 如果metadata 对象A 是一个用户类, 类文件是包括A_help.inc 的A.php。在这种情况下, 您能在简单表达式中调用定义在A_help.inc函数。

例子

  • <BizDataObj SearchRule="[Start]>'date(\"Y-m-d\")'">
  • <BizDataObj AccessRule="[OwnerId]='{@profile:USERID}'">
  • <BizDataObj UpdateCondition="[OrgId]=={@profile:ORGID}">
  • <BizDataObj DeleteCondition="'admin'=={@profile:ROLEID}">
  • <BizField Name="NeedApprove" Required="{[Amount]>1500}"/>
  • <BizField Name="Fee" Validator="{[Fee]>=15}"/>
  • <BizField Name="FullName" Value="{[LastName]}, {@:Field[FirstName].Value}"/>

BizDataObj 的配置

BizDataObj xml 的DTD 文件被列出在附录A.1

BizDataObj 对表格映射

Openbiz 映射数据库表格到BizDataObj 对象。这个章节介绍BizDataObj与表格映射的概念, 下个章节"ORM" 有映射的配置的全面详细。BizDataObj 必须有表格名字和表格column 和 BizDataObj fields的映射。

  • 指定基本表格: 

<BizDataObj Name="BizDataObjName" Table="TableName" ...>

  • 映射 Column 到 BizField: 

    <BizField Name="FieldName" Column="ColumnName"....>. BizFields 必须有命名作为"Id" 。这必需"Id" 通常映射到表的主键.

  • 映射 SQL Function 到 BizField: 

    用户能将由数据库引擎提供的SQL function设给BizField。句法是< BizField Name="FieldName" Column= "" SQLExpr="FUNC([FieldName1]... [FieldName2 ]...)"> 。要保证Column属性是空的。例如: < BizField Name="FullName" Column= "" SQLExpr="CONCAT([FirstName ], ' ', [LastName ])"... > 。请注意SQLExpr 是询问相关的属性。[ FieldName ] 是询问语言的句法。

  • 指定BizField 的缺省值:

    <BizField Name="FieldName" Column="ColumnName" DefaultValue="default_value">. 使用DefaultValue 属性, 当dataobject 创造一个新纪录时, 会将缺省值设给BizField。

BizDataObj的查询语言

Openbiz 用户不用担心组成的复杂的SQL 声明。BizDataObj 支持在对象水平更加直观的查询语言。基本的句法是"[FieldName] opr 'Value' AND/OR [fieldName] opr 'Value'...". 这里"opr" 是SQL 操作符。在运行时, openbiz 将[ FieldName ] 改变为column名字而产生SQL 声明。Openbiz 并可以将表格关系放入SQL中。

  • 在SearchRule中指定缺省询问
    例子: <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" SearchRule="[Start]>'1999-10-20'" ...>

  • 在SortRule中指定缺省排序
    例子: <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" SortRule="[Start] ASC" ...>

  • 在OtherSQLRule中指定另外的SQL 声明
    例子: <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" OtherSQLRule = "GROUP BY [EvtId] HAVING [Fee]>10" ...>

BizFields 的数据类型和格式

BizField 支持以下的数据类型和格式。

类型 格式 句法 格式例子
文本 文本是默认类型  
数字 格式由printf 支持 < BizField... Type="Number" Format="%..."... > %5.2f 打印浮点数字
  "Int" - 整数格式(与地点相关) < BizField... Type="Number" Format="Int"... > 如果locale=enu, 12345.678 被显示作为12,346
  "Float" - 浮点格式(与地点相关) < BizField... Type="Number" Format="Float"... > 如果locale=enu, 12345.678 被显示作为12,345.68
日期 在缺省只读方式下, 日期可能根据 数据格式被格式化。 < BizField... Type="Date" Format="date format"... > 6/21/2003 可能被格式化
%A, %b %d %Y - 星期六, 2003 年6月21 日如果系统地点是enu
Datetime 在缺省只读方式下, 日期可能根据 数据格式被格式化。 < BizField... Type="Datetime" Format="datetime format"... > 6/22/2003 9:30am 可能被格式化
%m/%d/%Y %H:%M:%S - 06/22/2003 09:30:00 如果系统地点是enu
货币 格式化(与地点相关) < BizField... Type="Currency" Format="Currency"... > 1456.89 被格式化作为$1,456.89 (enu)
1456.89 被格式化作为F1 456,89 (fra)
电话 格式化(根据指定的mask #) < BizField... Type="Phone" Format="mask string"... > 1234567890 被格式化 
mask=(###) ###-####, 
phone=(123) 456-7890
mask=###-###-####, phone=123-456-7890
  如果一个电话号码从开始"*", 它代表国际电话号码, 它不会被格式化   * 123 4567890 是国际数字
Blob/Clob < BizField... Type="Blob"... >
< BizField... Type="Clob"... >
 

数据检验

检验类型 例子
Required - 表明领域无法是空的 < BizField Name="Name" Required="Y" Column="NAME"/>
Validator - 简单表达式  < BizField Name="Fee" Type="Currency" Format="Currency" Validator="{[Fee]>=15}" Column="FEE" >

对象关系(O/R) 映射

为支持O/R 映射, TableJoin 和ObjectReference 被引入到BizDataObj metadata 文件。

用下面的例子来了解O/R 映射:

attendee:regist = 1:M (一对多), regist:attendee = M:1 (多对一)

events:regist = 1:M (一对多), regist:events = M:1 (多对一)

attendee:events = M:M (多对多)

映射一个表格到BizDataObj

映射表格到BizDataObj, 用户只需要在metadata配置BizFieldList。例如:

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
</BizDataObj>

主键(Id)的生成

从Openbiz 2.1RC, BizDataObj 支持多种id 生成算法。增加一个BizDataObj 属性
IdGeneration="Openbiz|Identity|Sequence:seqname|GUID|UUID|Other...".

IdGeneration 主键(Primary Key column) 生成方法 支持的数据库类型
Openbiz (default) 用"ob_sysids"表来生成Id. "ob_sysids"存储表格的 PK column. 适用于所有数据库类型
Identity 主关键字专栏由数据库引擎生成。
在SQL 服务器里, Id 叫做"Identity" column, 或在MySQL 叫做"自增" 专栏。
MySQL, SQL Server, Sybase, DB2
Sequence:seqname 主关键字栏由数据库序列生成。"seqname" 是序列名字被使用生成PK 。 Oracle, PostgreSQL, DB2
GUID GUID主关键字栏是数据库生成的GUID MySQL, SQL Server, Oracle
UUID 主关键字栏以php uuid()生成 适用于所有数据库类型
Other Developers can write customer specific Id generation algorithm by modifying function GetNewID(...) in genIdService class under openbiz/bin/service/genIdService.php

开发商能写客户具体Id 生成算法 - 修改在genIdService 组在openbiz/bin/service/genIdService.php 之下的 GetNewID(...) 

由客户决定 

组合关键字支持

In Openbiz 2.1, BizDataObj supports composite key. This feature would be useful when working with legacy database tables who does not have single primary key column. The syntax of BizDataObj whose Id field maps >2 primary key columns is:

在Openbiz 2.1, BizDataObj 支持组合关键字。这个特点会用在老式的没有唯一主关键字栏的数据库系统。BizDataObj 的Id 域映射到>2个主关键字栏. 句法是:

<BizDataObj Name="" Package="" Class="" ... IdGeneration="None">
<BizField Name="fpk1" Column="PK1"/>
<BizField Name="fpk2" Column="PK2"/>
<BizField Name="Id" Column="PK1,PK2" />
...

映射多表到BizdataObj

用户能通过Join映射多表到BizDataObj。这就是说基本表中的外键 (Foreign Key) column指到被Join的表一个column中. 例如, 

<BizObj Name="BORegist" Package="demo" Class="BizObj" Table="regist" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="EvtId" Column="EVENT_ID"/>
  <BizField Name="AttendeeId" Column="ATTENDEE_ID"/>
  <BizField Name="AttdLName" Join="attendee" Column="LASTNAME"/>
  <BizField Name="AttdFName" Join="attendee" Column="FIRSTNAME"/>
</BizFieldList>
<TableJoins>
  <Join Name="attendee" Table="attendee" Column="SYSID" ColumnRef="ATTENDEE_ID" JoinType="INNER JOIN"/>
</TableJoins>

Join 属性 描述
Name join 的名字.
Table joined 表名
Column joined column 名字
JoinRef 如果JoinRef 是空的, 被joined表连到基本表。用户能指定JoinRef 在2 级 join。
ColumnRef ColumnRef 指到基本表的column (或 JoinRef 表). 
JoinType INNER JOIN, LEFT JOIN, RIGHT JOIN, or FULL OUTER JOIN.

询问SQL类似于 "SELECT ... FROM BaseTable INNER JOIN JoinedTable ON BaseTable.ColumnRef=JoinedTable.JoinedColumn ...". 在上述例子, SQL 是 

SELECT T0.SYSID, T0.EVENT_ID, T0.ATTENDEE_ID, T1.LASTNAME, T1.FIRSTNAME 
FROM regist as T0
         INNER JOIN attendee as T1 ON T0.ATTENDEE_ID = T1.SYSID

- 关于JoinRef更多解释

JoinRef 支持 cascade-join. 例如, 表 A join B, 表 B join C. 表 A 和 C 通过 B join在一起. User 可能使用以下的方式连接C 和A 。

<TableJoins>
<Join Name="join_b" Table="B" Column="B_PK" ColumnRef="A_FK_B" JoinType="LEFT OUTER JOIN"/>
<Join Name="join_c" Table="C" JoinRef="join_b" Column="C_PK" ColumnRef="B_FK_C" JoinType="LEFT OUTER JOIN"/>
</TableJoins>

在BizDataObjs 之间多对一关系

在二个表之间多对一关系意味着表1 包含一个column 指向表2 的 key/unique column。映射在二个BizDataObjs 之间这样的关系, 要用在ObjectReference 部分定义的一个对象。例如, 

<BizObj Name="BORegist" Package="demo" Class="BizObj" Table="regist" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="EvtId" Column="EVENT_ID"/>
  <BizField Name="AttendeeId" Column="ATTENDEE_ID"/>
  <BizField Name="AttdLName" Join="attendee" Column="LASTNAME"/>
  <BizField Name="AttdFName" Join="attendee" Column="FIRSTNAME"/>
</BizFieldList>
<TableJoins>
  <Join Name="attendee" Table="attendee" Column="SYSID" ColumnRef="ATTENDEE_ID" JoinType="INNER JOIN"/>
</TableJoins>
<ObjReferences>
  <Object Name="BOEvent" Description="" Relationship="M-1" Table="events" Column="SYSID" FieldRef="EvtId"/>
</ObjReferences>

</BizObj>

对象 属性 描述
Name 被提到的BizDataObj 的名字
Description  
Relationship dataobj 之间的关系
Table 被提到的dataobj的表
Column 被提到的dataobj的表的column 
FieldRef 基本表中映射到 foreign key column 的 field 

从父dataobj调用GetRefObject($objame) 可以得到ObjReference 中的对象. 

在BizDataObjs 之间一对多关系

在二个表之间一对多关系意味着表2 包含一个 column 指向表1 的 key/unique column。映射在二个BizDataObjs 之间这样的关系, 要用在ObjectReference 部分定义的一个对象。例如, 

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
<ObjReferences>
  <Object Name="BORegist" Description="" Relationship="1-M" Table="regist" Column="EVENT_ID" FieldRef="Id" CascadeDelete="Y"/>
</ObjReferences>

</BizDataObj>

Object Attribute Description
Name 被提到的BizDataObj 的名字
Description  
Relationship dataobj 之间的关系
Table 被提到的 dataobj的表
Column 被提到的 dataobj的表的 column. 该 column 包含指到基本表中的 foreign key
FieldRef 基本表中映射到 foreign key column 的 field 
CascadeDelete 表明是否在基本表里删除一个纪录将导致在被提到的表里所有相关纪录的删除。

从父dataobj调用GetRefObject($objame) 可以得到ObjReference 中的对象. 

- 在BizDataObjs 之间一对一关系

一对一关系是多对一关系的一种特殊情况

在BizDataObjs 之间多对多关系

在二个表之间多对多关系意味着一个 intersection 表 (又叫作 cross reference table, 或 correlation table) 包含指向表1和表2的 key/unique columns. 映射在二个BizDataObjs 之间这样的关系, 要用在ObjectReference 部分定义的一个对象。例如,

<BizDataObj Name="BOEvent" Description="Event BizDataObj" Package="demo" Class="BizDataObj" Table="events" ...>
<BizFieldList>
  <BizField Name="Id" Column="SYSID"/>
  <BizField Name="Name" Column="NAME"/>
</BizFieldList>
<ObjReferences>
  <Object Name="BOAttendee" Description="" Relationship="M-M" Table="attendee" Column="SYSID" FieldRef="Id" CascadeDelete="Y"
XTable="regist" XColumn1="EVENT_ID" XColumn2="ATTENDEE_ID"/>
</ObjReferences>

</BizDataObj>

Object Attribute Description
Name 被提到的BizDataObj 的名字
Description  
Relationship dataobj 之间的关系
Table 被提到的 dataobj的表
Column 被提到的 dataobj的表的 column. 该 column 包含指到基本表中的 foreign key
FieldRef 基本表中映射到 foreign key column 的 field 
CascadeDelete 表明是否在基本表里删除一个纪录将导致在被提到的表里所有相关纪录的删除。
XTable intersection 表名
XColumn1 指到基本表foreign key 的 intersection 表 column
XColumn2 指到被提到基本表foreign key 的 intersection 表 column
XDataObj (New in 2.1) BizDataObject - 它的基本表是 intersection table (XTable). 

从父dataobj调用GetRefObject($objame) 可以得到ObjReference 中的对象. 

BizView 和BizForm 配置

BizView metadata DTD 文件可能被发现在附录A.2 。

BizForm metadata DTD 文件可能被发现在附录A.2 。

BizView - HTML页面容器

BizView 是包含多个BizForms 和其它HTML 元素的物理网页。它的布局根据smarty 模板 。BizView 定义BizForms 布局并且关系在BizForms 之间。

- BizForms 显示BizDataObj 关系

如果超过一个BizForm 被安置在BizView 并且在BizView指定他们的父子关系, BizForms 将回显示BizDataObj 的关系。

<BizView Name="EventView" ...>
<ControlList>
  <Control Name="fm_event" Form="FMEvent" SubCtrls="FMAttendeeChild"/>
  <Control Name="fm_attd" Form="FMAttendeeChild"/>
</ControlList>
</BizView>

SubCtrls 属性句法是 SubCtrls="childform1_name;childform2_name;...".它告诉子form 其父form 的名字, 这意味子form数据根据父form 的变动而改变。

由于BOEvent 和BOAttendee 有多对多关系,  event form 和 attendee form 将是M-M 的关系。他们在用户界面显示数据关系。

- Event View 例子:

EventView (Event-Attendee as M-M)

FMEvent as BizForm
 |-- BOEvent as BizDataObj
FMAttendeeChild as BizForm
 |-- BOAttendee as BizDataObj

基本BizForm 布局: 数据、工具栏和导航条

Openbiz BizForm 可分成三部份 - 数据部分、工具栏和导航条。

  • 数据部分是显示数据的区域。它可能被显示列单, 表单, 树等等。
  • 工具栏包含了BizForm 控制, 用户能从这些控制调用命令。
  • 导航条可以控制数据navigation 譬如换页, 卷动等。

这BizForm 的样品布局:

工具栏                                     导航条

数据部分

由BizForm表现BizDataObj 

BizForm 代表数据从BizDataObj 。BizForm 定义在BizForm中的BizCtrls 和在BizDataObj中的BizFields 之间的映射。例子,

<BizForm Name="FMRegist" ... BizObj="BORegist" ...>
<BizCtrlList>
  <BizCtrl Name="reg_id" FieldName="Id" DisplayName="Registration Id"/>
  <BizCtrl Name="reg_evtid" FieldName="EvtId" DisplayName="Event Id"/>
  <BizCtrl Name="reg_attdid" FieldName="AttendeeId" DisplayName="Attendee Id"/>
  <BizCtrl Name="reg_attdfn" FieldName="AttdFName" DisplayName="First Name"/>
  <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name"/>
</BizCtrlList>
</BizForm>

以各种各样的HTML 元素表现数据

HTMLControl 或BizCtrl 可以指定元素类型和属性来, 以各种各样的HTML 元素表现它的数据。HTML 元素被显示在edit/query 模式下

BizForm 中 HTMLControl 元素属性

Type Width Height HTMLAttr* Style** SeclectFrom Caption Image 评论
Text x x x
Limit the input length
x       文本输入。默认类型
Textarea x x x x       多行的文本输入
RichText x x x x       Rich text editor edit HTML source
ListBox x x x
Show ListBox or ComboBox
x x
Set list of values
    ListBox or ComboBox
CheckBox x x x x x
Set True value
    复选框
Radio x
Arrange radio list 
x x x x
Set list of values
    Radio 按钮
HTMLButton x x x x   x   标准HTML 按钮
SubmitButton x x x x   x   标准HTML Submit 按钮
ResetButton x x x x   x   标准 HTML Reset  按钮
Password x x x x       HTML password
Button x x x x   x x OpenBiz 图象按钮
Date x x x x       Textbox with date picker icon
Datetime x x x x       Textbox with datetime picker icon
HTMLBlock x x   x   x
Special Characters
   HTML block
File x x x x       文件控制上装文件

* HTMLAttr 域可包含任一个合法的HTML 元素类型的HTML 属性

** Style 域可包含所有合法的样式 (css)

Limit the input length: 

HTMLAttr="maxlength=N" 限制用户能输入在文本控制字符的最大数字

Show ListBox or ComboBox: 

由缺省展示comboBox 。如果HTMLAttr="size=N", 显示N 列listbox

Set list of values: 

SelectFrom="XmlFile(Key)" 意味控制是listbox 或radio button. 数据是在XmlFile文件中所有的"Key" 元素

Set True value: 

SelectFrom="Value" 意味这当用户检查复选框时, 复选框返回"Value"

Arrange radio list: 

By default the radion buttons are arranged horiztionally. If Width="1", you can force them arranged vertically.

缺省radio 按钮横向安排。如果Width="1", 您可能迫使他们垂直安排了

Special characters:

在 HTML block 使用"<" and ">" , 必须由"&lt;" 和 "&gt;"替换。参见 http://www.w3schools.com/html/html_entities.asp 以获得详情。

Rich text editor

Openbiz rich text editor 主要使用Kevin Roth http://www.kevinroth.com/rte/demo.htm的代码 (LGPL license) . 感谢他的优秀工作。它支持IE5.5+ 并且Firfox 1.x. 如下是screenshot 。

Date/Datetime picker

Openbiz 2.1 使用由dynarch.com 提供的开放源码DHTML calendar 1.0 (LGPL) . DHTML calendar 的文档资料在 http://www.dynarch.com/demos/jscalendar/doc/html/reference.html. 多谢 Nik Chankov 帮助集成的openbiz 与 DHTML calendar. Openbiz 使用系统样式日历

BizCtrl 另外的属性

  • FieldName - BizDataObj 的BizField 名字
  • DisplayName - BizField的标签, 可显示为表栏头
  • Link - 在READ显示方式之下, 控制的超链接. 一个例子: <BizCtrl Name="LName" FieldName="LastName" Link="a valid relative or absolute url"/>. 用户将看到 姓(即 Wilson) 链接 url.
  • DrilldownLink - 参见"配置drilldown 链接"
  • Sortable - 表明该领域是否可以排序
  • Order - BizCtrls 顺序
  • ValuePicker - 参见"配置BizCtrl 显示popup"

BizForm的事件处理 

当HTML 元素可能触发象onclick 和onblur的事件, 我们可以将事件处理函数联系各HTML 控制或BizCtrl 的事件。事件处理被定义在以下句法。

<Control Name="ControlName" Type="ControlType">
   <EventHandler Name="ehName" Event="eventName" Function="..." FunctionType="..." PostAction=""/> +
</Control>

可以联系更多的事件处理函数到一个控制上。这是一个在2.1的新特点。在Openbiz 2.0, 一控制可能有只一个事件处理函数。2.1, 函数和FunctionType 属性从控制元素被移动到控制元素的EventHandler 元素中。

- Event 是HTML 元素事件名字。参见 http://www.w3.org/TR/REC-html40/interact/scripts.html, 18.2.3 Intrinsic events。

- Function 服务器端应该有一个对应的BizForm 方法。当请求达到BizController, 它会调用正确的BizForm 方法。如果方法不存在, 错误返回。Function 的句法:

  <EventHandler ... Function="objectName.methodName(arg1, arg2...)" .../>. 

ObjectName 可能是空的, 这意味它调用当前的BizForm 方法。例如, < EventHandler... Function="SaveRecord()".../>. 用户能只调用基于metadata 文件对象的方法。这些对象包括BizForm 、BizDataObj 、BizView 和PluginService 。BizForm 方法和PluginService 方法被推荐为从客户端可调用的方法。

- FunctionType 可能是 RPC 或 Page 或 Form 或 Popup.

FunctionType 解释 例子
RPC 方法在服务器端由HTTPRequest (AJAX)调用 。RPC 是缺省值 New record button:
<Control Name="btn_new" Function="NewRecord()" FunctionType="RPC"/>
Page 方法在服务器端由页刷新调用, Form数据不传到服务器端 Export button to bring up a file save dialog in the page
<Control Name="btn_export" Function="CallService(ioService,exportXML)" FunctionType="Page"/>
Form 方法在服务器端由Form submission调用 Save button when there's file to upload in the form:
<Control Name="btn_save" Function="SaveRecord()" FunctionType="Form"/>
Popup 方法在服务器端调用, 返回的页被画在一个弹出式窗口中 Excel output button to show excel format in a popup:
<Control Name="btn_excel" Function="CallService(excelService,renderHTML)" FunctionType="Popup"/>

- ShortcutKey 将一个热键联系到函数。 "在BizForm键盘航海"会有解释 。

- PostAction 在函数调用之后, 重定向到page/view 。"控制页面航海"会有解释

BizForm的键盘导航

Openbiz 2.1RC 增加一个非常重要特点- 支持BizForm键盘导航。一旦热键被定义在BizForm, 用户能使用键盘对浏览纪录和页, create/edit/delete 纪录。

热键被定义在BizForm metadata 文件。控制的EventHandler 的ShortcutKey 属性可以将热键和函数联系在一起。句法是<Control Name="" Function="" ShortcutKey="key_combination".../> 。BizForm 只认可被定义在工具栏和Navbar 控制上的热键。

Openbiz 认可的热键包括:

输入的键 使用在ShortcutKey 属性中键的名字 
0,1,...9 0,1,...9
a,b,...z or A,B,...Z A,B,...Z
Ctrl key Ctrl
Shift key Shift
Alt key Alt
Enter key Enter 
Escape key Escape
Page up key PageUp
Page down key PageDown
Left arrow key Left
Right arrow key Right
Up arrow key Left
Down arrow key Down
Insert key Insert
Delete key Delete

开发商可能配置Ctrl 并且/或者 Shift 并且/或者 Alt 和其它键, 用"+" 连接他们。注意不要与缺省浏览器热键冲突。参见 http://www.mozilla.org/support/firefox/keyboard 为不同的浏览器的热键。

参见在demoapp/metadata/demo/FMEvent.xml 的热键例子。这个BizForm 支持以下热键:

热键 执行命令
Ctrl+Shift+Right go to next page
Ctrl+Shift+Left go to previous page
Ctrl+Shift+Down go to next record
Ctrl+Shift+Up go to previous record
Ctrl+Shift+N create a new record
Ctrl+Shift+E edit the selected record
Delete delete the selected record
Ctrl+Shift+Q switch to search record mode
Enter run search, or save record
Escape cancel search or cancel editing
Ctrl+Shift+C copy the selected record
Ctrl+Shift+R refresh form with default query

Form 控制的相互依赖

以复杂Form 中, 有通常一些控制依靠其它控制的值。当父控制变化, 它的子控制相应地变化。这是所谓的Form 控制的相互依赖。

在表示语言帮助下, 控制关系可被指定在BizForm metadata 文件中。在event handler帮助下, 在父控制变化事件将导致它的子控制的动态变动。

在demoapp/metadata/demo/FMFieldDepTest.xml 之下用一个例子

第一combobox 是主控制。根据它的值,
- 第2 控制将使能被enabled 或 disabled (BizForm 配置)
- 第3 控制将掩藏或将被显示 (BizForm 配置)
- 第4 控制将有不同的名单 (BizForm 配置)
- 第5 控制将改变价值和颜色当monuseover 第主控制时 (客户端 jbForm 的子类)

用来选择记录的popup BizForm 的配置

用户能从一个另外Form中选择纪录 (见以下例子):

  • 加/更改子纪录(父子是M-1关系) 。
  • 选择一个现有的子纪录, 加入到子Form中(父子是M-M关系) 
  • 在被joined域上, 从被joined的dataobj 中选择一个纪录。

有二种方式配置记录选择的popup BizForm 。

  • 配置HTML 控制显示popup

配置HTML 控制显示popup 形式, 用户在控制功能属性设置"showpopup($popupFormName)" 和FunctionTarget="Popup" 。这种配置可能被使用来在子Form中选择子纪录(M-1或M-M关系) 。

<Control Name="btn_new" Caption="Add" Type="Button" Function="ShowPopup(demo.FMAttendeePopup)" FunctionTarget="Popup"/>

On the popup form, add a button to call AddToParent() to add the current selected record to the parent form (the form trigger the popup). 

在popup form, 增加一个按钮来调用AddToParent(), 选择的纪录到父form 。

  • 配置BizCtrl 显示popup

配置BizCtrl 显示popup 从, 用户ValuePicker 属性

<BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup"/>

在popup form, 增加一个按钮来调用JoinToParent(), 选择的纪录到父form 。

  • 为BizCtrl配置自动记录选择器

You can user ValuePicker attribute to allow users to click the icon to show the picker popup window. Users may want to type in the value in the control and system will automatically pick the right record according to the user input. Openbiz supports this feature by BizForm's AutoPickValue($ctrlname) method. To configure auto picker.

您能用ValuePicker 属性允许显示用户选择器popup 窗口。用户也许想要在控制键入值并且系统自动地根据用户输入选择正确的纪录。Openbiz 由BizForm 的autopickvalue($ctrlname) 方法支持这个特点。配置自动选择器。

<BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup">
   <EventHandler Name="onchange" Event="onchange" Function="AutoPickValue(reg_attdln)" />
</BizCtrl>

根据用户输入, 行为被描述在以下表格:

用户输入 行为
not 空  以 [field] LIKE 'input_value%' 的 searchRule 来查询 valuepicker BizForm 的 DataObj. 根据询问结果:

  • 如果唯一纪录返回了, 以返回值自动填入所有相关控制中
  • 如果纪录没有返回, 显示没有searchRule的值选择器popup
  • 如果多个纪录返回了, 显示加上searchRule的值选择器popup

配置drilldown 链接对其它 view

您能配置BizCtrl 与一个链接(drilldown 链接), 这个链接指到其他的view。

在BizForm, 设置BizCtrl 的一个DillDownLink 属性。句法是

DrillDownLink="OtherView,OtherBizForm.OtherBizCtrl=MyBizCtrl".
OtherView - drilldown 链接指到其他的view的名字
OtherBizForm - 在OtherView中的一个独立BizForm, 不是其他BizForm 的子form
OtherBizCtrl -  OtherBizForm 的一个 BizCtrl
MyBizCtrl - 该BizForm 的一个 BizCtrl 

例子: <BizCtrl Name="reg_attdln" FieldName="AttdLName" DisplayName="Last Name" ValuePicker="FMAttendeePopup" DrillDownLink="AttendeeView,FMAttendee.attd_id=reg_attdid"/>.

从comboBox 或ListBox选择域数据

- 捆绑静态列表和comboBox

在您的BizForm, 您为BizCtrl设置SelectFrom="Selection(Fee)", 意味这comboBox域控制的数据是Selection.xml 文件"Fee" 元素的列表 。请在演示FMRegist.xml中参见例子 - BizCtrl reg_fee 被定义为comboBox。
<Selection>
  <Fee Value=""/>
  <Fee Value="15"/>
  <Fee Value="20"/>
</Selection>

并且, 您能给值和文本。如果只给值, openbiz 使用值作为显示文本。
<Selection>
   <ChartOption Value="AAA" Text="BarLine Chart"/>
   <ChartOption Value="BBB" Text="Pie Chart"/>
   <ChartOption Value="CCC" Text="GroupBar Chart"/>
</Selection>
您能选择的您自己的xml 文件。

-  捆绑动态列表(Table column) 和comboBox

在您的BizForm, 您为BizCtrl设 SelectFrom="BizDataObjName[BizFieldName ]" , 这意味comboBox 绑定了BizObjName 中BizFieldName 对应的 table column。避免同样的值出现在comboBox, 您需要确定BizObj 询问返回归一张独特的list。

Openbiz 也支持格式 SelectFrom="BizDataObjName[BizFieldName4Text:BizFieldName4Value ]" 。这样一来用户能在comboBox 中显示BizFieldName4Text 为文本, 而BizFieldName4Value 为值。

SearchRule 可以用在SelectFrom 中, 句法为 SelectFrom="BizDataObjName[BizFieldName4Text:BizFieldName4Value ], SearchRule_of_the_BizDataObj"。例如, <BizCtrl Name="" ... SelectFrom="BOEvent[Name], [Name] LIKE '%Soc%'"/>.

控制页面流程

Openbiz 有显示方式的一个独特的概念。BizForm 可能有超过一个显示方式。各个显示方式基本上是BizForm 的rendering 方式。Bizform 对BizDataObj 数据对用不同的显示方式显示.

- BizForm的显示方式

显示方式被指定在< BizForm metadata 文件的DisplayModes > 部分。您能将各个方式同smarty 模板联系在一起。为细节参见 创建 view 和 form web templates.。

通常BizForm 可能有READ, NEW, EDIT, QUERY 显示方式。但显示方式没有限制。例子是在/demoapp/metadata/shared/FMCalendar.xml 之下。它有显示方式"LIST", "DAY", "WEEK", "MONTH"。

在显示方式之间切换需要调用BizForm 方法setdisplaymode($mode)。代码在各个显示方式被运用时可实现特别逻辑。

各控制或BizCtrl 有DisplayMode 属性。您能设置DisplayMode = "MODE1|MODE2|... "。例如, < BizCtrl Name="LastName"... DisplayMode="EDIT|NEW"/>, 然后LastName 只被显示在EDIT 和NEW 模式。

- 在action 被执行后进行页面重定向

It's very common that users click on a button to trigger an action on server side and after the action is finished the page is redirected to another page. Page redirection can be specified as a post action in BizForm metadata file. The syntax is

用户点击按钮在服务器端触发一次action 并且在action 被执行后进行页面重定向, 这是非常普遍的。页面重定向可被指定在BizForm metadata 文件的post action中。句法是

<EventHandler Name="..." Function="..." PostAction="url|view"/> PostAction 可接受 url:url_string view:view_name.

例子在 login form demoapp/metadata/shared/FMAuth.xml

<Control Name="btn_submit" Image="" Caption="Submit" Type="HTMLButton" Function="Login()" PostAction="url:login.php?login=success"/>

- 错误页和错误信息

如果执行中有错误, 应用会返退错误页或显示错误弹出窗口到浏览器

BizForm中的输入和输出 (Import and Export)

数据输入和输出的支持对离线用户很重要。离线用户通常在他们的膝上计算机执行应用在, 然后再与服务器数据库进行同步。Openbiz 提供的输入和输出支持用以下方式:

Data export - implemented in exportXML method of ioService. The exported xml file has format as 

数据输出 - 被实施在ioService exportXML 方法。被输出文件是xml 格式 

<BizDataObj Name="demo.BOAttendeeX">
  <Record>
   <Field Name="field name" Value="field value" /> *
  </Record>
</BizDataObj>

数据输入 - 被实施在ioService importXML 方法。xml 文件输入有如上所述同样格式。

输入和输出按钮被配置在FMAttendee form 中。输入按钮直接地调用ioService 的exportXML 方法, 而输出按钮则弹出一个popup 窗口来问用户被输入的文件名。细节请参见demoapp/metadata/demo/FMAttendee.xml。

可以增加更多export/import 方法在ioService 支持以其它文件类型。

从BizForm上载文件

文件上载的支持在openbiz shared 包裹里。Metadata 文件在demoapp/metadata/shared/FMAttachment.xml, 它的类文件在demoapp/bin/shared/FMAttachment.php 。

上载文件, 用户需要配置BizCtrl 类型为"File" 。它映射对BizField 类型为"Blob" 。

下载文件, 用户需要配置BizCtrl 的Function 为download($record_id) 。下载方法被实施在FMAttachment 类。

参见FMAttachement 类和metadata 为细节。


Openbiz 开发指南

请参阅Openbiz开发指南


附录 A - 第三方库

库名 URL 描述 License
Smarty  http://smarty.php.net 模板引擎 LGPL
Adodb http://adodb.sourceforge.net  数据库抽象库 BSD
PHPMailer http://phpmailer.sourceforge.net  电子邮件 LGPL
jsval http://jsval.fantastic-bits.de  客户端数据有效性验证 LGPL
jscalendar http://www.dynarch.com/projects/calendar  DHTML 日历 LGPL
RTE http://www.kevinroth.com/rte/demo.htm  Rich Text 文本编辑 free
dompdf http://www.digitaljunkies.ca/dompdf  html 到 pdf 转f换器 free

附录 B - metadata DTD 文件

BizDataObj metadata DTD 文件

<!--OpenBiz BizObj metadata DTD-->

<!ELEMENT BizObj (BizFieldList, TableJoins, ObjRefernces, Parameters) >
<!ATTLIST BizObj Name CDATA #REQUIRED >
<!ATTLIST BizObj Description CDATA #REQUIRED >
<!ATTLIST BizObj Package CDATA #IMPLIED >
<!ATTLIST BizObj Class CDATA #REQUIRED >
<!ATTLIST BizObj InheritFrom CDATA #IMPLIED >
<!ATTLIST BizObj DBName CDATA #IMPLIED >
<!ATTLIST BizObj Table CDATA #REQUIRED >
<!ATTLIST BizObj SearchRule CDATA #IMPLIED >
<!ATTLIST BizObj SortRule CDATA #IMPLIED >
<!ATTLIST BizObj OtherSQLRule CDATA #IMPLIED >
<!ATTLIST BizObj AccessRule CDATA #IMPLIED >
<!ATTLIST BizObj UpdateCondition CDATA #IMPLIED >
<!ATTLIST BizObj DeleteCondition CDATA #IMPLIED >

<!ATTLIST BizObj CacheMode CDATA #IMPLIED >

<!ELEMENT BizFieldList (BizField+) >
<!ELEMENT BizField EMPTY >
<!ATTLIST BizField Name CDATA #REQUIRED >
<!ATTLIST BizField Class CDATA #IMPLIED >
<!ATTLIST BizField Join CDATA #IMPLIED >
<!ATTLIST BizField Column CDATA #REQUIRED >
<!ATTLIST BizField SQLExpr CDATA #IMPLIED >
<!ATTLIST BizField Type CDATA #IMPLIED >
<!ATTLIST BizField Format CDATA #IMPLIED >
<!ATTLIST BizField Required CDATA #IMPLIED >
<!ATTLIST BizField Validator CDATA #IMPLIED >
<!ATTLIST BizField DefaulValue CDATA #IMPLIED >
<!ATTLIST BizField Value CDATA #IMPLIED >
<!ATTLIST BizField OnAudit CDATA #IMPLIED >
<!ELEMENT TableJoins (Join+) >
<!ELEMENT Join EMPTY >
<!ATTLIST Join Name CDATA #REQUIRED >
<!ATTLIST Join Table CDATA #REQUIRED >
<!ATTLIST Join Column CDATA #REQUIRED >
<!ATTLIST Join JoinRef CDATA #IMPLIED >
<!ATTLIST Join ColumnRef CDATA #REQUIRED >
<!ATTLIST Join JoinType CDATA #REQUIRED >

<!ELEMENT ObjReferences (Object+) >
<!ELEMENT Object EMPTY >
<!ATTLIST Object Name CDATA #REQUIRED >
<!ATTLIST Object Description CDATA #IMPLIED >
<!ATTLIST Object Relationship CDATA #REQUIRED >
<!ATTLIST Object Table CDATA #REQUIRED >
<!ATTLIST Object Column CDATA #REQUIRED >
<!ATTLIST Object FieldRef CDATA #REQUIRED >
<!ATTLIST Object CascadeDelete CDATA #IMPLIED >
<!ATTLIST Object XTable CDATA #IMPLIED >
<!ATTLIST Object XColumn1 CDATA #IMPLIED >
<!ATTLIST Object XColumn2 CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizView metadata DTD file.

<!--OpenBiz BizView metadata DTD-->

<!ELEMENT BizView (ControlList, Parameters) >
<!ATTLIST BizView Name CDATA #REQUIRED >
<!ATTLIST BizView Description CDATA #REQUIRED >
<!ATTLIST BizView Package CDATA #IMPLIED >
<!ATTLIST BizView Class CDATA #IMPLIED >
<!ATTLIST BizView Template CDATA #IMPLIED >

<!ELEMENT ControlList (Control+) >
<!ELEMENT Control EMPTY >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Form CDATA #REQUIRED >
<!ATTLIST Control SubCtrls CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

BizForm metadata DTD 文件

<!--OpenBiz BizForm metadata DTD-->

<!ELEMENT BizForm (BizCtrlList, DisplayModes, Toolbar, Navbar, Parameters) >
<!ATTLIST BizForm Name CDATA #REQUIRED >
<!ATTLIST BizForm Description CDATA #REQUIRED >
<!ATTLIST BizForm Package CDATA #IMPLIED >
<!ATTLIST BizForm Class CDATA #REQUIRED >
<!ATTLIST BizForm InheritFrom CDATA #IMPLIED >
<!ATTLIST BizForm jsClass CDATA #REQUIRED >
<!ATTLIST BizForm Title CDATA #REQUIRED >
<!ATTLIST BizForm BizDataObj CDATA #REQUIRED >
<!ATTLIST BizForm PageSize CDATA #REQUIRED >
<!ATTLIST BizForm SearchRule CDATA #IMPLIED >

<!ELEMENT BizCtrlList (BizCtrl+) >
<!ELEMENT BizCtrl (EventHandler+) >
<!ATTLIST BizCtrl Name CDATA #REQUIRED >
<!ATTLIST BizCtrl Class CDATA #IMPLIED >
<!ATTLIST BizCtrl FieldName CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayName CDATA #IMPLIED
>
<!ATTLIST BizCtrl Type CDATA #IMPLIED >
<!ATTLIST BizCtrl Width CDATA #IMPLIED >
<!ATTLIST BizCtrl Height CDATA #IMPLIED >
<!ATTLIST BizCtrl HTMLAttr CDATA #IMPLIED >
<!ATTLIST BizCtrl Link CDATA #IMPLIED >
<!ATTLIST BizCtrl Image CDATA #IMPLIED >
<!ATTLIST BizCtrl Hidden CDATA #IMPLIED >
<!ATTLIST BizCtrl Enabled CDATA #IMPLIED >

<!ATTLIST BizCtrl Sortable (Y|N) "" >
<!ATTLIST BizCtrl Order CDATA #IMPLIED >
<!ATTLIST BizCtrl Style CDATA #IMPLIED >
<!ATTLIST BizCtrl ValuePicker CDATA #IMPLIED >
<!ATTLIST BizCtrl SelectFrom CDATA #IMPLIED >
<!ATTLIST BizCtrl DrillDownLink CDATA #IMPLIED >
<!ATTLIST BizCtrl DisplayMode CDATA #IMPLIED >

<!ELEMENT Toolbar (Control+) >
<!ELEMENT Navbar (Control+) >
<!ELEMENT Control (EventHandler+) >
<!ATTLIST Control Name CDATA #REQUIRED >
<!ATTLIST Control Class CDATA #IMPLIED >
<!ATTLIST Control Image CDATA #IMPLIED >
<!ATTLIST Control Caption CDATA #IMPLIED >
<!ATTLIST Control Type CDATA #IMPLIED >
<!ATTLIST Control Width CDATA #IMPLIED >
<!ATTLIST Control Height CDATA #IMPLIED >
<!ATTLIST Control HTMLAttr CDATA #IMPLIED >
<!ATTLIST Control Style CDATA #IMPLIED >
<!ATTLIST Control Hidden CDATA #IMPLIED >
<!ATTLIST Control Enabled CDATA #IMPLIED >
<!ATTLIST Control SelectFrom CDATA #IMPLIED >

<!ATTLIST Control DisplayMode CDATA #IMPLIED >

<!ELEMENT EventHandler EMPTY >
<!ATTLIST EventHandler Name CDATA #REQUIRED >
<!ATTLIST EventHandler Event CDATA #REQUIRED >
<!ATTLIST EventHandler Function CDATA #REQUIRED >
<!ATTLIST EventHandler FunctionType CDATA #IMPLIED >
<!ATTLIST EventHandler ShortcutKey CDATA #IMPLIED >
<!ATTLIST EventHandler PostAction CDATA #IMPLIED >
<!ELEMENT DisplayModes (Mode+) >
<!ELEMENT Mode EMPTY >
<!ATTLIST Mode Name CDATA #REQUIRED >
<!ATTLIST Mode TemplateFile CDATA #REQUIRED >
<!ATTLIST Mode DataFormat CDATA #REQUIRED >
<!ATTLIST Mode FormatStyle CDATA #IMPLIED >

<!ELEMENT Parameters (Parameter+) >
<!ELEMENT Parameter EMPTY >
<!ATTLIST Parameter Name CDATA #REQUIRED >
<!ATTLIST Parameter Value CDATA #IMPLIED >
<!ATTLIST Parameter Required CDATA #IMPLIED >
<!ATTLIST Parameter InOut CDATA #IMPLIED >

Plugin service metadata DTD 文件

<!--OpenBiz Plugin service metadata DTD-->

<!ELEMENT PluginService ANY >
<!ATTLIST PluginService Name CDATA #REQUIRED >
<!ATTLIST PluginService Description CDATA #IMPLIED >
<!ATTLIST PluginService Package CDATA #REQUIRED >
<!ATTLIST PluginService Class CDATA #REQUIRED >

Openbiz 2.0 中文手册(二)

这份文件是openbiz2.0中文手册(二)

Openbiz 开发指南


Openbiz 开发指南

Show openbiz views (pages)  - 尚待翻译...

- User URL string as controller.php?view=...&form=...&rule=...&mode=...&OtherInputs...

- Use client javascript GoToView(view, rule, loadPageTarget)

Input Description Sample
view bizview name shared.CalDetailView
form bizform name. This form must not depend on (a subform of) another bizform shared.FMCalDetail
rule the search rule of a bizform

syntax is "form.ctrl operator value".
operator can be =,>,>=,<,<=,!=. "LIKE %" SQL format is also valid rule. "AND", "OR" can be used to add more restriction.

FMSponsor.spr_exp>=12000 

FMSponsor.spr_name=\'Midas Auto\' OR FMSponsor.spr_id=\'SPSR_2\'

FMSponsor.spr_name LIKE \'S%\'

loadPageTarget the window or frame target to load the page  

Build view and form web templates

Smarty template engine is used in OpenBiz to render the HTML output. We provides some basic templates for render BizForm and BizView. You can create your own templates. Remember that an openbiz form must begin with a form tag <form id={$name} name={$name}>. For detail, please refer to http://smarty.php.net/docs.php 

Smarty engine recognizes the subdirectories under the main template directory. So you can create a fold under demoapp/templates/ and put template files there. When you give template file name in metadata file, just give Template="subdir/view.tpl".

- Draw BizForm as a html table

In BizForm xml file, you need give DataFormat as "block" and FormatStyle as table style which is given in css file.
<Mode ... TemplateFile="list.tpl" ... DataFormat="htmltable" FormatStyle="tbl"/>

In template file, {$fmttable}represents form whole html table.

Please refer to demo files FMEvent.xml and list.tpl

- Draw BizForm as a set of controls

Since the array dataformat output to smarty template is associated array, user can easily layout controls by their names. The associated array has format as fields[control_name][label] and fields[control_name][control].

Please refer to demo files FMEvent.xml and edit.tpl

Three DataFormats decide what data is passed to templates

DisplayMode DataFormat Data passed to template Controllability on template Example
array - Variable name to use in template is $fields
- associated array of single record
- array (control_name=>array ("label"=>label_text, "control"=>control_html))
Highly controllable in template edit.tpl
table - Variable name to use in template is $table
- 2D array of multiple records
- array (index=>array (control1_name=>value1, control2_name=>value2, ...))
  array[0] is column header
  array[1-n] are the 1st record to nth record
Highly controllable in template rptlist.tpl
block - Variable name to use in template is $block
- HTML string
lowly controllable in template list.tpl

Using BizDataObj functionalities

Only basic usage of BizDataObj is listed below. Please refer to the API doc for details.

Query and get results

1.x BizObj is renamed as BizDataObj in 2.0, because it mainly acts as business data unit. 

1.x use GetField and SetField to do get and set field values. In 2.0, no field level methods, but using GetRecord() and UpdateRecord() method to do record level operations. The idea behind is to make easier coding to retrieve query results and provide coarse-grained interfaces between 2 layers.

1.x way to query and get records

$bizobj->SetSearchRule("...");    // set search rule
$bizobj->RunSearch(-1);    // run query against the database tables. 
$bizobj->Home();    // reset the result record set
$hasVal = $bizobj->MoveFirst();    // move cursor to first record
while ($hasVal)
{
    foreach ($fieldlist as $field)
        $field_val[] = $bizobj->GetField($field);
   
// user logic code can be put here. 
    $hasVal = $bizobj->MoveNext();    // move cursor to next record
}

2.0 way to query and get records - option 1

$bizobj->SetSearchRule("...");    // set search rule
$bizobj->RunSearch(-1);    // run query against the database tables. query results can be cached
while ($recArray = $bizobj->GetRecord(1))    // get current record and move the cursor to the next record 
{
    // user logic code can be put here. recArray is an associated array whose key is "fieldname" and value is value of the field
}

2.0 way to query and get records - option 2

$bizobj->FetchRecords ($searchRule, $resultSet, $numRecords);    // get the whole recordset (list of recArray), query results won't be cached

Insert, Update and Delete a record 

// Insert Record
$recArr = $boUser->NewRecord();    // NewRecord returns an empty record array with a generate Id field
$recArr["LastName"] = "Test";
$recArr["FirstName"] = "Add";
$ok = $boUser->InsertRecord($recArr);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

// Update a record
$boUser->SetSearchRule("[Id]='USER-1006'");
$boUser->RunSearch();
$recArray = $bizobj->GetRecord(0);
$recArray["FirstName"] = "Update";
$ok = $boUser->UpdateRecord($recArray);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

// Delete a record
$boUser->SetSearchRule("[Id]='USER-1006'");
$boUser->RunSearch();
$recArray = $bizobj->GetRecord(0);
$ok = $boUser->DeleteRecord($recArray);
if (!$ok)     // handle error message
  print $boUser->GetErrorMessage();

Using BizForm functionalities

User can configure function in BizForm metadata file to invoke appropriate action on server side. The commonly used BizForm methods are listed below. Please refer to the API doc for details.

Query and show results

  • SearchRecord - show the query record mode
  • RearchRecord - Issue the query with user input in query mode and return to read mode

Insert a new record

  • NewRecord - show the new record mode
  • SaveRecord - Save current edited record with user input in query mode and return to read mode

Update a record

  • EditRecord - show the edit record mode on current focus record
  • SaveRecord - Save current edited record with user input in query mode and return to read mode

Delete a record

  • DeleteRecord - delete the current focus record

Copy a record

  • CopyRecord - copy the current focus record to new record

Page Navigation

  • MoveNext - show next page records
  • MovePrev - show previous page records

User input validation

According the topic at http://www.boringguys.com/?p=30, there are 3 different types of data validation checks one can do:

  • Syntactic validation - check data syntax 
  • Semantic validation - check one piece of data makes sense in regards to other incoming data
  • Domain or model validation - check data against another source of acceptable values

Syntactic and semantic validation can be implemented on client side and service side. Domain validation involves query data source, it is usually done in service code that connects to database.

Client side form validation

Openbiz does input validation using jsval library (LGPL, http://jsval.fantastic-bits.de/). To configure a validation rules for an openbiz HTMLControl, developers can use jsVal's "Inline initialization" to add validation attributes to HTMLAttr part of HTMLcontrol and FieldControl.

<Control Name="" Type="" HTMLAttr="jsval validation attributes here" ... /> 

Example: <BizCtr Name="email" Type="Text" HTMLAttr="regexp='JSVAL_RX_EMAIL' minlength=5..." ... /> 

In addition, HTMLControl has a Required (=Y|N) attribute. It is passed to pass as $fields['required'] (along with $fields['label'] and $fields['control']) to smarty template. In smarty template (edit.tpl), has code {if $item.required=="Y"} <span class='required'>*</span>{/if} to append a * to the label. Then the required control's label looks as "Email *"

Server side input validation

Openbiz mainly support validation on BizDataObj. In BizField, Required and Validator attributes are used for such purpose. Please see the BizDataObj configuration chapter for explanation of these two attributes.

Developers can use customer class to override DataObj::ValidateInput() method or Field::Validate() method achieve their own validation rules.

BizForm has an empty ValidateForm method which may be overridden by customer classes to implment special validation logic.

Extend OpenBiz classes

OpenBiz provide many functionalities to building a complicated web application. But different application has different requirement, so you may extend OpenBiz packages to build customer applications.

Extend server side classes

Because OpenBiz packages are based on object-oriented design, you can easily build up your own object by extending these packages and inherit all useful functions provided by them.

Extended classes are automatically loaded on demand. Extended class  must be included in a file with format as ClassName.php.

Use can specify class name for BizDataObj, BizField, BizView, BizForm, BizCtrl, Control and PluginService by filling the "Class" attribute of in metadata file

Base Class Where to specify the extend class
BizDataObj <BizDataObj ... Class="" ...>
BizField <BizField ... Class="" ...>
BizView <BizView ... Class="" ...>
BizForm <BizForm ... Class="" ...>
FieldControl <BizCtrl ... Class="" ...>
HTMLControl <Control ... Class="" ...>

Example: Extend BizDataObj and BizForm

/**
* class BOUser is the BizDataObj class to implement USER logic object
*/

class BOUser extends BizDataObj 
{
    function BOUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

/**
* class FMUser is the BizForm class to implement USER UI object
*/

class FMUser extends BizForm 
{
    function FMUser($xmlFile=null) {} 

      function my_special_function() {}    // new function

      function Render() {}    // override Render()
}

Extend client side classes

BizForm is the main server side presentation class, it has its counterpart class on client browser side. In the BizForm metadata, users can specify client side class in jsClass attribute of BizForm element. For example.

<BizForm Name="FMEvent" ... Class="BizForm" jsClass="jbForm"...>

Openbiz provides two client side classes AjaxForm and jbForm that is a subclass of AjaxForm.

AjaxForm methods:

  • CallFunction(method, params_array) - convert function to request and send it to server. A server side BizForm method is invoked by this method if there's no specific method implemented in the client class. For example, a BizForm, whose jsClass=jbForm, has a method named "SelectRecord". Openbiz will check if "SelectRecord" method is defined in jbForm class. If yes, it calls jbForm's SelectRecord(params_array), otherwise it calls CallFunction(method, params_array).
  • CallbackFunction(retContent) - Ajax callback function. It passes the returned content to Show().
  • CollectFormData() - collect form data into a message in Ajax call
  • Show(retContent) - called by callback function to show Ajax returned content in the form

jbForm methods:

  • CollectFormData() - overriding AjaxForm CollectFromData(), add additional "selected row" in the form data
  • SelectRecord(params_array) - special logic on select record call
  • SortRecord(params_array) - special logic on sort record call
  • DeleteRecord(params_array) - special logic on delete record call

To implement UI logic on client side, developers need to create their own client side class like jbForm and give the class name to jsClass attribute of BizForm element. If you need special logic in some methods, add these methods in the client class, which can be subclass of either AjaxForm or jbForm. These methods can be pure client code or it can this.CallFunction(...) to send the request to server.

An example:

Form metadata file is like:

<BizForm ... Class="MyForm" jsClass="MyjbForm"...>
...
   <BizCtrl Name="mybutton" ...>
      <EventHandler Name="onclick" Event="onclick" Function="server_MyButtonClick"/>
      <EventHandler Name="onblur" Event="onblur" Function="js_MyButtonBlur"/>
...
</BizForm>

In server side MyForm class, server_MyButtonClick() needs to be defined.

In client side MyjbForm class, js_MyButtonBlur() needs to be defined. Of course, if server_MyButtonClick() is defined in client class, server_MyButtonClick() needs to call this.CallFunction("server_MyButtonClick", params_array) at the end of the method to send the request to server MyForm server_MyButtonClick() method. The client side code will be like:

function MyjbForm(name) {}
MyjbForm.inheritsFrom(jbForm); //set inheritance
MyjbForm.prototype.js_MyButtonBlur = function (params_array)
{
    // put client logic here
    ...
}
MyjbForm.prototype.server_MyButtonClick= function (params_array)
{
    // put client logic here
    ...
    // send request to server side at the end
    this.CallFunction("server_MyButtonClick", params_array);
}

Implement Plug-in Service

Openbiz customer can write their special logic by implement Plug-in Service. Plugin services are also metadata-driven objects. Service code is under bin/service and metadata is under /metadata/service. The plugin service metadata only gives the service name, package and implementing class. Any xml elements can be child of the root PluginService element. This is because different services may have different metadata configuration. Please refer to the Appendix to see the DTD of plugin service metadata xml file.

Openbiz core library includes services under openbiz/bin/service/ and their metadata files under openbiz/metadata/service/.

  • excelService.php - print Excel output with HTML or CSV formats
  • authService.php - authentication service, please refer to next chapter for usage
  • accessService.php - view access control service, please refer to next chapter for usage
  • profileService.php - user profile service, please refer to next chapter for usage
  • logService.php - write log to file
  • ioService - data winput/output service
  • pdfService.php -  prints PDF report
  • emailService.php - integrated with PHPMailer to send emails through smtp mail server.
  • doTriggerService - BizDataObj trigger service
  • auditService - audit trail service to trace data change

In the application, you can specify your own plugin service implementation with following methods.

  1. Change the service metadata content under your_app/metadata/service/, still use the core service. For example, you can write different accessService.xml to control the view access rule, but the implementing class is accessService.php in core library. The accessService.xml is like 
    <PluginService Name="accessService" Package="service" Class="accessService">
       application specific view access definition
    </PluginService>
  2. Specify the service implementing class. For example, different applications have different profile service. The profileService.xml is like 
    <PluginService Name="profileService" Package="service" Class="your_own_service_class">
    </PluginService>
  3. Combine the above 2 methods.

Write a plug-in service

Implement the class and method in the ClassName.php
A input argument of the method are the caller's object name (a BizForm name) and the input data string (a collection of form values from client browser). It implements the user-specific business logic and returns void. See the following code snippet.

class pdfService
{
 function pdfService() {}

 function renderView($viewName)
 {
  global $g_BizSystem;
  // get the view object and render the view to a html string
  $viewobj = $g_BizSystem->GetObjectFactory()->GetObject($viewName);
  if($viewobj) {
    $viewobj->SetConsoleOutput(false);
  $sHTML = $viewobj->Render();
  // convert HTML to PDF
  // ... customer code to do the convert 
 }
}

Call a plug-in service method

  • Call service in form. Define the caller function in BizForm metadata file
    <... Function="CallService(ClassName,MethodName)"...> is to call a method "MethodName" of the service "ClassName". ClassName is a class which defined in ClassName.php under bin/usrlib/ directory
  • Call service with url. Use url like bin/BizController.php?F=Invoke&P0=[servicename]&P1=[methodname]&P2=[parameter1]... The example is bin/BizController.php?F=Invoke&P0=[pdfService]&P1=[renderView]&P2=[demo.ReportView]
  • Call service in code. 
    global $g_BizSystem;
    $svcobj = $g_BizSystem->GetService($class);
    $svcobj->$method($this->m_Name);

Implement authentication, view and data access control

User authentication

Openbiz uses authentication service (usrlib/authService.php) to authenticate username and password

public function AuthenticateUser ($userid, $password) is called to authenticate user. 

  • AuthenticateUser by default querys on "User Id" and "Password" fields defined in metadata/shared/BOAuth.xml. If input user id and password is found in in BOAuth, AuthenticateUser returns true. AuthenticateUser method is to be modified to fit customer logic.
  • metadata/shared/SignupView.xml is the default login view. This view can be configured for change the login look and feel.

Role-based view access control

View access control depended on the AccessControl attribute in view metadata file in Openbiz 1.x. From Openbiz RC1, openbiz implements role-based view access control in its new security architecture. 

Openbiz uses profile service (usrlib/profileService.php) to get user profile that includes "role". Then match this role to access service (usrlib/accessService.php) to determine the users' accessibility to the view

public function GetProfile ($userid=null) is called to get user profile array which is an associated array with profile key and profile value pairs.

  • Customer must replace the default GetProfile method in openbiz package, because the default GetProfile method returns some randomly made array.

public function AllowViewAccess ($viewName, $role=null) is called to check the accessibility of a view

  • accessService has a configuration file (accessService.xml) that defines the view access permission. Please see an example below.

  • The xml configuration file is easy to understand. Customer needs to put their own logic in the accessService.xml.

Attribute-based data access control

Openbiz uses profile service (usrlib/profileService.php) to get user profile that includes attributes. Then based on these attributes to determine browse/update/delete permission of data record. The data access permissions are controlled in BizDataObj.

User can refer to attributes by @profile:attribute in BizDataObj metadata files. Profile attributes are all from profileService. When user first login, profileService returns a profile array that is saved in session. If an attribute is found in the profile array, the attribute value is returned. If the profile array doesn't contain such attribute, profileService method GetAttribute ($userid, $attr) is called to return the attribute value. Customer must implement GetAttribute method with their own logic.

- Data browse permission. A typical access control requirement is to limit the accessibility of table record to different users. This feature can be achieved by configuring AccessRule in BizDataObj metadata file. We do the configuration with the following two scenario.

Scenario  Configuration
Event can be only accessed by the owner

(personal access control)

<BizDataObj Name="Event" ... AccessRule="[OwnerId]='@profile:ORGID'" ...>

<BizField Name="OwnerId" Column="OWNER_ID"/>

Event can be accessed by all invited attendees 

(if the login user is one of the attendees, he can access the event)

<BizDataObj Name="Event" ... AccessRule="[AttendeeId]='@profile:USERID'" ...>

<BizField Name="AttendeeId" Column="ATTD_ID" Join="Attendee"/>

<Join Name="Attendee" Table="evts_attds" Column="EVT_ID" ColumnRef="SYSID" JoinType="LEFT JOIN"/>

- Data update permission. UpdateCondition is to control the record update permission. UpdateCondition expects true or false. A sample is UpdateCondition = "[OrgId]=={@profile:ORGID}". {} is the evaluated as simple expression.

- Data delete permission. DeleteCondition is to control the record delete permission. DeleteCondition expects true or false. A sample is DeleteCondition = "'admin'=={@profile:ROLEID}"

Build a multi-step wizard view

Wizard is a sequence of forms (questionnaires) which guide users to complete a complicated task. An example is filling an expense report which include different types (hotel, airfare, other activities...) of expenses.

Openbiz support wizard by easy metadata configuration. Openbiz wizard has following features:

  • Each form has "Next", "Back", "Cancel" and "Finish" navigation buttons.
  • If user clicks cancel button, user input data is not saved to database.
  • User input data won't to commit to database until user clicks finish button.

To see sample of wizards, go to Test view, click on "Wizard tests +" submenus. As you can see from the demo, wizard can be accessed with an url. 

As shown in the 2nd link, developer can give the parameter on the fly to run the wizard against given record

Configuration of wizard view

Openbiz wizard is a regular view that contains several wizard forms. So configuring a wizard in openbiz is no harder than  configuring a BizView. The difference between a wizard view and regular view is wizard view show the wizard forms one by one based on the their sequence in view metadata file, but regular view show all forms in one page. Below is an example of a wizard view metadata file.

<?xml version="1.0" standalone="no"?>
<BizView Name="EventWizardView" Description="" Package="demo" Class="BizViewWizard" Template="view.tpl">
   <ControlList>
      <Control Name="wizardForm1" Form="FMEventWzd1"/>
      <Control Name="wizardForm2" Form="FMEventWzd2"/>
   </ControlList>
   <Parameters>
      <Parameter Name="Evt_Id" Value="" />
   </Parameters>
</BizView>

Configuration of wizard forms

A wizard form is a regular form with class as BizFormWizard or BizFormNewWizard (or their subclasses).

  • BizFormWizard - to edit a record
  • BizFormNewWizard - to create a record

This is a typical wizard form metadata file.

<?xml version="1.0" standalone="no"?>
<BizForm Name="FMNewEventWzd1" Package="demo" Class="BizFormNewWizard" jsClass="jbForm" Title="Enter event information:" SearchRule="" Description="Event BizForm" BizDataObj="BOEvent">
  <DisplayModes>
    <Mode Name="EDIT" TemplateFile="edit.tpl" DataFormat="array" FormatStyle="" />
  </DisplayModes>
  <BizCtrlList>
    <BizCtrl Name="evt_id" FieldName="Id" DisplayName="Event Id" />
    <BizCtrl Name="evt_name" FieldName="Name" DisplayName="Name" Type="" Width="250" />
    <BizCtrl Name="evt_desc" FieldName="Description" DisplayName="Description" Type="Textarea" />
    <BizCtrl Name="evt_host" FieldName="Host" DisplayName="Host" />
  </BizCtrlList>
  <Toolbar>
    <Control Name="btn_back" Image="" Caption="&lt; Back" Type="Button" Function="GoPrev()" />
    <Control Name="btn_next" Image="" Caption="Next &gt;" Type="Button" Function="GoNext()" />
    <Control Name="btn_cancel" Image="" Caption="Cancel" Type="Button" Function="DoCancel()" PostAction="view:demo.EventView"/>
    <Control Name="btn_finish" Image="" Caption="Finish" Type="Button" Function="DoFinish()" PostAction="view:demo.EventView"/>
  </Toolbar> 
  <Navbar>
  </Navbar> 
</BizForm>

Extend wizard with customer wizard class

If application has speical logic, Openbiz suggest developers to write their own wizard form class drived from BizWizardForm. By overriding GoPrev(), GoNext(), DoCancel() and DoFinish() methods, developers can do different handling on navigation buttons events.

Openbiz wizard view play the role as a form controller where wizard form can set/get input data, cancel/finish the whole wizard process and render wizard forms. Please see the API document for details.

Implement dataobject events trigger

Upon dataobjects update/delete operations, openbiz allows triggering different alerts and action requests based on boolean results from search criteria for specific object. Briefly it is called DO Trigger which executes in a response to a change in the values stored in the database. DO trigger has two parts - trigger events and trigger actions. These information are defined in DOTrigger plugin service metadata files. At runtime when user update/delete a BizDataObj record, openbiz searches for this dataobj's trigger by looking for its trigger metadata file with name DataObjName_trigger.xml under the same directory. For example, demo/BOEvent's dataobj trigger metadata file is demo/BOEvent_trigger.xml.

Define a dataobject trigger metadata

<PluginService Name="BOEvent_Trigger" Description="" Package="demo" Class="service.doTriggerService" DataObjectName="BOEvent">
<DOTrigger TriggerType="UPDATE|DELETE">*
  <TriggerCondition Expression="" ExtraSearchRule="" />
  <TriggerActions>
    <TriggerAction Action="Method_Name" Immediate="Y|N" DelayMinutes="" RepeatMinutes="">
      <ActionArgument Name="" Value="" /> *
    </TriggerAction>
  </TriggerActions>
</DOTrigger>
</PluginService>

Trigger conditions Description Sample
trigger type Update or Delete record  
expression any expression supported by openbiz {[Expense]}>100. Check if current record's Expense field > 100
extra search rule search rule added on the current dataobj search rules {[AlertFlag]}='Y'. Check if there's at least one record whose AlertFlag is 'Y'
Trigger action methods Description Parameters
ExecuteSQL ExecuteSQL method executes SQL statement Name="DBName" Value="Default"
Name="SQL" Value="select * from regist where EVENT_ID='{[Id]}'"
ExecuteShell ExecuteShell method executes external application Name="Script" Value="dir"
Name="Inputs" Value=" > d:\temp\out.txt"
SendEmail SenEmail method sends outbound emails. 

It calls emailService's sendEmail method

Name="EmailService" Value="service.emailService"
Name="Account" Value="MyPhpopenbiz"
Name="TOs" Value="rockyswen@gmail.com; rockyswen@phpopenbiz.org"
Name="CCs" Value=""
Name="BCCs" Value=""
Name="Subject" Value="alert message"
Name="Body" Value="This is an alert message. \nPlease notice that the record with {[Id]} was updated."
Name="Attachments" Value="" 
AuditTrail Trace record field change

It calls auditService Audit method

Name="AuditService" Value="service.auditService"
Name="DataObjectName" Value="{@:Name}"
any method in doTriggerService The method of doTriggerService is called  Parameters needed to the method

Make customer specific UI components

Due to the extensibility nature of metadata xml files, developers can create their own metadata file, which does not comply with openbiz metadata DTD, to describe the behavior of objects. Openbiz converts xml file to a php array and pass it to the class constructor to save developers' parsing work. Developers need to write their own code to extend from MetaObject class and read in the array by overriding ReadMetadata(&$xmlArr) method.

Tabs component

This is the good example of using customer metadata xml file. Openbiz 2.1 supports tabs UI component. The metadata file (demo/tabs.xml) is like

<?xml version="1.0" standalone="no"?>
<BizForm Name="Tabs" Package="demo" Class="HTMLTabs">
  <TabViews>
    <View Name="demo.AttendeeView" URL="" Caption="Attendees"/>
    <View Name="demo.EventView" URL="" Caption="Events"/>
  </TabViews>
</BizForm>

The class code is under openbiz/bin/HTMLTabs.php. Its css file is in openbiz.css.

Developer can draw more UI widgets like tree, menu using the same approach. 

Menu component 

Openbiz 2.1 supports menu UI component. The metadata file of a menu (i.e. demo/Menus.xml) is like

<?xml version="1.0" standalone="no"?>
<Menu Name="Menus" Package="demo" Class="HTMLMenus">
  <MenuItem URL="" Caption="" Target=""> *
    <MenuItem URL="" Caption="" Target=""/> *

The class code is under openbiz/bin/HTMLMenus.php. Its css file is /css/menu.css

The menu provided in the demo application can be seen in "Test" view. This menu is a horizontal dropdown menu. It is a pure css menu. The idea is copied from http://solardreamstudios.com/learn/css/cssmenus. The output html (<ul><li>...) has same format of the output of well-known DynarchMenu http://www.dynarch.com/products/dhtml-menu/. So integration with DynarchMenu is an easy job. Of course, developers are free to modify the HTMLMenus class to work with other menu libraries. Same principle will apply to other customer UI components.

Tree component

Openbiz 2.1 supports tree UI component. The metadata file of a tree (i.e. demo/Tree.xml) is like

<?xml version="1.0" standalone="no"?>
<Tree Name="Tree" Package="demo" Class="HTMLTree">
  <Node URL="" Caption="" Target=""> *
    <Node URL="" Caption="" Target=""/> *

The class code is under openbiz/bin/HTMLTree.php. Its css file is in openbiz.css

The tree provided in the demo application can be seen in "Test" view. The technique of drawing tree is same as the tree of Eclipse help system http://help.eclipse.org/help30/index.jsp. Again, developers are free to modify the HTMLTree class to work with other tree libraries.

Control the look and feel with css files

The openbiz look and feel is controlled by stylesheet css files. The main css file is /css/openbiz.css

Control BizForm table style

In case of using Format="block" in the BizForm's displayMode, users can modify the following section in css/openbiz.css file.

/* -------- table style -------- */
.tbl {...}
.tbl .head {...}
.tbl .rowodd {...}
.tbl .roweven {...}
.tbl .rowsel {...}
.tbl .cell {...}

Control tabs style

In order to give user specific tab styles, users can modify the following section in css/openbiz.css file.

/* -------- tabs style -------- */
.tabmenu {...}
.tabmenu li {...}
.tabmenu a, a.active {...}
.tabmenu a.active {...}
.tabmenu a:hover {...}
.tabmenu a:visited {...}
.tabmenu a.active:hover {...}

Control menu style

In order to give user specific tab styles, users can modify the following section in css/menu.css file.

Control tree style

In order to give user specific tree styles, users can modify the following section in css/openbiz.css file.

/* ----- tree style ----- */
UL.expanded {...}
UL.collapsed {...}
LI.tree {...}

Control rich text editor (RTE) style

In order to give user specific RTE styles, users can modify the following section in pages/rte/rte.css file.

Date and Datetime picker

The DHTML calendar is well documented at  http://www.dynarch.com/demos/jscalendar/doc/html/reference.html. The javascript file is under demoapp/js/jscalendar.

Debug strategies

- Logging. BizSystem::log() method  can be called to log 4 priority levels LOG_EMERG, LOG_ERR, LOG_WARNING and LOG_DEBUG. Also a subject can be specified to give log messages different categories. The error is logged under /log/log_error.html, open it and you may find out what's wrong

- Debugging. Other than the DEBUG flag in 1.1.x is still valid, developers can turn on other 2 debug flags.
  1) Open the sysheader.inc under /bin, turn on debug log by changing define("DEBUG", 1); Then you'll see some debug information in /log/log_debug.html. This debug file records mainly the database calls and other operations
  2) Turn on SQL debug flag. Uncomment //$this->m_DbConnection[$rDBName]->debug = true; in BizSystem::GetDBConnection().
  3) Turn on RPC debug flag, each RPC response is printed in a separate window. Set var RPC_DEBUG = true; in clientUtil.js.

API document

Openbiz 2.0 API document

中文Powerpoint 教程

下载 中文Powerpoint 教程 

Openbiz Eclipse插件用户手册

Openbiz Eclipse插件用户手册

  1. 安装
  2. 在openbiz 项目上工作
    2.1 创造openbiz 项目
    2.2 创造和编辑BizObj
    2.3 创造和编辑BizForm
    2.4 创造和编辑BizView
    2.5 在浏览器测试BizView 

1. 安装

Openbiz Eclipse插件协助openbiz 用户在Eclipse环境里开发openbiz 应用。

首先删除旧的Openbiz Eclipse插件。下载openbiz_eclipse_0.9.x.zip 从openbiz sourceforge 网站。同其它Eclipse plugins 的安装一样, 将文件unzip 到eclipse目录。然后再开始Eclipse。Openbiz 插件工作在Eclipse3.x 之上。

以确信openbiz 插件可以连接到必需为openbiz 开发所需要的数据库, 请编辑在ECLIPSE_ROOT/plugins/org.openbiz.metadata_0.9.x/config 之下的config.xml 文件。在文件立有一个被预设的数据库元素, 它将使用connect/j JDBC driver 连接本机的MySql 数据库。请将其改成正确jdbc driver 和数据库url。

在config.xml中预设的数据库元素

<Database DriverFile="D:\java\eclipse\plugins\org.openbiz.metadata_0.9.x\lib\mysql-connector-java-3.1.10-bin.jar" DriverClass="com.mysql.jdbc.Driver" ConnectURL="jdbc:mysql://localhost:3306/demo" Schema="" User="root" Password="root"/>

配置数据库元素, 以下属性必须正确地被设定。

  • DriverFile - jdbc driver jar file 路径
  • DriverClass - jdbc driver 类
  • ConnectURL - 连接数据库服务器jdbc 的 URL
  • Schema - schema 名字. 一些数据库类型(如Oracle) 支持。
  • User - 连接到数据库服务器用户名
  • Password - 连接到数据库服务器密码

2. 在openbiz 项目上工作

2.1 创建openbiz 项目

在 Eclipse 的帮助下, openbiz 的目录可被 eclipse 项目(project)管理. 用户可创建一个指到openbiz 应用目录(或 openbiz/metadata) 的项目. Openbiz project 树会出现在 eclipse Navigator view. 见下图

2.2 创建一个 BizDataObj - 映射到数据库表的对象

从主菜单上点击 File -> New -> Others... , 或用鼠标右击 openbiz project, 选择New -> Others..., 一个窗口会弹出. 选择Openbiz Metadata Object -> BizDataObj metadata file.

 

然后在后面的页上做以下任务。

  1. 键入metadata 文件名
  2. 从config.xml 的数据库名单中选择一个数据库
  3. 选择一张数据库表为BizDataObj 基本的表
  4. 选择表栏(table columns)映射到BizFields

在您点击结束按钮之后, 新metadata 文件被打开在编辑区域。编辑看起来象eclipse Plug-in Menifest 编辑。概要页显示根metadata 对象, 其他页展示xml 树第二层次xml 元素的信息。见下图

plugin提供三种方式来编辑metadata 文件, 见下图

  • 增加, 删除或移动元素
  • 在editbox键入值或在comboBox选择值
  • 点击"..."按钮, 选择一个值, 譬如 table, column 或metadata 对象

2.3 创建BizForm - 对应于BizDataObj 的界面对象

像创建 BizDataObj 一样, 从主菜单上点击 File -> New -> Others... , 或用鼠标右击 openbiz project, 选择 New -> Others..., 一个窗口会弹出. 选择Openbiz Metadata Object -> BizForm metadata file.

然后在后面的页上做以下任务。

  1. 键入metadata 文件名
  2. 选择一个BizForm 依赖的BizDataObj 
  3. 选择BizDataObj's BizFields 映射到BizForm's BizCtrls
  4. 创建Toolbar 控制的Navigation bar 控制
  5. 为controls and BizCtrls 加上event handlers

在您点击结束按钮之后, 新metadata 文件被打开在编辑区域。

Screenshot: 用鼠标右键单击控制, 从菜单项目增加EventHanlder

Screenshot: 编辑控制的event handler

2.4 创造和编辑BizView - BizForm 的容器

像创建 BizDataObj 一样, 从主菜单上点击 File -> New -> Others... , 或用鼠标右击 openbiz project, 选择New -> Others..., 一个窗口会弹出. 选择Openbiz Metadata Object -> BizView metadata file.

然后键入metadata 文件名, 点击结束按钮

在您点击结束按钮之后, 新metadata 文件被打开在编辑区域。

2.5 在浏览器中测试BizView

BizView 可以用以下url 格式:

openbiz_root_path/bin/controller.php?view=package.viewname

例如, http://localhost/demoapp/bin/controller.php?view=shared.SignupView

Tutorial

2.4 Quick start videos

Tutorial

Best Practice


A simple tutorial

This simple tutorial is to guide you publish a table to web step by step. We just use text editor to edit metadata files. To configure more complex table relationship and use openbiz eclipse plugin, please refer to tutorial.pdf and plugin designer manual available at the openbiz web site.

1. Prepare
- Make sure you follow the openbiz installation steps described in the openbiz manual
- You can bring up demo applications correctly

2. Map a table to a DataObj
- The table must have a single primary key column (composite key is supported in 2.1)
- We can use the attendee table in the demo database
- Copy BOAttendee.xml to BOTest.xml. Open BOTest.xml and modify the column to field mapping under <BizFieldList>.
For example, remove the "OtherName" field.

3. Map a DataObj to Form
- Copy FMAttendee.xml to FMTest.xml. Open FMTest.xml and modify the column to field mapping under <BizCtrlList>.
For example, remove BizCtrl with FieldName as "OtherName"

4. Include a Form in a View
- Copy AttendeeView.xml to TestView.xml. Open TestView.xml and replace the FMAttendee to FMTest.

5. Test the View
- "http://localhost/demoapp/bin/controller.php?view=demo.TestView"
- The OtherName column is not shown on the view.

Attribute FullPage




We can use the attribute BizForm::FullPage = 'N' to show the existing

records without empty rows. For example: 
If the PageSize attribute is 10 and the number of records is 9 we'll see just 9 rows.

 

 Sorry for post here, I make a mistake ñ_ñ