@ 2015-07-02T01:53:00Z <?php
declare(strict_types=1);
namespace Dshafik;
class Struct {
// Because gettype() and ReflectionType->__toString() are inconsistent
/**
* @var array Type mappings
*/
private $__typeMap = [
'int' => 'integer',
'bool' => 'boolean',
'float' => 'double',
];
/**
* @var array Reflection data
*/
private $__reflection = [];
/**
* @var array The struct values
*/
protected $__values = [];
public function __construct()
{
$this->introspect();
$this->hoist(func_get_args());
}
public function __get($what)
{
return $this->__values[$what];
}
public function __set($what, $value)
{
if (($type = gettype($value)) === $this->__reflection[$what]) {
return $this->__values[$what] = $value;
} else {
throw new \TypeError("Key '$what' must be of type {$this->__reflection[$what]}, $type given.");
}
}
final protected function introspect()
{
if ($this->__reflection) {
return;
}
$class = new \ReflectionObject($this);
$constructor = $class->getConstructor();
foreach ($constructor->getParameters() as $arg) {
$type = (string) $arg->getType();
$this->__reflection[$arg->name] = $this->__typeMap[$type] ?? $type;
}
}
final protected function hoist($args)
{
$this->introspect();
$i = 0;
foreach ($this->__reflection as $key => $type) {
$this->__set($key, $args[$i]);
$i++;
}
}
}
// With strict types, will throw a TypeError, or coerce otherwise on mismatch
$struct = new class(1, "Hello") extends Struct {
public function __construct(int $foo, string $bar) {
$this->hoist(func_get_args());
}
};
var_dump($struct);
// Works
$struct->foo = 2;
var_dump($struct);
// Will throw a TypeError
$struct->foo = 'World';
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
Output for 8.0.0 - 8.0.30 , 8.1.0 - 8.1.28 , 8.2.0 - 8.2.18 , 8.3.0 - 8.3.6 object(Dshafik\Struct@anonymous)#1 (3) {
["__typeMap":"Dshafik\Struct":private]=>
array(3) {
["int"]=>
string(7) "integer"
["bool"]=>
string(7) "boolean"
["float"]=>
string(6) "double"
}
["__reflection":"Dshafik\Struct":private]=>
array(2) {
["foo"]=>
string(7) "integer"
["bar"]=>
string(6) "string"
}
["__values":protected]=>
array(2) {
["foo"]=>
int(1)
["bar"]=>
string(5) "Hello"
}
}
object(Dshafik\Struct@anonymous)#1 (3) {
["__typeMap":"Dshafik\Struct":private]=>
array(3) {
["int"]=>
string(7) "integer"
["bool"]=>
string(7) "boolean"
["float"]=>
string(6) "double"
}
["__reflection":"Dshafik\Struct":private]=>
array(2) {
["foo"]=>
string(7) "integer"
["bar"]=>
string(6) "string"
}
["__values":protected]=>
array(2) {
["foo"]=>
int(2)
["bar"]=>
string(5) "Hello"
}
}
Fatal error: Uncaught TypeError: Key 'foo' must be of type integer, string given. in /in/dC8Lu:42
Stack trace:
#0 /in/dC8Lu(86): Dshafik\Struct->__set('foo', 'World')
#1 {main}
thrown in /in/dC8Lu on line 42
Process exited with code 255 . Output for 7.4.0 - 7.4.33 Deprecated: Function ReflectionType::__toString() is deprecated in /in/dC8Lu on line 55
Deprecated: Function ReflectionType::__toString() is deprecated in /in/dC8Lu on line 55
object(class@anonymous)#1 (3) {
["__typeMap":"Dshafik\Struct":private]=>
array(3) {
["int"]=>
string(7) "integer"
["bool"]=>
string(7) "boolean"
["float"]=>
string(6) "double"
}
["__reflection":"Dshafik\Struct":private]=>
array(2) {
["foo"]=>
string(7) "integer"
["bar"]=>
string(6) "string"
}
["__values":protected]=>
array(2) {
["foo"]=>
int(1)
["bar"]=>
string(5) "Hello"
}
}
object(class@anonymous)#1 (3) {
["__typeMap":"Dshafik\Struct":private]=>
array(3) {
["int"]=>
string(7) "integer"
["bool"]=>
string(7) "boolean"
["float"]=>
string(6) "double"
}
["__reflection":"Dshafik\Struct":private]=>
array(2) {
["foo"]=>
string(7) "integer"
["bar"]=>
string(6) "string"
}
["__values":protected]=>
array(2) {
["foo"]=>
int(2)
["bar"]=>
string(5) "Hello"
}
}
Fatal error: Uncaught TypeError: Key 'foo' must be of type integer, string given. in /in/dC8Lu:42
Stack trace:
#0 /in/dC8Lu(86): Dshafik\Struct->__set('foo', 'World')
#1 {main}
thrown in /in/dC8Lu on line 42
Process exited with code 255 . Output for 7.0.0 - 7.0.33 , 7.1.0 - 7.1.33 , 7.2.0 - 7.2.33 , 7.3.0 - 7.3.33 object(class@anonymous)#1 (3) {
["__typeMap":"Dshafik\Struct":private]=>
array(3) {
["int"]=>
string(7) "integer"
["bool"]=>
string(7) "boolean"
["float"]=>
string(6) "double"
}
["__reflection":"Dshafik\Struct":private]=>
array(2) {
["foo"]=>
string(7) "integer"
["bar"]=>
string(6) "string"
}
["__values":protected]=>
array(2) {
["foo"]=>
int(1)
["bar"]=>
string(5) "Hello"
}
}
object(class@anonymous)#1 (3) {
["__typeMap":"Dshafik\Struct":private]=>
array(3) {
["int"]=>
string(7) "integer"
["bool"]=>
string(7) "boolean"
["float"]=>
string(6) "double"
}
["__reflection":"Dshafik\Struct":private]=>
array(2) {
["foo"]=>
string(7) "integer"
["bar"]=>
string(6) "string"
}
["__values":protected]=>
array(2) {
["foo"]=>
int(2)
["bar"]=>
string(5) "Hello"
}
}
Fatal error: Uncaught TypeError: Key 'foo' must be of type integer, string given. in /in/dC8Lu:42
Stack trace:
#0 /in/dC8Lu(86): Dshafik\Struct->__set('foo', 'World')
#1 {main}
thrown in /in/dC8Lu on line 42
Process exited with code 255 . Output for 5.4.0 - 5.4.45 , 5.5.0 - 5.5.38 , 5.6.0 - 5.6.40 Warning: Unsupported declare 'strict_types' in /in/dC8Lu on line 2
Parse error: syntax error, unexpected '?' in /in/dC8Lu on line 56
Process exited with code 255 . Output for 5.3.0 - 5.3.29 Warning: Unsupported declare 'strict_types' in /in/dC8Lu on line 2
Parse error: syntax error, unexpected '[' in /in/dC8Lu on line 10
Process exited with code 255 . Output for 4.4.2 - 4.4.9 , 5.1.0 - 5.1.6 , 5.2.0 - 5.2.17 Parse error: syntax error, unexpected T_STRING in /in/dC8Lu on line 3
Process exited with code 255 . Output for 4.3.0 - 4.3.1 , 4.3.5 - 4.3.11 , 4.4.0 - 4.4.1 , 5.0.0 - 5.0.5 Parse error: parse error, unexpected T_STRING in /in/dC8Lu on line 3
Process exited with code 255 . Output for 4.3.2 - 4.3.4 Parse error: parse error in /in/dC8Lu on line 3
Process exited with code 255 . preferences:dark mode live preview
311.88 ms | 401 KiB | 459 Q