Slice identifiers map to PHP identifiers of the same name, unless the Slice identifier conflicts with a PHP reserved word, in which case the mapped identifier is prefixed with an underscore. For example, the Slice identifier
echo is mapped as
_echo.
A flattened mapping is used for identifiers defined within Slice modules because PHP does not have an equivalent to C++ namespaces or Java packages. The flattened mapping uses underscores to separate the components of a fully-scoped name. For example, consider the following Slice definition:
module M {
enum E { one, two, three };
};
In this case, the Slice identifier M::E is flattened to the PHP identifier
M_E.
Note that when checking for a conflict with a PHP reserved word, only the fully-scoped, flattened identifier is considered. For example, the Slice identifier
M::function is mapped as
M_function, despite the fact that
function is a PHP reserved word. There is no need to map it as
M__function (with two underscores) because
M_function does not conflict with a PHP reserved word.
However, it is still possible for the flattened mapping to generate identifiers that conflict with PHP reserved words. For instance, the Slice identifier
require::once must be mapped as
_require_once in order to avoid conflict with the PHP reserved word
require_once.
PHP has a limited set of primitive types: boolean,
integer,
double, and
string. The Slice built‑in types are mapped to PHP types as shown in
Table 28.2.
PHP’s integer type may not accommodate the range of values supported by Slice’s
long type, therefore
long values that are outside this range are mapped as strings. Scripts must be prepared to receive an integer or string from any operation that returns a
long value.
enum Fruit { Apple, Pear, Orange };
class Fruit {
const Apple = 0;
const Pear = 1;
const Orange = 2;
}
Slice structures map to PHP classes. For each Slice data member, the PHP class contains a variable of the same name. For example, here is our
Employee structure from
Section 4.9.4 yet again:
struct Employee {
long number;
string firstName;
string lastName;
};
class Employee {
var $number;
var $firstName;
var $lastName;
}
Slice sequences are mapped to native PHP indexed arrays. The first element of the Slice sequence is contained at index 0 (zero) of the PHP array, followed by the remaining elements in ascending index order.
// Make a small platter with one Apple and one Orange
//
$platter = array(Fruit::Apple, Fruit::Orange);
Slice dictionaries map to native PHP associative arrays. The PHP mapping does not currently support all Slice dictionary types, however, because native PHP associative arrays support only integer and string key types. A Slice dictionary whose key type is
boolean,
byte,
short,
int or
long is mapped as an associative array with an integer key.
1 A Slice dictionary with a string key type is mapped as associative array with a string key. All other key types cause a warning to be generated.
$e1 = new Employee;
$e1‑>number = 42;
$e1‑>firstName = "Stan";
$e1‑>lastName = "Lipmann";
$e2 = new Employee;
$e2‑>number = 77;
$e2‑>firstName = "Herb";
$e2‑>lastName = "Sutter";
$em = array($e1‑>number => $e1, $e2‑>number => $e2);
const bool AppendByDefault = true;
const byte LowerNibble = 0x0f;
const string Advice = "Don't Panic!";
const short TheAnswer = 42;
const double PI = 3.1416;
enum Fruit { Apple, Pear, Orange };
const Fruit FavoriteFruit = Pear;
define("AppendByDefault", true);
define("LowerNibble", 15);
define("Advice", "Don't Panic!");
define("TheAnswer", 42);
define("PI", 3.1416);
class Fruit {
const Apple = 0;
const Pear = 1;
const Orange = 2;
}
define("FavoriteFruit", Fruit::Pear);
A Slice exception maps to a PHP class. For each exception member, the corresponding class contains a variable of the same name. All user exceptions ultimately derive from
Ice_UserException (which, in turn, derives from
Ice_Exception, which derives from PHP’s base
Exception class):
abstract class Ice_Exception extends Exception {
function __construct($message = '') {
...
}
}
abstract class Ice_UserException extends Ice_Exception {
function __construct($message = '') {
...
}
}
If the exception derives from a base exception, the corresponding PHP class derives from the mapped class for the base exception. Otherwise, if no base exception is specified, the corresponding class derives from
Ice_UserException.
exception GenericError {
string reason;
};
exception BadTimeVal extends GenericError {};
exception BadZoneName extends GenericError {};
class GenericError extends Ice_UserException {
function __construct($message = '') {
...
}
var $reason;
}
class BadTimeVal extends GenericError {
function __construct($message = '') {
...
}
}
class BadZoneName extends GenericError {
function __construct($message = '') {
...
}
}
try {
...
} catch(BadZoneName $ex) {
// Handle BadZoneName
} catch(GenericError $ex) {
// Handle GenericError
} catch(Ice_Exception $ex) {
// Handle all other Ice exceptions
print_r($ex);
}
The Ice run time throws run-time exceptions for a number of pre-defined error conditions. All run-time exceptions directly or indirectly derive from
Ice_LocalException (which, in turn, derives from
Ice_Exception, which derives from PHP’s base
Exception class):
abstract class Ice_Exception extends Exception {
function __construct($message = '') {
...
}
}
abstract class Ice_LocalException extends Ice_Exception {
function __construct($message = '') {
...
}
}
An inheritance diagram for user and run-time exceptions appears in Figure 4.4 on
page 110. Note however that the PHP mapping only defines classes for the local exceptions listed below:
Instances of all remaining local exceptions are converted to the class Ice_UnknownLocalException. The
unknown member of this class contains a string representation of the original exception.
A Slice interface maps to a PHP interface. Each operation in the interface maps to a method of the same name, as described in
Section 28.4.9. The inheritance structure of the Slice interface is preserved in the PHP mapping, and all interfaces ultimately derive from
Ice_Object:
interface A {
void opA();
};
interface B extends A {
void opB();
};
interface A implements Ice_Object
{
function opA();
}
interface B implements A
{
function opB();
}
A Slice class maps to an abstract PHP class. Each operation in the class maps to an abstract method of the same name, as described in
Section 28.4.9. For each Slice data member, the PHP class contains a variable of the same name. The inheritance structure of the Slice class is preserved in the PHP mapping, and all classes ultimately derive from
Ice_ObjectImpl (which, in turn, implements
Ice_Object):
class Ice_ObjectImpl implements Ice_Object
{
}
class TimeOfDay {
short hour; // 0 ‑ 23
short minute; // 0 ‑ 59
short second; // 0 ‑ 59
string format(); // Return time as hh:mm:ss
};
abstract class TimeOfDay extends Ice_ObjectImpl
{
var $hour;
var $minute;
var $second;
abstract function format();
}
Class factories are installed by invoking addObjectFactory on the communicator (see
Section 28.4.11). A factory must implement the interface
Ice_ObjectFactory, defined as follows:
interface Ice_ObjectFactory implements Ice_LocalObject
{
function create(/* string */ $id);
function destroy();
}
class TimeOfDayI extends TimeOfDay {
function format()
{
return sprintf("%02d:%02d:%02d", $this‑>hour,
$this‑>minute, $this‑>second);
}
}
class TimeOfDayFactory extends Ice_LocalObjectImpl
implements Ice_ObjectFactory {
function create($id)
{
return new TimeOfDayI;
}
function destroy() {}
}
$ICE‑>addObjectFactory(new TimeOfDayFactory, "::M::TimeOfDay");
Each operation defined in a Slice class or interface is mapped to a PHP function of the same name. Furthermore, each parameter of an operation is mapped to a PHP parameter of the same name, with
out parameters passed by reference. Since PHP is a loosely-typed language, no parameter types are specified.
2
interface I {
float op(string s, out int i);
};
An untyped proxy is equivalent to the Slice type
Object*. The communicator operation
stringToProxy returns an untyped proxy, as do several of the core proxy methods. A script cannot invoke user-defined operations on an untyped proxy, nor can an untyped proxy be passed as an argument where a typed proxy is expected.
A typed proxy is one that has been associated with a Slice class or interface type. There are two ways a script can obtain a typed proxy:
$obj = $ICE‑>stringToProxy("a:tcp ‑p 12345");
$obj‑>opA(); // WRONG!
$a = $obj‑>ice_checkedCast("::A");
$a‑>opA(); // OK
Attempting to invoke opA on
$obj would result in a fatal error, because
$obj is an untyped proxy.
The Ice_ObjectPrx interface supplies the standard proxy methods described in
Section 32.10.2, as well as two additional methods for downcasting purposes:
interface Ice_ObjectPrx {
/* ... standard proxy methods ... */
function ice_uncheckedCast(/* string */ $type,
/* string */ $facet = null);
function ice_checkedCast(/* string */ $type,
/* string */ $facet = null);
}
$p = $ICE‑>stringToProxy("a:tcp ‑p 12345");
$p = $p‑>ice_oneway();
$p = $p‑>ice_secure(true);
$p = $p‑>ice_uncheckedCast("::A");
The script receives an untyped proxy as the return value of stringToProxy. Since the stringified proxy did not contain any proxy options, it is configured by default as a twoway, insecure proxy with no timeout. However, our goal is to obtain a secure oneway proxy for interface
A, therefore we invoke
ice_oneway, followed by
ice_secure. At this point, we have an untyped proxy configured for secure oneway invocations. Finally, we call
ice_uncheckedCast to obtain a typed proxy.
3
$p = $ICE‑>stringToProxy("a:tcp ‑p 12345");
$p = $p‑>ice_oneway()‑>ice_secure(true)‑>ice_uncheckedCast("::A");
The order that the proxy factory methods are invoked is usually not important, except in the case of
ice_checkedCast and
ice_uncheckedCast. For example, if the script above had invoked
ice_uncheckedCast first, followed by the other factory methods, then the result would have been an untyped proxy:
$p = $ICE‑>stringToProxy("a:tcp ‑p 12345");
$p = $p‑>ice_uncheckedCast("::A"); // WRONG!
$p = $p‑>ice_oneway();
$p = $p‑>ice_secure(true);
The reason for this unexpected behavior is that most of the factory methods return an untyped proxy, thereby discarding any type that might have been associated with the original proxy. By invoking
ice_oneway on the typed proxy returned from
ice_uncheckedCast, the script has lost its typed proxy.
All remote operations on a proxy support an optional final parameter of type Ice::Context representing the request context. The standard PHP mapping for the request context is an associative array in which the keys and values are strings. For example, the code below illustrates how to invoke
ice_ping with a request context:
$p = $ICE‑>stringToProxy("a:tcp ‑p 12345");
$ctx = array("theKey" => "theValue");
$p‑>ice_ping($ctx);
Certain core proxy operations use the type Ice_Identity, which is the PHP mapping for the Slice type
Ice::Identity (see
Section 32.5). This type is mapped using the standard rules for Slice structures, therefore it is defined as follows:
class Ice_Identity {
var $name;
var $category;
}
Two communicator functions are provided for converting Ice_Identity values to and from a string representation. See
Section 28.4.11 for details.
28.4.11 Mapping for Ice::Communicator
Since the Ice extension for PHP provides only client-side facilities, many of the operations provided by
Ice::Communicator operations are not relevant, therefore the PHP mapping supports a subset of the communicator operations. The mapping for
Ice::Communicator is shown below:
interface Ice_Communicator {
function getProperty(/* string */ $name,
/* string */ $def = "");
function stringToProxy(/* string */ $str);
function proxyToString(/* Ice_ObjectPrx */ $prx);
function propertyToProxy(/* string */ $property);
function stringToIdentity(/* string */ $str);
function identityToString(/* Ice_Identity */ $id);
function addObjectFactory(/* Ice_ObjectFactory */ $factory,
/* string */ $id);
function findObjectFactory(/* string */ $id);
function flushBatchRequests();
}
The getProperty method returns the value of a configuration property. If the property is not defined, the method returns the default value if one was provided, otherwise the method returns an empty string.
See Section 32.10.2for a description of the remaining operations.
PHP scripts are not allowed to create or destroy communicators. Rather, a communicator is created prior to each PHP request, and is destroyed after the request completes.
The communicator instance created for a request is available to the script via the global variable
$ICE. Scripts should not attempt to assign a different value to this variable. As with any global variable, scripts that need to use
$ICE from within a function must declare the variable as global:
function printProxy($prx) {
global $ICE;
print $ICE‑>proxyToString($prx);
}