bouw7/accessor-generator-plugin

此包已被弃用,不再维护。没有建议的替代包。

动态生成获取、设置、添加、删除方法。

安装: 376

依赖者: 0

建议者: 0

安全: 0

星级: 0

关注者: 1

分支: 10

类型:composer-plugin

5.0.2 2019-11-27 14:37 UTC

README

欢迎使用 Accessor Generator composer 插件。

目标

此插件的目标是为基于我们从文档注释中可以读取的信息的类提供动态生成的获取、设置、添加、删除访问器方法。目前我们可以处理 Doctrine ORM 注释。

由于代码是自动生成的,因此您不需要(单元)测试它,并且它将与大量添加的样板代码非常一致,这些样板代码将在您使用生成的函数时使用错误类型或数量的参数而导致您的代码过早失败。

限制

安装

hostnet/accessor-generator-plugin-lib 添加到您的 composer.json,然后运行 composer require hostnet/accessor-generator-plugin-lib

如果您想在安装后调用生成,可以运行 php composer.phar dump-autoload。向 dump-autoload 命令添加 -vv 以获得更多详细信息。

用法

<?php
namespace Hostnet\Product\Entity;

use Doctrine\ORM\Mapping as ORM;
use Hostnet\Component\AccessorGenerator\Annotation as AG;

/**
 * @ORM\Entity
 * @ORM\Table(name="periode")
 */
class Period
{
    use Generated\PeriodMethodsTrait;                   // This is the file that is generated with the
                                                        // accessor methods inside.
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(name="id", type="integer")
     * @AG\Generate                                     // Here you ask methods to be generated
     *
     * @var int
     */
    private $id;

    // ...
}

文件将在相对于当前文件的子目录和命名空间(Generated)中生成。此文件可以作为 trait 包含。

指定要生成的方法

您可以通过在注释中指定它们来禁用某些访问器方法的生成。

/**
 * @AG\Generate(add="none",set="none",remove="none",get="none",is="none")
 */

Isget 的别名。如果您的属性是布尔类型,将生成 isProperty 方法而不是 getProperty 方法。对于 ORM\GeneratedValue 属性,将不会生成设置器。**注意,上面的示例将不会生成任何代码**。

如果没有指定配置,对于所有标量类型属性,默认行为是生成获取器和设置器方法。当类型是可迭代的(例如,DoctrineCollection 或数组)时,将生成添加器和移除器。

加密

要在列的值上使用非对称加密,请将 'encryption_alias' 字段添加到 Generate 注释中。同时确保数据库列的类型有足够大的长度。对于密钥和 IV 至少需要 1064,再加上密封数据的长度。

/**
 * @AG\Generate(encryption_alias="database.table.column")
 */
 private $encrypted_variable;

在那里使用的别名应按如下方式添加到应用程序的 composer.json 中

