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.
Related
I have an action in the controller for mass instert in the database...
So this uses a lot of resources and the profiler is caching everything and server goes down.
How can i disable the profiler (and all the debug services) in one action on the controller?
The controller looks like :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Sync\Incomming\Syncronize;
/**
* #Route("/sync")
*/
class SyncController extends AbstractController
{
private $syncronize;
public function __construct(Syncronize $syncronize)
{
$this->syncronize = $syncronize;
}
/**
* #Route("/",name="sync_index")
*/
public function index(Request $request, Profiler $profiler)
{
$message = "Hello";
return $this->render( 'sync/output.html.twig', ['message' => $message ]);
}
}
if I try to autowire the profiler in the constructor method then I get the error public function __construct(Syncronize $syncronize, Profiler $profiler):
Cannot autowire service "App\Controller\SyncController": argument
"$profiler" of method "__construct()" references class
"Symfony\Component\HttpKernel\Profiler\Profiler" but no such service
exists. You should maybe alias this class to the existing "profiler"
service.
if I try to autowire the profiler in the index method then I get the error public function index(Request $request, Profiler $profiler):
Controller "App\Controller\SyncController::index()" requires that you
provide a value for the "$profiler" argument. Either the argument is
nullable and no null value has been provided, no default value has
been provided or because there is a non optional argument after this
one.
EDIT
For big queries disabling the profiler was not the solution... Actually you need to disable the setSQLLogger:
$em->getConnection()->getConfiguration()->setSQLLogger(null);
Symfony 3.4 / 4
https://symfony.com/doc/4.0/profiler/matchers.html
use Symfony\Component\HttpKernel\Profiler\Profiler;
class DefaultController
{
// ...
public function someMethod(Profiler $profiler)
{
// for this particular controller action, the profiler is disabled
$profiler->disable();
// ...
}
}
If you have an error with autowiring
# config/services.yaml
services:
Symfony\Component\HttpKernel\Profiler\Profiler: '#profiler'
Old:
If you want to disable the profiler from a controller, you can like this:
use Symfony\Component\HttpKernel\Profiler\Profiler;
// ...
class DefaultController
{
// ...
public function someMethod(Profiler $profiler)
{
// for this particular controller action, the profiler is disabled
$profiler->disable();
// ...
}
}
Source: https://symfony.com/doc/current/profiler/matchers.html
Another way would be to use: $this->get('profiler')->disable();
Older:
Simply switch the app to prod mode and disable debug mode.
To do this, open the .env file on the server in your favourite editor (Note: You should never commit this file to Git, as you store secrets in there!).
In that file, you should see a section starting with: ###> symfony/framework-bundle ###
Just below that there is a APP_ENV=dev and APP_DEBUG=1, change these two lines to APP_ENV=prod and APP_DEBUG=0. Then save the file.
Next you should clear the cache for prod mode and install the assets. To do this, run the following commands:
php bin/console cache:clear --env=prod --no-debug
php bin/console cache:warmup --env=prod --no-debug
php bin/console assets:install --env=prod --no-debug --symlink
If you now load the application, it is in prod mode, which includes more caching and is faster as debug is disabled.
Note:
There will still be a timelimit for PHP. If you still hit that limit, you can either change your PHP setting or alternatively you could run the import from CLI, as CLI usually has no timelimit. If users need to be able to upload on their own, I'd suggest having them upload the file, enter a "note" about the file to a db and have a cronjob reading that db for not imported files and import them.
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
I'm trying to build my first Compiler Pass in Symfony 2. For now, I'm just trying to get the core event_dispatcher service from FrameWorkBundle inside a SampleBundle, but I get this error :
error InvalidArgumentException: The service definition "event_dispatcher" does not exist.
Here is the code for my compiler :
<?php
namespace Me\SampleBunlde\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
class RegisterListenersPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('event_dispatcher');
}
}
?>
I'm a bit surprised since I'm following step by step a professionnal Symfony book who assures me that I will find this service with that id.
I've done some researches about that, and I discovered that only the debug.event_dispatcher service was avaible. Then I checked for aliases and saw that there was a private Alias named 'event_dispatcher' pointing to debug.event_dispatcher. So I'm really confused about all that. And I'm wondering :
Why is the Alias private ? Do I need to set him Public or is it the wrong way ?
Why Symfony does not automatically interprets my event_dispatcher call ?
Thank you for your help !
Use findDefinition() instead of getDefinition(). findDefinition also looks for aliases.
I'm implementing the classic Blog app with Symfony2, and the "app/console doctrine:fixtures:load" returns an error. My BlogFixtures.php file is like this:
<?php
namespace MGF\Bundles\WebBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use MGF\Bundles\WebBundle\Entity\Blog;
use MGF\Bundles\CRMBundle\Util\Util;
class BlogFixtures extends AbstractFixture implements FixtureInterface
{
public function load(ObjectManager $em)
{
$blog1 = new Blog();
$title = 'First post';
$blog1->setTitle($title);
$slug1 = Util::getSlug($title);
$blog1->setSlug($slug1);
$blog1->setImage('beach.jpg');
$blog1->setTags('symfony2, php, paradise, symblog');
$blog1->setCreated(new \DateTime('now'));
$blog1->setUpdated($blog1->getCreated());
$em->persist($blog1);
$author1 = $em->getRepository('MGFBCBundle:User')->findOneByUser('sarah');
$author1->addBlog($blog1);
$em->persist($author1);
$em->flush();
}
}
And the error:
app/console doctrine:fixtures:load
Careful, database will be purged. Do you want to continue Y/N ?Y
> purging database
> loading MGF\Bundles\WebBundle\DataFixtures\ORM\BlogFixtures
PHP Fatal error: Call to a member function addBlog() on a non-object in /var/www/METRO/src/MGF/Bundles/WebBundle/DataFixtures/ORM/BlogFixtures.php on line 33
Fatal error: Call to a member function addBlog() on a non-object in /var/www/METRO/src/MGF/Bundles/WebBundle/DataFixtures/ORM/BlogFixtures.php on line 33
I don't see where I go wrong. Any hints?
Thanks in advance.
The problem was that even though the user 'sarah' exists in the db from the fixtures, when trying to load fixtures again, db gets purged. So I needed to reference my users when created from the fixtures, and retrieve them by their reference, as explained here:
http://symfony.com/doc/master/bundles/DoctrineFixturesBundle/index.html#sharing-objects-between-fixtures
Fixtures loading is working again.
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