PHP - PG
PHP - PG
Programmer’s Guide
May 2013
MATISSE PHP Programmer’s Guide
This manual and the software described in it are copyrighted. Under the
copyright laws, this manual or the software may not be copied, in whole or in
part, without prior written consent of Matisse Software Inc. This manual and
the software described in it are provided under the terms of a license between
Matisse Software Inc. and the recipient, and their use is subject to the terms of
that license.
The product described in this manual may be protected by one or more U.S. and
international patents.
3
Updating Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Retrieving Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Retrieving Objects from a SELECT statement . . . . . . . . . . . . . . . . . . . . . . . 31
Retrieving Objects from a Block Statement . . . . . . . . . . . . . . . . . . . . . . . . . 32
Executing DDL Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Executing SQL Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Deleting Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
10 Handling Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Connection with Factory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Creating your Object Factory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1 Introduction
Scope of This Document
This document is intended to help PHP programmers learn the aspects of Matisse design and
programming that are unique to the Matisse PHP binding.
Aspects of Matisse programming that the PHP binding shares with other interfaces, such as basic
concepts and schema design, are covered in Getting Started with Matisse.
Future releases of this document will add more advanced topics. If there is anything you would like to see
added, or if you have any questions about or corrections to this document, please send e-mail to
support@matisse.com.
• Install the PHP version 5.3.2 or later for your operating system (a free download from www.php.net).
• Download and extract the Matisse PHP binding source code and sample code from the Matisse Web
site:
http://www.matisse.com/developers/documentation/
The sample code files are grouped in subdirectories by chapter number. For example, the code
snippets from the following chapter are in the chap_2 directory.
• Build the Matisse PHP binding from the source code. Follow the building instructions as detailed in
the BUILD file.
• Create and initialize a database. You can simply start the Matisse Enterprise Manager, select the
database ‘example’ and right click on ‘Re-Initialize’.
• From a Unix shell prompt or on MS Windows from a ‘Command Prompt’ window, change to the
chap_x subdirectory in the directory where you installed the examples.
• If applicable, load the ODL file into the database. From the Enterprise Manager, select the database
‘example’ and right click on ‘Schema->Import ODL Schema’. For example you may import
chap_3/objects.odl for the Chapter 3 demo.
Introduction 5
Matisse PHP Programmer’s Guide
Introduction 6
Matisse PHP Programmer’s Guide
Note that in this chapter there is no ODL file as you do not need to create an application schema.
UNIX:
php -c ../../php.ini connect.php host database
$db->open();
$db->startTransaction();
$db->commit();
$db->close();
} catch (\matisse\MtException $mtex) {
echo "Error:".$mtex->getMessage()."\n";
echo "Error code:".$mtex->getErrorCode()."\n";
}
UNIX:
php -c ../../php.ini connect.php host database
Read-Only Access
The following code connects to a database in read-only mode, suitable for reports:
try {
$db = new \matisse\MtDatabase($hostname, $dbname);
$db->open();
$db->startVersionAccess();
$db->endVersionAccess();
$db->close();
print "Completed\n";
} catch (\matisse\MtException $mtex) {
echo "Error:".$mtex->getMessage()."\n";
echo "Error code:".$mtex->getErrorCode()."\n";
}
UNIX:
php -c ../../php.ini versionConnect.php host database
Version Access
The following code illustrates methods of accessing various versions of a database.
function listVersions1($db) {
$it = $db->versionIterator();
foreach ($it as $pos => $ver) {
$vtime = $db->getVersionFromName($ver);
echo "{$pos} - {$ver} ({$vtime})\n";
}
}
function listVersions2($db) {
$it = $db->versionIterator();
while($it->valid()) {
print "{$it->key()} - {$it->current()}\n";
$it->next();
}
$it->close();
}
function listVersions3($db) {
$it = $db->versionIterator();
while($it->valid()) {
$it->next();
}
$it->rewind();
while($it->valid()) {
print "{$it->key()} - {$it->current()}\n";
$it->next();
}
$it->close();
}
function removeVersions($db) {
$it = $db->versionIterator();
foreach ($it as $pos => $ver) {
$vtime = $db->getVersionFromName($ver);
echo "{$pos} - {$ver} ({$vtime})\n";
$db->removeVersion($ver);
}
}
if ((!isset($argv[1])) || (!isset($argv[2]))) {
echo "Error: Need to specify arguments: $argv[0] localhost dbname\n";
exit();
} else {
require_once("matisse.php");
$hostname = $argv[1];
$dbname = $argv[2];
try {
$db = new matisse\MtDatabase($hostname, $dbname);
$db->open();
$db->startTransaction();
echo "Version list before regular commit:\n";
listVersions1($db);
$db->commit();
$db->startTransaction();
echo "Version list after regular commit:\n";
listVersions2($db);
$versionName = $db->commit("mysnapshot-");
$db->startVersionAccess();
echo "Version list after named commit:\n";
listVersions3($db);
$db->endVersionAccess();
$db->startVersionAccess($versionName);
echo "Successful access to version: $versionName\n";
$db->endVersionAccess();
$db->startTransaction();
removeVersions($db);
$db->commit();
$db->close();
print "Completed\n";
} catch (matisse\MtException $mtex) {
echo "Error:".$mtex->getMessage()."\n";
}
UNIX:
php -c ../../php.ini versionNavigation.php host database
Specific Options
This example shows how to enable the local client-server memory transport and to set or read various
connection options and states.
function startAccess($db, $readonly) {
if ($readonly) {
$db->startVersionAccess();
echo "read-only access to $db\n";
} else {
$db->startTransaction();
echo "read-write access to $db\n";
}
}
function endAccess($db) {
if ($db->isVersionAccessInProgress()) {
$db->endVersionAccess();
echo "version access ended\n";
} else if ($db->isTransactionInProgress()) {
$db->commit();
echo "transaction committed\n";
} else {
echo "No transaction nor version access in progress\n";
}
}
function isReadOnlyAccess($db) {
return ($db->getOption(matisse\MtDatabase::DATA_ACCESS_MODE) ==
matisse\MtDatabase::DATA_READONLY);
}
function setAccessMode($db, $mode) {
switch ($mode) {
case "T":
$db->setOption(matisse\MtDatabase::DATA_ACCESS_MODE,
matisse\MtDatabase::DATA_MODIFICATION);
echo "DATA_MODIFICATION (read-write transaction) mode\n";
break;
case "V":
$db->setOption(matisse\MtDatabase::DATA_ACCESS_MODE,
matisse\MtDatabase::DATA_READONLY);
echo "DATA_READONLY (version) mode\n";
break;
case "S":
$db->setOption(matisse\MtDatabase::DATA_ACCESS_MODE,
matisse\MtDatabase::DATA_DEFINITION);
echo "DATA_DEFINITION (schema definition) mode\n";
break;
default:
echo "unknown mode\n";
break;
}
}
$hostname = $argv[1];
$dbname = $argv[2];
$mode = $argv[3];
try {
$db = new matisse\MtDatabase($hostname, $dbname);
$db->open();
setAccessMode($db, $mode);
startAccess($db, isReadOnlyAccess($db));
endAccess($db);
print "Completed\n";
} catch (matisse\MtException $mtex) {
echo "Error:".$mtex->getMessage()."\n";
}
UNIX:
php -c ../../php.ini advancedConnect.php host database
The object interface can be used with Matisse PHP SQL interface as well. For example, you can retrieve
objects with SQL, then use the object interface to navigate to other objects from these objects, or update
properties of these objects using the accessor methods defined on these classes.
3. Load objects.odl into the database. From the Enterprise Manager, select the database ‘example’
and right click on ‘Schema->Import ODL Schema’, then select chap_3/objects.odl for this demo.
Creating Objects
This section illustrates the creation of objects. The stubclass provides a default constructor which is the
base factory for creating persistent objects.
public static function createPerson($db) {
return new Person(self::getClass($db));
}
You can also use the default constructor defined on the class.
/**
* Factory constructor. This constructor is called by <code>MtObjectFactory</code>.
* It is public for technical reasons but is not intended to be called
* directly by user methods.
* Cascaded constructor, used by subclasses to create a new object in the database.
* It is protected for technical reasons but is not intended to be called
* directly by user methods.
* @param cls a class descriptor (the class to instantiate)
* @param db a database
* @param mtOid an existing object ID in the database
*/
$a = new PostalAddress(PostalAddress::getClass($db));
$a->setCity("Portland");
$a->setPostalCode("97201");
$p->setAddress($a);
UNIX:
php -c ../../php.ini createObjects.php host database
If your application need to create a large number of objects all at once, we recommend that you use the
preallocate() method defined on MtDatabase which provide a substantial performance optimization.
$db->startTransaction();
$a = new PostalAddress(PostalAddress::getClass($db));
$addrIdx = rand() % MAX_SAMPLES;
$a->setCity($addressSample[$addrIdx][0]);
$a->setPostalCode($addressSample[$addrIdx][1]);
$e->setAddress($a);
if ($i % OBJECT_PER_TRAN_CNT == 0) {
$db->commit();
$db->startTransaction();
}
// check the remaining number of preallocated objects.
if ($db->numPreallocated() < 2) {
$db->preallocate(DEFAULT_ALLOCATOR_CNT);
}
}
if ($db->isTransactionInProgress())
$db->commit();
UNIX:
php -c ../../php.ini loadObjects.php host database
Listing Objects
This section illustrates the enumeration of objects from a class. The instanceIterator() static method
defined on a generated stubclass allows you to enumerate the instances of this class and its subclasses.
The getInstanceNumber() method returns the number of instances of this class.
// List all Person objects
print "\n". Person::getInstanceNumber($db) ." Person(s) in the database.\n";
print "\n". PostalAddress::getInstanceNumber($db) ." Address(s) in the database.\n";
$iter = Person::instanceIterator($db);
while($iter->valid()) {
$x = $iter->current();
$iter->close();
UNIX:
php -c ../../php.ini listObjects.php host database
The ownInstanceIterator() static method allows you to enumerate the own instances of a class
(excluding its subclasses). The getOwnInstanceNumber() method returns the number of instances of a
class (excluding its subclasses).
$iter = Person::ownInstanceIterator($db);
while($iter->valid()) {
$x = $iter->current();
$iter->close();
UNIX:
php -c ../../php.ini listOwnInstances.php host database
Deleting Objects
This section illustrates the removal of objects. The remove() method delete an object.
// Remove created objects
...
// NOTE: does not remove the object sub-parts
$p->remove();
To remove an object and its sub-parts, you need to override the deepRemove() method in the stubclass to
meet your application needs. For example the implementation of deepRemove() in the Person class that
contains a reference to a PostalAddress object is as follows:
/**
* Overrides MtObject.deepRemove() to remove the Address object if any.
*/
public function deepRemove() {
$pAddr = $this->getAddress();
if ($pAddr != null)
$pAddr->deepRemove();
parent::deepRemove();
}
...
$p->deepRemove();
UNIX:
php -c ../../php.ini deleteObjects.php host database
The removeAllInstances() method defined on MtClass delete all the instances of a class.
Person::getClass($db)->removeAllInstances();
UNIX:
php -c ../../php.ini deleteAllObjects.php host database
Comparing Objects
This section illustrates how to compare objects. Persistent objects must be compared with the equal()
method. You can’t compare persistent object with the === operator.
...
if($p1->equals($p2))
print("Same objects\n");
This example uses the database created for Objects Example. It creates objects, then manipulates its
values in various ways.
// Setting strings
$e->setComment("FirstName, LastName, Age, HireDate & Salary Set");
$e->setFirstName("John");
$e->setLastName("Jones");
// Setting numbers
$e->setAge(42);
UNIX:
php -c ../../php.ini setObjectValues.php host database
UNIX:
php -c ../../php.ini getObjectValues.php host database
Removing Values
This section illustrates the removal of object property values. Removing the value of an attribute will
return the attribute to its default value.
if ( ! $e->isAgeNull() )
print " {$e->getAge()} years old\n";
else
print " Age: null". ($e->isAgeDefaultValue() ? " (default value)" : "") ."\n";
UNIX:
php -c ../../php.ini removeObjectValues.php host database
Streaming Values
This section illustrates the streaming of blob-type values (MT_BYTES, MT_AUDIO, MT_IMAGE,
MT_VIDEO). The stubclass provides streaming methods (setPhotoElements(), getPhotoElements()) for
each blob-type property defined in the class. It also provides a method (getPhotoSize()) to retrieve the
blob size without reading it.
// Setting blobs
UNIX:
php -c ../../php.ini readWriteStreamingValues.php host database
$db->open();
$db->startVersionAccess();
if (isset($_GET['photoid'])) {
// image request, send out the image
$photoid = intval($_GET['photoid']);
$p = $db->upcast($photoid);
$bytes = $p->getPhoto();
$db->endVersionAccess();
$db->close();
header("Content-type: image/gif");
echo $bytes;
flush ();
exit ();
}
3. Load examples.odl into the database. From the Enterprise Manager, select the database ‘example’
and right click on ‘Schema->Import ODL Schema’, then select chap_4/examples.odl for this demo.
$e = Employee::createEmployee($db);
...
// Set a relationship
$e->setReportsTo($m1);
$c1 = Person::createPerson($db);
...
$c2 = Person::createPerson($db);
...
// Set successors
$m1->setChildren( array($c1, $c2) );
...
// Get all successors
$c = $m1->getChildren();
Windows:
php -c ..\..\php.ini setRelationships.php host database
UNIX:
php -c ../../php.ini setRelationships.php host database
UNIX:
php -c ../../php.ini addToRelationship.php host database
php -c ../../php.ini removeFromRelationship.php host database
while($iter->valid()) {
$x = $iter->current();
print " {$x->getFirstName()}";
$iter->next();
}
print "\n";
$iter->close();
UNIX:
php -c ../../php.ini iterateRelationship.php host database
UNIX:
php -c ../../php.ini getRelationshipSize.php host database
3. Load examples.odl into the database. From the Enterprise Manager, select the database ‘example’
and right click on ‘Schema->Import ODL Schema’, then select chap_5/examples.odl for this demo.
Index Lookup
This section illustrates retrieving objects from an index. The stubclass provides a lookup and a iterator
method for each index defined on the class.
// the lookup function returns null to represent no match
$found = Person::lookupPersonName($db, $lastName, $firstName);
UNIX:
php -c ../../php.ini lookupObjects.php host database
$iter->next();
}
$iter->close();
UNIX:
php -c ../../php.ini iterateIndex.php host database
UNIX:
php -c ../../php.ini lookupObjectsCount.php host database
UNIX:
php -c ../../php.ini countIndexEntries.php host database
3. Load examples.odl into the database. From the Enterprise Manager, select the database ‘example’
and right click on ‘Schema->Import ODL Schema’, then select chap_6/examples.odl for this demo.
UNIX:
php -c ../../php.ini lookupObjects.php host database
$hits = 0;
$hits++;
$iter->next();
}
UNIX:
php -c ../../php.ini iterateEpDict.php host database
$count = Person::getCommentDictDictionary($db)->getObjectNumber($searchstring,
null);
print "{$count} matching object(s) retrieved\n";
UNIX:
php -c ../../php.ini lookupObjectsCount.php host database
3. Load examples.odl into the database. From the Enterprise Manager, select the database ‘example’
and right click on ‘Schema->Import ODL Schema’, then select sql/examples.odl for this demo.
You can create more specific Statement objects for different purposes:
• MtStatement - It is specifically used for the SQL statements where you don't need to pass any value
as a parameter
• MtPreparedStatement - It is a subclass of the statement class. The main difference is that, unlike the
statement class, prepared statement is complied and optimized once and can be used multiple times
by setting different parameter values.
• MtCallableStatement - It provides a way to call a stored procedure on the server from a PHP
program. Callable statements also need to be prepared first, and then their parameters are set using
the set methods.
• MtResultSet - It represents a table of data, which is usually generated by executing a statement that
queries the database. A ResultSet object maintains a cursor pointing to its current row of data.
NOTE: With the Matisse PHP SQL interface you usually don’t need to use the
PHP stub classes unless you want to retrieve objects from a SQL
statement or from the execution of a SQL method.
Creating Objects
You can also create objects into the database without the PHP stub classes. The following code
demonstrates how to create multiple objects of the same class using a prepared statement.
$db->startTransaction();
// Set parameters
$pstmt->setString(1, "James");
$pstmt->setString(2, "Watson");
$pstmt->setInt(3, 75);
$db->commit();
// Clean up
$pstmt->close();
UNIX:
php -c ../../php.ini insertObjects.php host database
Updating Objects
You can also create objects into the database without the PHP stub classes. The following code
demonstrates how to create multiple objects of the same class using a prepared statement.
$db->startTransaction();
// Clean up
$stmt->close();
$db->commit();
UNIX:
php -c ../../php.ini insertObjects.php host database
Retrieving Values
You use the ResultSet object, which is returned by the executeQuery method, to retrieve values or
objects from the database. Use the next method combined with the appropriate getString, getInt, etc.
methods to access each row in the result.
The following code demonstrates how to retrieve string and integer values from a ResultSet object after
executing a SELECT statement.
// Create an instance of PreparedStatement
$commandText = "SELECT FirstName, LastName, Spouse.FirstName AS Spouse, Age FROM
Person WHERE LastName = ? LIMIT 10;";
$pstmt = $db->prepareStatement($commandText);
// Set parameters
$pstmt->setString(1, "Watson");
while ($rset->next()) {
// Get values for the first and second column
$fname = $rset->getString(1);
$lname = $rset->getString(2);
$sfname = $rset->getString(3);
$age = $rset->getInt(4);
// The third column 'Age' can be null. Check if it is null or not first.
if ($rset->wasNull()) $age = "NULL";
UNIX:
php -c ../../php.ini selectValues.php host database
To retrieve objects, use REF in the select-list of the query statement and the getObject method returns
an object. The following code example shows how to retrieve Person objects from a ResultSet object.
// Set the SELECT statement. Note that we use REF() in the select-list
// to get the PHP objects directly (rather than values)
$commandText = "SELECT REF(p) FROM Person p WHERE LastName = 'Watson';";
$pstmt = $db->createStatement();
while ($rset->next()) {
// Get the Person object
$p = $rset->getObject(1);
// Clean up
$rset->close();
$pstmt->close();
UNIX:
php -c ../../php.ini selectObjects.php host database
The getObject method defined on a MtCallableStatement is used to return one object as well as an
object collection. The following code example shows how to retrieve a collection of Person objects
from a MtCallableStatement.
// Set a block statement
$commandText =
"BEGIN\n".
" DECLARE res SELECTION(Employee);\n".
" DECLARE emp_sel SELECTION(Employee);\n".
" DECLARE mgr_sel SELECTION(Manager);\n".
" SELECT REF(p) FROM ONLY Employee p WHERE p.ReportsTo IS NULL INTO emp_sel;\n".
" SELECT REF(p) FROM Manager p WHERE COUNT(p.Team) > 1 INTO mgr_sel;\n".
" SET res = SELECTION(emp_sel UNION mgr_sel);\n".
" RETURN res;\n".
"END";
$stmt = $db->prepareCall($commandText);
$isRset = $stmt->execute();
if ( \matisse\reflect\MtType::SELECTION == $returnType ||
\matisse\reflect\MtType::OID == $returnType ) {
$sel = $stmt->getObject(0);
// Clean up
$stmt->close();
UNIX:
php -c ../../php.ini insertObjects.php host database
Creating a Class
You can create schema objects using the executeUpdate Method as long as the transaction is started in
the DATA DEFINITION mode.
$db = new \matisse\MtDatabase($hostname, $dbname);
// In order to execute DDL statements, the transaction needs to be
// started in the "Data Definition" mode
$db->setOption (\matisse\MtDatabase::DATA_ACCESS_MODE,
\matisse\MtDatabase::DATA_DEFINITION);
$db->startTransaction();
// Execute the DDL statement
stmt = $db->createStatement ();
stmt->executeUpdate ("CREATE CLASS Manager UNDER Employee (bonus INTEGER)");
$db->commit();
$db->close();
Creating a schema object using the execute Method does not require to start a transaction. A transaction
will be automatically started in the DATA DEFINITION mode.
$db->open();
$stmt = $db->createStatement();
// The first method returns the number of Person objects which have a specified
last name
$commandText =
"CREATE STATIC METHOD CountByLName(lname STRING)\n".
"RETURNS INTEGER\n".
"FOR Person\n".
"BEGIN\n".
" DECLARE cnt INTEGER;\n".
" SELECT COUNT(*) INTO cnt FROM Person WHERE LastName = lname;\n".
" RETURN cnt;\n".
"END;";
$stmt->execute($commandText);
// Clean up
$stmt->close();
$db->commit();
$db->close();
UNIX:
php -c ../../php.ini createSqlMethod.php host database
The following program code shows how to call the SQL method CountByLName of the Person class.
// Specify the stored method. we call a static method,
// the name is consisted of class name and method name.
// Use CALL syntax to call the method
// Set parameters
$stmt->setString(1, "Watson");
// Print it
print ("{$count} objects found\n");
// Clean up
$stmt->close();
UNIX:
php -c ../../php.ini callSqlMethod1.php host database
The following program code shows how to call the SQL method FindByName of the Person class.
// Specify the SQL method. Since we call a static method,
// the name is consisted of class name and method name.
// Use CALL syntax to call the method
$commandText = "CALL Person::FindByName('Watson', 'James');";
// Print it
if ($p)
print("Found: {$p->getLastName()} {$p->getFirstName()}\n");
else
print("no matching object found\n");
// Clean up
$stmt->close();
Windows:
php -c ..\..\php.ini callSqlMethod2.php host database
UNIX:
php -c ../../php.ini callSqlMethod2.php host database
The following program code shows how to retrieve the execution stack trace of a SQL method when an
error occurs.
try {
$db->open();
$db->startVersionAccess();
// Clean up
$stmt->close();
$db->endVersionAccess();
$db->close();
UNIX:
php -c ../../php.ini callSqlMethod3.php host database
Deleting Objects
You can delete objects from the database with a DELETE statement as follows:
$db->open();
$db->startTransaction();
$stmt = $db->createStatement();
// Clean up
$stmt->close();
$db->commit();
$db->close();
UNIX:
php -c ../../php.ini clearPersonObjects.php host database
3. Load examples.odl into the database. From the Enterprise Manager, select the database ‘example’
and right click on ‘Schema->Import ODL Schema’, then select reflection/examples.odl for this
demo.
Creating Objects
This example shows how to create persistent objects without the corresponding PHP stubclass. The static
method get() defined on all Matisse Meta-Schema classes (i.e. MtClass, MtAttribute, etc.) allows you
to access to the schema descriptor necessary to create objects. Each object is an instance of the MtObject
base class. The MtObject class holds all the methods to update the object properties (attribute and
relationships (i.e. setString(), setSuccessors(), etc.).
// the MtCoreObjectFactory class provides a minimal object factory
// well suited for applications using reflection to manipulate objects
$db = new \matisse\MtDatabase($hostname, $dbname, new MtCoreObjectFactory());
$db->open();
$db->startTransaction();
$db->commit();
$db->close();
UNIX:
php -c ../../php.ini createObjects.php host database
Listing Objects
This example shows how to list persistent objects without the corresponding PHP stubclass. The
instanceIterator() method defined on the MtClass object allows you to access all instances defined
on the class.
// List all objects
$pClass = \matisse\reflect\MtClass::get($db, "Person");
$fnAtt = \matisse\reflect\MtAttribute::get($db, "FirstName", $pClass);
$lnAtt = \matisse\reflect\MtAttribute::get($db, "LastName", $pClass);
$cgAtt = \matisse\reflect\MtAttribute::get($db, "collegeGrad", $pClass);
$iter = $pClass->instancesIterator();
while($iter->valid()) {
$p = $iter->current();
$iter->next();
}
$iter->close();
UNIX:
php -c ../../php.ini listObjects.php host database
if ($count > 1) {
// More than one matching object
// Retrieve them with an iterator
$iter = $iClass->iterator($key, $key);
while($iter->valid()) {
$p = $iter->current();
print " found {$p->getString($fnAtt)} {$p->getString($lnAtt)} OID={$p-
>getMtOid()}\n";
$iter->next();
}
} else {
// At most 1 object
// Retrieve the matching object with the lookup method
$p = $iClass->lookup($key);
if ($p != null) {
print " found {$p->getString($fnAtt)} {$p->getString($lnAtt)}\n";
} else {
print " Nobody found";
}
}
Windows:
php -c ..\..\php.ini indexLookup.php host database
UNIX:
php -c ../../php.ini indexLookup.php host database
if ($count > 1) {
// More than one matching object
// Retrieve them with an iterator
$iter = $epClass->iterator($collegeGrad);
while($iter->valid()) {
$p = $iter->current();
print " found OID={$p->getMtOid()} {$p->getString($fnAtt)} {$p-
>getString($lnAtt)}";
print " collegeGrad=". var_export($p->getBoolean($cgAtt), true) ."\n";
$iter->next();
}
} else {
// At most 1 object
// Retrieve the matching object with the lookup method
$p = $epClass->lookup($collegeGrad);
if ($p != null) {
print " found OID={$p->getMtOid()} {$p->getString($fnAtt)} {$p-
>getString($lnAtt)}";
print " collegeGrad=". var_export($p->getBoolean($cgAtt), true) ."\n";
} else {
print " Nobody found\n";
}
}
UNIX:
php -c ../../php.ini entryPointLookup.php host database
$iter = $pClass->instancesIterator();
while($iter->valid()) {
$p = $iter->current();
while($propIter->valid()) {
$a = $propIter->current();
$propName = $a->getMtName();
$propType = $a->getMtType();
$valType = $p->getType($a);
$fmtVal = null;
switch ($valType) {
case MT_DATE:
$fmtVal = $p->getDate($a)->format("Y-m-d");
break;
case MT_NUMERIC:
$fmtVal = $p->getNumeric($a);
break;
case MT_NULL:
$fmtVal = 'null';
break;
default:
$fmtVal = $p->getValue($a);
}
print " {$propName} (". \matisse\reflect\MtType::toString($propType) .
"):\t ". var_export($fmtVal, true) ." (".
\matisse\reflect\MtType::toString($valType). ")\n";
$propIter->next();
}
$propIter->close();
while($rshpIter->valid()) {
$r = $rshpIter->current();
$rshpIter->next();
}
$rshpIter->close();
$iter->next();
}
$iter->close();
UNIX:
php -c ../../php.ini listObjectProperties.php host database
Adding Classes
This example shows how to add a new class to the database schema. The connection needs to be open in
the DDL (MtDatabase.DATA_DEFINITION) mode. Then you need to create instances of MtClass,
MtAttribute and MtRelationship and connect them together.
$db->startTransaction();
$db->commit();
$db->close();
UNIX:
php -c ../../php.ini addClass.php host database
Deleting Objects
This example shows how to delete persistent objects.The MtObject class holds remove() and
deepRemove(). Note that on MtObject deepRemove() does not execute any cascading delete but only
calls remove().
$db->startTransaction();
while($iter->valid()) {
$p = $iter->current();
$p->deepRemove();
$iter->next();
}
$iter->close();
$db->commit();
UNIX:
php -c ../../php.ini deleteObjects.php host database
Removing Classes
This example shows how to remove a class for the database schema. The deepRemove() method defined
on MtClass will delete the class and its properties and indexes. The connection needs to be open in
MtDatabase.DATA_DEFINITION mode.
$db->startTransaction();
$paClass->deepRemove();
$db->commit();
$db->close();
UNIX:
php -c ../../php.ini removeClass.php host database
UNIX:
php -c ../../php.ini subscribeEvents.php host database
php -c ../../php.ini notifyEvents.php host database
Events Subscription
This section illustrates event registration and event handling. Matisse provides the MtEvent class to
manage database events. You can subscribe up to 32 events (MtEvent.EVENT1 to MtEvent.EVENT32)
and then wait for the events to be triggered.
$TEMPERATURE_CHANGES_EVT = \matisse\MtEvent::EVENT1;
$RAINFALL_CHANGES_EVT = \matisse\MtEvent::EVENT2;
$HIMIDITY_CHANGES_EVT = \matisse\MtEvent::EVENT3;
$WINDSPEED_CHANGES_EVT = \matisse\MtEvent::EVENT4;
// Subscribe
$subscriber->subscribe($eventSet);
} else {
print "No Event received after 1 sec\n";
}
Events Notification
This section illustrates event selection and notification.
$TEMPERATURE_CHANGES_EVT = \matisse\MtEvent::EVENT1;
$RAINFALL_CHANGES_EVT = \matisse\MtEvent::EVENT2;
$HIMIDITY_CHANGES_EVT = \matisse\MtEvent::EVENT3;
$WINDSPEED_CHANGES_EVT = \matisse\MtEvent::EVENT4;
$eventSet = $HIMIDITY_CHANGES_EVT;
$eventSet |= $WINDSPEED_CHANGES_EVT;
// Notify of 2 events
$notifier->notify($eventSet);
$db->close();
10 Handling Namespaces
You can generate your class stubs in the company\project\module PHP namespaces with the mt_sdl
utility using -n option as follows:
mt_sdl stubgen --lang php -n 'company\project\module' -f examples.odl
When your persistent classes are defined in a specific namespace, you need to give this information to the
Connection object so that it can find these classes when returning objects.
For example, the persistent classes are defined in the company\project\module PHP namespace. In this
case, you need to pass an MtDynamicObjectFactory object as the third argument for the MtDatabase
constructor.
$db = new \matisse\MtDatabase("host", "db", new
\matisse\MtDynamicObjectFactory(array ("\\company\\project\\module" =>
"company.project.module")));
By default, the anonymous default namespace is searched as well as the specified namespaces.
Using MtCoreObjectFactory
This factory is the basic MtObject-based object factory. This factory is the most appropriate for
application which does use generated stubs. This factory is faster than the default Object Factory used by
MtDatabase since it doesn't use reflection to build objects.
$db = new \matisse\MtDatabase("host", "db", new \matisse\MtCoreObjectFactory());
The MtObjectFactory interface describes the mechanism used by MtDatabase to create the
appropriate PHP object for each Matisse object. Implementing the MtObjectFactory interface requires
to define the getPHPClass() method which returns the PHP class corresponding to a Matisse Class
Name, the getDatabaseClass() method which returns a Matisse class name corresponding to a PH
class name and the getObjectInstance() method which returns a PHP object based on an oid.
class MyAppFactory implements MtObjectFactory
{
/**
* Implements <code>MtObjectFactory.getPHPClass</code>.
*
* @param mtClsName a Matisse Class Name
* @return MtObject classname
Handling Namespaces 48
Matisse PHP Programmer’s Guide
*/
public function getPHPClass($mtClsName) {
return "\matisse\reflect\MtObject";
}
/**
* Implements <code>MtObjectFactory.getDatabaseClass</code>.
*
* @param string phpClsName a PHP Full Class Name
* @return string the Matisse Full class name
*/
public function getDatabaseClass($phpClsName) {
$res = $phpClsName;
return $res;
}
/**
* Implements <code>MtObjectFactory.getObjectInstance</code>.
*
* @param db a database
* @param mtOid the OID of the PHP object to create
* @return the PHP object represented by <code>mtOid</code>
*/
public function getObjectInstance($db, $mtOid) {
if ($mtOid == 0) {
return NULL;
}
return new \matisse\reflect\MtObject(NULL, $db, $mtOid);
}
}
/**
* Implements <code>MtObjectFactory.getDatabaseClass</code>.
*
* @param string phpClsName a PHP Full Class Name
* @return string the Matisse Full class name
*/
public function getDatabaseClass($phpClsName) {
$res = $phpClsName;
// your Matisse class name as you see fit
Handling Namespaces 49
Matisse PHP Programmer’s Guide
return $res;
}
/**
* Implements <code>MtObjectFactory.getObjectInstance</code>.
*
* @param db a database
* @param mtOid the OID of the PHP object to create
* @return the PHP object represented by <code>mtOid</code>
*/
public function getObjectInstance($db, $mtOid) {
if ($this->isSchemaObject($db, $mtOid)) {
return parent::getObjectInstance$db, $mtOid);
} else {
// Create your PHP object as you see fit
return anObject;
}
}
}
Handling Namespaces 50
Matisse PHP Programmer’s Guide
1. matisse.php contains all the core classes defined in the matisse namespace. These classes
manages the database connection, the object factories as well as the objects caching mechanisms. It
also includes the Matisse meta-schema classes defined in the matisse\reflect namespace.
2. matisseSql.php contains all the SQL-related classes defined in the matisse\sql namespace. These
classes manages the execution of al types of SQL statements.
The Matisse PHP API documentation included in the delivery provides a detailed description of all the
classes and methods.
A .php file will be created for each class defined in the database. If you need to define these
persistent classes in a specific namespace, use -n option. The following command generates classes
under the namespace MyCompany\MyProject:
When you update your database schema later, load the updated schema into the database. Then, execute
the mt_sdl utility in the directory where you first generated the class files, to update the files. Your own
program codes added to these stub class files will be preserved.
...
// END of Matisse SDL Generated Code
The following methods are created for each schema class. These are class methods (also called static
methods): that is, they apply to the class as a whole, not to individual instances of the class. These
examples are taken from Person.
Sample createPerson($db)
constructor
The following methods are created for each attribute. For example, if the ODL definition for class Check
contains the attributes Date and Amount, the Check.PHP file will contain the methods getDate and
getAmount. These examples are taken from Person.firstName.
The following methods are created for each list-type attribute. These examples are from Person.photo.
The following methods are created for each relationship. These examples are from Person.spouse.
The following methods are created for each relationship with a maximum cardinality of 1. These
examples are from Manager.assistant.
The following methods are created for each relationship with a maximum cardinality greater than 1.
These examples are from Manager.team.
Remove removeTeam($succ)
successors
removeTeam($succs)
For indexes
The following methods are created for every index defined for a database. These examples are for the
only index defined in the example, Person.personName.
The following methods are created for every entry-point dictionary defined for a database. These
examples are for the only dictionary defined in the example, Person.commentDict.