6.2 KiB
CLR vs. PHP types
This article provides information on how the runtime treats .NET types. As a result, with respect to this specification, it is possible to pass values between .NET (assuming C#
) and PHP
code implicitly, without the need of marshalling or additional conversions.
Type System
The following table shows compatible .NET types and the corresponding PHP type:
.NET | PHP | PHP Features |
---|---|---|
PhpValue | mixed | |
bool | boolean | |
int, uint, long | integer | |
double, float | double | |
string, PhpString, byte[] | string | |
object | object | -> |
null | NULL | |
PhpResource | resource | is_resource |
PhpNumber | integer|double | |
PhpArray, ArrayAccess, IList | array, ArrayAccess | [] |
Iterator, IteratorAggregate, IEnumerable | iterable | foreach , is_iterable |
delegate, IPhpCallable, string, PhpArray(2) | callable | call_user_func , is_callable , etc. |
Nullable<T> | value|NULL | isset , unset |
System.Nullable<T>
Values can be read from and assigned to the Nullable<T>
type. Any value of type Nullable<T>
is treated as its contained value or NULL
. An automatic conversion is performed. The operator isset
is using the Nullable.HasValue
property implicitly.
class Test {
public int? Number; // nullable field
public double? Foo() { ... }; // return nullable from method
public void Bar(bool? b) { } // gets nullable parameter
}
<?php
$t = new Test;
$t->Number = 123; // assigns `new Nullable<int>(123)`
$t->Number = null; // assigns `default(Nullable<int>)`
isset( $t->Number ); // gets Number.HasValue
print_r( $t->Foo() ); // gets NULL or double
$t->Bar( NULL ); // passes `default(Nullable<bool>)` to the method
$t->Bar( true ); // passes `new Nullable<bool>(true)` to the method
System.Delegate
PHP's concept of callables works with string
pointing to a function name, array
of two dimensions referring to a class and its method, classes with the __invoke
method or instances of the Closure
class. Variables of these types, denoted as callable
, can be used for indirect calls as depicted in the sample below:
<?php
assert( is_callable($delegate) );
print_r( $delegate($arg1, $arg2) ); // $delegate is `callable`
PeachPie extends the set of callable
types with any CLR delegate
or objects implementing the IPhpCallable
interface (Peachpie.Runtime.dll).
Sample C# code that passes a delegate to a PHP global variable:
mycontext.Globals["delegate"] = new Func<string, bool>( str => str.IsNormalized() );
System.Collections.IEnumerable
The sample PHP code below is able to consume a variety of CLR objects in addition to PHP's array
and Traversable
.
<?php
foreach ($enumerable as $key => $value) { }
$enumerable
may implement the following CLR interfaces:
IPhpEnumerable
(Peachpie.Runtime.dll) is the extended version ofIEnumerable
. Objects implementing this interface are capable of being enumerated in PHP'sforeach
.IDictionary
; objects implementing this interface.IEnumerable<(Key, Value)>
; objects implementingIEnumerable<>
ofValueTuple
with two items.IEnumerable<KeyValuePair<Key, Value>>
; objects implementingIEnumerable<>
ofKeyValuePair<,>
.IEnumerable
in general works withforeach
as well.$key
is auto-incremented starting with0
,$value
is the current value of the enumerator.
As a result, standard .NET classes such as .NET arrays, ArrayList
, List<>
, Dictionary<,>
or enumerators created using C# yield
are transparently supported by PHP's foreach
construct.
foreach
by reference
<?php
foreach ($enumerable as $key => &$value) { $value = 0; }
In order to support an iteration by reference, the enumerable object must return the value of type PhpAlias
from the enumerator. Otherwise an exception of type InvalidOperationException
is thrown.
System.Collections.IList
PHP allows the accessing of an array
and objects implementing ArrayAccess
with square brackets []
as shown in the example below:
<?php
echo $list[10];
PeachPie provides the feature for System.Collections.IList
, which allows consuming .NET arrays, List
s and other classes in PHP.
C# Event
Implemented in
1.2.0
(#1141)
PeachPie runtime allows working with .NET/CLR event
class members in order to register and unregister callables. The following code depicts a sample C# class and a sample PHP program adding and removing an anonymous function (or any PHP callable) to it.
class SampleContainer
{
public event EventHandler MyEvent;
}
<?php
$obj = new SampleContainer;
// add callable to the event handler:
$hook = $obj->MyEvent->add(
function ($sender, $arg) {
echo "hello!";
}
);
// remove callable from the event handler
$hook->close();
In PHP, the event
class member is represented by an instance of a special class #!php Pchp\Core\ClrEvent
with the following method:
#!php ClrEvent::add( callable $callback ): Pchp\Core\ClrEvent\Hook
The Pchp\Core\ClrEvent\Hook
class methods:
#!php Hook::close()
#!php Hook::dispose() // alias to close
C# Indexers
PHP array operator []
can be used on objects implementing C# indexers.
The following example defines a C# indexer with sample get
and set
accessors.
using System;
class SampleIndexer
{
string[] arr = new string[100];
// Define the indexer to allow to use [] operator.
public string this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}
}
The following PHP code makes use of the C# indexer implicitly.
<?php
$sample = new \SampleIndexer;
$sample[0] = "Hello";
echo $sample[0]; // prints "Hello"
The indexer implementation
#c# this[]
is a syntactic sugar that results in compiler generated specialget_Item
andset_Item
methods. PeachPie translates the array operator into the call to the correspondingget_Item
orset_Item
method.