Chapter 3

Preface

In this chapter, I will present how to:
We will create a table to hold car model information:
EXAMPLE: You can find fully working code for this task is contained in the EXAMPLE/admin/model where it is used to edit the model table.

Header file

Again, header file is the most interesting: Include definitions (here we show what really is in the example - including global definitions and including DBLIB classes from path set in a global variable):
<?
require('../../global.php');
require_once("$DBLIB_PATH/DBLMYSQLQuery.php");
require_once("$DBLIB_PATH/DBLView.php");
require_once("$DBLIB_PATH/DBLTextField.php");
require_once("$DBLIB_PATH/DBLJSLCField.php");
require_once("$DBLIB_PATH/DBLIntegerField.php");
require_once("$DBLIB_PATH/DBLLabelField.php");
Now we will instantiate the view:
     $view =& new DBLView("model");
Now we will define fields we use in the view. First will be the name field:
  // Name
$view->addField($name =& new DBLTextField("name","Name","",32,30));
$name->allowEmpty = false;
$name->dbName = "model.name";
$name->filterSize = 20;
The field may not be empty and will have only 20 characters in the filter. dbName is set to tableName.fieldName. It is necessary for the filter to work, since there will be actually two name columns in the select. See discussion in index.php for closer explanation.

Next we will define the brand field. User will select the brand from a list of defined brands. However, we suppose we will have many brands, so that selection using combo box would not be convenient. So we will use DBLJSLCField. It works much like the DBLLCField, but the value of the field is selected in another (popup) window, brought up by clicking on a button. As the name suggests, this field requires JavaScript to work. First we define query to get possible field values:
  $bq = new DBLMYSQLQuery($DBDEF,"brand");
$bq->setFields("id,name as text");
$bq->setOrder("text");
Query is the same as it was for DBLLCField. Now we define the field itself:
  $view->addField($brand =& new DBLJSLCField("brand","Brand","",30,"brands.php?",$bq));
$brand->allowEmpty = false;
$brand->referenceURL = "../brand/detail.php?id=";
The fourth parameter to the constructor is width of the readonly textbow, which shows selected value. Following is a path to script to do the selection. Here we say it is in the brands.php script. We have to put question mark at the end, so the field may add parameters (and not care whether there are some more or not, we could, e.g. use "brand.php?style=1&amp;" for the script).

Last parameter is the query which defines the values.

We want the field contents to be a hyperlink to brand detail. DBLIB allow this to be accomplished easy - we just set referenceURL to a script and the text will be hyperling to this URL. Record id will be appended after the URL. So the above example will work just fine.

Next we will define two fields to hold first and last year of the model:
  $view->addField($f =& new DBLIntegerField("firstYear","First year","",6,4,false));
$f->default = 1990;
$f->minVal = 1940;
$f->maxVal = 2100;

$view->addField($f =& new DBLIntegerField("lastYear","Last year","",6,4,false));
$f->default = 1990;
$f->minVal = 1940;
$f->maxVal = 2100;
There are several things worth noting. The DBLIntegerField (which is descentant of the DBLNumberField) is created almost same as a DBLTextField. There is only one extra parameter, called allowNegativeValues. We do not want negative values entered as the year :-)

Then we set several properties (for both fields) - default, minimum and maximum values accepted. Of course, minimum/maximum values will be checked on record entry. Default value will be pre-filled when user creates new record.

There's nothing much interesting below - we just define delete field, links, formats and query:
  // Setup links
$view->detailField = "name";
$view->deleteField = "delete";

// Define formats
$indexFormat = "name;brand;delete";
$detailFormat = "name;brand\nfirstYear;lastYear";
$editFormat = "name;brand\nfirstYear;lastYear";
$filterFormat = "name;brand\nfirstYear;lastYear\n_apply;_order;_clear";
$orderDef = array("name","brand");
$defaultOrder = "name";

// Create query
$q = new DBLMYSQLQuery($DBDEF,"model");
?>

Record index

Now we will look at the record index page (index.php).

