我是Symfony 4的新手,并试图为YML Nelmio/Alice编写自己的功能,但是在我运行bin/console doctrine:fixtures:load
之后,我得到了此错误:
在deepcopy.php行177中:
类" ReflectionClass"类不可链式。
这是我的fixtures.yml文件:
AppEntityPost:
post_{1..10}:
title: <customFunction()>
这是我的appfixture.php文件:
<?php
namespace AppDataFixtures;
use DoctrineBundleFixturesBundleFixture;
use DoctrineCommonPersistenceObjectManager;
use NelmioAliceLoaderNativeLoader;
class AppFixtures extends Fixture
{
public function load(ObjectManager $manager)
{
$loader = new NativeLoader();
$objectSet = $loader->loadFile(__DIR__.'/Fixtures.yml',
[
'providers' => [$this]
]
)->getObjects();
foreach($objectSet as $object) {
$manager->persist($object);
}
$manager->flush();
}
public function customFunction() {
// Some Calculations
return 'Yep! I have got my bonus';
}
}
研究了Nelmio/Alice新版本后,我找到了解决方案:
我们应该首先创建一个提供商,该提供商是包含我们新自定义功能的类。其次,扩展NativeLoader
类以注册我们的新提供商。第三,使用我们的新Nativeloader(这是CustomNativeloader(,它允许我们使用新的格式化器。
这是CustomFixtureProvider.php中的提供商:
<?php
namespace AppDataFixtures;
use FakerFactory;
class CustomFixtureProvider
{
public function title()
{
$faker = Factory::create();
$title = $faker->text($faker->numberBetween(20,100));
return $title;
}
}
作为旁注,title
函数为您的文章或帖子或帖子等生成了一些虚拟标题,这些标题具有动态长度在20..100字符之间。此功能使用Faker Alice内置格式化。
这是CustomNativeloader.php:
<?php
namespace AppDataFixtures;
use NelmioAliceFakerProviderAliceProvider;
use NelmioAliceLoaderNativeLoader;
use FakerFactory as FakerGeneratorFactory;
use FakerGenerator as FakerGenerator;
class CustomNativeLoader extends NativeLoader
{
protected function createFakerGenerator(): FakerGenerator
{
$generator = FakerGeneratorFactory::create(parent::LOCALE);
$generator->addProvider(new AliceProvider());
$generator->addProvider(new CustomFixtureProvider());
$generator->seed($this->getSeed());
return $generator;
}
}
这是LoadFixture.php:
<?php
namespace AppDataFixtures;
use AppDataFixturesCustomNativeLoader;
use DoctrineBundleFixturesBundleFixture;
use DoctrineCommonPersistenceObjectManager;
class LoadFixtures extends Fixture
{
public function load(ObjectManager $manager)
{
$loader = new CustomNativeLoader();
$objectSet = $loader->loadFile(__DIR__ . '/fixtures.yml')->getObjects();
foreach($objectSet as $object) {
$manager->persist($object);
}
$manager->flush();
}
}
,最后是使用我们的新title
格式化的示例:
AppEntityPost:
post_{1..10}:
title: <title()>
我知道这是编写较小功能的很长的路要走,但是根据我的调查,这是扩展新版本中格式器的标准方法。
您可以以这种简单的方式做到这一点:
1.创建自己的提供商(例如,在/src/datafixtures/faker/customprovider.php(:
<?php
namespace AppDataFixturesFaker;
class CustomProvider
{
public static function customFunction()
{
// Some Calculations
return 'Yep! I have got my bonus';
}
}
2.在config/services.yaml中注册提供商:
AppDataFixturesFakerCustomProvider:
tags: [ { name: nelmio_alice.faker.provider } ]
就是这样。
P.S。您可以在此处查看更多详细信息:https://github.com/hautelook/alicebundle/blob/master/doc/doc/faker-providers.md
也可能喜欢(补充解决方案bellow https://stackoverflow.com/a/54116196/261058(:
EntityServiceProvider.php
<?php
declare(strict_types=1);
namespace AppInfrastructureFixtureProvider;
use DoctrineORMEntityManagerInterface;
use Exception;
use FakerGenerator;
use FakerProviderBase;
class EntityServiceProvider extends Base
{
public function __construct(Generator $generator, private EntityManagerInterface $entityManager)
{
$this->unique(true);
parent::__construct($generator);
}
/**
* @template T of object
* @param class-string<T> $class
* @return T
* @throws Exception
*/
public function entityReference(string $class, string $columnName, string|int|bool $columnValue)
{
if (!class_exists($class)) {
throw new Exception(sprintf('Class "%s" does not exist or it isn't loaded', $class));
}
$repository = $this->entityManager->getRepository($class);
$foundEntity = $repository->findOneBy([$columnName => $columnValue]);
if (!$foundEntity instanceof $class) {
throw new Exception(sprintf('Entity "%s" with given criteria wasn't found', $class));
}
return $foundEntity;
}
}
服务定义:service.yaml
AppInfrastructureFixtureProviderEntityServiceProvider:
tags:
- { name: 'nelmio_alice.faker.provider' }
用法在固定装置中使用yaml
AppDomainLocationAddress:
address0:
id: '<numberBetween(3000,99999)>'
country: '<entityReference(AppDomainLocationCountry, code, DE)>'
从夹具yaml
加载对象protected function loadObjectsFromFixtures(array $files): array
{
return (new NativeLoader($this->getService(FakerGenerator::class)))->loadFiles($files)->getObjects();
}