Each class contains instance variables and instance methods. Some of these variables and methods are available for customization, some are internal to the classes themselves. All are documented, but tampering with internal variables and methods is not supported. Internal interfaces are subject to change without notice from one version of the library to another.
DB_Sql
is used by Session
and Auth
to access a
SQL database. You are encouraged to use it directly, too.
Host |
Parameter to mysql_pconnect . |
Database |
Parameter to mysql_pconnect . |
User |
Parameter to mysql_pconnect . |
Password |
Parameter to mysql_pconnect . |
Record | Hash of the current table result row. |
Row | Number of the current result row starting at 0. |
Errno | Integer: error number of last database operation. |
Error | String: error message of last database operation. |
Link_ID | SQL Link ID. |
Query_ID | SQL Result ID. |
query_string
is a SQL statement that is sent to the database.
After sending the statement, Error
and Errno
are updated.
If the query is syntactically incorrect (no valid result id is
being produced), halt()
is called with a meaningful error
message.
If there is no active link to the database, a pconnect()
is
made using the information from the Host
, Database
,
User
and Password
instance variables.
Returns the result of the query()
statement, which is
guaranteed to be a valid result id.
next_record()
advances the cursor through the
current query result and updates the Record
, Row
,
Errno
and Error
instance variables.
Returns true, if there is a new result record. Returns false, if
done with the current results. free_result()
is called
automatically before false is returned.
Positions the Row
pointer within the result set. Useful for
reading the same result set twice or otherwise jumping around
within the result. $pos
is not checked in any way for
validity.
$table
is a SQL table name in the current database. The
function returns a hash indexed by table
(table of which
this column is part of), name
(name of this column),
type
(column data type), len
(column width) and
flags
(database specific column flags, if applicable)
with one row per table column. Each row describes a column
in your table.
NOTE: At the moment, the Postgres and ODBC interface only report
the table
, name
and type
data reliably. You are
encouraged to fix this.
Returns the number of rows returned by the current SELECT query.
Returns the number of rows affected by the current INSERT, UPDATE or DELETE query.
Returns the number of columns returned by the current query.
Prints the number of rows returned by the current query.
Identical to accessing Record[$field]
.
Identical to printing Record[$field].
Used by query()
if the initial database connection cannot
be made or the target database does not exist. Prints an
error message, then halts Script execution.
Use a subclass to provide the appropriate parameters for a
database connect. You may overwrite halt()
to customize the
error message, although a sensible default is provided.
class DB_Article extends DB_Sql {
var $classname = "DB_Article";
var $Host = "sales.doma.in";
var $Database = "shop_project";
var $User = "webuser";
var $Password = "";
function halt($msg) {
printf("</td></table><b>Database error:</b> %s<br>\n", $msg);
printf("<b>MySQL Error</b>: %s (%s)<br>\n",
$this->Errno, $this->Error);
printf("Please contact shopmaster@doma.in and report the ");
printf("exact error message.<br>\n");
die("Session halted.");
}
}
Use an instance of the subclass to manage your queries:
$q = new DB_Article;
$query = sprintf("select * from articles where article like '%%%s%%'",
$searchword);
$q->query($query);
while($q->next_record()) {
printf("<tr><td>%s</td><td>%s</td></tr>\n",
$q->Record["art_id"],
$q->Record["article"]);
}
Page Management currently consists a collection of functions:
This function is to be called with an array of page features/classname pairs. Valid features are at the moment:
This page makes use of session variables.
This page uses session authentication. If you
specify the auth
feature, you MUST specify
the sess
feature, also.
This page is protected by permissions and only
accessible to authenticated users with matching rights.
If you specify the perm
feature, you MUST specify
the auth
and sess
features, also.
This page makes use of user variables. If you specify
the user
feature, you MUST specify the auth
and
sess
features, also.
This page uses a shopping cart. If you specify the
cart
feature, you MUST specify the sess
feature,
also.
Each feature specifies the name of the class that implements that feature, for example
page_open(array("sess" => "Shop_Session", "cart" => "Shop_Cart"));
The function creates an instance of Shop_Session
as
$sess
and of Shop_Cart
as $cart
and
initializes them. It also checks feature dependencies. Note that
you are expected to provide implementations of the classes
Shop_Session
and Shop_Cart
. This is
usually done in local.inc
and usually you do so by
extending the provided Session
and Cart
classes.
Examples on how to do this is given in the documentation below when the classes are introduced.
At the end of your page (after all results have been calculated)
you have to call page_close()
. This will save all
page state, session and user variables into database. Changes to
session or user variables after page_close()
has
been called are not recorded. Currently it is allowed to call
page_close()
multiple times on a single page (not
guranteed for future versions!). Each time session state will be
saved.
Advanced feature. Some applications have need to manually load data belonging to one or multiple session classes. @@TODO
Advanced feature. @@TODO
<?pgp
page_open(array("sess" => "Shop_Session"));
$sess->register("s"); // See "Session" below for explaination.
?>
<html>
<h1><?php print ++$s ?></h1>
</html>
<?php page_close(); ?>
The session class keeps a list of global variable names and provides a set of functions to load and save these variables from and to a database. The named variables may be scalar variables (strings, integers and floats) or arrays. Objects are handled as well, provided they implement two instance variables naming their class and enumerating their (persistent) slots.
classname | Serialization helper: The name of this class. |
mode |
Mode of Session ID propagation. Either cookie or get . |
fallback_mode |
Mode of Session ID propagation should $mode not work. Set $mode to cookie and $fallback_mode to get . |
lifetime | Lifetime of the session cookie in minutes or 0 to use session cookies. |
gc_time | Garbage collection tuning parameter, see below. |
gc_probability | Garbage collection tuning parameter, see below. |
database_class | A classname. Session uses this class to make its database connection. |
database_table | Database table used to keep the session variables. |
pt | Internal array of names of persistent variables. |
name | A tag (name) for the session type. |
id | Id of the current session. |
db | Database connection object instance. |
Registers a global variable name as a session variable. The name may identify a scalar variable, an array or an object. If an object is to be made persistent, it must have two instance variables:
A string with the name of the objects class.
An array with the names of all object slots to save.
Unregisters a global variable name as a session variable. The variable is not deleted, but its value will be lost at the end of a page. It is no longer saved to the database.
Return an URL referencing the current session. If in get
mode, the current session id is attached to this URL, else the
URL is returned unmodified.
A shorthand for print $this->url($url);
Return an URL referencing the current page, including
PHP_SELF
and QUERY_STRING
information.
If in get
mode, the session id is included.
A shorthand for print $this->self_url()
.
When a FORM
variable is made persistent, that form variable is
imported into PHP, then page_open() is being called and
the new variable value is overwritten from the database. The
FORM
value is lost.
If you had enabled track_vars
and were accessing
HTTP_GET_VARS
directly, which is recommended,
this were not a problem. Some legacy scripts rely on persistent
FORM
input variables, though.
These scripts may call the appropriate
reimport
_x_vars()
functions. These
functions will re-read the tracked variable arrays and
reinitialize the appropriate global variables after session
variables have been restored.
Use of this function is discouraged.
See reimport_get_vars()
.
See reimport_get_vars()
.
See get_id()
.
get_id() is used internally to determine a session identifier. Currently, a session identifier is a hex number of 32 characters (128 bits) and it is generated by md5(uniqid("")) to make it hard to guess.
get_id() may be called with an optional session id to use as a parameter. This is useful if you want to change a session id without breaking the session (taking over an old, left over session).
get_id() can be overwritten by a subclass, if you want a different system to create session ids. For example, some applications want to use a constant session id that is not propagated to the client to use a shared pool of persistent variables (a guestbook for example). These applications need locking (to be implemented soon).
put_id() is used internally to "unuse" a session it. At the moment it deletes the client side cookie.
serialize() is used internally to append to str all PHP code needed to reconstruct the variable named in prefix.
freeze() serializes all register()ed variables and writes the resulting code into the database, tagged with the current session id and the current session name.
thaw() loads a set of freeze()ed variables for the current session id and session name out of the database and recreates them.
The active_sessions
table contains one row for
each session. That row is uniquely identified by the sid
and name
values (name
is the name of the session
class that has written the row). Each time that row is written,
the column changed
is updated with the current time.
The gc() function deletes all rows that are older than
gc_time
minutes and have a matching name
field. For speed reasons, gc() is not not called every time
an update to active_sessions
is being made.
Instead it is called randomly with a probability of
gc_probability
.
Used to implement the three official reimport functions.
Initialization function, to be called after object instantiation. Calls get_id() to get the current session id, creates a database connection, then calls thaw() to load all session variables. Randomly activates gc().
Use a subclass to provide the appropriate parameters to your session. Usually your subclass looks like this:
class My_Session extends Session {
var $classname = "My_Session"; ## Persistence support
var $mode = "cookie";
var $lifetime = 0; ## use session cookies
## DB_Sql subclass and database table to use
var $database_class = "DB_Session";
var $database_table = "active_sessions";
}
Remember that you have to provide a DB_Sql
subclass with the
parameters needed to access your database.
Use the page management functions (see above) to use your
session subclass. The feature name for session management is
sess
; provide the name of your session subclass as a parameter
to the sess feature:
page_open(array("sess" => "My_Session"));
Use the register()
instance method to register variables as
persistent. If $sess
is your session object, use
$sess->register("s");
to make the global variable $s
persistent. $s
may be a
scalar value, an array or an object with persistence support
slots.
Do not use the instance methods freeze()
and thaw()
directly, but use the page management functions instead.
Authentication management can be used to authenticate a session, that is, to identify the user at the client side of the session.
Authentication is done inline, with HTML forms, not with HTTP authentication (that's the browser popups you get when you hit a .htaccess protected page). Inline authentication has several advantages over HTTP authentication:
classname | Serialization helper: The name of this class. |
persistent_slots | Serialization helper: The names of all persistent slots. |
lifetime | Maximum allowed idle time before the authentication expires. |
mode |
Authentication mode: log or reg (see below). |
database_class | A classname. Auth uses this class to make a database connection. |
database_table | Database table used to keep the session variables. |
magic | An arbitrary value used in uniqid generation. |
db | Internal: The database connection object instance. |
auth | Internal: User authentication information, see below. |
A function that can be used in auth_loginform()
a and
auth_registerform
. It returns the appropriate "action="
attribute to the form tag.
A function that can be used in auth_loginform()
a and
auth_registerform
. It prints the appropriate "action="
attribute to the form tag.
This function must be overridden by a subclass to Auth. It
should output HTML that creates a login screen for the user.
We recommend that you use an include()
statement to include
your HTML file.
This function is called when the user submits the login form
created by auth_loginform()
. It must validate the user input.
If the user authenticated successfully, it must set up
several fields within the $auth[]
instance variable:
must contain the user id associated with that user.
must contain the user name as entered by the user.
must not be tampered with (field is maintained by
start()
, contains the time when the login expires).
if you want to use the permission feature, you must store the permissions of the validated user here.
See the example below for more information.
See auth_doregister().
These functions mirror auth_loginform()
and
auth_validatelogin()
in registration mode.
Initialization function, does the authentication. If we are
in log
(login) mode, auth_loginform()
is
called to draw a login screen. When the login screen is
submitted back, auth_validatelogin()
is called to
validate the login. If the validation was successful, the
actual page content is shown, otherwise we're back at
auth_loginform()
.
In reg
mode, auth_registerform()
is called to draw a
registration form. When the registration form is submitted
back, auth_doregister()
is called to register the user and
to validate the session. If registration was successful, the
actual page content is shown, otherwise we're back at
auth_registerform()
.
Use a subclass of Auth
to provide parameters for your
authentication class and to implement your own auth_*
functions.
class My_Auth extends Auth {
var $classname = "My_Auth"; # Object serialization support
var $persistent_slots = "auth";
## DB_Sql subclass and database table to use
var $database_class = "DB_Session";
var $database_table = "active_sessions";
## Some magic value to make our uids harder to guess.
var $magic = "Abracadabra";
function auth_loginform() {
global $sess;
include("loginform.ihtml");
}
function auth_validatelogin() {
global $username, $password; ## form variables from loginform.html
## If authentication fails, loginform.html will
## find $this->auth["uname"] set and use it.
$this->auth["uname"]=$username;
## Value to return in case auth fails.
$uid = false;
## Check the database for this user and password pair.
$query = sprintf("select * from %s where username = '%s' and password = '%s'",
$this->database_table, $username, $password);
$this->db->query($query);
## If we found a matching user, grab the uid and permissions...
while($this->db->next_record()) {
## Required.
$uid = $this->db->Record["uid"];
## Optional, for the perm feature.
$this->auth["perm"] = $this->db->Record["perm"];
}
return $uid;
}
}
Your loginform.ihtml
contains HTML and PHP code to draw a login
form. $this->auth["uname"]
will be empty on the first login
attempt and set on all further login attempts. You can use this
to detect repeated login attempts and display an appropriate
error message. You must print the result of $this->url()
to
create your forms action attribute.
See the provided loginform.ihtml
for an example.
Use the page management functions (see above) to use your
authentication subclass. The feature name for authentication
management is auth
; provide the name of your Auth
subclass as
a parameter to the auth
feature. The auth
feature requires the
sess
feature:
page_open(array("sess" => "My_Session", "auth" => "My_Auth"));
Permission management relies on an authenticated session. It associates a set of required permissions with a page. The actual page content is only visible to users with ALL matching permissions; all other users are shown a screen of your design.
classname | Serialization helper: The name of this class. |
permissions | A hash of (name, permission bit) pairs. |
Checks that the currently authenticated user has all the
rights that are specified in required
. If not,
perm_invalid()
is called.
If one or more of the required rights or user rights are
invalid (not to be found in the permissions hash),
perm_invalid()
is called as well.
Similar to check()
in usage, only that it doesn't halt the
session if the user doesn't have the appropriate rights: This
function returns true, if the user has the required rights,
false otherwise.
Logically or's all the rights and returns a pair (valid,
or_result)
. If valid is true, an or_result
is provided. If valid is false, the or_result
is
undefined and one or more of the rights do not exist at all.
This is a severe error and the application should be halted at
once.
Called in case of an access violation. does_have
is a string
listing the rights the user actually has. must_have
are the
rights the page requires.
Use a subclass of Perm
to provide parameters for your
permission class and to implement your own perm_invalid
function.
class My_Perm extends Perm {
var $classname = "My_Perm";
var $permissions = array (
"user" => 1,
"author" => 2,
"editor" => 4,
"moderator" => 8,
"admin" => 16
);
function perm_invalid($does_have, $must_have) {
global $perm, $auth, $sess;
include("perminvalid.ihtml");
}
}
Use the page management functions (see above) to use your
permission subclass. The feature name for permission
management is perm
; provide the name of your Perm
subclass as
a parameter to the perm
feature. The perm
feature requires the
sess
feature and the auth
feature:
page_open(array("sess" => "My_Session", "auth" => "My_Auth", "perm" => "My_Perm"));
Use the check()
instance method to protect your page:
$perm->check("admin"); ## This page is for users with admin rights only.
The user class is an extension (a subclass) of the Session class. It keeps a list of global variable names and provides a set of functions to load and save these variables from and to a database. The same restrictions as for session variables apply to user variables.
Unlike session variables, user variables are not lost when the user stops and restarts the browser or moves to a different workplace (the session id is then lost and consequently all session variables are lost, since they are bound to the session id).
User variables require instead that the user logs in. A user id becomes then available and the User class binds variables to this user id. A user id is only present for logged in (authenticated) users. Thus, User is dependent on Auth.
The User class is an extension of the Session class. It has all instance variables and instance methods of Session, only that some are implemented different. This documentation only describes these differences.
Note that Session and User can successfully share an
active_sessions
table in a database due to the
different values in the name
column.
mode | Not meaningful for User. |
fallback_mode | Not meaningful for User. |
lifetime | Not meaningful for User; see authentication lifetime in Auth instead.. |
gc_time | Functional, but probably not useful in User. |
gc_probability | Functional, but should be set to 0 in User. |
database_class | A classname. User uses this class to make its database connection. |
database_table | Database table used to keep the user variables. |
pt | Internal array of names of persistent variables. |
name | A tag (name) for the session type. |
id | Id of the current session. |
db | Database connection object instance. |
Works as exspected.
Works as exspected.
Not useful with User.
Not useful with User.
Not useful with User.
Not useful with User.
Works as exspected.
Works as exspected.
Works as exspected.
This is only a stub implementation that depends on
the user id provided by the page management functions.
The page management functions will use
$auth->auth["uid"]
, which is set up by Auth
.
Empty. Not useful with User.
Works as exspected.
Works as exspected.
Works as exspected.
Works as exspected. You do not want to use it, though.
Works as exspected.
Initialization function, to be called after object instantiation. Calls get_id() to get the current session id, creates a database connection, then calls thaw() to load all session variables. NOTE: gc() activation is commented out! Remove the comments if you really want gc with User variables.
Use a subclass to provide the appropriate parameters to your user variables. Usually your subclass looks like this:
class My_User extends User {
var $classname = "My_User"; ## Persistence support
## DB_Sql subclass and database table to use
var $database_class = "DB_Session";
## We share this table with My_Session - not a problem.
var $database_table = "active_sessions";
}
Remember that you have to provide a DB_Sql
subclass with the
parameters needed to access your database.
Use the page management functions (see above) to use your
User subclass. The feature name for user variables is
user
; provide the name of your User subclass as a parameter
to the user feature:
page_open(array("sess" => "My_Session", "auth" => "My_Auth", "user" => "My_User"));
Use the register()
instance method to register variables as
persistent. If $user
is your user object, use
$user->register("u");
to make the global variable $u
persistent. $u
may be a
scalar value, an array or an object with persistence support
slots.
Do not use the instance methods freeze()
and thaw()
directly, but use the page management functions instead.
The Cart class is programmatically independent, but makes sense only if its instances are made persistent in some way. The Cart class automatically registers itself as a session variable.
Cart implements a shopping cart. At the moment, items within the shopping cart are independent of each other; the cart can only hold simple things. Support for compound articles that require other articles to function and provide a base for dependent articles is to be added at a future time.
An example of a simple article is any article with no options, for example an apple or a book. Common examples for compound articles are a pizza (which requires a foundation in either american or italian style, a selection of toppings, and cheese, to function correctly) and a computer system (which requires a housing, a motherboard, RAM, a video card, etc to function correctly).
classname | Serialization helper: The name of this class. |
persistent_slots | Serialization helper: The names of all persistent slots. |
item | Multidimensional array of items in the cart. |
currentItem | A counter for item positions. |
Checks that an item with the given article number $art
is
in the cart. Returns an array of a boolean value and an integer
number. If the boolean is true, there are number many articles
of that article number in the cart.
Add $num
many articles of article number $art
to the current
shopping cart. Returns the position number of $art
in the
shopping cart.
Remove $num
many articles of article number $art
from the
shopping cart, if there are at least that many articles in the
cart. Returns the position number of $art
in the shopping cart
or false, if there weren't enough $art
to remove them from the
cart. If the function does return false, the cart has not been
modified.
Calls show_item_open()
once at the beginning of a shopping
cart listing. Then calls show_item()
once for each item in
the shopping cart. Calls show_item_close()
once at the end
of a shopping cart listing.
This function should be provided by the user. It renders the
HTML to display a single item from the cart. $art
is the
article number of the item and there are $num
of these in
the cart.
This function should be provided by the user. It renders the prologue HTML to display a shopping cart listing.
This function should be provided by the user. It renders the epilogue HTML to display a shopping cart listing.
Use a subclass of Cart
to provide an implementation of
show_item()
.
class My_Cart extends Cart {
var $classname = "My_Cart";
// Look up article numbers...
var $database_class = "DB_Article";
var $database_table = "articles";
var $db;
var $sum = 0;
function show_cart_open() {
printf("<table class=cart_table>\n");
$this->sum = 0;
}
function show_cart_close() {
printf("</table>\n");
printf("That's a total of %s.\n", $this->sum);
}
function show_item($art, $num) {
if (!isset($this->db)) {
$class = $this->database_class;
$this->db = new $class;
}
$query = sprintf("select * from %s where artid = '%s'",
$this->database-table,
$art);
$this->db->query($query);
while($this->db->next_record()) {
printf(" <tr class=cart_row>\n <td class=cart_cell>%s</td>\n",
$this->db->Record["name"]);
printf(" <td class=cart_cell>%s</td>\n",
$this->db->Record["price"]);
printf(" <td class=cart_cell>%s</td>\n",
$num);
$rowsum = $num * $this->db->Record["price"];
$this->sum += $rowsum;
printf(" <td class=cart_cell>%s</td>\n",
$rowsum);
printf(" </tr>\n");
}
}
}
Use the page management functions (see above) to use your Cart
subclass. The feature name for the shopping cart feature is
cart
; provide the name of your Cart subclass as a parameter
to the cart
feature. The cart
feature requires the
sess
feature, because it registers itself as a session
variable.
page_open(array("sess" => "My_Session", "cart" => "My_Cart"));
Use add_item()
and remove_item
to work with your Cart:
$cart->add_item("101", 2); ## Add two pieces of "101"
$cart->remove_item("101", 1); ## Drop one piece of "101"
Use show_all()
to display the contents of your cart.
$cart->show_all(); ## What's in a cart, anyway?
The Table class is a neat way to format two-dimensional associative arrays of data or the results of a database query into a table. Table and its subclasses allow you to simply pass them either an array or a query result and they spit out the proper HTML for a table containing all the values. Table has some primitive filtering capabilities making it useful even without subclassing, but for the full power of Table you have to write your own subclass.
When used with the check option, it is assumed that the table
is part of a HTML FORM
element. Code is generated to create
an INPUT TYPE=CHECKBOX
element before each table row. The
checkboxes will form an array indexed by row number. The name of
the array will whatever you set the check
instance variable
to.
Exactly one of two types of possible column filtering take place
when each table row is generated. If the fields
instance
variable is set, only the columns keyed by the named fields in
that array are shown in that order. That is, if you fill in the
fields
instance variable with array("a", "c", "e")
,
only the columns a
, c
and e
become part of the
generated table.
If fields
has not been set, all data columns are traversed
with each()
and all columns whose names match the regexp in
filter
are shown in the table. By default, this regular
expression lets through all column names that start with an
alphabethic character and continue with either alphanumeric
characters or "_" (underscore). This default has been
chosen, because the DB_Sql database class uses
mysql_fetch_array()
internally to get data
from the database and this function returns all columns twice
with both a numeric index and proper column names. The default
filter will make all data show up only once and with proper
column names.
A subclass of Table, CSV_Table, is being provided to allow to
create CSV representations of your data with minimal effort. CSV
(comma separated values) can be imported by MySQLs LOAD DATA
INFILE
statement and many spreadsheet import functions.
classname | Serialization helper: The name of this class. |
check | If set, the check option is active. |
filter | A regular expression selecting the columns that are shown. |
fields | A list of colum names that are shown. |
heading | A flag; if set, a heading is being created. |
Will format and print the twodimensional array (or hash)
$ary
as a table according to the filtering rules explained
above. If $class
is set, each HTML element will be tagged
as belonging to the named class; this is useful with cascading
style sheets.
Will format and print the result set of $db
. $db
is
exspected to be a subclass of DB_Sql
that has just
been sent a query. Table
will grab all available results
from the result set of that query by calling
$db->next_record()
repeatedly and format them
into a table.
This function can be overridden by a subclass of Table. It
is called as the very first step in table creation and
should output HTML that opens a table (for example
printf("<table%s>\n", $class?" class=$class":"");
).
This function can be overridden by a subclass of Table. It
is called as the very last step in table creation and
should output HTML that closes a table (for example
printf("<
table>\n");/).
This function can be overridden by a subclass of Table. It
is called as the very first step in row creation and
should output HTML that opens a table row. It is also
responsible for the creation of headings in row 0 (must check
for $this->heading
being set).
$row
is the current row number. $data
is a hash of
column name/value pairs for that row and $class
is an
optional HTML CSS class name for all generated elements.
This function can be overridden by a subclass of Table. It is called as the very last step in row creation and should output HTML that closes a table row.
This function can be overridden by a subclass of Table. It is called each time a table cell is to be generated.
$row
is the current row number, $cell
is the
current cell number. $key
is the current column name,
$val
is the value of the cell. $class
is the
HTML CSS class of the element that is to be generated.
Table is not automatically included or prepended into each page. Include the table class into the pages that are to use Table. Then create an instance of Table:
<?php
// Include Table
require("table.inc");
// make a Table instance
$t = new Table;
// We want table headings to be printed.
$t->heading = "on";
Now create a twodimensional array or prepare a database query and have table print it.
// Create a database object
$db = new DB_Session;
// create a twodim array called $tab
$tab = $db->metadata("active_sessions");
// print that array
$t->show($tab, "metadata");
// prepare a database query
$db->query("select * from active_sessions");
// print that result
$t->show_result($db, "data");