Inserting into a ManyToMany
…best superhero of all time? Um, I mean, how
can we insert things into this join table? How can we join a Genus and a User
together?
Doctrine makes this easy... and yet... at the same time... kind of confusing!
First, you need to completely…
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…
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…
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…
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…
Config.yml: Control Center for Services
…twig and doctrine -
corresponds to a bundle that is being configured:
All of this stuff under framework is configuration for the FrameworkBundle:
Everything under twig is used to control the behavior of the services from TwigBundle:
The job of a bundle is to give us…
Parameters: The Variables of Configuration
…and set that
to a value. Why is this cool? Because you can then reuse that value in any other file
by saying %locale%.
Look under the doctrine key:
Hey, a bunch more, like %database_host% and %database_port%. These are set just
like locale…
parameters.yml & %kernel.root_dir%
…the path from it.
Earlier, just to show off, we configured the DoctrineCacheBundle to store the
markdown cache in /tmp/doctrine_cache:
Referencing absolute paths is a little weird: why not just store this stuff in Symfony's
cache dir? Ok, ok, the bundle actually…
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…
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…
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…
Database Migrations
…But this
bundle primarily gives us something different: a new set of console commands. Run
bin/console with no arguments:
Hiding in the middle is a whole group starting with doctrine:migrations. These
are our new best friend.
Our goal is to find a way…
Query for a List of Genuses
…create a new page that will show off all the genuses. Create
public function listAction() and give it a route path of /genus:
Remember, everything in Doctrine starts with the all-powerful entity manager. Just
like before, get it with $em = $this->getDoctrine()->getManager…
Injecting the Cache Service
…Perfect!
We know this won't work: there is no get() function in this class. And more importantly,
we don't have access to the doctrine_cache.provider.my_markdown_cache service.
How can we get access? Dependency injection.
This time, add a second argument…
The Mysterious "User Provider"
…the user provider
is responsible for loading the User from the session and making sure that it's
up to date. In Doctrine, we'll want our's to re-query for a fresh User object to
make sure all the data is still up…
Controlling Data / Fixtures in a Test
…is stored statically on the parent
test class:
// src/Yoda/UserBundle/Tests/Controller/RegisterControllerTest.php
// ...
public function testRegister()
{
}
Now, grab the Doctrine entity manager by getting the doctrine service
and calling getManager. If you’re not comfortable with what I just did,
don’t worry…
After-dinner Mint
…Let’s pretend
that the email field isn’t requied. Remove the NotBlank constraint
from it and set a nullable=true option in the Doctrine metadata. Don’t
worry about updating your schema - this change is just temporary:
// src/Yoda/UserBundle/Entity/User.php
// ...
/**
@ORM\Column…
Sharing Data between Fixture Classes
…ORM/LoadUsers.php
// ...
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
class LoadUsers implements FixtureInterface, ContainerAwareInterface, OrderedFixtureInterface
{
}
Head over to LoadEvents and make the same change, except returning 20
so that the class is run second:
// src/Yoda/EventBundle/DataFixtures/ORM/LoadEvents.php
// ...
use Doctrine\Common\DataFixtures\OrderedFixtureInterface…
Adding createdAt and updatedAt Timestampable Fields
…library does this for us. It’s called timestampable,
enable it in config.yml:
# app/config/config.yml
# ...
stof_doctrine_extensions:
Head to the timestampable section of the documentation to see how this works.
We already have the Gedmo annotation, so just copy in the…
ManyToMany Relationship
…
Like with a ManyToOne, we just need an annotation that tells
Doctrine what type of association this is and what entity it relates to:
// src/Yoda/EventBundle/Entity/Event.php
// ...
/**
@ORM\ManyToMany(targetEntity="Yoda\UserBundle\Entity\User")
/
protected $attendees;
Whenever you have a relationship that…
x
1000+