Record index script is almost the same as for the previous examples. Except one thing. As you may have seen, we have not used indexDBConversion. So we must somehow get brand name to be in the result of the select. The column must be named as the field with the _txt appended. We will set source and fields:
  $q->setSource("model left join brand on brand.id=model.brand");
$q->setFields("model.*,brand.name as brand_txt");
This is how we will get the name in the list. There is one more thing that can make problems. If we try to filter by the name field, the SQL where clausule would be: "WHERE name='xxx'". But SQL engine would complain - there is a name field in both model and brand table so the where clausule is ambigous. Now back to the header. When we set:
  $name->dbName = "model.name"
all will be OK, since DBLIB will use "model.name" as field name in the where clausule and all will be clear.

NOTE: We COULD use indexDBConversion. But using this with DBLJSLCField has another disadvantage. Besides worse performance, it would not be possible to filter by such field. This is because this field is filtered similarly as a text field - by entering text pattern. To match the pattern, we must have the text in the SELECT.

The rest of the script is same as before - here is the complete script:
<?
require('header.php');
require('../../header.html');

$q->setSource("model left join brand on brand.id=model.brand");
$q->setFields("model.*,brand.name as brand_txt");

// Print filter
$view->filter($q,$filterFormat,$orderDef,$defaultOrder);

$view->index($q,$indexFormat);
?>
<P><A HREF="../">&lt;&lt; Menu</A>
</BODY>
</HTML>

Record detail

Record detail is same as before.

Record edit form

We have decided, that we will not allow "first year" to be greater than "last year" - such input does not make sense. So we have placed two checks in the edit form script:
<?
require('header.php');

// Javascript check
$view->userJSCheck = " if (document.editFrm.firstYear.value > document.editFrm.lastYear.value) {
alert('Last year should be greater than or equal to first year!');
return false;
}";

// Check year order
$err = array();
if (isset($_POST["firstYear"])) {
if (intval($_POST["firstYear"]) > intval($_POST["lastYear"])) $err[] = "Last year must be greater or equal to first year!";
}

$view->standardEdit($q,$editFormat,"../../header.html",$editFormat,$err);
?>
</BODY>
</HTML>
First, we setup javascript check - we set property of the view. Our javascript code will be executed after all the checks. When values are not correct, we will display error message and then return false (canceling submit of the form).

Then we check if the POST variable is set (means record was posted). When it was, we check the condition. If this fails, we add error message to the $err array. The array is passed to the standardEdit method. We use extended parameters - fourth parameter is format, which lists fields that are accepted. By default, this is the same as format of the form - you want these two to differ only in very special cases.

Last parameter is an array. It may contain error message(s). When there are some, the form is not accepted and error(s) are printed above it.

Brand selecting script

Brand selecting script is in the brands.php file. We will use the DBLJSExternalSelection class, which provides all we need. First, we have to include definitions:
<?
require('../../global.php');
require('../../header.html');
require("$DBLIB_PATH/DBLJSExternalSelector.php");
require("$DBLIB_PATH/DBLMYSQLQuery.php");
Next, we define query to list possible values:
  $q =& new DBLMYSQLQuery($DBDEF,"brand");
$q->setFields("id, name as text");
$q->setOrder("text");
Create selector and forbid empty value:
  $selector = new DBLJSExternalSelector($_GET["formName"],$_GET["name"],"Choose brand",$q);
$selector->allowEmpty = false;
The parameters are:
Finally we call method to show the selection form. The only parameter is id, which should by selected by default. DBLJSLCField passes it in the value GET parameter:
  $selector->show($_GET["value"]);
Then we just finish page:
?>
</BODY>
</HTML>

Deleting records

Situation here is similar as in the previous example - we have to add check to the brand delete script.

Finally

Check how everything works, mainly the checks (with and without javascript turned on). Also check the hyperlink to brand. Play with the brand selection - when you write someting to the text widget above, the list will show only choices starting with the text you wrote.

Also try following: Create a brand for testing. Select this brand in the record, but do not submit it. Meanwhile, delete the brand. Then try to submit the record. Guess, what will happen ;-)

<< Previous chapter
Chapter index
Next chapter >>