Chapter 1
Preface
In this chapter, you will be introduced to the simplest use of DBLIB.
Imagine we need to have a list of countries in the database. So we set
up a simple table which has only two columns. One is numeric primary
key (country ID), the other is a textual field (country name). We need
to provide user a way to edit this table. Since the table will have
only several entries, we will not make use of filtering.
EXAMPLE: You can find fully working code for this task is contained in
the example/cars/admin/country
directory, where it is used to edit the country table.
File layout
Now I will introduce you to the file layout my applications (and this
guide and DBLIB examples) use.
There are two styles of writing a web (PHP) application. The first one
is monolithic. It uses one or several scripts, which handle all the
functions. The function to do is passed to the script by a parameter.
I use another approach. (Almost) each function has its own file/script.
Moreover, there is a separate directory for each view. As you can see
in the example, the language
directory contains scripts, used to edit the language table.
The scripts I use in examples/guide are:
- header.php -
Included in all scripts. Includes all necessary classes, creates view
and query instances. It also defines formats, but that is mostly a
convenience to have all things defined on one place, you may define
them as well in the scripts.
- index.php -
Shows record index (i.e., list of the records)
- detail.php -
Shows record detail (i.e., show the record in "read only" mode)
- edit.php -
Shows record edit/new record form. Also processes posted values, and
when all values are OK, it modifies/creates the record and redirects to
record index.
- filter.php -
Processes posted filter values setting filter according to them. Then
redirects to record index.
- delete.php -
Deletes record
NOTE: Some scripts may be ommited in some directories (like detail.php and filter.php in this first
simple example).
Creating header file
First, we have to include DBLIB classes we will use. Here we suppose
the classes will be in the include path. The example mentioned above
uses another technique - DBLIB directory is stored in a global variable.
<?
require_once("DBLView.php");
require_once("DBLTextField.php");
require_once("DBLMYSQLQuery.php");
Please note, that we use require_once()
here. Because all DBLIB classes include their superclasses, it is
necessary to use require_once() to
prevent defining the same class more than once (which yields error).
Now we will instantiate the view:
$view =& new DBLView("country");
Please note the use of "=&". Simply said, this has better
performance than using only "=". For more information, please see php
reference manual.
We use only one argument here - a string. This string is a view name.
Why name views? Because of filters. If a filter is set on a view, DBLIB
stores the filter settings to a session variable. So when you come
again to the same view (i.e., view the same table), the filter you have
set before will still be used. To distinguish the filters, they are
stored under the view's name. So this is why the view has to have set
unique name. Beware! The record offset (current page in the record
index) is also considered a part of the filter and it is stored under
the view name.
$view->sortByColumnTitles = 0;
The above line disables sorting by clicking on column title, since we won't
support sorting in this simple example.
Now we will define fields we use in the view. There is one field - the
text to edit. The ID column is a primary key and it is not edited by
the user, so we do not need to add it here.
$name =& new DBLTextField("name","Name","",32,30);
$name->allowEmpty = false;
$view->addField($name);
First we create a text field. The first argument is field name. It
serves both as a name of the database field (column) and to reference
the field in calls to DBLIB (formats, filters, ... - see below). Then
we provide a textual title. It is a simple ASCII string. It is used in
error messages etc. The third argument is HTML title. It is used as a
column/field title in record index/detail/edit form. Usually, those two
are the same. So when HTML title is empty, DBLIB sets it to htmlspecialchars(<textual title>).
This feature is used in the above code.
Next two parameters are widget width (in characters) and maximum
characters that can be input into the field. I have found, that
it is best when the width is two characters more than maximum
characters, so there is enough place for the cursor and the field
contents are not scrolled.
On the second line we define that empty value is not allowed. Then we
add the field to the view. Please note, that the view does not copy the
field object, it only creates a reference to it. So even after you add
the field, you can make changes to it using the $name variable.
Now we need to establish link from the record index. Since there is
only one field, we will not use record detail, but the link will be
directly to record edit form. It can be accomplished very simply:
$view->editField = "name";
This will tell the view, that the field named name in the record index should be
link to the edit form. How view knows where is the edit form? The name
of the script is contained in the editURL property of the view,
which is set to point to the edit.php
script by default.
Next thing will be to define formats (format strings). Then need not to
be defined at all, they can be directly specified in the function
calls. But I found it useful to define formats in header.php - when you need to add
another field later, you have to edit only header.php. That is nice.
Here are the formats we will use:
$indexFormat = "name";
$editFormat = "name";
Since this is very simple example, I will not describe the formats
here. Please, see chapter 2 for more
explanation. For now, you can see that there is a field name present.
As the last thing in the header, we will create a query.
$q =& new DBLMYSQLQuery(new DBLDBDef("localhost","","","dblib_cars"),"country");
The first parameter of the query is database definition. The arguments
are:
- Host name
- User name
- Password
- Namespace (database name in this case)
The second parameter of the query is a source definition. It may be
join of tables or whatever, but here it is just a table name. In the
real world, I define database parameters (instantiate DBLDBDef class)
in the header and store it in a global variable, so the above call is
just:
$q =& new DBLMYSQLQuery($DBDEF,"country");
This allows easy change of the database location. You may even want to
create the query itself globally and only change its source. This eases
moving to another database engine (MySQL/Postgres). However, there are
several cases where you need to create another queries (lookup fields
discussed in further examples), so this is not a complete solution.
We are finished with definitions.
Creating record index
In this part, we will create a script that will print out record index.
At the beginning, you have to do three things:
- Start session (session_start()),
if you want to use filters/paging (this is usually required for
authentication too). This should be first, since starting a session may
send cookies.
- Include header.php
- Start HTML page (<HTML>, header, <BODY> ...)
I usually construct header.phpso
that it itself includes global definitions.
Since we want the records to appear in some order, we will set it now:
$q->setOrder("name");
And finally, we will print the record index:
$view->index($q,$indexFormat);
That's all. Just two calls :-) Of course, now you need to somehow
generate page footer. Usually hyperlink somewhere "up in the
application" and HTML code end.
Creating edit form
Now we come to editing the form. Here we will create one script, which
will print edit form and also processed posted data (creating a new
record or modifying an existing one). This is useful in the case that
there is an error in the entered data. The error message can be printed
above the form and then the form with the entered data can be
displayed, so user is able to correct them immediatelly.
This script is also very simple. First we have to include view
definition:
<?
require('header.php');
Then we just call:
$view->standardEdit($q,$editFormat,$HTML_HEADER);
First two arguments are easy. They are a query and edit format
descrption.
The third argument is a path to a file (here it is shown as if it was
contained in a global variable). This file may be either HTML, or PHP.
Its purpose is to generate HTML page startup (<HTML>, header,
<BODY> ...). The edit.php
script may not include this directly. It is because after an edit form
is posted, two cases make take place:
- Entered data are OK, the browser gets redirected to a record index
- There is something wrong, user gets error message and a form
In the first case, HTML page must not be started for the redirect to
proceed. However, in the second case, the page must be started. To
accomplish this, the method is given path to a header file. If it is to
output something, it includes (by the PHP includefunction) the given header
file. That's it.
Finally, we have to somehow finish the page, for example by:
?>
</BODY>
</HTML>
Deleting records
We also need to provide a way to delete a record. Default references
will lead to a delete.php script. You can do it like this:
<?
require('header.php');
Include a header.
$q->addCondition("id","=",intval($_GET["id"]));
Setup filter/condition on the query so that only the record with the ID
passed as a parameter is used. (NOTE: You need not to do intval() here,
since the query class will escape the values correctly. But I am used
to use it everywhere :-) It's safer. )
$q->deleteRecord();
Delete the record.
Header("Location: ./");
?>
Redirect to a record index.
NOTE: Actual delete.php in the example directory does also
check for existance of the master record. This is discussed in the next
chapter.
Finally
Now you may try to point your browser to the example and look, how the
code works. Also try to create a record with an empty name. First, try
it with javascript turned on in your browser, then turn it off and try
again. You will see, how the automatic consistency control in DBLIB
works.
Also try creating more records (>30) to see how automatic record
index paging works.