"extra": {
     "accessor-generator": {
         <encryption_alias>: {
             "public-key": <public_key_file>
             "private-key": <private_key_file>
...

为了加密或解密数据,必须指定有效的私钥和公钥。

  • **公钥**用于加密数据。
  • **私钥**用于解密数据。

为了开始加密数据,需要公钥。然而,您首先需要一个私钥,才能从中提取公钥。我们可以使用 openssl 工具来完成此操作。

创建一个密钥

$ openssl genrsa -out database.table.column.private_key.pem 2048

从私钥中提取公钥

$ openssl rsa -in database.table.column.private_key.pem -pubout > database.table.column.public_key.pem

如果应用程序需要加密,添加公钥。如果应用程序需要解密,添加私钥。如果应用程序需要两者都要,添加两者。

<public_key_file><private_key_file>的值必须包含相对于composer.json文件的密钥的文件路径。

不要忘记在构造函数中使用setter方法来触发给定值的加密,而不是直接分配值给属性。

<?php
class MyEntity
{
    /**
     * @AG\Generate(encryption_alias="<encryption_alias>")
     */
    private $my_value;
    
    public function __construct(string $my_value)
    {
        $this->my_value = $my_value;  // No encryption is taking place.
        $this->setMyValue($my_value); // The value is now encrypted in the field.
    }
}

使用ENUM类的参数

从2.8.0版本开始,增加了参数化集合访问器的生成支持。由于需要PHP 7.1中添加的ReflectionConstant,因此增加了对PHP 7.1的支持。

想象一下有一个实体持有另一个实体(该实体持有参数)的ArrayCollection。例如

$task = new Task();
$task->setParam(MyParamEnum::I_CLIENT_ID, 123456);

echo $task->getParam(MyParamEnum); 
// 12345

正如你可能注意到的,尽管参数名称以I_开头——这表明我们正在处理一个整数——但你仍然可以设置任何数据类型,只要setParam的实现支持它。如果你在一个大型团队或较大的项目中工作,可能不是每个人都意识到存在一个枚举类,该类定义了所有常见的参数名称,这些名称应该在整个应用程序中用于此实体。

2.8.0版本引入了为枚举类生成访问器的功能。

要求

拥有实体(如上面的示例中的Task)必须实现一个属性,该属性为类型ArrayCollection,它
定义了一个与Parameter实体的OneToMany关系。

class Task
{
    // ...
    
    /**
     * @ORM\OneToMany(targetEntity="Parameter", cascade={"persist"})
     */
    private $parameters;

    // ...
}

Parameter实体必须实现以下内容

use Hostnet\Component\AccessorGenerator\Enum\EnumeratorCompatibleEntityInterface;

class Parameter implements EnumeratorCompatibleEntityInterface
{
    /**
     * @ORM\ManyToOne(targetEntity="Task")
     */
    private $owner;
    
    /**
     * @ORM\Column(type="string")
     */
    private $name;
    
    /**
     * @ORM\Column(type="string")
     * @AG\Generate()
     */
    private $value;
    
    // This signature is a requirement for enum accessor generation.
    public function __construct($task, string $name, ?string $value)
    {
        $this->owner = $task;
        $this->name  = $name;
        $this->value = $value;
    }
}

枚举类

"枚举类"仅由使用名称前缀以表示它们在数据库中持有的值的类型的公共常量组成。

以下类型受支持

前缀 类型 示例
S_ 字符串 "foobar"
I_ 整数 1234
F_ 浮点数 3.14
B_ 布尔值 true
A_ 数组 数组

现在,让我们以一个带有一些参数的枚举类为例

class MyTaskParamNames
{
    /**
     * Represents the client if the task is currently runnnig for.
     */
    public const I_CLIENT_ID = 'CLIENT_ID';
    
    /**
     * An awesome URL.
     */
    public const S_AWESOME_URL = 'https://www.hostnet.nl/';
}

现在我们有了三个类(TaskParameterMyTaskParamNames),我们可以开始生成代码。

"枚举器"注解

随着2.8.0版本的推出,出现了Enumerator注解,它可以在现有的Generate注解中使用。

从2.8.0升级到2.8.1:注解中的"name"设置已更改为"name"以更一致。从2.8.1版本开始,通过其他类属性添加内联枚举的能力已添加。有关更多信息,请参阅以下内容。

使用上面示例中编写的代码,我们可以通过修改我们的Task类的parameters属性的注解来生成MyTaskParamNames的访问器方法。

class Task
{
    use Generated\TaskMethodsTrait;

    /**
     * @ORM\OneToMany(targetEntity="Parameter", cascade={"persist"})
     * @AG\Generate(enumerators={
     *     @AG\Enumerator("MyTaskParamNames", property="my_params")
     * })
     */
    private $property;
    
    /**
     * @var Generated\MyTaskParamNamesEnum
     */
    private $my_params;
}

一旦代码生成,你将现在有一个新生成的类MyTaskParamNamesEnum在相对于MyTaskParamNames命名空间中的Generated目录(和命名空间)中。使用TaskMethodsTrait中的property设置生成对此类的访问器。

根据上面的代码,这个枚举的访问器将被调用为 getMyParams()。只要适合作为方法名,您可以给它任何名称。

代码生成后,您将每个参数有5个方法可以使用


$task = new Task();

// hasClientId() will check if a parameter with the name I_CLIENT_ID exists in the collection of parameters belonging to
// this Task instance.
if (! $task->getMyParams()->hasClientId()) {
    
    // Create the I_CLIENT_ID parameter with a value of 1234.
    $task->getMyParams()->setClientId(1234);  
}

// Update the value of the existng parameter.
$task->getMyParams()->setClientId(999);

// Retrieve the value
$client_id = $task->getMyParams()->getClientId();

// Clear the value (keeps the element in the collection, but nullifies the value).
// hasClientId() will now return FALSE as if the parameter doesn't exist.
$task->getMyParams()->clearClientId();

// Remove the element entirely, effectively dropping the record from the database.
$task->getMyParams()->removeClientId();

所有方法都是基于枚举类的前缀进行严格类型定义的。

查看ParamNameEnum 类,以了解生成的代码示例。

警告:如果使用枚举器,访问器方法(get/is/set/add/remove)的默认可见性将被设置为 none。如果您仍然需要生成这些方法,您必须明确指定它们。

多个枚举器

您可能已经注意到,Generate 注解的 enumerators 属性可以接受一个或多个 Enumerator 注解的列表。您可以指定一个或多个使用相同集合作为其“存储”的枚举类。

如果您的注解看起来像这样

/**
 * @AG\Generate(enumerators={
 *     @AG\Enumerator("MyTaskParamNames", property="my_params"),
 *     @AG\Enumerator("BetterParamNames", property="better_params")
 * });
 */
 private $parameters;
 
 /**
  * @var Generated\MyTaskParamNamesEnum
  */
 private $my_params;
 
 /**
  * @var Generated\BetterParamNamesEnum
  */
 private $better_params;

生成器现在将为这些参数枚举创建两个访问器,您可以使用如下方式使用它们

$task->getMyParams()->hasClientId();       // From MyTaskParamNames
$task->getBetterParams()->setFoobar(1234); // From BetterParamNames

分离的枚举器访问器生成

您还可以在 @Generate 注解之外定义枚举器。如果与 entity-plugin-lib 结合使用,可以定义一个包含引用实体集合的枚举属性的 trait

假设我们想向之前编写过的 - 已存在的 - Task 实体添加一个额外的枚举器。

use Hostnet\Component\AccessorGenerator\Annotation as AG;

trait TaskTrait
{
    use Generated\TaskTraitMethodsTrait;

    /**
     * @AG\Enumerator("\My\Namespace\MyExtraParamName", name="parameters")
     * @var \My\Namespace\Generated\MyExtraParamNameEnum
     */
    private $some_extra_params;
}

name 设置指的是包含该实体所有参数的 ArrayCollection 属性。

一旦代码生成,您现在可以像调用任何其他枚举器一样调用枚举器

<?php

$task = new Task();
$task->getSomeExtraParams()->...

// Whilst still having access to the already existing enumerators that we defined before.
$task->getMyParams();
$task->getBetterParams();

确保在任务实体中包含 trait Generated\TaskTrait - 或您实体的任何名称 - 以使此操作正常。因此,

<?php
class Task
{
    use Generated\TaskMethodsTrait;
}

变为

<?php
class Task
{
    use Generated\TaskTrait;
    use Generated\TaskMethodsTrait;
}

请参阅entity-plugin-lib 获取更多信息。