Foundry: Fixture Model Factories
…we deserve better! Let's use a super fun new library instead. Google for
"Zenstruck Foundry" and find its GitHub Page.
Foundry is all about creating Doctrine entity objects in an easy, repeatable
way. It's perfect for fixtures as well as for functional tests…
Data Fixtures
…random controller like QuestionController, we can install a bundle to
do it properly. Find your terminal and run:
composer require orm-fixtures --dev
This is another flex alias: orm-fixtures installs doctrine/doctrine-fixtures-bundle
When this finishes... it installed a recipe! I committed all…
Request Object & POST Data
…read the direction value and increase or decrease the vote
count. We could do this with an AJAX call instead of a form submit. From
a Doctrine and Symfony perspective, it really makes no difference. So I'll
keep it simple and leave JavaScript out…
How Entity Controller Arguments Work
…is that code?
At first, you might think this is another argument value resolver. But, there's
nothing in that list that mentions "doctrine" or "entity". In reality, this is
working via a different system.
If we refresh now, the page still works. But if…
Hunting the Final Deprecations
…Ctrl+C to exit the "tail" mode and run this again,
but this time "pipe" it to grep Deprecated:
We're now watching the log file for any lines that contain Deprecated. Unfortunately,
because of that annoying doctrine/persistence stuff, it does contain extra
noise…
Upgrading KnpPaginatorBundle & PHP Platform Version
…TreeBuilder::root() thing. This is a low-level function that
third-party bundles use. And if you dig through the list, this
stof_doctrine_extensions comes from StofDoctrineExtensionsBundle... as does
most of the other ones - like orm, and mongodb. The last one comes from
KnpPaginatorBundle…
The N+1 Problem & EXTRA_LAZY
…familiar!
We have the same number 1 exclusive-time function as before:
UnitOfWork::createEntity(). In that situation, it meant that we were querying
for too many items and so Doctrine was hydrating too many objects. Is it the
same problem now? And if so, why…
Hello Flex: Moving Final Files
…console doctrine:migrations:status
Ah! I guess not! It says that my migration class wasn't found: Is it placed in
a DoctrineMigrations namespace? Bah! I don't know!
Our files have an Application\Migrations namespace. What's going on? Open the
config/packages/doctrine…
Autowiring & Service Deprecations
…In Symfony 3, when Symfony
saw a type-hint - like EntityManager - it would first look to see if there was
a service or alias in the container with that exact id: so Doctrine\ORM\EntityManager.
If there was not, it would then scan every service…
Optimizing with Cache
…do we need to clear this cache
on each deploy? Nope! Internally, Symfony uses a cache namespace for Doctrine
that includes the directory of our project. Since Ansistrano always deploys into
a new releases/ directory, each deploy has its own, unique namespace.
When provisioning finishes…
Database Setup
…Then cheat and copy the previous task. This
is simple enough: run doctrine:migrations:migrate with --no-interaction, so
that it won't interactively ask us to confirm before running the migrations.
Interactive prompts are no fun for an automated deploy:
Register another variable - run…
Configuring Specific (Named) Arguments
…clear out the arguments, and add $cache: '@doctrine_cache.providers.my_markdown_cache':
The dollar sign is the important part: it tells Symfony that we're actually configuring
an argument by its name. $cache here must match $cache here.
And it works beautifully - refresh now…
Collection Filtering: The Easy Way
…that my User correctly has a studiedGenuses property
with a mappedBy option...
But on GenusScientist, I forgot to add the inversedBy() that points back to this:
I don't really know why Doctrine requires this... since it didn't seem to break anything,
but hey…
Deleting an Item from a Collection: orphanRemoval
…relationship:
In other words, if we remove or add a GenusScientist from this array, it doesn't
make any difference! Doctrine ignores changes to the inverse side.
How to fix it? We already know how! We did it back with our ManyToMany relationship!
It's…
Joining Across a ManyToMany + EXTRA_LAZY Fetch
… Yes!
But now click the Doctrine icon down in the web debug toolbar to see how the queries
look on this page. This is really interesting: we have one query that's repeated
many times: it selects all of the fields from user and then…
Removing a ManyToMany Item
…remove the User from the genusScientists property and
save. Doctrine will notice that the User is missing from that collection and
take care of the rest.
Let's start inside the the genus/show.html.twig template. Add a new link for
each user: give…
Fetching Items from a ManyToMany Collection
…out this query happens automagically, and the matching users are
set into the $genusScientists property. Yea, Doctrine just does it! All we need
to do is expose this private property with a getter: public function, getGenusScientists(),
then return $this->genusScientists:
Now, open up the show…
Give me Clean URL Strings (slugs!)
…But! But, but but! I have good news: if we can understand just a few important
concepts, Doctrine collections are going to fall into place beautifully. So let's
take this collection of chaos and turn it into a collection of.. um... something awesome...
like…
Querying on a Relationship
…just like before - start with return $this->createQueryBuilder()
with genus_note as a query alias. For now, don't add anything else: finish with
the standard ->getQuery() and ->execute():
Doctrine doesn't know about this new repository class yet, so go tell it! In
GenusNote…
The King of Relations: ManyToOne
…use a different example,
this would be if each product had many tags, but also each tag related to many
products.
And when it comes to Doctrine relations - don't trust the Internet! Some people
will try to confuse you with other relationships like OneToMany…
x
1000+