Doctrine PHP DataFixture : "Compile Error: Cannot redeclare class" - php

I created a PHP class to generate some fixtures :
namespace DashboardBundle\DataFixtures\ORM;
use DashboardBundle\Entity\Property;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoadPropertyData extends AbstractFixture implements FixtureInterface, ContainerAwareInterface, OrderedFixtureInterface
{
/** #var ContainerInterface */
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load(ObjectManager $manager)
{
$properties = $this->container->get('dashboard.properties_generator');
foreach ($properties as $key => $propertyConfig) {
$property = new Property();
$property->setName($key);
$property->setType($propertyConfig);
$this->addReference('property-' . $key, $property);
$manager->persist($property);
}
$manager->flush();
}
public function getOrder()
{
return 1;
}
}
But I get this error :
➜ dashboard git:(guillaume) ✗ bin/console -v fixtures:load
/* ... some stuff ... */
[Symfony\Component\Debug\Exception\FatalErrorException]
Compile Error: Cannot redeclare class DashboardBundle\DataFixtures\ORM\LoadPropertyData
The namespace seems and the class name seems correct. There is no other file in the DashboardBundle\DataFixtures\ORM directory.
I tried to restart the servers (PHP-FPM and Nginx), I tried to clear the Symfony cache, but there is no effect.
In brief, I have no idea why Symfony throws this exception.
Any idea ? Thanks !

Related

Symfony doesn't load my custom validator defined as service

I'm trying to inject EntityManagerInterface in my custom validator, but I have this error:
Attempted to load class "validator_check_client_id" from the global namespace.
Did you forget a "use" statement?
My code is:
CheckClientId.php
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
/**
* #Annotation
*/
class CheckClientId extends Constraint{
public $message = 'Test';
public function validatedBy(){
return 'validator_check_client_id';
}
}
CheckClientIdValidator.php
namespace App\Validator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class CheckClientIdValidator extends ConstraintValidator{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager) {
$this->entityManager = $entityManager;
}
public function validate($value, Constraint $constraint){
//Todo
return;
}
}
services.yaml
validator.check_client_id:
class: App\Validator\CheckClientIdValidator
autowire: false
arguments:
$entityManager: '#doctrine.orm.entity_manager'
tags:
- {
name: validator.constraint_validator,
alias: validator_check_client_id,
}
Should I do an extra step to register my service? I think that symfony cannot find it because it is not properly registered.
I also tried to do what this answer says symfony validator as service not working, but I get a similar error:
Attempted to load class "app.validator.blog.slug_unique" from the global namespace.
Did you forget a "use" statement?
Do you have any idea what is happening?
Thank you for your help!
Thanks to autowire and autoconfig, all you really have to do is to get your class names right. No changes to services.yaml. Here is a working example using a fresh 5.2 project.
# src/Validator/CheckClientId.php
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
/** #Annotation */
class CheckClientId extends Constraint
{
public $message = 'CheckClientId';
}
# =============================
# src/Validator/CheckClientIdValidator
namespace App\Validator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
class CheckClientIdValidator extends ConstraintValidator
{
public function __construct(private EntityManagerInterface $entityManager)
{
}
public function validate($value, Constraint $constraint)
{
dump('validate ' . $value);
throw new UnexpectedValueException($value, 'string');
}
}
# ===============================
# Test Entity
# src/Entity/Client.php
namespace App\Entity;
use App\Validator as AcmeAssert;
class Client
{
/** #AcmeAssert\CheckClientId */
public $id = 42;
}
# ====================================
# Test Command
# src/Command/ValidateCommand
namespace App\Command;
use App\Entity\Client;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ValidateCommand extends Command
{
protected static $defaultName = 'test:validator';
public function __construct(private ValidatorInterface $validator)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$client = new Client();
$errors = $this->validator->validate($client);
echo $errors;
return Command::SUCCESS;
}
}
Get the test command working and move on from there.

Can't get the IriConverter from the container because it's not public

I trying to load the api_platform.iri_converter but get an error:
The \"api_platform.iri_converter\" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.
This is the code:
declare(strict_types=1);
namespace App\Security\Authorization\Voter;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class BaseVoter extends Voter
{
public ContainerInterface $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
}
declare(strict_types=1);
namespace App\Security\Authorization\Voter;
class VenueVoter extends BaseVoter
{
protected function voteOnAttribute(): bool
{
/** #var User $tokenUser */
$tokenUser = $token->getUser();
if (self::VENUE_CREATE === $attribute) {
$iri = $this->container->get('api_platform.iri_converter')->getItemFromIri($valueWithIri);
}
}
}
Do not inject the Container.
Instead, inject the IriConverter directly.
use ApiPlatform\Core\Bridge\Symfony\Routing\IriConverterInterface;
abstract class BaseVoter extends Voter
{
public IriConverterInterface $iriConverter;
public function __construct(IriConverterInterface $iriConverter)
{
$this->iriConverter = $iriConverter;
}
}

Symfony ContainerAwareCommand not found using Xdebug and PhpStorm

