Concept

Exciting new model architecture

AX Framework brings along some very exciting new concepts, that might change the way you think web application development forever.

With AX Framework you no longer think of your application in endless complex-logic view layouts, but in seperate layers of object representation, that will make your source code lean, clean, compact, efficient and rock-solid.

 

Schematic overview

With all being windowed content, you will rethink intranet development. You will concept your project in dynamic, data-object related pages and multiforms.

Data Flow Overview

Here is how unaltered page calls are handled with ax:
  1. A Page is requested by the client; either the user has clicked a) on a link on another page, b) on a link on his desktop, or c) he chose an entry point from the the menusystem. In most cases, this call typically comes with an id, that refers to the specified dataset - the so-called DataOjbect-Id - which is the primary id of the primary data table.
  2. The rendered HTML content of the page is shown within the newly created ProcessLayer (=UI-window) In most common cases this ProcessLayer will just hold a placeholder for an MultiForm, which will be initialized by ProcessLayer's JavaScript now.
  3. The MultiForm (client) gets initialized and asks the DataProcessor (server) for wanted layout and data.
  4. The DataProcessor (server) instanciates the necessary DataObject(s) and replies with form layout (XML) and the dataset in JSON format.
  5. The form can now be presented to user

 

 

Module/Project structure

Here's a very run down example how a project (here: a simple carsharing module) could be built up within ax: Please keep in mind ax actually built for high comlex projects more than simple three table layouts.

Example

Let's imagine we have a bunch of cars at our disposal, which are being rented out to people we know.
We would like to keep track of information about: Cars, Persons and Bookings.

Tables

For this we will initialize three tables. Let's use "Demo Carpool" as our project/module name.

  • democarpool_cars
  • democarpool_persons
  • democarpool_bookings
table democarpool_car
table democarpool_persons
table democarpool_bookings

Pages

  • Cars
    let's create a page like this to edit our car data and keep track of bookings
  • Persons
    let's create a page like this to edit the persons
table democarpool_bookings
table democarpool_bookings

Forms

for these pages we will lay out two forms:

  • Cars
  • Persons

AX Entities

