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 librariesAppendix B - metadata DTD filesOverview of Openbiz 2.0Openbiz 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 architectureMetadata-driver frameworkThe 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 MVCOne 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.
Openbiz's implementation of persistent object and ORMSimilar 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.
Openbiz security modelOpenbiz 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:
Openbiz 2.0 package organizationOpenBiz 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.
Class diagram of multi-layer architecture |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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.
- ADODB, http://php.weblogs.com/ADODB.
- Smarty template engine, http://smarty.php.net/.
We recommend you install PHP optimization packages.
- Zend Performance Suite http://www.zend.com/store/products/zend-performance-suite.php
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:
- Is your application web-based application or can be converted to web-based application?
- Is your application need manipulate different types of data using database?
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?
- It brings developers a clear logic picture - openbiz core library and application code are under different locations.
- Openbiz core library is more portable than the openbiz application, it can be shared by multiple applications.
- If openbiz core has new release, it's easy to upgrade.
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.
- Copy demoapp directory and rename it to your application name, say "testapp"
- Open testapp/bin/app.inc, change the constants appropriately. If the default values may work for you, no change is needed.
- 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
- 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.
Fit your system design in Openbiz
Fit your design in Openbiz framework, you leverage the power of the framework. Your design will have
- Clear three-layer architecture stack
- XML metadata driven application
- MVC (Model-View-Controller) design pattern
- Rich set libraries and valuable crafts
- Common application features
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
Sample implementation - Calendar
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
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 &form=shared.FMCalDetail &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 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.
- 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
Literals
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
Operators
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.
Variables
- Simple expression allows developers to use variables of openbiz metadata objects:
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_nameget 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_nameget 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 elementCall 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.
-
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
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
- <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}"/>
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.
- Specify the base table:
<BizDataObj Name="BizDataObjName" Table="TableName" ...>
- Map Column to BizField:
<BizField Name="FieldName" Column="ColumnName"....>. One of BizFields must have name as "Id". This is required. This Id field usually map to the primary key column of a table.
- Map SQL Function to BizField:
Users can assign a BizField with SQL functions provided by the database engine. The syntax is <BizField Name="FieldName" Column="" SQLExpr="FUNC([FieldName1]...[FieldName2]...)">. Make sure that the Column attribute is empty. For example: <BizField Name="FullName" Column="" SQLExpr="CONCAT([FirstName],' ',[LastName])"...>. Please note that SQLExpr is a query related attributes, [FieldName] is not evaluated to field value. [FieldName] is the syntax of query lanaguage.
- Specify default value of BizField:
<BizField Name="FieldName" Column="ColumnName" DefaultValue="default_value">. Use DefaultValue attribute to give default value to the BizField when dataobject creates a new record.
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.
-
Specify the default query in SearchRule
Example: <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" SearchRule="[Start]>'1999-10-20'" ...> -
Specify the default sort in SortRule
Example: <BizObj Name="BOCalendar" Description="Calendar BizObj" Package="shared" Class="MyClass" Table="calevts" SortRule="[Start] ASC" ...> -
Specify additional SQL statement in OtherSQLRule
Example: <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
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 |
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)
|
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
|
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 |
x | Single line text input. Default type | |||
| Textarea | x | x | x | x | Multi-line Text input | |||
| RichText | x | x | x | x | ||||
| ListBox | x | x | x |
x | x |
ListBox or ComboBox | ||
| CheckBox | x | x | x | x | x |
CheckBox | ||
| Radio | x |
x | x | x | x |
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 | ||||
| Datetime | x | x | x | x | ||||
| HTMLBlock | x | x | x | x |
Caption is treated as HTML block | |||
| File | x | x | x | x | File control to upload file | |||
* HTMLAttr field can contain any valid additional HTML attribute applied on the HTML element type
** Style field can contain any valid style properties (css)
HTMLAttr="maxlength=N" to limit the maximum number of characters that the user can enter in a text control.
By default show comboBox. If HTMLAttr="size=N", show N-row listbox.
SelectFrom="XmlFile(Key)" means this field control is a listbox or radio buttons whose data is from the "Key" elements in XmlFile.
SelectFrom="Value" means this checkbox returns the Value when user check the checkbox.
By default the radion buttons are arranged horiztionally. If Width="1", you can force them arranged vertically.
"<" and ">" used in HTML block have to be replaced by "<" and ">". Please refer to http://www.w3schools.com/html/html_entities.asp for more details.
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.

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
- 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 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:
- 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 current selected record to the parent form (the form trigger the popup).
- Configure a BizCtrl to show 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).
- Configure an automatic value picker for a 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.
<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". |
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.
- 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> - 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> - 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.
- http://localhost/demoapp/bin/controller.php?view=demo.EventNewWizardView
- http://localhost/demoapp/bin/controller.php?view=demo.EventWizardView¶m:Evt_Id=EVT_2
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="< Back" Type="Button" Function="GoPrev()" />
<Control Name="btn_next" Image="" Caption="Next >" 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
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 TableJoins (Join+) > |
BizView metadata DTD file.
<!--OpenBiz BizView metadata DTD--> |
BizForm metadata DTD file.
<!--OpenBiz BizForm metadata DTD--> <!ELEMENT DisplayModes (Mode+) > |
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 >
-
- Printer-friendly version
- Login to post comments








