Symfony MongoDb can't retrieve new field values - php

I have added new entry in Document description
/**
* #MongoDB\Field(type="string")
*/
protected $city;
Then let Doctrine generate entities. Now newly created records have new field "city" with values as expected. However I can see these values only in mongo console. In Doctrine output they are allways set to "null". The entity entries seems correct
public function getFirstName()
{
return $this->firstName;
}
/**
* Get city
*
* #return string $city
*/
public function getCity()
{
return $this->city;
}
I have repository
public function allQuery($cat)
{
$q = $this->createQueryBuilder()
->sort('createdAt', 'DESC');
if ($cat) {
$q->field('category.$id')->equals(new \MongoId($cat));
}
return $q;
}
And service
function addAllPager($perPage = 10, $cat)
{
return $this->_addPager($this->repo()->allQuery($cat), $perPage);
}
In Controller
$helper = $this->get('appbundle.test.helper');
$tests = $helper->addAllPager(10, $cat);
Symfony profiler shows me query db.Test.find().sort({ "createdAt": -1 }).limit(10).skip(0). Dumped Contents of $tests
#firstName: "John"
#city: null
What I am missing?
EDIT
Cache clearing with php bin/console cache:clear solved the problem.
php bin/console doctrine:mongodb:cache:clear-metadata was not enough. Thank you malarzm.

I know this is 8 months after the question has been asked but had the same issue and fought with doctrine for a while. I am using Symfony 3 and I tried php bin/console doctrine:mongodb:cache:clear-metadata with no luck.
I finally ran the command php bin/console cache:clear or just delete the cache with this command sudo rm -rf var/cache and that fixed the issue.

Related

error when i run php artisan migrate command on line 51

When I run the php artisan migrate command in terminal I'm left with this.
ParseError
syntax error, unexpected ')'
at C:\laragon\www\testnum2\vendor\laravel\framework\src\Illuminate\Bus\BusServiceProvider.php:51
47▕ return new DatabaseBatchRepository(
48▕ $app->make(BatchFactory::class),
49▕ $app->make('db')->connection(config('queue.batching.database')),
50▕ config('queue.batching.table', 'job_batches'),
➜ 51▕ );
52▕ });
53▕ }
54▕
55▕ /**
1 C:\laragon\www\testnum2\vendor\composer\ClassLoader.php:322
Composer\Autoload\includeFile("C:\laragon\www\testnum2\vendor\composer/../laravel/framework/src/Illuminate/Bus/BusServiceProvider.php")
2 [internal]:0
Composer\Autoload\ClassLoader::loadClass("Illuminate\Bus\BusServiceProvider")
PS C:\laragon\www\testnum2>
I'm not quite sure what is causing but this is the code for that file thats causing the error.
<?php
namespace Illuminate\Bus;
use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
use Illuminate\Contracts\Bus\QueueingDispatcher as QueueingDispatcherContract;
use Illuminate\Contracts\Queue\Factory as QueueFactoryContract;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
class BusServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->singleton(Dispatcher::class, function ($app) {
return new Dispatcher($app, function ($connection = null) use ($app) {
return $app[QueueFactoryContract::class]->connection($connection);
});
});
$this->registerBatchServices();
$this->app->alias(
Dispatcher::class, DispatcherContract::class
);
$this->app->alias(
Dispatcher::class, QueueingDispatcherContract::class
);
}
/**
* Register the batch handling services.
*
* #return void
*/
protected function registerBatchServices()
{
$this->app->singleton(BatchRepository::class, DatabaseBatchRepository::class);
$this->app->singleton(DatabaseBatchRepository::class, function ($app) {
return new DatabaseBatchRepository(
$app->make(BatchFactory::class),
$app->make('db')->connection(config('queue.batching.database')),
config('queue.batching.table', 'job_batches'),
);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return [
Dispatcher::class,
DispatcherContract::class,
QueueingDispatcherContract::class,
BatchRepository::class,
];
}
}
I hope that this is enough to get help.
I wanna also mention that I've used php artisan migrate before and recently I had to upgrade some things like composer and phpmyadmin
The problem is that the PHP version you're using ( below 7.3 ) does not support trailing comma in function calls.
Please read this: Trailing Commas are allowed in Calls
Solution is to switch to > PHP 7.3
Well my problem was my PHP being <7.3
But when I simply checked it in phpinfo file it showed up as 7.4.11.
#lagbox helped me by saying : "there are different versions on your system, and the CLI and the webserver can have different configurations"
To be honest I wasn't sure exactly what to do from that but I decided to just delete PHP 7.2 from my PATH.
My hope was that it would then recognize I was using 7.4 and to my suprise it did.
Also I'm sure there are more effective ways of doing this but that was the way I chose.

Symfony 4 PHPunit, not truncating tables in SQLite

I am trying to setup a simple test in PPHunit in my Symfony 4.4 app, but it seems that the test database (SQLite) is not truncating.
So it will work the first time you run it, but not after that as the auto increment column id is not resetting.
It's strange as this was working for me on another project until very recently:
// tests/BaseWebTestCase.php
protected function tearDown(): void
{
parent::tearDown();
$purger = new ORMPurger($this->em);
$purger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE);
$purger->purge();
}
But maybe a recent update has meant it doesn't work anymore. How can I update this so that the tables are truncated every time my test is run?
When I run the test I get the following error:
There was 1 error:
1) App\Tests\Controller\BlogPostControllerTest::testAUserCanAccessBlogPost
Error: Call to a member function getId() on null
/home/vagrant/code/tests/Controller/BlogPostControllerTest.php:26
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
This is my test:
// tests/Controller/BlogPostControllerTest.php
public function testAUserCanAccessBlogPost()
{
$blogPost = $this->em
->getRepository(BlogPost::class)
->findOneBy([
'id' => rand(1, 20)
]);
$this->client->request('GET', '/' . $blogPost->getId());
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
}
And the fixtures function:
public function load(ObjectManager $manager)
{
$faker = Factory::create('en_GB');
// Create blog posts
for ($i = 0; $i < 20; $i++) {
$blogPost = new BlogPost();
$blogPost->setTitle($faker->sentence(3));
$blogPost->setBody($faker->paragraph);
$manager->persist($blogPost);
}
$manager->flush();
}
If I add a die statement to the test I am able to login to the SQLite database and I can see that the ids for the posts are incrementing and not resetting to start with 1, which is causing the error.
UPDATE
I am now able to get this working if I clear the cache:
sudo rm -rf var/cache
The test will work once, but fail if I run a second time, hence the original issue remains.