So for our project we will need the following entities:

  • Carpool
    • do
      • Car.php
      • Person.php
      • Booking.php
    • dp
      • Cars.php
      • Person.php
    • forms
      • Cars.xml
      • Person.xml
    • pages
      • Cars.php
      • Person.php
    • sopts
      • Person.php

								<?php

	class Car extends AX_DataObject {
		
		public function create() {
			$this->data = $this->db->getObjectByTablename("democarpool_cars");
		}
		
		public function load() {
			$this->data = $this->db->fetchRowBySQL("SELECT * FROM democarpool_cars WHERE id = $this->id");
		}
		
		public function nestBookings() {
			$this->data->Bookings = $this->extendBySQL("SELECT id FROM democarpool_bookings WHERE Car = " . $this->id, "Booking");
			foreach($this->data->Bookings as $myBooking) {
				$myBooking->load();
				$myBooking->nestPerson();
				$myBooking->prepare();
			}
		}
		
		public function prepare() {
			$this->data->_Cartype = $this->data->Cartype;
			$this->data->_Info = $this->data->Info;
			
			$this->data->_text = $this->data->Cartype;
			$this->data->_html = $this->data->_text;
		}
		
		public function save() {
			if(isset($this->data->Bookings)) {
				$this->stdSaveChilds((object) array( 
						"table" => "democontractor_bookings",
						"data" => $this->data->Bookings,
						"childDO" => "Booking",
						"childCond" => (object) array(
							"Car" => $this->id
						),
						"prepareRows" => function($myDataRow,$mainId) {
							$myDataRow->Car = $mainId;
							return $myDataRow;
						}
				));
			}
			$this->stdSaveMain((object) array (
					"table" => "democarpool_cars"
			));
		}
		
		public function delete() {
			; // currently no delete of cars permitted
		}
		
		public function findByText($searchVal) {
			$sql = "SELECT id FROM democarpool_cars WHERE (Cartype LIKE '$searchVal%' OR License LIKE '$searchVal%')";
			return $this->db->fetchColBySQL($sql);
		}
		
		
	}
							

								<?php

	class Person extends AX_DataObject {
		
		public function create() {
			$this->data = $this->db->getObjectByTablename("democarpool_persons");
		}
		
		public function load() {
			$this->data = $this->db->fetchRowBySQL("SELECT * FROM democarpool_persons WHERE id = $this->id");
		}
		
		public function nestBookings() {
			$this->data->Bookings = $this->extendBySQL("SELECT id FROM democarpool_bookings WHERE Person = " . $this->id, "Booking");
			foreach($this->data->Bookings as $myBooking) {
				$myBooking->load();
				$myBooking->nestCar();
				$myBooking->prepare();
			}
		}
		
		public function prepare() {
			$this->data->_Name = $this->data->Name;
			$this->data->_LastBooking = '';
			
			$this->data->_text = $this->data->Name;
			$this->data->_html = $this->data->_text;
		}
		
		public function save() {
			$this->stdSaveMain((object) array (
					"table" => "democarpool_persons"
			));
		}
		
		public function delete() {
			$Bookings = $this->db->fetchRowsBySQL("SELECT * FROM carsharing_bookings WHERE Person = " . $this->id);
			if(count($Bookings)>0) {
				$this->addError("Person " . $this->data->_text . " is linked in Bookings and can therefore not be deleted");
				return false;
			}
			$this->db->performSQLString("DELETE FROM democarpool_persons WHERE id = " . $this->id);
		}
		
		public function findByText($searchVal) {
			$sql = "SELECT id FROM democarpool_persons WHERE (Name LIKE '$searchVal%' OR Info LIKE '$searchVal%')";
			return $this->db->fetchColBySQL($sql);
		}
		
		
	}
							

								<?php

	class Booking extends AX_DataObject {
		
		public function create() {
			$this->data = $this->db->getObjectByTablename("democarpool_bookings");
		}
		
		public function load() {
			$this->data = $this->db->fetchRowBySQL("SELECT * FROM democarpool_bookings WHERE id = $this->id");
		}
		
		public function nestPerson() {
			$this->data->Person = new Person($this->data->Person);
			$this->data->Person->load();
			$this->data->Person->prepare();
		}
		
		public function nestCar() {
			$this->data->Car = new Car($this->data->Car);
			$this->data->Car->load();
			$this->data->Car->prepare();
		}
		
		public function prepare() {
			$this->data->_text = "";
			$this->data->_html = $this->data->_text;
		}
		
		public function save() {
			$this->stdSaveMain((object) array (
					"table" => "democarpool_bookings"
			));
		}
		
		public function delete() {
			$this->db->performSQLString("DELETE FROM democarpool_bookings WHERE id = " . $this->id);
		}
		
		public function findByText($searchVal) {
			;
		}
		
		
	}
							

								<?php

	require_once "../../../core/php/headers/dp.php";
	
	if($action=="getForm") {
		if(hasRole("user")) {
			$myFormProcessor = new AX_FormProcessor();
			$myFormProcessor->loadForm('../forms/Car.xml');
			$myFormProcessor->renderAsXML();
		}
		else {
			exitJSONError("Missing rights");
		}
	}

	if($action=="getData") {
		if(hasRole("user")) {
			$myCar = new Car($data->id);
			if($myCar->probeUTS($plUID,$plProps)) {
				;
			}
			else {
				$myCar->load();
				$myCar->nestBookings();
				$myCar->prepare();
				$myCar->addLock();
			}
			$myCar->renderAsJSON();
		}
		else {
			exitJSONError("Missing rights");
		}
	}

	if($action=="saveData") {
		if(hasRole("user")) {
			$myCar = new Car($data->id);
			$myCar->probeUTS($plUID,$plProps);
			$myCar->overwriteWithData($data);
			if($myCar->isValid()) {
				$myCar->save();
				$myCar->discardUTS();
			}
			$myCar->renderErrorStackAsJSON();
		}
		else {
			exitJSONError("Missing rights");
		}
	}

	
	if($action=="showLog") {
		if(hasRole("user")) {
			$myCompany = new Car($data->id);
			$myCompany->renderLogAsJSON();
		}
		else {
			exitJSONError("Missing rights");
		}
	}							

								<?php

	require_once "../../../core/php/headers/dp.php";
	
	if($action=="getForm") {
		if(hasRole("user")) {
			$myFormProcessor = new AX_FormProcessor();
			$myFormProcessor->loadForm('../forms/Person.xml');
			$myFormProcessor->renderAsXML();
		}
		else {
			exitJSONError("Missing rights");
		}
	}

	if($action=="getData") {
		if(hasRole("user")) {
			$myPerson = new Person($data->id);
			if($myPerson->probeUTS($plUID,$plProps)) {
				;
			}
			else {
				$myPerson->load();
				$myPerson->nestBookings();
				$myPerson->prepare();
				$myPerson->addLock();
			}
			$myPerson->renderAsJSON();
		}
		else {
			exitJSONError("Missing rights");
		}
	}

	if($action=="saveData") {
		if(hasRole("user")) {
			$myPerson = new Person($data->id);
			$myPerson->probeUTS($plUID,$plProps);
			$myPerson->overwriteWithData($data);
			if($myPerson->isValid()) {
				$myPerson->save();
				$myPerson->discardUTS();
			}
			$myPerson->renderErrorStackAsJSON();
		}
		else {
			exitJSONError("Missing rights");
		}
	}

	
	if($action=="showLog") {
		if(hasRole("user")) {
			$myCompany = new Person($data->id);
			$myCompany->renderLogAsJSON();
		}
		else {
			exitJSONError("Missing rights");
		}
	}							

								<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workInProgress>
