Issue when trying to reload the fixtures - symfony

When I try to reload my fixtures using
php app/console doctrine:fixtures:load
I'm getting this error:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails (foo_db.Book, CONSTRAINT FK_C29271DD816C6140 FOREIGN KEY (author_id) REFERENCES Author (id))
The error is showed when the status "> purging database" is showed.
This is my code:
class Book{
...
/**
* #ORM\ManyToOne(targetEntity="Author", inversedBy="books")
*/
private $author;
...
}
class Author{
...
/**
* #ORM\OneToMany(targetEntity="Book", mappedBy="author")
*/
private $books;
}
More: my boss has the same code and it doesn't have that error.
Any idea?
sf 2.0.1 (just updated)/ubuntu 10.10.

If I'm guessing correctly, you are using a MySQL database. If yes, then you are facing a bug/problem with the current version of the doctrine-fixtures library for Doctrine2. The problem is that they are using the TRUNCATE command to purge the current database values but this command has problem deleting foreign associations in MySQL.
See this issue and this one on the GitHub repository of the library for more information and workarounds.
In my particular case, I run this command from a script, so to make the command work correctly, I do:
php app/console doctrine:database:drop --force
php app/console doctrine:database:create
php app/console doctrine:schema:update --force
php app/console doctrine:fixtures:load --append
This way, the purging is done by the drop command and appending has the same effect as not appending since the database is empty when the fixtures are loaded.
I must admit I don't know why your boss doesn't have the problem, maybe there is no book associated with an author in his database.
Hope this help.
Regards,
Matt

I've created a simple Event Subscriber class for Symfony 4. All you need to fix the self-referencing foreign keys issue is to add the below class somewhere to your Symfony 4 project.
This subscriber fires before each Symfony CLI command. In case if the command's name is doctrine:fixtures:load, it performs database purge, but doing SET FOREIGN_KEY_CHECKS = 0 first.
This solves the issue without any other modification.
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ConsoleCommandEventSubscriber implements EventSubscriberInterface
{
/**
* #var EntityManagerInterface
*/
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public static function getSubscribedEvents()
{
return [
ConsoleEvents::COMMAND => 'onCommand',
];
}
public function onCommand(ConsoleCommandEvent $event)
{
if ($event->getCommand()->getName() === 'doctrine:fixtures:load') {
$this->runCustomTruncate();
}
}
private function runCustomTruncate()
{
$connection = $this->entityManager->getConnection();
$connection->exec('SET FOREIGN_KEY_CHECKS = 0');
$purger = new ORMPurger($this->entityManager);
$purger->setPurgeMode(ORMPurger::PURGE_MODE_DELETE);
$purger->purge();
$connection->exec('SET FOREIGN_KEY_CHECKS = 1');
}
}

Add to your composer.json new section script
"scripts": {
"load-fixtures": [
"bin/console doctrine:database:drop --if-exists --force",
"bin/console doctrine:database:create",
"bin/console doctrine:mi:m",
"bin/console doctrine:fixtures:load"
]
}
Then you can run composer install && composer load-fixtures

Related

Custom Repository does not work

Symfony 3.3,
I do according to the documentation https://symfony.com/doc/current/doctrine/repository.html
$entityManager = $this->getDoctrine()->getManager();
$users = $entityManager->getRepository(Users::class)->findAllOrderedByName();
I get exception:
BadMethodCallException:
Undefined method 'findAllOrderedByName'. The method name must start with either findBy or findOneBy!
at vendor\doctrine\orm\lib\Doctrine\ORM\EntityRepository.php:226
at Doctrine\ORM\EntityRepository->__call('findAllOrderedByName', array())
(src\AppBundle\Controller\DefaultController.php:28)
at Doctrine\ORM\EntityRepository->findAllOrderedByName()
(src\AppBundle\Controller\DefaultController.php:28)
at AppBundle\Controller\DefaultController->indexAction(object(Request))
at call_user_func_array(array(object(DefaultController), 'indexAction'), array(object(Request)))
(var\cache\dev\classes.php:4453)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(var\cache\dev\classes.php:4408)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Kernel.php:171)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(web\app_dev.php:29)
Users entity:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Users
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UsersRepository")
*/
class Users
{
...
}
UsersRepository
namespace AppBundle\Repository;
use AppBundle\Entity\Users;
use Doctrine\ORM\EntityRepository;
/**
* Created by PhpStorm.
* User: Hett
* Date: 21.07.2017
* Time: 14:25
*/
class UsersRepository extends EntityRepository
{
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQueryBuilder()
->select("u")
->from(Users::class, "u")
->orderBy("name")
->getQuery()
->getArrayResult();
}
}
As I understand $entityManager->getRepository(Users::class) return default EntiryRepository. Why? What's my mistake?
UPD: I tried to clear cache, but it has no effect:
Hett#Range MINGW64 /c/www/symfony (master)
$ ./bin/console cache:clear
// Clearing the cache for the dev environment with debug
// true
[WARNING] Calling cache:clear without the --no-warmup option is deprecated
since version 3.3. Cache warmup should be done with the cache:warmup
command instead.
[OK] Cache for the "dev" environment (debug=true) was successfully cleared.
Hett#Range MINGW64 /c/www/symfony (master)
$ ./bin/console doctrine:cache:clear-metadata
Clearing ALL Metadata cache entries
Successfully deleted cache entries.
I have auto-generated file
src/AppBundle/Resources/config/doctrine/Users.orm.yml
As I understand .yml configs rewrites annotations congiruation,
when I remove Users.org.yml or add line repositoryClass: AppBundle\Repository\UsersRepository - all work fine.
Which method is correct?

