Skip to content

Instantly share code, notes, and snippets.

@jsylvanus
Last active January 5, 2019 20:07
Show Gist options
  • Save jsylvanus/72526fb10585345380f09cfe1c5a5a37 to your computer and use it in GitHub Desktop.
Save jsylvanus/72526fb10585345380f09cfe1c5a5a37 to your computer and use it in GitHub Desktop.
Structs in PHP. Work in progress.
<?php
require("struct.php");
class FooClass
{
use Struct;
public $property;
}
class MyStruct
{
use Struct;
/** @var FooClass */
public $foo_class;
/** @var integer */
public $bar_int;
/** @var Testing\Bar */
public $baz;
}
$tmp = new MyStruct(new FooClass("anything works here"), 456, new Testing\Bar());
<?php
trait Struct {
private function structGetTypeHint($docCommOutput)
{
if ($docCommOutput == null) {
return null;
}
if (preg_match('/@var\s+([^\s\*]+)/', $docCommOutput, $matches)) {
list(, $type) = $matches;
return $type;
}
return null;
}
private function structAssignArgs($args)
{
$refl = new \ReflectionClass($this);
$props = $refl->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
$val = null;
if (count($args) > 0) {
$val = array_shift($args);
}
$docComm = $prop->getDocComment();
$typeHint = $this->structGetTypeHint($docComm);
$valType = is_object($val) ? get_class($val) : gettype($val);
if ($typeHint !== null && $valType != $typeHint) {
$name = $prop->getName();
throw new \Exception("Type mismatch: property {$name} must be of type {$typeHint} but was {$valType}.");
}
$prop->setValue($this, $val);
}
}
public function __construct()
{
// would prefer C extension "phpstruct_treat_args_as_property_assignment()"
$this->structAssignArgs(func_get_args());
}
}

PHP Struct Trait

This should really be a C extension but this is an OK prototype of the concept. Structs in PHP!

TODO

  • Add magic setter to enforce type safety.
  • Like, maybe typed arrays?
  • Probably static caching the reflection info so we don't have to do the reflection dance on each instantiation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment