I have defined some fixtures in doctrine.
When i try to run using this
php app/console doctrine:fixtures:load then it asks me to purge the database.
is it possible to load it without purging database.
I remeber Django has fixtures which can be loaded in separate tables without purging existing database
Use the --append option
php app/console help doctrine:fixtures:load
Usage:
doctrine:fixtures:load [--fixtures[="..."]] [--append] [--em="..."] [--purge-with-truncate]
Options:
--fixtures The directory or file to load data fixtures from. (multiple values allowed)
--append Append the data fixtures instead of deleting all data from the database first.
--em The entity manager to use for this command.
--purge-with-truncate Purge data by using a database-level TRUNCATE statement
DoctrineFixtures are nice for the first init of an empty database or in development - but not in production.
Take a look at DoctrineMigrations and symfonys DcotrineMigrationsBundle, this is a good and safe way to migrate your database in production.
It is possible to update previously added data to DB (which was loaded by running app/console doctrine:fixtures:load). I used EntityManager->createQuery for that.
But I still wonder if there is or ever will be an opportunity to do it by simply running an app/console command. Something like app/console doctrine:schema:update --force, but applied to the data itself.
For now I had to write a ton of code to get my data updated and appended properly. For example to make --append work I had to write the following:
class LoadCategoryData implements FixtureInterface
{
/**
* {#inheritDoc}
*/
public function load(ObjectManager $em)
{
//a category has name and shortcut name (st)
$categories = array (
[0]=> array('name' => 'foo', 'st' = 'bar'),
...
);
foreach ($categories as $cat) {
$query = $em->createQuery(
"SELECT c
FROM MyBundle:Category c
WHERE c.st = ?1"
)->setParameter(1, $cat['st'])->getResult();
if (count($query) == 0) {
$c = new Category();
$c->setName($cat['name']);
$c->setSt($cat['st']);
$em->persist($c);
}
$em->flush();
}
}
}
Related
I am upgrading our Symfony application from version 3.4 to version 4.4, which includes an upgrade of Doctrine from 1.12 to 2.3. I had previously written a class that modified the results to the doctrine:schema:update command, which worked great, but appears not to be working now. The class is below.
To modify doctrine:schema:update, I created a class called DoctrineUpdateCommand, which extended \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand, and placed it in the Command folder of the bundle. This was all that was needed. I referenced this answer to figure out how to do it: How to set up entity (doctrine) for database view in Symfony 2.
We need to override the doctrine:schema:update command because one of our entities refers to a MySQL view instead of a MySQL table. Further, the entity is referenced as both a stand alone entity, and as a many-to-many join. The override class caused the entity and join to be ignored. It also added a sql statement to create the view.
After the upgrade, if I run php console doctrine:schema:update --dump-sql, I get these results:
19:08:16 CRITICAL [console] Error thrown while running command "doctrine:schema:update --dump-sql". Message: "The table with name 'nest_qa.assignedrole_privilegerole' already exists." ["exception" => Doctrine\DBAL\Schema\SchemaException^ { …},"command" => "doctrine:schema:update --dump-sql","message" => "The table with name 'nest_qa.assignedrole_privilegerole' already exists."]
In SchemaException.php line 112:
The table with name 'nest_qa.assignedrole_privilegerole' already exists.
I am fairly certain that the extension of the doctrine command is no longer being called, and it's using the default command instead, but I can't figure out how to change that. Any help would be appreciated.
Here is the original class:
<?php
namespace ApiBundle\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\Tools\SchemaTool;
class DoctrineUpdateCommand extends \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand{
protected $ignoredEntities = array(
'ApiBundle\Entity\AssignedrolePrivilegerole',
);
protected $ignoreAssociationMappings = array(
'ApiBundle\Entity\Privilegerole' => 'assignedroles',
'ApiBundle\Entity\Assignedrole' => 'privilegeroles',
);
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) {
/** #var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
$newMetadatas = array();
foreach ($metadatas as $metadata) {
if (array_key_exists($metadata->getName(), $this->ignoreAssociationMappings)) {
if(array_key_exists($this->ignoreAssociationMappings[$metadata->getName()], $metadata->getAssociationMappings())){
unset($metadata->associationMappings[$this->ignoreAssociationMappings[$metadata->getName()]]);
}
}
//If metadata element is not in the ignore array, add it to the new metadata array
if (!in_array($metadata->getName(), $this->ignoredEntities)){
array_push($newMetadatas, $metadata);
}
}
parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas, $ui);
$output->writeln("------Create view for assignedrole_privilegerole");
$output->writeln("CREATE VIEW `assignedrole_privilegerole` AS select `Assignedrole`.`id` AS `assignedrole_id`,`Privilegerole`.`id` AS `privilegerole_id` from (`Assignedrole` join `Privilegerole`) where ((`Assignedrole`.`role_id` = `Privilegerole`.`role_id`) and ((`Assignedrole`.`unit_id` = `Privilegerole`.`unit_id`) or `Privilegerole`.`unit_id` in (select `Unittree`.`ancestor_id` from `Unittree` where (`Unittree`.`descendant_id` = `Assignedrole`.`unit_id`)))) ;");
}
}
Console commands in symfony <4.x were registered by scanning Command folder inside a bundle. Since bundles are obsolete in symfony 4+, you have to define commands in your services definition by tagging the command class, or use DI autoconfiguration.
Option 1: explicitly add console.command tag to the service definition:
services:
ApiBundle\Command\DoctrineUpdateCommand:
tags:
- { name: twig.extension }
Option 2: use DI autoconfiguration:
services:
ApiBundle\Command\DoctrineUpdateCommand:
autoconfigure: true
After your class is registered as a console command, it must override the default one.
See symfony docs for more: Console Command
I'm using The Symfony Lock package to check if a class method can be executed
if ($this->lock->acquire()) {
$this->execute();
$this->lock->release();
}
Important: I'm not using the Symfony Framework, only the Lock component
I want to make a test that asserts that the execution is locked when running in multiple threads, but I have not found any documentation on how to achieve this.
Is it a good idea to use pthreads? If not, which is the best way to make this test?
Thank you very much.
Referring to the Lock Component documentation :
https://symfony.com/doc/current/components/lock.html#usage
Information on the CommandTester :
https://symfony.com/doc/current/console.html#testing-commands
Solution for PHPUnit test :
use Symfony\Component\Lock\Factory;
use Symfony\Component\Lock\Store\SemaphoreStore;
public function testLockIsSet()
{
// Create a new Semaphore lock with the same ID as the one that would be
// created if you were running the command / class / process etc.
$store = new SemaphoreStore();
$factory = new Factory($store);
$lock = $factory->createLock('lock-name-used-eg-generate-pdf');
if ($lock->acquire()) {
// In my use case I was running multiple commands to see if the lock
// was working properly
$commandTester = new CommandTester($this->command);
// Try and run the command. The lock should already be set.
$commandTester->execute(
[
'command' => $this->command->getName()
]
);
// You could also use expectException() here for LogicException
$this->assertContains(
'The command is already running in locked mode.',
$commandTester->getDisplay()
);
$lock->release();
}
}
I've just added a new attribute in my model:
/**
* #ORM\Column(name="has_donation", type="boolean", options ={"default":false})
*/
private $hasDonation;
And then I tried running:
php app/console doctrine:schema:update --force
which gave me the following result:
Updating database schema...
Database schema updated successfully! "1" queries were executed
The problem is that each time I run the schema:update command, I get the same result - without making any changes to my entities. Any idea why? Thanks!
Update
Here's the out for php app/console doctrine:schema:update --dump-sql:
ALTER TABLE Clinic CHANGE has_donation has_donation TINYINT(1) DEFAULT '0' NOT NULL;
I can assume that this issue arises because of usage of illegal or irrelevant mapping information.
In case of the question author, the option "default":false was illegal.
I had same issue with code:
/**
* #ORM\Column(
* type="boolean",
* nullable=false,
* options={"unsigned":true, "comment":"Is file uploaded manually?"}
* )
*/
protected $manual = false;
In my case the option "unsigned":true was irrelevant. After removing this option, I got the code working.
First, try deleting cache.
Then, try php app/console doctrine:schema:update --dump-sql to see what updated.
These options with "default": false differences are not recorded sometimes. At least on PostgreSQL we use.
You might need them to run them manually.
Tip from our workflow:
1) we setup entities
2) then run php app/console doctrine:schema:update --force
3) then run migrations that add there details that are not transformed to database
I want to have a simple form with PHP that takes YAML code as an input and stores it in to MongoDB when submitted. The update of records should also happen in the same way with editing yaml codes.
I am a beginner in programming and I don't want to use a framework or any complicated stuff just simple php form that takes yaml and converts to mongodb to be stored.
How should I do that?
Any recommendations or sample codes or if you know previous similar work?
Use the YAML Symfony component to load and parse the YAML file. The result of parsing the file will be a PHP array. This array can be easily saved into MongoDB:
1) Download Composer
curl -sS https://getcomposer.org/installer | php -- --install-dir=bin
2) Use composer to install the YAML Component. Create a composer.json file and add the following information:
{
"require": {
"symfony/yaml": "2.3.*#dev"
}
}
3) Install the component
$ php composer.phar install
4) Create a php file with the code to load from the YAML file and save the result to the db. Part of the following code was taken from the php.net mongodb tutorial :
<?php
// autoload.php will be installed by composer
require_once __DIR__.'/vendor/autoload.php';
use Symfony\Component\Yaml\Yaml;
// Parse YAML file
$yaml = Yaml::parse(__DIR__.'/path/to/file.yml');
// connect
$mongo = new \MongoClient();
// select a database
$db = $mongo->yaml;
// select a collection (analogous to a relational database's table)
$collection = $db->imports;
// add a record
$document = $yaml;
$collection->insert($document);
// find everything in the collection
$cursor = $collection->find();
echo "<pre>";
// iterate through the results
foreach ($cursor as $document) {
print_r($document);
}
echo "</pre>";
Check out the data in MongoDB :
> show dbs;
yaml 0.203125GB
> use yaml;
switched to db yaml
> show collections;
imports
system.indexes
> db.imports.find();
I'm trying to import a mailing list from CSV to my DATABASE. I have two models in my Laravel which is responsible for doing this: Target and Mailing (one Target has many Mailings)
I'm using Queue system with Beanstalkd. I'm using:
Queue::push('ImportCSV', array(
'file' => $file->getClientOriginalName(),
'target' => $name
));
To push my jobs and then I have the ImportCSV job class:
class ImportCSV
{
public function fire($job, $data)
{
Log::info("Starting to add {$data['target']} to database");
$target = new Target();
$target->name = $data['target'];
$target->save();
$reader = new \EasyCSV\Reader($data['file']);
// There must be a Email field in CSV file
/*if(!in_array('Email', $reader->getHeaders() ))
throw new Exception("Email field not found", 1);*/
while ($row = $reader->getRow())
{
$mailing = new Mailing();
$mailing->target()->associate($target);
$mailing->email = $row['Email'];
$mailing->save();
}
Log::info("Mailing list {$target->name} added to database");
$job->delete();
}
}
All the code seems to be working since I get these messages in my Log file
[2013-09-10 21:03:25] log.INFO: Starting to add TEst to database [] []
[2013-09-10 21:03:25] log.INFO: Mailing list TEst added to database [] []
But no records are added to my database. How should I use models inside a job? I already tested it in a Controller for example and everything works fine
Since you don't see other errors, I'm thinking this is an environment issue.
First - environments
Make sure your call to php artisan queue:listen (or queue:work, if applicable) is using the correct environment so the correct database is getting used:
$ php artisan queue:listen --env=YOUR_ENV
Here's a post on setting up queues in Laravel 4 which might be helpful for more information.
Second - namespaces
As you (apparently?) aren't seeing any PHP errors, this is less likely, but another idea:
If your class is namespaced, you may need to use the \ character to get your models, which are in the global namespace.
// From:
$mailing = new Mailing();
// To:
$mailing = new \Mailing();