Symfony2: How do I clear all of Symfony's (and all 3rd party plugins) cache in 1 command?

so I've been testing Doctrine queries and other Symfony code and I have to run several commands just to clear Doctrine/Symfony caches. I was searching for the net and came across another command to clear Assetic assets/etc.
From what I've read
php app/console cache:clear
will only clear Symfony cache. it won't include Doctrine and perhaps more.
I know I can create a bash script to clear all my caches but this obviously means I know all the "clear cache" commands. I only found out about the Assetic clear cache/assets by accident. What about those I don't know?
So is there 1 "clear cache" command that can do it for me? This will have to include Symfony/Doctrine/Assetic/Twig and whatever plugins I have installed.
Thanks a lot
What you are looking for is highly dependent on the developer of the bundle that uses the cache. Not even doctrine, that comes with the standard version of symfony has its cache clear command integrated. But what you can do is extend the default symfony command with a listener that runs all the cache clear command you want like this:
<?php
namespace DefaultBundle\Event\Listener;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Process\Process;
class CacheClearListener implements CacheClearerInterface
{
private $environment;
/**
* #return array
*/
private static function getCommands()
{
return array(
'php ./app/console doctrine:cache:clear-metadata --no-debug --flush',
'php ./app/console doctrine:cache:clear-query --no-debug --flush',
'php ./app/console doctrine:cache:clear-result --no-debug --flush'
);
}
public function clear($cacheDir)
{
$output = new ConsoleOutput();
$output->writeln('');
$output->writeln('<info>Clearing Doctrine cache</info>');
foreach (self::getCommands() as $command) {
$command .= ' --env='.$this->environment;
$success = $this->executeCommand($command, $output);
if (!$success) {
$output->writeln(sprintf('<info>An error occurs when running: %s!</info>', $command));
exit(1);
}
}
}
/**
* #param string $command
* #param ConsoleOutput $output
*
* #return bool
*/
private function executeCommand($command, ConsoleOutput $output)
{
$p = new Process($command);
$p->setTimeout(null);
$p->run(
function ($type, $data) use ($output) {
$output->write($data, false, OutputInterface::OUTPUT_RAW);
}
);
if (!$p->isSuccessful()) {
return false;
}
$output->writeln('');
return true;
}
/**
* #param Kernel $kernel
*/
public function setKernel(Kernel $kernel)
{
$this->environment = $kernel->getEnvironment();
}
}
Register the listener like this:
<service id="cache_clear_listener" class="DefaultBundle\Event\Listener\CacheClearListener">
<call method="setKernel">
<argument type="service" id="kernel"/>
</call>
<tag name="kernel.cache_clearer" priority="254" />
</service>
And that is all. Now all you need to do is keep adding your new cache clear command to the getCommands() method. In order to find this commands you can run something like
php app/console | grep cache
to see all available commands that contain the word "cache" in them
After your listener is set, every time you run php app/console cache:clear it will trigger all the command that you listed in the getCommands() method of your listener.
Hope this helps,
Alexandru

Doctrine load fixtures --no-interaction flag is not working when running in a Symfony command

