The course is built on Symfony 4, but the principles still apply perfectly to Symfony 5 - not a lot has changed in the world of relations!
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/doctrine-bundle": "^1.6.10", // 1.10.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
"knplabs/knp-paginator-bundle": "^2.7", // v2.7.2
"knplabs/knp-time-bundle": "^1.8", // 1.8.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"sensio/framework-extra-bundle": "^5.1", // v5.1.4
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.0.4
"symfony/console": "^4.0", // v4.0.14
"symfony/flex": "^1.0", // v1.21.6
"symfony/framework-bundle": "^4.0", // v4.0.14
"symfony/lts": "^4@dev", // dev-master
"symfony/twig-bundle": "^4.0", // v4.0.4
"symfony/web-server-bundle": "^4.0", // v4.0.4
"symfony/yaml": "^4.0", // v4.0.14
"twig/extensions": "^1.5" // v1.5.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
"easycorp/easy-log-handler": "^1.0.2", // v1.0.4
"fzaninotto/faker": "^1.7", // v1.7.1
"symfony/debug-bundle": "^3.3|^4.0", // v4.0.4
"symfony/dotenv": "^4.0", // v4.0.14
"symfony/maker-bundle": "^1.0", // v1.4.0
"symfony/monolog-bundle": "^3.0", // v3.1.2
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.0.4
"symfony/stopwatch": "^3.3|^4.0", // v4.0.4
"symfony/var-dumper": "^3.3|^4.0", // v4.0.4
"symfony/web-profiler-bundle": "^3.3|^4.0" // v4.0.4
}
}
44 Comments
Hey Denis,
Could you explain exactly what you renamed to what? Like name and new name... It's important to know so we could be able to help you. Most probably you renamed it bad, e.g. class name does not match file name, etc. Or probably you renamed the class, but still reference the old name somewhere.
Cheers!
If anyone's like me and going through this before it's finished and would like an example for the getRandomReference function, here you go:
protected function getRandomReference($class)
{
$all = $this->manager->getRepository($class)->findAll();
return $all[array_rand($all)];
}
Haha, hey again GDIBass! I'm also happy to post our version, fwiw. It looks like this:
Cheers!
Thank you!
The logic here is to generate fixtures for related entities separately. This is very time consuming and counter intuitive for me. For example, I generate invoices and those invoices have items. My goal is to generate invoices that are meaningful and consistent. With the solutions suggested here invoices could have no items at all. Also I have a related "Offer" entity with an expected billing amount. The invoice items' total amount should (at least almost) match with the offer amount in meaningful cases.
My point is:
It would be far easier for me to generate the fixtures this way:
But it feels a bit like this is against best practices. Or is this a false impression and my suggested solution is also reasonable?
<s>Second question: Why is
getRandomReference()implementing a "cache" ($referencesIndex)? Is a plain call toreferenceRepository->getReference()expensive?</s>Edited: This is not caching the references but their indices.
Hey Uli Hecht!
> But it feels a bit like this is against best practices. Or is this a false impression and my suggested solution is also reasonable?
I think they way you want to create the fixtures is TOTALLY fine. There is no best practice that you're violating, imo. It is just that, in many situations, it's nice to organize your fixtures by entity. But your example of an Invoice with InvoiceItems is a perfect example of something that you would want to keep together, so do it :).
Cheers!
Hey Farry7,
Please, double check your migration. Looks like it's not perfect, it may work on the empty database, but because you have some data there - it fails. I'd recommend you to check that FK_2CE0D8114D5B19A3 constraint and see its related columns, there's some a problem with relations.
I hope this helps!
Cheers!
All of this is outdated now in Symfony 5, I guess? Because I was using AppFixtures and Factory in another tutorial.
Hey Farry,
I wouldn't say it's all outdated, most of the content is still relevant, although, you may encounter with a few deprecations here and there, but when in doubt, you can always ask us your questions
Cheers!
Heya @weaverryan yo a question, the variable $count in createmany is usable to print the current position in the loop?
another question, how about I want to have a value in the database called "number" that has nothing to do with ID, so I want each new insert, to be equal to "last record inserted +1", for example.
a Web Novel has a title, a description an image, and it has chapter, so I have a novel entity and a chapter entity.
the chapter entity has a field called "number" for "Chapter Number" related to that specific "novel"
how do I go around, checking that "the current chapter inserted belongs to XX novel, so I want to get the last inserted "number" value, related to the XX novel, and then set this NEW insert to "latest chapter number for novel XX + 1"
dont know if im explaining myself properly.
jlchafardet @everyone
Now I'm sitting on an entirely different problem.
When I try to run fixtures now, with 2 fixtures requiring relationships (using DependentFixtureInterface and the new method getDependencies) it errors me saying that it cannot find an entity thats attempted to be loaded.
josec@Josefo-Desktop: /D/vhosts/novelreader
$ bin/console doctrine:fixtures:load
In SymfonyFixturesLoader.php line 76:
The "App\Entity\Novel" fixture class is trying to be loaded, but is not available. Make sure thi
s class is defined as a service and tagged with "doctrine.fixture.orm".
josec@Josefo-Desktop: /D/vhosts/novelreader
$
so let me show you my code.
AuthorFixtures no need for relations yet imho as I dont have to add novels nor chapters to add an author.
NovelFixtures https://pastebin.com/58NjFGEC
ChapterFixtures https://pastebin.com/AHLTs9bw
BaseFixture https://pastebin.com/rfprPd8r
The error is as stated above, whenever I try to run the fixtures, I get the error that the Entity Novel is trying to be loaded but not available, when it actually is.
oh mah gawd! I found the problem, I was trying to use the entities themselves, not the fixtures when calling the dependencies, as soon as I realized that I was doing return [novel::class] instead of [NovelFixtures::class] i changed it, and presto, worked.
now, the issue I have is, with fixtures, when adding chapters, I need the field "number" to start from 1 for each "new" novel, then add 1 to the previously added number, so each chapter thats added, is incrementally numbered "in a per novel manner".
what I mean is, if there are 20 novels, and each novel has more than 3 chapters, there will be 20 chapters "numbered" 1, 2 and 3, its just that they are "related" to a specific novel.
does that makes any sense at all to you?
Hey JLChafardet,
Haha, tricky misprint but you caught it, good job! :)
I think I got it! Hm, well, first of all, if your fixtures are simple - you can write them in the same fixtures file, like create both Novel and Chapter entities in the same fixtures class, then probably it would be easier to do what you want :)
Otherwise, you just need to play in ChapterFixtures and create Chapter entities in a loop but every new 4th iteration you need to start from 1 again. You can use a separate variable that you will manually increment and re-set in the loop :)
I hope this helps!
Cheers!
Yeah I think I get the idea of what you are proposing, anyway as its for testing purposes, for now, I just lowered the amount of chapters and novels, that way I dont have to sweat much about it. so I can easily go to phpmyadmin and change the chapter number of each novel, that way I can test what I really want, which is the "next, prev" buttons, so you can go straight to the next or previous chapter of a specific novel.
this is an internal "for my own entertainment" work that I'm doing, so I'm using it as both a learning and practicing experiment.
Hey JLChafardet,
Yeah, if you want to do this tweak only once - sounds good to do it directly in the DB... but if you need those tweaks every time you load fixtures and you do it often - it definitely worth to do in fixtures :)
Cheers!
Hi all !
I'm trying to use these tutorials, and adapt it to my own use.
So... I'm trying to have create datas for User.
When I load the fixtures, referring to my terminal, I have this:
Which seems to be correct since I have 2 fixtures files:
<b> UserGroupFixtures </b>
`
<?php
namespace App\DataFixtures;
use App\Entity\UserGroup;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
/**
@package App\DataFixtures
/ class UserGroupFixtures extends Fixture { /*
@param ObjectManager $manager
*/
public function load(ObjectManager $manager)
{
/** @var UserGroup $adminUserGroup */
$adminUserGroup = new UserGroup();
$adminUserGroup->setTitle('admin');
$manager->persist($adminUserGroup);
/** @var UserGroup $adminUserGroup */
$userUserGroup = new UserGroup();
$userUserGroup->setTitle('user');
$manager->persist($userUserGroup);
/** @var UserGroup $adminUserGroup */
$viewerUserGroup = new UserGroup();
$viewerUserGroup->setTitle('viewer');
$manager->persist($viewerUserGroup);
$manager->flush();
}
}
`
<b>UserFixtures</b>
`
<?php
namespace App\DataFixtures;
use App\Entity\User;
use App\Entity\UserGroup;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserFixtures extends BaseFixture implements DependentFixtureInterface
{
}
`
But still.... I have this error:
<b>Cannot find any references for class "App\Entity\UserGroup"</b>
Is there anybody having an idea ?
Thanks for your help
Hey Christina,
I see you call getRandomReference(UserGroup::class) in UserFixtures, but I don't see you add that reference in UserGroupFixtures. We do it behind the scene in createMany() method, see addReference call in this class (better to expand all lines in that code block to see the full picture):
https://symfonycasts.com/sc... . So, if you do not call that createMany(), then you would probably need to call that addReference() method manually to create the reference first.
I hope this helps!
Cheers!
Cheers!
` public function getDependencies()
in the end code. ArticleFixture<b>s</b>?
Hey Ozornick
Awesome catch! Thanks for your attention! We fixed it!
Cheers!
Thank you.
Hi! Looks like the
getRandomReference()function only works on ManyToOne relations... I'm using a OneToOne relation and the$this->faker->randomElement()makes the commanddoctrine:fixtures:loadthrow this error:SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '61' <br /> for key 'UNIQ_4B6C0887A76ED395'How can I adapt it to work for any relation type?
Hey picks
That's a good question. I think what you can do is to create a new method that duplicates the logic of
getRandomReferencebut it removes the fetched reference fromreferencesIndexproperty. Give it a try and let us know if it worked :)Cheers!
Hi! Unfortunaly I can't find the tutorial when you have started to use Fixtures, so I have copied the BaseFixture and create a UserFixture like you have done. Yet when I try to run the command load fixtures I get this error:
In BaseFixture.php line 12:
Attempted to load class "Factory" from namespace "Faker".
Did you forget a "use" statement for "Doctrine\Migrations\
Version\Factory"?
Can you help me?
Hey Gballocc7
That error makes me believe that you don't have Fake installed or for some reason you forgot to copy the use statements from BaseFixture file. Give it a check and let us know if the error continues
Cheers!
Solved, thanks! Now I can't execute the load fixture look at that:
Using UserFixtures:
$this->createMany(User::class,3 , function($i) {
$user = new User();
$user->setUsername(sprintf('prova', $i));
$user->setRoles(["USER_ROLE"]);
$user->setPassword($this->passwordEncoder->encodePassword(
$user,
'prova'
));
return $user;
});
And I get:
In AbstractMySQLDriver.php line 103:
An exception occurred while executing 'INSERT INTO user (username, roles, password) VALUES (
?, ?, ?)' with params [null, "[]", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'username' cannot be null
In PDOStatement.php line 119:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'username' cannot be null
In PDOStatement.php line 117:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'username' cannot be null
How??
Hey Giacomo,
I see it's a duplicate of: https://symfonycasts.com/sc...
Let's continue discuss it there to avoid fixing this problem in a few places.
Cheers!
hey there
This is super weird =) But I have probably a solution for you
composer install(!!!not update needed)Cheers!
hey there
It's a little weird, but I tried your code locally and everything works as expected, Could you please share your
php -voutput?Cheers!
Is it possible to get the same error due to using php 7.2.18?
I think it's possible with any version of PHP it looks like some cache issue have you tried solution from comments below?
Hmm, now I'm getting this error on fixtures load after switching over to the dependencies code near the end.
PHP Fatal error: Class App\DataFixtures\PostFixtures contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Doctrine\Common\DataFixtures\DependentFixtureInterface::getDependencies) in /var/www/dev/svfx/src/DataFixtures/PostFixtures.php on line 51
Hey Aaron,
I don't see we have PostFixtures in the course code. Please, look at parent classes and find the abstract method that is not implemented in your final PostFixtures class. I think PhpStorm may help with it, go to "Generate" menu or press Cmd + N on a Mac, and choose "Implement methods" - you will be suggested to choose what methods you need to implement. Also, I suppose your PostFixtures should be underlined with a red wavy line, if you hover over it - PhpStorm will suggest you what abstract method you have to implement. You can also look inside our any fixture class, e.g. ArticleFixtures to see what methods are implemented there and what's exact implementation of it.
Cheers!
FYI -- fixed it by returning AppFixtures as a dependency for ArticleFixtures equivalent.
Hey Aaron, if your fixture class doesn't have any dependencies, then it must not implement the
DependentFixtureInterfaceI chose a different name other than "Article" and instead used "Post" because I'm going to leverage the services I build in this tutorial as a foundation for a site where "Post" makes more sense than "Article". Anyway, I did generate and that definitely is the problem for the Article class equivalent. Although it's demanding I return a class in an array. Returning nothing and an empty array both give different errors.
I don't see anything in the tutorial covering this case, so I'm guessing the behavior changed from when this was created and the current stable version of Symfony/Doctrine?
Hey guys,
when i implement the getDependencies() function and return [ArticleFixture::class] i get this error in my console:
In Loader.php line 321:
Fixture "App\DataFixtures\ArticleFixture" was declared as a dependency, but it should be added in fixture loader fi
rst.
Adding to that IntelliJ also tells me that ArticleFixture is a undefined class
Hey Kristof!
Try ArticleFixtures with an “s”. I’m afraid that I was accidentally a bit inconsistent and used the s on some fixture classes but not others - if you’re following the code, this one should end in an s.
Let me know if that helps!
Cheers!
yeah that was the error :) thx Ryan
Why I can't see my "AuthorsName" ?
If load DATA from "BaseFixture" it's work (prev. course)
createMany(Comment::class, 7, function(Comment $comment) {
$comment->setStatus(1);
// $comment->setAuthor($this->faker->AuthorsName);
Hey Student!
What exactly code do you have? As I see in your comment, you commented out the line with setAuthor(). Could you give us a bit more context?
Cheers!
Hi.. I am getting this in th console when i use in my fixture the when i use the
getRandomReference(Article::calss). (edit: Woooorks!!)
Booooooo!!!!!
-------------------------------------------------------------------------------
In ReferenceRepository.php line 167: Warning:
Illegal offset type in isset or empty
--------------------------------------------------------------------------------
using the getReference(Article::class . '_' . $this->faker->numberBetween(0, 9) Woooorks!!
I'm on symfony 4.1.2. upgraded today...
because I had a Deprecation Log Message in the Profiler:
----------------------------------------------------------------------------------------
User Deprecated: Doctrine\Common\ClassLoader is deprecated.
----------------------------------------------------------------------------------------
Am I the only I see it???
What may I do wrong...?
_______________________________________________________________
edit:
I found what i did..
geReference( getRandomReference() )
-- NEVER do that --
Ohh, you were trying to get the reference of a reference... yeah, it sound's like the system may behave weird
Hi!!!
For me is confusing a method that sets and gets data. Wouldn't be clearer to have two methods?
{
}
Hey Luis M.!
Yea, I think this certainly makes sense :). I was really "working around" the fact that the normal
addReference()method doesn't give us any "hook" or easy way to "fetch" references out (it's just one big array). But, we could set referencesIndex() from inside ofcreateMany()to avoid needing to build this array later :). I wouldn't worry too much about a method that sets & gets data - the referencesIndex() is more of an "internal cache" to help us out. However, certainly your suggestion makes sense!Cheers!
"Houston: no signs of life"
Start the conversation!