Xap requirements:
- PHP 5.5+
- PHP PDO database extension
- Database table names cannot include characters
.
,/
,:
or[
Install Xap options:
- Git clone:
git clone https://github.com/shayanderson/xap.git
- Subversion checkout URL:
https://github.com/shayanderson/xap/trunk
- Subversion checkout library files only:
https://github.com/shayanderson/xap/trunk/lib/Xap
- Subversion checkout library files only:
- Download ZIP file
Here is a list of Xap commands:
add
- insert record (can also useinsert
)call
- call stored procedure or function (andcall_affected
andcall_rows
)cache
- set single cache expire timeclose
- close the database connectioncolumns
- show table columnscommit
- commit transactioncount
- count table recordsdebug
- get debug info for connectionsdel
- delete record(s) (can also usedelete
)error
- check if error has occurrederror_last
- get last error, when error has occurredexists
- check if record existsid
- get last insert IDlimit
- global max limit for querieslog
- get debug log (debugging must be turned on)log_handler
- add log message to database log (debugging must be turned on)mod
- update record(s) (can also useupdate
)pagination
- get/set pagination paramsquery
- execute manual queryreplace
- replace recordrollback
- rollback transactiontables
- show database tablestransaction
- start transactiontruncate
- truncate table
Xap supports:
- Custom log handler
- Custom error handler
- Query options
- Multiple database connections
- Pagination
- Pagination Helper Class
- Data Modeling (ORM)
- Data Decorators
- Caching
Edit the xap.bootstrap.php
file and add your database connection params:
// register database connection
xap([
// database connection params
'host' => 'localhost',
'database' => 'test',
'user' => 'myuser',
'password' => 'mypass',
'errors' => true, // true: Exceptions, false: no Exceptions, use error methods
'debug' => true // turn logging on/off
]);
Next, include the bootstrap file in your project file:
require_once './xap.bootstrap.php';
Now execute SELECT query:
$user = xap('users WHERE id = ?', [14]); // same as "SELECT * FROM users WHERE id = '14'"
if($user) echo $user->fullname; // print record column value
Simple select queries examples:
$r = xap('users'); // SELECT * FROM users
$r = xap('users(fullname, email)'); // SELECT fullname, email FROM users
$r = xap('users LIMIT 1'); // SELECT * FROM users LIMIT 1
$r = xap('users WHERE is_active = 1'); // SELECT * FROM users WHERE is_active = 1
Select query with named parameters:
// SELECT fullname, email FROM users WHERE is_active = '1'
// AND fullname = 'Shay Anderson'
$r = xap('users(fullname, email) WHERE is_active = :active AND fullname = :name'
. ' LIMIT 2', ['active' => 1, 'name' => 'Shay Anderson']);
Select query with question mark parameters:
// SELECT fullname, email FROM users WHERE is_active = 1
// AND fullname = 'Shay Anderson' LIMIT 2
$r = xap('users(fullname, email) WHERE is_active = ? AND fullname = ? LIMIT 2',
[1, 'Shay Anderson']);
Select distinct example query:
$r = xap('users(fullname)/distinct'); // SELECT DISTINCT fullname FROM users
Simple insert example:
// INSERT INTO users (fullname, is_active, created)
// VALUES('Name Here', '1', NOW())
$affected_rows = xap('users:add', ['fullname' => 'Name Here', 'is_active' => 1,
'created' => ['NOW()']]);
// can also use action ':insert'
// xap('users:insert', ...);
The replace
command can also be used, for example:
// REPLACE INTO users (id, fullname, is_active, created)
// VALUES(5, 'Name Here', '1', NOW())
$affected_rows = xap('users:replace', ['id' => 5, 'fullname' => 'Name Here',
'is_active' => 1, 'created' => ['NOW()']]);
Insert query and get insert ID:
// INSERT INTO users (fullname, is_active, created) VALUES('Name Here', '1', NOW())
xap('users:add', ['fullname' => 'Name Here', 'is_active' => 1,
'created' => ['NOW()']]);
// get insert ID
$insert_id = xap(':id');
Insert ignore query example:
// INSERT IGNORE INTO users (user_id, fullname) VALUES('3', 'Name Here')
xap('users:add/ignore', ['user_id' => 3, 'fullname' => 'Name Here']);
Insert into table using object instead of array:
// note: all class public properties must be table column names
class User
{
public $user_id = 70;
public $fullname = 'Name';
public $created = ['NOW()'];
}
$affected_rows = xap('users:add', new User);
Simple update query example:
// UPDATE users SET fullname = 'Shay Anderson' WHERE user_id = '2'
$affected_rows = xap('users:mod WHERE user_id = :user_id',
['fullname' => 'Shay Anderson'], ['user_id' => 2]);
// can also use action ':update'
// xap('users:update', ...);
When using the
mod
(orupdate
) command all params must be named params like:my_param
and not question mark parameters
Update ignore query example:
// UPDATE IGNORE users SET user_id = '3' WHERE user_id = 6
$affected_rows = xap('users:mod/ignore WHERE user_id = 6', ['user_id' => 3]);
Delete query examples:
// delete all
$affected_rows = xap('users:del'); // DELETE FROM users
// can also use action ':delete'
// xap('users:delete', ...);
// DELETE FROM users WHERE is_active = 1
$affected_rows = xap('users:del WHERE is_active = 1');
// DELETE FROM users WHERE user_id = '29'
$affected_rows = xap('users:del WHERE user_id = ?', [29]);
Delete ignore query example:
// DELETE IGNORE FROM users WHERE user_id = 60
$affected_rows = xap('users:del/ignore WHERE user_id = 60');
Execute manual query example:
// execute any query using the 'query' command
$r = xap(':query SELECT * FROM users LIMIT 2');
// use params with manual query:
$r = xap(':query SELECT * FROM users WHERE user_id = ?', [2]);
The query command can use these query options: /query, /first, /value, /pagination, /cache. For example:
$query_string = $r = xap(':query/query SELECT * FROM users LIMIT 2');
Get back a count (integer) query example:
// returns int of all records
$count = xap('users:count'); // SELECT COUNT(1) FROM users
// SELECT COUNT(1) FROM users WHERE is_active = 1
$count = xap('users:count WHERE is_active = 1');
// SELECT COUNT(1) FROM users WHERE user_id > '2' AND is_active = '1'
$count = xap('users:count WHERE user_id > ? AND is_active = ?', [2, 1]);
Check if record(s) exists:
$has_records = xap('users:exists'); // check if records exists
if($has_records) // do something
// use query params example:
$is_record = xap('users:exists WHERE user_id = ? AND is_active = 1', [2])
if($is_record) // do something
A table can be truncated using:
xap('table_name:truncate');
Call SP/SF example:
xap(':call sp_name'); // CALL sp_name()
// Call SP/SF with params:
// CALL sp_addUser('Name Here', '1', NOW())
xap(':call sp_addUser', ['Name Here', 1, ['NOW()']]);
// Call SP/SF with params and out param
xap(':query SET @out = "";'); // set out param
// CALL sp_addUser('Name Here', '1', NOW(), @out)
xap(':call sp_addUserGetId', ['Name Here', 1, ['NOW()'], ['@out']]);
// get out param value
$r = xap(':query SELECT @out;');
The call
command will return a boolean
value. If a recordset array
or affected rows integer
is required instead use:
// get recordset:
$rows = xap(':call_rows sp_getActiveUsers'); // array
// or get affected rows count:
$affected = xap(':call_affected sp_updateUser'); // integer
Query options can be used with the
call
command like:xap(':call/query sp_name');
Transactions are easy, for example:
xap(':transaction'); // start transaction (autocommit off)
xap('users:add', ['fullname' => 'Name 1']);
xap('users:add', ['fullname' => 'Name 2']);
if(!xap(':error')) // no error
{
if(xap(':commit')) ... // no problem, commit + continue with logic
}
else // error
{
xap(':rollback'); // problem(s), rollback
// warn client
}
When errors are on, use try/catch block like:
try
{
xap(':transaction'); // start transaction (autocommit off)
xap('users:add', ['fullname' => 'Name 1']);
xap('users:add', ['fullname' => 'Name 2']);
if(xap(':commit')) ... // no problem, commit + continue with logic
}
catch(\Exception $ex)
{
xap(':rollback'); // problem(s), rollback
// warn client
}
Show database tables query example:
$tables = xap(':tables'); // returns array of tables
Show table columns query example:
$columns = xap('users:columns'); // returns array of table column names
A global max limit can be set to force max limits, for example:
// the query below may crash if too many records exist (exceeds memory limit)
$docs = xap('documents'); // SELECT * FROM documents
// this problem can be solved globally by using global limit
xap(':limit 50'); // now all select queries auto use limit
$docs = xap('documents'); // SELECT * FROM documents LIMIT 50
$users = xap('users'); // SELECT * FROM users LIMIT 50
// reset limit
xap(':limit'); // or xap(':limit 0')
$docs = xap('documents'); // SELECT * FROM documents
The global limit will not override a LIMIT clause already in a query.
Global limit will not work with other options like
/first
,/model
,/pagination
,/value
Get debug log array example:
$log = xap(':log'); // returns array of debug log messages
Debug mode must be enabled for this example
The default log handler retains the most recent five thousand log messages (memory safe). A custom log handler can except all log messages.
Check if error has occurred when errors are on (throws exceptions) example:
try
{
$user = xap('users.14'); // same as "SELECT * FROM users WHERE id = '14'"
if($user) echo $user->fullname; // print record field value
}
catch(\Exception $ex)
{
// warn here
echo 'Database error: ' . $ex->getMessage();
}
Or, if errors are off use error commands:
$user = xap('users.14'); // same as "SELECT * FROM users WHERE id = '14'"
if(!xap(':error'))
{
if($user) echo $user->fullname; // print record field value
}
else
{
echo xap(':error_last'); // print error
}
Get last error string example:
if(xap(':error'))
{
echo xap(':error_last');
}
For getting last error message errors must be disabled, otherwise exception is thrown
To display all registered connections, debug log and errors use:
print_r( xap(':debug') ); // returns array with debug info
A database connection can be closed using the close command:
xap(':close');
All database connections will automatically close, but the close command can be used explicitly when runtime between database calls exceeds the connection timeout - and can eliminate errors like
server has gone away
, for example:
xap(':call spProcessQueue'); // long runtime
xap(':close'); // close connection
// below query will automatically open new connection
xap('job_queue:count WHERE status = 0');
A custom log handler can be used when setting a database connection, for example:
// register database connection
xap([
// database connection params
'host' => 'localhost',
...
'debug' => true, // debugging must be enabled for log handler
// register custom log handler (must be callable)
'log_handler' => function($msg) { echo '<b>Message:</b> ' . $msg . '<br />'; }
Now all Xap log messages will be sent to the custom callable log handler.
If a custom log handler is used and the Xap log handler should be disabled the custom log handler callable must return
true
, for example:
...
'log_handler' => function($msg)
{
echo '<b>Message:</b> ' . $msg . '<br />';
return true; // flag as handled, do not pass message to Xap log handler
}
...
Now the default Xap log handler has been disabled.
The log_handler
command can be used to insert log message into the database (without logging the actual log message being sent to the database), for example:
...
// send all log messages to the `event_log` table columne `message`
'log_handler' => function($msg) { xap('event_log:log_handler', ['message' => $msg]); }
...
A custom error handler can be used when setting a database connection, for example:
// register database connection
xap([
// database connection params
'host' => 'localhost',
...
'errors' => true, // errors must be enabled for error handler
// register custom error handler (must be callable)
'error_handler' => function($err) { echo '<b>Error:</b> ' . $err . '<br />'; }
Now all Xap error messages will be sent to the custom callable error handler.
Query options are used like: table:command/[option]
and can be used with SELECT
commands and other commands.
Example of option use:
$r = xap('users(fullname)/distinct'); // DISTINCT option
Options can be chained together to complete valid MySQL statements:
// UPDATE LOW_PRIORITY IGNORE users SET fullname = 'Shay Anderson' WHERE user_id = '2'
$affected_rows = xap('users:mod/low_priority/ignore WHERE user_id = :user_id',
['fullname' => 'Shay Anderson'], ['user_id' => 2]);
The array
option can be used to force return type of arrays instead of objects when using objects in configuration settings:
$r = xap('users(fullname)/distinct/array LIMIT 5');
Now the $r
variable is an array with arrays instead of an array with objects.
The
array
option is helpful when using objects for connection in configuration settings but array return types are desired for a single or several select commands. This option is used withSELECT
commands only.
The query
option can be used to return the query string only, without executing the query (for debugging), for example:
// returns string 'SELECT DISTINCT fullname FROM users'
$r = xap('users(fullname)/distinct/query');
The following commands can use the
query
option:add
,call
,columns
,count
,del
,mod
,query
,replace
, andtables
The first
option can be used to return the first record only, for example:
$user = xap('users/first WHERE is_active = 1');
if($user) echo $user->fullname;
This can simplify using the first record only instead of having to use:
if(isset($user[0])) echo $user[0]->fullname;
The
first
option will auto limit the rows to 1, multiple rows are not allowed
The value
option is used to return the first value only (scalar), for example:
$fullname = xap('users(fullname)/value WHERE id = ?', [1]); // string
If multiple columns are in the query only the first column value is returned, example:
$email = xap(':query/value SELECT email, fullname FROM users WHERE id = ?', [1]); // string
The
value
option will auto limit the rows to 1, multiple rows are not allowed
Other options not mentioned here are: /cache
, /pagination
and /model
Using multiple database connections is easy, register database connections in bootstrap:
// connection 1 (default connection)
xap(['host' => 'host1.server.com',
// more here
]);
// connection 2
xap(['host' => 'host2.server.com',
// more here
]);
// or manually set connection ID
xap(['host' => 'host5.server.com',
// more here
'id' => 5 // manually set ID (int only)
]);
Note: manually set ID must be integer
Now to use different connections:
// select from connection 1 / default connection
$r = xap('users.2'); // SELECT * FROM users WHERE id = '2'
// select from connection 2, where '[n]' is connection ID
$r2 = xap('[2]users.2'); // SELECT * FROM users WHERE id = '2'
Pagination is easy to use for large select queries, here is an example:
// set current page number, for this example use GET parameter 'pg'
$pg = isset($_GET['pg']) ? (int)$_GET['pg'] : 1;
// next set 10 Records Per Page (rpp) and current page number
xap(':pagination', ['rpp' => 10, 'page' => $pg]);
// execute SELECT query with pagination (SELECT query cannot contain LIMIT clause)
// SELECT DISTINCT id, fullname FROM users WHERE LENGTH(fullname) > '0' LIMIT x, y
$r = xap('users(id, fullname)/distinct/pagination WHERE LENGTH(fullname) > ?', [0]);
// $r['pagination'] contains pagination values:
// rpp, page, next, prev, offset, next_string, prev_string
// $r['rows'] contains selected rows
Displaying the previous page numbers can done using:
if($r['pagination']->prev > 0)
{
// set last 5 pages viewed, so if on page 12 the pages would be: [7,8,9,10,11]
$pages = array_slice(range(1, $r['pagination']->prev), -5);
}
Note: Pagination can also use decorators.
Pagination only works on select commands like
users(id, fullname)/pagination
and select queries like:query/pagination SELECT id, fullname FROM users
Before reading this section read the Pagination section
The \Xap\Pagination
helper class can be used to simplify pagination, for example:
// set GET var name for current page if not the default 'pg'
// \Xap\Pagination::$conf_page_get_var = 'pg';
// set object
$pagination = new \Xap\Pagination(xap('users/pagination'));
if($pagination->has_rows)
{
foreach($pagination->rows as $v) // access rows
// print pagination controls
echo $pagination;
}
HTML can be added to style the controls:
// change default link HTML
\Xap\Pagination::$conf_html_next = '<li><a href="{$uri}">Next »</a></li>';
\Xap\Pagination::$conf_html_prev = '<li><a href="{$uri}">« Previous</a></li>';
// HTML wrapper around all controls
\Xap\Pagination::$conf_html_wrapper_before = '<div class="pagination"><ul>';
\Xap\Pagination::$conf_html_wrapper_after = '</ul></div>';
// then use object
$pagination = new \Xap\Pagination(xap('users/pagination'));
The URI can be appended with #jump-here
by using:
$pagination = new \Xap\Pagination(xap('users/pagination', '#jump-here'));
A previous page numbers range can be displayed, for example:
// optional, globally enable
// \Xap\Pagination::$conf_prev_page_range = true;
// optional, globally set total number of page numbers to display (default is 5)
// \Xap\Pagination::$conf_prev_page_range_count = 5;
// set HTML wrapper
\Xap\Pagination::$conf_html_prev_page_range = '<li><a href="{$uri}">{$number}</a></li>';
// set active page HTML
\Xap\Pagination::$conf_html_prev_page_range_active = '<a href="#">{$number}</a>';
// then use object
$pagination = new \Xap\Pagination(xap('users/pagination'), null, true); // enable for this object only
// optonal, set page numbers to display for object only
// $pagination = new \Xap\Pagination(xap('users/pagination'), null, true, 10);
A page number filter can be used to modify page numbers, for example:
\Xap\Pagination::$conf_page_num_filter = function($n) { return base64_encode($n); };
// then use object
// $pagination = new \Xap\Pagination(x);
When setting the pagination object there is an option to set the first URI, meaning the URI used for the first page (when no more previous pages are availble), for example:
$pagination = new \Xap\Pagination(xap('users/pagination', null, false, 0, '/user/view'));
This does not need to be set because the pagination object uses auto first URI logic - but that can be overridden by using the option above
Data Modeling (or ORM) can be used in Xap. First, ensure the \Xap\Model
class is included in the xap.bootstrap.php
file:
require_once './lib/Xap/Model.php';
Next, set the data model object using the /model
option and load (select) the model record data:
$user = xap('users/model'); // \Xap\Model object
$user->id = 14; // set primary key column value
if($user->load()) // load record data
{
echo $user->fullname;
}
If the table primary key column name is not
id
use the\Xap\Model::setTableKey(table, key_name)
method, for example:
\Xap\Model::setTableKey('users', 'user_id'); // must do BEFORE using model
$user = xap('users/model'); // \Xap\Model object
$user->user_id = 14;
$user->load();
This can also be done using:
$user = xap('users/model'); // \Xap\Model object
if($user->load(14)) // load record data with primary key column value
{
echo $user->fullname;
}
Column names can also be defined to optimize the load query:
$user = xap('users(fullname)/model'); // only load 'fullname' column
Note: if column names are not defined they are automatically set by the model object, meaning that an update following a load (select) will update all the automatically loaded columns instead of defined columns (which is recommended)
Adding (inserting) a model record is simple:
// set model object and define model columns (required for insert)
$user = xap('users(fullname,is_active,created)/model');
// set model column values
$user->fullname = 'Shay Anderson';
$user->is_active = 1;
$user->created = ['NOW()']; // plain SQL as array value
// add model record
if($user->add())
{
// now the insert ID is ready:
$insert_id = $user->id;
}
else
{
// warn failed to add user record
}
Modifying (updating) a model record is simple:
// set model object and define model columns (required for update)
$user = xap('users(fullname,is_active)/model');
// set model record primary key value (required for update)
$user->id = 14; // update record with ID = 14
// set new model column values
$user->fullname = 'New Name';
$user->is_active = 1;
// update model record
if($user->save())
{
// do something
}
else
{
// warn failed to save user record
}
Deleting a model record is simple:
$user = xap('users/model'); // set model object
// set model record primary key value (required for delete)
$user->id = 14; // delete record with ID = 14
// delete model record
if($user->delete())
{
// do something
}
else
{
// warn failed to delete user record
}
Checking if a model record exists is simple:
$user = xap('users/model'); // set model object
// set model record primary key value (required for exists)
$user->id = 14; // does record with ID = 14 exist
// check if model record exists
if($user->exists())
{
// do something
}
else
{
// warn user record does not exist
}
Query SQL can be added when setting the model object, for example:
$user = xap('users/model WHERE is_active = 1'); // set model object with where clause
$user->id = 14; // set primary key column value (required)
// check if model record exists 'WHERE id = 14 AND is_active = 1'
if($user->exists())
{
// active user with ID 14 exists
}
Also query params (named query params) can be used:
$user = xap('users/model WHERE is_active = :active', ['active' => 1]);
Query SQL rules:
- The
LIMIT
clause cannot be used with the model object - Do not include the model primary key column name as a named parameter (in the query paramters) because it is automatically set by the model object
- Select with key like
users.14/model
will not work with the model object
Other useful \Xap\Model
methods are:
getColumns()
- get model column names in arraygetData()
- get the loaded model record datagetKey()
- get the model primary key column namegetTable()
- get the table nameisColumn()
- check if a column existsisLoaded()
- check if the model record is loadedsetData()
- set the model record data
Data decorators can be used in Xap. First, ensure the \Xap\Decorate
class is included in the xap.bootstrap.php
file:
require_once './lib/Xap/Decorate.php';
Here is a simple example of a data decorator using a select query:
// SELECT * FROM users LIMIT 3
$decorated = xap('users LIMIT 3',
'<tr><td>{$id}</td><td>{$fullname}</td><td>{$is_active}</td></tr>');
// $decorated is string
Now the decorated data can be printed as string:
if(!empty($decorated))
{
echo '<table>' . $decorated . '</table>';
}
else
{
echo 'No records found';
}
Which will output something like:
<table><tr><td>1</td><td>Shay Anderson</td><td>1</td></tr>
<tr><td>2</td><td>Mike Smith</td><td>1</td></tr>
<tr><td>3</td><td>John Smith</td><td>0</td></tr></table>
The above decorator can be improved using a value switch decorator which uses the logic x?:y
where x
is used for a positive value (> 0
when numeric or length > 0
when string) and y
is used for a negative value, for example change the decorator:
echo xap('users LIMIT 3', '{$id} - {$fullname} - {$is_active:Yes?:No}<br />');
Notice the {$is_active:Yes?:No}
switch decorator. Now the output will be:
1 - Shay Anderson - Yes<br />2 - Mike Smith - Yes<br />3 - John Smith - No<br />
Decorators work for all commands except:
columns
,commit
,debug
,key
,log
,pagination
(but will work with the pagination select query),rollback
,tables
,transaction
Callable decorator filters can be used with decorators, for example:
echo xap('users LIMIT 3', '{$id} - {$fullname:upper} - {$is_active:Yes?:No}<br />',
['upper' => function($name) { return strtoupper($name); }]);
Notice the {$fullname:upper}
where upper
is the filter name, and in the array of filters the key upper
is used to denote the filter by name. Now the output will be:
1 - SHAY ANDERSON - Yes<br />2 - MIKE SMITH - Yes<br />3 - JOHN SMITH - No<br />
Or a callable filter can be used with the entire array (or row), for example the example above could be rewritten as:
echo xap('users LIMIT 3', '{$id} - {$:upper} - {$is_active:Yes?:No}<br />',
['upper' => function($row) { return strtoupper($row['fullname']); }]);
When using decorate filters the array of callable filters must be passed to the Xap directly after the decorator string
When using decorate filter(s) with string values, like error decorators, the value passed to the callable filter is the value and not an array, for example:
echo xap(':error_last', '<b>{$error:upper}</b>',
['upper' => function($error) { return strtoupper($error); }]);
Test decorators are used for commands like add
, count
, del
exists
and mod
when the command returns a boolean
or integer
value and use the logic x?:y
(where x
is used when value is true
or integer > 0
, otherwise y
), for example:
echo xap('users:del WHERE user_id = ?', [122],
'User has been deleted ?: Failed to delete user');
The value User has been deleted
is displayed if the user exists and has been deleted, otherwise the value Failed to delete user
is displayed.
Error decorators can be used when error exceptions are turned off, for example:
echo xap(':error', 'Error has occurred ?: No error occurred');
Or when display last error:
if(xap(':error')) echo xap(':error_last', '<div class="error">{$error}</div>');
Decorators can be used with pagination, for example:
$decorated = xap('users/pagination WHERE is_active = 1',
'{$id} - {$fullname} - {$is_active:Yes?:No}<br />');
// display the decorated (and paginated) data:
echo $decorated['rows'];
Pagination values are still available in
$decorated['pagination']
Decorators can also be used for the pagination values next_string
and prev_string
, for example:
// set decorators for 'next_string' and 'prev_string'
xap(':pagination', ['next_string' => '<a href="?pg={$next}">Next</a>',
'prev_string' => '<a href="?pg={$prev}">Prev</a>'])
$data = xap('users/pagination');
Now when the value $data['pagination']->next_string
is called and there is a next page it will output HTML like:
<a href="?pg=2">Next</a>
And likewise for the value $data['pagination']->prev_string
. If there is no next page then no value will be set, and same for the previous page value.
Decorators can be used with data modeling, for example:
$user = xap('users/model', '{$id} - {$fullname} - {$is_active:Yes?:No}');
$user->load(14); // load (select) user record
echo $user; // display decorated data
This example would display something like:
14 - Mike Smith - Yes
Caching can be used to reduce database calls. First, ensure the \Xap\Cache
class is included in the xap.bootstrap.php
file and the cache settings are set:
require_once './lib/Xap/Cache.php';
...
// set global cache expire time to 10 seconds (default is 30 seconds)
\Xap\Cache::setExpireGlobal('10 seconds');
// set global cache directory path for cache writes
\Xap\Cache::setPath('/var/www/app/cache');
Security Warning: Do not use caching to store private data that should be stored in a secure database. Also, for Web applications the global cache directory path should be protected from public (external) requests using Web server configuration files.
Here is a simple example of caching using a select query and the /cache
option:
// SELECT title, sku, is_active FROM items LIMIT 10
$items = xap('items(title, sku, is_active)/cache LIMIT 10');
Now the recordset has been cached and will expire in 10 seconds (the global expire time). When the cache expires it will be rewritten with current data.
Caching can be used for all different types of select commands and queries, but cannot be used with the
/model
option
To use a custom expire time for a single query (and not the global cache expire time) use:
xap(':cache 1 hour'); // refresh cache every hour
$items = xap('items(title, sku, is_active)/cache LIMIT 10');
Now the recordset will expire every 1 hour.
Cache expire times can be strings like:
1 hour
or30 minutes
or15 seconds
, or an integer for seconds like25
would be converted to25 seconds
. Also the cache expire timenever
can be used to allow a never expire cache.
A custom expire time is only used for a single query, for example:
xap(':cache 1 hour'); // refresh cache every hour
$items = xap('items(title, sku, is_active)/cache LIMIT 10');
// $items_inactive cache expires in the global expire time and not in 1 hour
$items_inactive = xap('items(title, sku)/cache WHERE is_active = 0 LIMIT 10');
A custom cache key prefix can be used. This can be helpful when managing cache files with scripts. Here is an example:
// set cache key prefix to 'item', cache key will be 'item-[cache key]'
\Xap\Cache::setCacheKeyPrefix('item');
// only this cache will use the 'item' cache key prefix
// it must be set again for any other caches
$items = xap('items(title, sku, is_active)/cache LIMIT 10');
Custom cache key prefixes should only include word characters (
\w
), all other characters will be removed
Likewise, a custom cache key can be used, for example:
// set cache key to 'my-custom-cache'
\Xap\Cache::setCacheKey('my-custom-cache');
Custom cache keys can only include word characters (
\w
) and hyphens-
All cache files can be removed by using the command:
\Xap\Cache::flush(); // flush all cache files
By default Xap uses compression for cache files (requires PHP Zlib functions). To globally disable compression use:
\Xap\Cache::$use_compression = false;