Joining Across a ManyToMany
…Behind the scenes, to get this
data, Doctrine will need to query across the join table and the tag table.
But... we don't really care about that! We just get to say question.tags and
that returns all the Tag objects for this Question…
Field Types & Options
…we now know that, because we've bound our form to our entity, the form type
"guessing" system is able to read the Doctrine metadata, notice that content
looks like a big field, and "guess" that it should be a textarea.
Field type guessing is…
Custom Validation, Callback and Constraints
…Event entity
that looks like this (with some extras, like getter and setter methods):
// src/KnpU/QADayBundle/Entity/Event.php
namespace KnpU\QADayBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
@ORM\Entity(repositoryClass="KnpU\QADayBundle\Entity\EventRepository")
/
class Event
{
@ORM\Column(name="id", type="integer")
…
Clean URLs with Sluggable
…it does!
It adds slug including a UNIQUE INDEX for slug. And when we run it with
symfony console doctrine:migrations:migrate
it explodes... for the same reason as last time: Not null violation. We're
adding a new slug column to our table that…
Final Upgrades & Cleanups
…s possible that some recipes
have new versions we can update to. Run:
composer recipes:update
Oh, whoops! I need to commit my changes:
git commit -m 'upgrading doctrine/dbal from 2 to 3'
Perfect! Now run
composer recipes:update
and... cool! There are two…
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…
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…
The ManyToOne Relation
…want to do is relate an Answer to a Question.
To do this... well... forget about Doctrine for a second. Let's just think about
how this would look in a database. So: each answer belongs to a single question.
We would normally model this…
Rendering Answer Data & Saving Votes
…templates/question/show.html.twig.
If you scroll down a bit - here it is - we loop over the answers variable. That
will still work: the Doctrine collection is something that we can loop over.
But the answer variable will now be an Answer object. So…
Decorating Data Persisters vs Context Builders
…called just DataPersister. Back in PhpStorm, hit
Shift+Shift, search for DataPersister and make sure to include "non-project items".
Select the one from ApiPlatform's Doctrine Bridge.
And... cool! This looks pretty much exactly like we expected: it persists and
flushes. This is what…
Custom Filter apply()
…an admin.
Why are we talking about these extension classes? Because one of the core
Doctrine extensions is called FilterExtension.
Let's open it up: Shirt+Shift and look for FilterExtension.php making sure to
include all non-project items. Get the one from Orm\…
Custom User Method
…the new
file:
And... yep! It looks perfect. Move back to your terminal one more time and run:
php bin/console doctrine:migrations:migrate
Excellent! Now that we have the new field, let's set it on our dummy users in the
database. Open UserFixture…
Article Admin & Low-Level Access Controls
…you see this "Proxies" thing, ignore
it. This is an internal object that Doctrine sometimes wraps around your entity
in order to enable some of its lazy-loading relation awesomeness. The object looks
and works exactly like User.
Second, the error itself basically means that…
Dynamic Roles
…ORM\Column annotation and set its type to json_array:
This is really cool because the $roles property will hold an array of roles,
but when we save, Doctrine will automatically json_encode that array and store
it in a single field. When we query…
Creating an Entity Class
…need a use statement for it. This
will look weird, but add a use for a Column class and let it auto-complete from
Doctrine\ORM\Mapping. Remove the Column part and add as ORM:
Every entity class will have that same use statement. Next…
Adding More Columns
…above each:
These tries to guess the right field type - but it's not always right. speciesCount
should clearly be an integer - set it to that. For a full-list of all the built-in
Doctrine types, check their docs. The most important are string…
x
1000+