【问题标题】:API Platform + alice UserDataPersister not working with fixturesAPI 平台 + alice UserDataPersister 无法使用固定装置
【发布时间】:2021-04-19 19:54:17
【问题描述】:

我配置了以下 UserDataPersister(直接取自 tutorial):

Information for Service "App\DataPersister\UserDataPersister"
============================================================= 
  Service ID       App\DataPersister\UserDataPersister            
  Class            App\DataPersister\UserDataPersister            
  Tags             api_platform.data_persister (priority: -1000)  
  Public           no                                             
  Shared           yes                                            
  Abstract         no                                             
  Autowired        yes                                            
  Autoconfigured   yes                                            

和以下用户夹具:

App\Entity\User:
    user_{1..10}:
        email: "usermail_<current()>\\@email.org"
        plainPassword: "plainPassword_<current()>"
        __calls:
          - initUuid: []

但加载此夹具时出现错误:

  An exception occurred while executing 'INSERT INTO "user" (id, uuid, roles, password, email) VALUES (?, ?, ?, ?, ?)' with params [281, "16ac40d3-53af-45dc-853f-e26f188d  
  1818", "[]", null, "usermail1@email.org"]:                                                                                                                                
                                                                                                                                                                            
  SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "password" of relation "user" violates not-null constraint                                            
  DETAIL:  Failing row contains (281, 16ac40d3-53af-45dc-853f-e26f188d1818, [], null, usermail1@email.org).                                                                 

我的 UserDataPersister 实现与this 相同。

【问题讨论】:

  • 您能否编辑您的问题以包含App\DataPersister\UserDataPersister 的源代码?
  • @ArleighHix,我添加了一个指向我复制的代码的链接。
  • idk 为什么他们在模型中使用字段,最好的方法是将模型与您的数据对象分开。这样,您始终可以利用良好的旧数据结构,然后将数据对象从端点分别传入和传出。 DTO / Normalizers 是实现这一点的最佳方式。我不明白为什么作者选择这样做,这似乎从字面上滥用框架和学说。
  • 这个错误的产生是因为你的fixture代码不会触发encodePassword,你的持久化器只有在通过端点真正请求时才会被调用。根据代码,每当请求到来并且 api paltform 捕获事件时,密码字段都来自 DataPersistor。 Fixtures 不会生成将触发此持久器的内核事件,因为它不是框架的一部分。你可以在你的夹具中调用编码密码方法来通过自定义 Faker 或其他方法解决这个问题。
  • @MaulikParmar 本教程是从旧的 Symfony 版本发展而来的,所以我想他们太“懒惰”了,无法修改它以适应新的模式和实践。

标签: symfony fixtures api-platform.com alice


【解决方案1】:

引自文章末尾

如果我们现在停下来……耶!我们没有……真的……做任何事:我们 添加了这个新的 plainPassword 属性...但没有使用它!所以, 该请求最终会在数据库中爆炸,因为我们的 $password 字段将为空。

接下来,我们需要挂钩到请求处理过程:我们需要 在反序列化之后但在持久化之前运行一些代码。干的好 使用数据持久化器。

由于单元测试会 POST 请求,因此数据持久化器由 api-platform 调用,它将按事件获取编码逻辑。在夹具的情况下,直接进行教条批量插入,这将绕过所有持久性逻辑并导致密码为空。

@rishta 提到有一种方法可以解决这个问题,如 Documentation 中所引用的,使用处理器实现数据夹具的哈希

<?php
namespace App\DataFixtures\Processor;

use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Fidry\AliceDataFixtures\ProcessorInterface;
use App\Entity\User;

final class UserProcessor implements ProcessorInterface
{
    private $userPasswordEncoder;

    public function __construct(EntityManagerInterface $entityManager, UserPasswordEncoderInterface $userPasswordEncoder) {
        $this->userPasswordEncoder = $userPasswordEncoder;
    }

    /**
     * @inheritdoc
     */
    public function preProcess(string $fixtureId, $object): void {
        if (false === $object instanceof User) {
            return;
        }

        $object = $this->userPasswordEncoder(
                $object,
                $object->getPlainPassword()
        );
    }

    /**
     * @inheritdoc
     */
    public function postProcess(string $fixtureId, $object): void
    {
        // do nothing
    }
}

注册服务:

# app/config/services.yml

services:
    _defaults:
        autoconfigure: true

    App\DataFixtures\Processor\UserProcessor: ~
        #add tag in case autoconfigure is disabled, no need for auto config
        #tags: [ { name: fidry_alice_data_fixtures.processor } ]

在 API 平台中进行输入屏蔽的更好方法之一是使用与文章建议相反的 DTO 模式,您可以在其中:

  • 创建单独的输入和输出数据对象
  • 在对象之间转换基础日期
  • 根据需要为每个操作选择不同的 IO 对象

documentation 中有关 DTO 的更多信息

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多