interface FooStruct
{
public function name() : string;
}
interface BarStruct
{
public function id() : int;
}
interface MyStruct
{
public function foo() : FooStruct;
public function bar() : BarStruct;
}
interface FooStruct
{
public function getName() : string;
public function setName(string $value) : FooStruct;
}
interface BarStruct
{
public function getId() : int;
public function setId(int $value) : BarStruct;
}
interface MyStruct
{
public function getFoo() : FooStruct;
public function setFoo(FooStruct $value) : MyStruct;
public function getBar() : BarStruct;
public function setBar(BarStruct $value) : MyStruct;
}
interface FooStruct
{
public function name() : string;
}
interface BarStruct
{
public function id() : int;
}
interface MyStruct
{
public function foo() : FooStruct;
public function bar() : BarStruct;
}
class Foo implements FooStruct
{
protected $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function name() : string
{
return $this->name;
}
}
class Bar implements BarStruct
{
protected $id;
public function __construct(string $id)
{
$this->id = $id;
}
public function id() : int
{
return $this->id;
}
}
class My implements MyStruct
{
protected $foo, $bar;
public function __construct(FooStruct $foo, BarStruct $bar)
{
$this->foo = $foo;
$this->bar = $bar;
}
public function foo() : FooStruct
{
return $this->foo;
}
public function bar() : BarStruct
{
return $this->bar;
}
}
使用接口进行类型提示: (如果 IDE 支持的话)
如果您不介意不进行严格的类型检查,那么另一种方法是在 IDE 中使用带注释的接口或类。
/**
* Interface My
* @property Foo $foo
* @property Bar $bar
*/
interface My
{
}
/**
* Interface Foo
* @property string|integer $id
* @property string $name
*/
interface Foo
{
}
/**
* Interface Bar
* @property integer $id
*/
interface Bar
{
}
这在 Google 上是相当高级的,所以我想我应该分享一个使用 PHP8语法的伪结构的实现。ToArray ()方法确实依赖于 Illumination Support Str 将键转换为 Snake case (对于针对 Laravel 模型的大规模分配非常有用) ,但是如果它不适合您的用例,就删除它。
基类:
<?php
namespace App\Infrastructure\Structs;
use App\Infrastructure\Exceptions\CannotMutateStructException;
use App\Infrastructure\Exceptions\ClassPropertyNotFoundException;
use Illuminate\Support\Str;
use ReflectionClass;
abstract class Struct
{
/**
* @param string $name
* @param mixed $value
* @throws CannotMutateStructException
*/
public function __set(string $name, mixed $value): void
{
throw new CannotMutateStructException(
'Structs are immutable. If you need mutable data then use a class instead.'
);
}
public function all(): array
{
$reflector = new ReflectionClass(static::class);
$response = [];
foreach ($reflector->getProperties() as $property) {
$response[$property->name] = $this->{$property->name};
}
return $response;
}
public function toArray(bool $snakeCase = false): array
{
$all = self::all();
if ($snakeCase === false) {
return $all;
}
$snakeCaseAll = [];
foreach ($all as $key => $value) {
$snakeCaseAll[Str::snake($key)] = $value;
}
return $snakeCaseAll;
}
}
使用方法:
<?php
namespace App\Infrastructure\Structs;
class Person extends Struct
{
public function __construct(
public string $name,
public int $age,
public int $heightInCentimetres,
) {}
}
如何与之互动:
>>> $t = new \App\Infrastructure\Structs\Person('Max', 26, 182);
>>> $t->age
=> 26
>>> $t->age = 40
App\Infrastructure\Exceptions\CannotMutateStructException with message 'Structs are immutable. If you need mutable data then use a class instead.'
>>> $t->toArray(true)
=> [
"name" => "Max",
"age" => 26,
"height_in_centimetres" => 182,
]