silvanus/structs

PHP 结构体。简单的数据传输对象。

v1.1.2 2023-04-23 07:00 UTC

This package is auto-updated.

Last update: 2024-09-11 18:34:43 UTC


README

PHP 结构体。简单的数据传输对象。

安装

通过 Composer

composer require silvanus/structs

为了使用自动加载机制,您必须在您的代码中包含 vendor/autoload.php 文件。

动机

PHP 没有真正的结构体。许多其他语言如 C++、Rust 或 Go 中都有这一特性。TypeScript 接口也与结构体相似。结构体对于具有形状的简单数据(如数据传输对象)来说是有用的。

在 PHP 中,您不能要求接口中的属性,只有方法。因此,结构体类似对象的接口并没有太大的意义。但是,如果您只使用一个具有公共属性的课程,您仍然会让客户端动态地声明新的属性。最好是保持数据的形状与结构体定义的方式相同。

这个库旨在通过提供具有合理默认值的 AbstractStruct 类来解决这个问题,以阻止动态分配新的或不正确的类属性/成员。

使用方法

声明新的结构体。

<?php

namespace YourNameSpace\Structs;

// Parent class.
use Silvanus\Structs\AbstractStruct;

class Employee extends AbstractStruct
{    
    public string $name;    
    public string $department;
    public int $salary;
}

使用新结构体

<?php

use YourNameSpace\Structs\Employee;

$employee = new Employee();

// Set up data by property.
$employee->name       = 'Eiríkr Blóðøx';
$employee->department = 'Norway';
$employee->salary     = 954;

echo $employee->name; // Eiríkr Blóðøx

/**
 * You can only use properties set in class / struct level.
 */
$employee->hobbies = "Raiding"; // Throws CanNotSetPropertyException.
echo $employee->hobbies // Throws CanNotGetPropertyException

您也可以在创建时直接填充结构体。

<?php

use YourNameSpace\Structs\Employee;

$data = array(
	'name' => 'Eiríkr Blóðøx',
	'department' => 'Norway',
	'salary' => 954,
	// Setting incorrect fields here will likewise throw exceptions.
);

$employee = new Employee($data);

不可变版本

您还可以使用一个不允许一旦设置就修改数据的结构体版本。

创建不可变结构体

<?php

namespace YourNameSpace\Structs;

// Different parent class
use Silvanus\Structs\AbstractStructImmutable;

class EmployeeImmutable extends AbstractStructImmutable
{    
    public string $name;    
    public string $department;
    public int $salary;
}

使用不可变结构体

<?php

use YourNameSpace\Structs\EmployeeImmutable;

$data = array(
	'name' => 'Eiríkr Blóðøx',
	'department' => 'Norway',
	'salary' => 954,
	// Setting incorrect fields here will likewise throw exceptions.
);

$employee = new EmployeeImmutable($data);

// You can access the properties.
echo $employee->name;
echo $employee->department;
echo $employee->salary;

// ... But you cannot edit them.
$employee->name = 'Eiríkr inn rauða'; // Throws CanNotSetPropertyException.

与直接使用默认类或数组相比的优势是什么

  • 您可以锁定附加属性的创建。这样,您的数据保持您期望的形状。
  • 您保护属性免受拼写错误的影响。$employee->salary 是有效的,但 $employee->salayr 会抛出异常。
  • 类型提示 Employee $employee

它是如何工作的?

没有太多花哨的!只是在抽象父类上写 final __setfinal __get 方法。它们阻止获取和创建未声明的属性。子类仍然可以添加公共属性,因为调用公共属性不会触发 __get__set

不可变版本的工作方式略有不同。它首先将给定的属性设置在公共属性中,以触发 PHP 类型验证(如果 7.4 或更高),但之后删除这些值,并将它们存储在单个数组中。 __get 自动使用此 $properties 数组来提供值。