<MultiForm id="Car" label="Car">
	<Page id="Overview" label="Overview">
		<Input id="_Cartype" label="Cartype" type="text" width="100%" disabled="true" />
		<Input id="_Info" label="Info" type="textarea" width="100%" disabled="true" />
	</Page>
	<Page id="Basic data" label="Basic data">
		<Input id="Cartype" label="Cartype" type="text" width="100%" />
		<Input id="License" label="License" type="text" width="100%" />
	</Page>
	<Page id="Bookings" label="Bookings">
		<Grid id="Bookings" label="Bookings" type="text" width="100%" >
			<GridColumn id="Person" label="Person" type="single" />
			<GridColumn id="FromDate" label="FromDate" type="date" />
			<GridColumn id="FromTime" label="FromTime" type="time" />
			<GridColumn id="ToDate" label="ToDate" type="date" />
			<GridColumn id="ToTime" label="ToTime" type="time" />
			<GridColumn id="Info" label="Info" type="text" />
			<RowEditPage>
				<Select id="Person" label="Person" type="single" sopts="Person" width="50%" />
				<Input id="FromDate" label="From" type="date" width="30%" />
				<Input id="FromTime" label="Time" type="time" width="20%" />
				<br/>
				<Spacer width="50%" />
				<Input id="ToDate" label="To" type="date" width="30%" />
				<Input id="ToTime" label="Time" type="time" width="20%" />
				<br/>
				<Input id="Info" label="Info" type="textarea" width="100%" />
				<Spacer width="60%" />
				<Button id="_ButtonAccept" width="20%" action="this.parentObj.acceptRowEdit()" eval="'Accept'" />
				<Button id="_ButtonCancel" width="20%" action="this.parentObj.cancelRowEdit()" eval="'Cancel'" />
			</RowEditPage>
		</Grid>
	</Page>
	<Page id="Info" label="Info">
		<Input id="Info" label="Info" type="textarea" height="100%" />
	</Page>