Symfony hangs after using Doctrine

I am trying to debug something so I made this test controller:
/**
* #Route("/test")
*/
public function reventarAction()
{
$a = $this->getDoctrine()
->getRepository(MyTable::class)
->find(1);
var_dump($a->getId());
die();
}
This works just fine. The ID gets dumped.
However, when I try to debug something else such as the object itself:
var_dump($a);
It loads forever presumably in some sort of recursive loop to the point where my computer freezes.
Any help debugging from Doctrine?

How to test Doctrine Migrations?

I'm working on a project that does NOT have a copy of production DB on development environment.
Sometimes we have an issue with DB migrations - they pass on dev DB but fail in production/testing.
It's often beacuse Dev environent data is loaded from Fixtures that use the latest entities - filling all tables properly.
Is there any easy way to make sure Doctrine Migration(s) will pass in production?
Do you have/know any way to write an automatic tests that will make sure data will be migrated properly without downloading the production/testing DB and running the migration manually?
I would like to avoid downloading a production/testing DB to dev machine so I can check migrations becasue that DB contains private data and it can be quite big.
First, you need to create a sample database dump in state before the migration. For MySQL use mysqldump. For postgres pg_dump, e.g.:
mysqldump -u root -p mydatabase > dump-2018-02-20.sql
pg_dump -Upostgres --inserts --encoding utf8 -f dump-2018-02-20.sql mydatabase
Then create an abstract class for all migrations tests (I assume you have configured a separate database for integration testing in config_test.yml):
abstract class DatabaseMigrationTestCase extends WebTestCase {
/** #var ResettableContainerInterface */
protected $container;
/** #var Application */
private $application;
protected function setUp() {
$this->container = self::createClient()->getContainer();
$kernel = $this->container->get('kernel');
$this->application = new Application($kernel);
$this->application->setAutoExit(false);
$this->application->setCatchExceptions(false);
$em = $this->container->get(EntityManagerInterface::class);
$this->executeCommand('doctrine:schema:drop --force');
$em->getConnection()->exec('DROP TABLE IF EXISTS public.migration_versions');
}
protected function loadDump(string $name) {
$em = $this->container->get(EntityManagerInterface::class);
$em->getConnection()->exec(file_get_contents(__DIR__ . '/dumps/dump-' . $name . '.sql'));
}
protected function executeCommand(string $command): string {
$input = new StringInput("$command --env=test");
$output = new BufferedOutput();
$input->setInteractive(false);
$returnCode = $this->application->run($input, $output);
if ($returnCode != 0) {
throw new \RuntimeException('Failed to execute command. ' . $output->fetch());
}
return $output->fetch();
}
protected function migrate(string $toVersion = '') {
$this->executeCommand('doctrine:migrations:migrate ' . $toVersion);
}
}
Example migration test:
class Version20180222232445_MyMigrationTest extends DatabaseMigrationTestCase {
/** #before */
public function prepare() {
$this->loadDump('2018-02-20');
$this->migrate('20180222232445');
}
public function testMigratedSomeData() {
$em = $this->container->get(EntityManagerInterface::class);
$someRow = $em->getConnection()->executeQuery('SELECT * FROM myTable WHERE id = 1')->fetch();
$this->assertEquals(1, $someRow['id']);
// check other stuff if it has been migrated correctly
}
}
I've figured out simple "smoke tests" for Doctrine Migrations.
I have PHPUnit test perfoming following steps:
Drop test DB
Create test DB
Load migrations (create schema)
Load fixtures (imitate production data)
Migrate to some older version
Migrate back to the latest version
This way I can test for the major issues, we've had recently.
Example of PHPUnit tests can be found on my blog: http://damiansromek.pl/2015/09/29/how-to-test-doctrine-migrations/