I am using PhpStorm with Symfony. What I am trying to do is to debug a Symfony command from inside the IDE by using the debug button (Shift + F9).
I am getting the following error.
PHP Fatal error: Class 'Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand' not found in /home/user/Projects/project1/symfony/src/AppBundle/Command/testScriptCommand.php on line 8
PHP Stack trace:
It's weird as I have followed the Symfony documentation for creating commands and I have included the following classes:
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class testScriptCommand extends ContainerAwareCommand
{
protected function configure(): void
{
$this->setName('app:test-script');
}
protected function execute(InputInterface $input, OutputInterface $output): void
{
echo 1;
}
}
The debugger works inside the IDE until line 8 and once try to continue it fails with the already mentioned fatal error.
It seems to me as line 4 is not actually importing the ContainerAwareCommand that is needed.
Any ideas?
Extend Symfony\Component\Console\Command\Command
Dependency Inject the ContainerInterface with your commands constructor, something like this - in my case using autowired services:
/** #var ContainerInterface $container */
protected $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
Then you should be able to call fe. $this->container->getParameter('project.parameter')
What documentation did you followed?
For creating Commands you need to extend Command, no ContainerAwareCommand
// src/Command/CreateUserCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CreateUserCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'app:create-user';
protected function configure()
{
// ...
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// ...
}
}
For more information: https://symfony.com/doc/current/console.html
EDIT:
Adding info...
ContainerAwareCommand is for Symfony version <= 2.6 https://symfony.com/doc/2.6/cookbook/console/console_command.html Soooo old

Symfony 3 unit test form with constructor

I am trying to unit test a form which has 2 dependencies (ObjectManager and EventDispatcher)
I had tried to follow official doc but without success.
My testing file:
<?php
namespace Lch\MediaBundle\Tests\Form;
use Lch\MediaBundle\Form\AddImageType;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\PreloadedExtension;
use Symfony\Component\Form\Test\TypeTestCase;
class AddImageTypeTest extends TypeTestCase
{
private $entityManager;
private $eventDispatcher;
protected function setUp()
{
$this->entityManager = $this->createMock(ObjectManager::class);
$this->eventDispatcher = $this->createMock(EventDispatcher::class);
parent::setUp();
}
protected function getExtensions()
{
$type = new AddImageType($this->entityManager, $this->eventDispatcher);
return array(
new PreloadedExtension(array($type), array()),
);
}
public function testSubmitValidData()
{
$form = $this->factory->create(AddImageType::class);
}
}
I got this error when I execute my test suite:
TypeError: Argument 1 passed to
LCH\MediaBundle\Form\AddImageType::__construct() must implement
interface Doctrine\Common\Persistence\ObjectManager, none given,
called in
/home/matthieu/www/lch/media/src/Lch/MediaBundle/vendor/symfony/symfony/src/Symfony/Component/Form/FormRegistry.php
on line 85
It seems that the job I do in the getExtensions method is not working, but cannot figure it out.
Does anyone have a clue?
ObjectManager is an interface, meaning you can't instantiate or pass it directly to other constructors.
If you are using Doctrine, replace it with Doctrine\ORM\EntityManager which implements ObjectManager interface and can be instantiated, otherwise replace it with your own implementation.
<?php
namespace Lch\MediaBundle\Tests\Form;
use Lch\MediaBundle\Form\AddImageType;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\PreloadedExtension;
use Symfony\Component\Form\Test\TypeTestCase;
class AddImageTypeTest extends TypeTestCase
{
private $entityManager;
private $eventDispatcher;
protected function setUp()
{
$this->entityManager = $this->createMock(EntityManager::class);
$this->eventDispatcher = $this->createMock(EventDispatcher::class);
parent::setUp();
}
protected function getExtensions()
{
$type = new AddImageType($this->entityManager, $this->eventDispatcher);
return array(
new PreloadedExtension(array($type), array()),
);
}
public function testSubmitValidData()
{
$form = $this->factory->create(AddImageType::class);
}
}

Container is non-object error in Symfony data fixtures

I'm trying to access to the service api.service.feedback in fixture class below but for some reason container returns error below on if statement in load() method:
ERROR: PHP Fatal error: Call to a member function has() on a non-object
Note: If anyone wants to know, the service api.service.feedback itself is accessible in all the controllers and has no problem with it.
<?php
namespace .........;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoadOrderFixtures extends AbstractFixture implements FixtureInterface, ContainerAwareInterface
{
/**
* #var ContainerInterface
*/
private $container;
/**
* {#inheritDoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* {#inheritDoc}
*/
public function load(ObjectManager $manager)
{
if ($this->container->has('api.service.feedback')) {
exit('EXISTS');
}
}
......
}
You are just implementing the ContainerAwareInterface. If you want the container, you have to inject it:
services:
bundle.service_name:
class: ...
calls:
- [ setContainer, [ #service_container ] ]
You can extend directly ContainerAware:
class LoadArticlesData extends ContainerAware implements FixtureInterface, OrderedFixtureInterface {
public function load(ObjectManager $manager)
{
$dummy = $this->container->getParameter('dynamic.dummy');
...
}
}

Categories