The --no-interaction flag on the doctrine:fixtures:load command is not working running within a Symfony command. It is working however via the terminal. I'm I calling it correctly?
When I run this from a bundle:
/**
* Loads the fixtures
* #param \Symfony\Component\Console\Output\OutputInterface $oOutput
* #return \Symfony\Component\Console\Output\OutputInterface
*/
protected function loadFixturesCommand($oOutput) {
$oOutput->writeln('<fg=white>Attempting to load fixtures</fg=white>');
$updateCommand = $this->getApplication()->find('doctrine:fixtures:load');
$updateArguments = array(
'command' => 'doctrine:fixtures:load',
'--no-interaction' => true,
);
$updateInput = new ArrayInput($updateArguments);
$updateCommand->run($updateInput, $oOutput);
try {
$updateCommand->run($updateInput, $oOutput);
} catch (ContextErrorException $e) {
//..
}
return $this;
}
I get prompted to load the fixtures
But running this:
php app/console doctrine:fixtures:load --no-interaction
Doesn't prompt me.
What am I doing wrong?
I've found the solution.
Simply call:
$input->setInteractive(false);
Like so:
protected function loadFixturesCommand($oOutput) {
$oOutput->writeln('<fg=white>Attempting to load fixtures</fg=white>');
$updateCommand = $this->getApplication()->find('doctrine:fixtures:load');
$updateArguments = array(
'command' => 'doctrine:fixtures:load'
);
$updateInput = new ArrayInput($updateArguments);
$updateInput->setInteractive(false);
$updateCommand->run($updateInput, $oOutput);
try {
$updateCommand->run($updateInput, $oOutput);
} catch (ContextErrorException $e) {
//..
}
return $this;
}
If you make a drop from your database you could also use this command I think, to be confirmed.
By default Doctrine Data Fixtures uses DELETE statements to drop the existing rows from the database.
If you want to use a TRUNCATE statement instead you can use the --purge-with-truncate flag:
php bin/console doctrine:fixtures:load --purge-with-truncate
You can use --append param to suppress interaction.
i.e. doctrine:fixtures:load --append

How to add a field in entity in Symfony2

I try to add a cahmps in entity. I have this code:
/**
* #var integer $colorevent
* #ORM\Column(name="colorevent", type="integer")
*/
private $colorevent;
/**
* Get colorevent
* #return integer
*/
public function getColorevent()
{
return $this->colorevent;
}
/**
* Set colorevent
* #return integer
*/
public function setColorevent($colorevent)
{
return $this->colorevent = $colorevent ;
}
I run these commands:
php app/console doctrine:schema:update
php app/console doctrine:schema:update --dump-sql
php app/console doctrine:schema:update --force
which renders this message:
Nothing to update yopur database is already in sync with the current
entity metadata
How do I add a field in entity?
How did you generated the entity class in the first time?
It the entity file was generated via doctrine:generate:entities then what you need to do is:
update the Resources/config/doctrine/XXXXXXXXX where xxxx is the entity name.
run app/console doctrine:generate:entity. This will regenerate the php entity file, and the private property, getter and setter.
run php app/console doctrine:schema:update and update the DB
There may be some changes depending of the format you are using (I'm using yml) but the bottom line is that the doctrine:schema:update needs to find changes between the current and the cached (metadata) entity objects.
Each entity must have the Entity annotation
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class MyEntity
{
// some code
}
I would also suggest using the console tools provided to create the entities.
app/console doctrine:generate:entity
For more information please read the official book (Doctrine, Propel).
If you're using yaml or annotations as described in the other two answers you can use the doctrine command. However the command must contain the entity name:
php app/console doctrine:generate:entities AcmeMyBundle:Customer

Symfony2 fixtures with references not loading (constraint violation)

I've been struggling for several hours on my Symfony2 project fixtures. Here is the error I get :
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`wpanel_dev`.`sshuser`, CONSTRAINT `FK_612DE3EE18F45C82` FOREIGN KEY (`website_id`) REFERENCES `Website` (`id`))
Having read a lot of answers, I tried this method without success :
php app/console doctrine:database:drop --force
php app/console doctrine:database:create
php app/console doctrine:schema:update --force
php app/console doctrine:fixtures:load (with or without --append)
Here is the fixture code that is generating the error ($new->setWebsite($this->getReference('website-'.$i));)
<?php
namespace WPanel\AdminBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\FixtureInterface;
use WPanel\AdminBundle\Entity\SSHUser;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
class LoadSSHUserData extends AbstractFixture implements OrderedFixtureInterface
{
public function getOrder()
{
return 5;
}
public function load(ObjectManager $manager)
{
for($i = 1; $i <= 20; $i++) {
$new = new SSHUser();
$new->setUser('sshuser'.$i);
$new->setPassword('sshuser'.$i);
$new->setPath('/var/www/website'.$i.'.com');
$new->setWebsite($this->getReference('website-'.$i));
$manager->persist($new);
}
$manager->flush();
}
}
?>
I'm sure the reference is ok. I've been using add/getReference on other classes without any problem.
Thanks for your help !
This error means that there isn't any record on the website table with that ID if I understood correctly.
Either there is a problem with your ordering, or typo in reference.
It seems that you do not have 20 websites object fixtures since you are using the $i counter from 0 to 20.

Resources