Doctrine won't add persist entity relationship

I have two entities, View and Location
Each View can have a Location.
In my view I thus have:
class View
{
//..... Other Stuff.....
/**
* #ManyToOne(targetEntity="Location", inversedBy="views")
**/
private $location;
//...setters and getters....
public function setLocation($location){
$this->location = $location;
}
}
and then for my Location
class Location
{
//.....other stuff.....
/**
* #OneToMany(targetEntity="View", mappedBy="location")
**/
private $views;
public function __construct() {
$this->created = $this->updated = new \DateTime("now");
$this->views = new \Doctrine\Common\Collections\ArrayCollection();
}
// .... Getters and Setters ....
}
But when I try and do this:
<?php
$this->pageview = $this->em->getRepository('Entities\View')->find(1);
$this->location = $this->em->getRepository('Entities\Location')->find(1);
$this->pageview->setLocation($this->location);
$this->em->persist($this->pageview);
$this->em->flush();
?>
Or even when I create new entities:
<?php
$pv = new Entities\Pageview;
$lc = new Entities\Location;
$this->em->persist($lc);
$this->em->flush();
$pv->setLocation($lc);
$this->em->persist($pv);
$this->em->flush();
?>
Doctrine never sets the location_id in the database (it is always NULL).
I've checked the SQL queries and they're not even being attempted at being set, all I'm getting is:
INSERT INTO View (field1, field2, created, updated) VALUES ('val1', 'val2', '2013-07-17T12:10:56+01:00', '2013-07-17T12:10:56+01:00')
No reference to locations whatsoever...The weird thing is I can update field1 and field2 fine...and all other relations are working throughout my application...I just can't get views and locations to work...
EDIT
I have the exact some code working now on another computer. I don't know why it wasn't working, but I just moved the files back and restarted my computer and now it is...cacheing problem I guess?
Restarted my computer and the problem got solved...I don't know why it was going wrong!
Maybe something to do with caches or proxies...I dunno...
You could try explicitly referencing the correct columns that Doctrine needs to do a join on.
/**
* #ManyToOne(targetEntity="Location")
* #JoinColumn(name="location_id", referencedColumnName="id")
*/
private $location;
Also, in this example:
$this->pageview = $this->em->getRepository('Entities\View')->find(1);
$this->location = $this->em->getRepository('Entities\Location')->find(1);
$this->pageview->setLocation($this->location);
$this->em->persist($this->pageview);
$this->em->flush();
You do not need to persist the entity if you are just updating the existing data.
I think you need load the view in the location. So you must create a method in your Location entity like this:
public function getViews() {
return $this->views;
}
and then to persist into database, do this:
$location = new Entity\Location();
$view = new Entity\View();
$location->getViews()->add($view);
$this->em->persist($location)
$view->setLocation($location);
$this->em->persist($view);
$this->em->flush();
This is related to the Doctrine ORM cache drivers:
doctrine:
orm:
entity_managers:
default:
metadata_cache_driver: apcu
result_cache_driver: apcu
query_cache_driver: apcu
We used APCu to even on DEV do caching, clearing APCu (by restarting Apache) did the trick.

Categories