</MultiForm>							

								<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workInProgress>
<MultiForm id="Person" label="Person">
	<Page id="Overview" label="Overview">
		<Input id="_Name" label="Name" type="text" width="100%" disabled="true" />
		<Input id="_LastBooking" label="Last Booking" type="textarea" width="100%" disabled="true" />
	</Page>
	<Page id="Basic data" label="Basic data">
		<Input id="Name" label="Name" type="text" width="100%" />
		<Input id="Address" label="Address" type="text" width="100%" />
		<Input id="Telephone" label="Telephone" type="text" width="100%" />
	</Page>
	<Page id="Bookings" label="Bookings">
		<Grid id="Bookings" label="Previous Bookings" type="text" width="100%" insert="false" edit="false" delete="false">
			<GridColumn id="Car" label="Car" type="single" />
			<GridColumn id="FromDate" label="FromDate" type="date" />
			<GridColumn id="FromTime" label="FromTime" type="time" />
			<GridColumn id="ToDate" label="ToDate" type="date" />
			<GridColumn id="ToTime" label="ToTime" type="time" />
			<GridColumn id="Info" label="Info" type="text" />
		</Grid>
	</Page>
	<Page id="Info" label="Info">
		<Input id="Info" label="Info" type="textarea" height="100%" />
	</Page>
</MultiForm>							

								<?php
	
	require_once "../../../core/php/headers/page.php";
	
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
    	<script>
    	
			$(document).ready(function () {
				
				var myCurrentPL = myAx.myProcessLayerHandler.getProcessLayerById(<?php echo $plUID; ?>);
				myCurrentPL.setStandardMultiFormButtons();
				myCurrentPL.updateButtons();
								
				myCurrentPL.myMultiForm = new AX_MultiForm({
					ctx: myCurrentPL.ctx.find('#myMultiForm'),
					dp: 'Car',
					data: <?php echo json_encode($data); ?>
				},myCurrentPL);
				
			});
			
        </script>
		<title>Car: </title>
	</head>
<body>
<div id="myMultiForm" class="MultiForm" style="height:100%;width:100%;background-color:#f8ffff;" />
</body>
</html>
							

								<?php
	
	require_once "../../../core/php/headers/page.php";
	
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
    	<script>
    	
			$(document).ready(function () {
				
				var myCurrentPL = myAx.myProcessLayerHandler.getProcessLayerById(<?php echo $plUID; ?>);
				myCurrentPL.setStandardMultiFormButtons();
				myCurrentPL.updateButtons();
								
				myCurrentPL.myMultiForm = new AX_MultiForm({
					ctx: myCurrentPL.ctx.find('#myMultiForm'),
					dp: 'Person',
					data: <?php echo json_encode($data); ?>
				},myCurrentPL);
				
			});
			
        </script>
		<title>Person: </title>
	</head>
<body>
<div id="myMultiForm" class="MultiForm" style="height:100%;width:100%;background-color:#f8ffff;" />
</body>
</html>
							

								<?php

	require_once "../../../core/php/headers/sopt.php";
	
	if(hasRole("user")) {
		$db = new AX_DB();
		$sql = "SELECT id,
					Name as _text,
					Name as _html
				FROM democarpool_persons";
		$result = $db->fetchRowsBySQL($sql);
		json_header();
		echo '{"results": ' . json_encode($result) . ', "more": false }';
	}
	else {
		exitJSONError("Missing rights");
	}
	
	

								

AX Entities (explained)

  • one project (module) folder carsharing/
    • one DataObject(s) folder do/ holding as many DataObject(s) as you want.
    • one DataProcessor folder dp/ holding as many DataProcessors as you want.
    • one axMultiForm folder forms/ holding as many form definitions as you want.
    • one Page folder pages/ holding as many pages as you want.
    • one sopts/ folder holding the bits of code necessary to display select options for Cars and Persons.