Query Logic Re-use & Shortcuts
…we can make the argument to addIsPublishedQueryBuilder()
also optional:
Inside, use the new method: return $this->getOrCreateQueryBuilder() passing it $qb,
and then our andWhere():
But the real beautiful thing is back up top. This whole method can now be one
big chained call: return $this…
EntityType Validation: Restrict Invalid programmerId
…and
clicking ProgrammerRepository. Add public function createQueryBuilderForUser()
with the User $user argument:
Inside, return $this->createQueryBuilder() and alias the class to programmer.
Then, just andWhere('programmer.user = :user') with ->setParameter('user', $user):
Done! The controller passes the User to the form, and the form…
SELECT the SUM (or COUNT)
…Keep the alias consistent for an entity, it'll
save you heartache later.
Next, we need an andWhere() because we need to only find FortuneCookie
results for this Category. So, fc.category - because category is the
name of the property on FortuneCookie for the relationship…
DQL & The Query Builder
…the property... even though
the column in the table is asked_at. Now add ->orderBy() with
q.askedAt and DESC.
Oh, and notice that I'm using andWhere()... even though there are no WHERE
clauses before this! I'm doing this for 2 reasons. First..…
EntityType Checkboxes with ManyToMany
…list? Simple! Start by opening UserRepository: create
a new public function called createIsScientistQueryBuilder():
Very simple: return $this->createQueryBuilder('user'), andWhere('user.isScientist = :isScientist')
and finally, setParameter('isScientist', true):
This doesn't make the query: it just returns the query builder.
Over in GenusFormType, hook…
Querying on a Relationship
…id =
some number. The only tricky part is that the andWhere() is done on
the genus property - not the genus_id column: you always reference
property names with Doctrine.
Finish this with another andWhere('genus_note.createdAt > :recentDate') and
->setParameter('recentDate', new \DateTime(…
Twig Template Inheritance
…the
Homepage class. It's the same concept in Twig.
And these block names - like javascripts, stylesheets and body - aren't special
names... and they're not registered anywhere. Feel free to create new blocks however
and whenever you want. For example, suppose we want…
Twig Partials & for Loops
…These are called template
partials... since they hold code for just part of the page.
Copy this code, and in the main/ directory - though this could go anywhere - add
a new file called _shipStatusAside.html.twig. Paste inside.
Back in homepage.html.twig, delete that…
PHP Enums
…unpublished & draft - or sizes - small, medium
or large - or anything similar.
In the Model/ directory - though this could live anywhere... we're creating the
enum for our own organization - create a new class and call it StarshipStatusEnum.
As soon as I typed the word enum…
Non-Autowireable Arguments
…duplicating our autowired PHP attributes in multiple places. Super handy!
Since we're not currently using that parameter anywhere except our config, we
can get rid of this for now.
Next: Let's see how we can autowire non-autowireable services. It's
surprisingly easy.
Processing the Submitted Form
…to unwanted parts floating around in space - let's finish the
process with a redirect. This is a classic best practice for POST forms.
Let's return $this->redirectToRoute().
We can redirect anywhere, but I'll send users back to the part list for
convenience…
Let’s Write some PHP!
…you see here is just an HTML page that I’ve loaded in my browser
http://localhost:8000/index.php
This is a template based on Twitter Bootstrap and it’s just a bunch of
hardcoded text and links that don’t go anywhere yet…
Setting the Relation
…control the foreign key column: nullable: false means that every
StarshipPart must belong to a Starship.
So how do we say that this part belongs to this Starship?
The answer is beautifully simple. Anywhere before flush(), say
$part->setStarship($starship):
That's it. With Doctrine…
Message, Handler & the Bus
…create a new Message/ directory. We can put our command, or
"message", classes anywhere... but this is a nice way to organize things. Create
a new PHP class called AddPonkaToImage... because that describes the intent
of what we want to happen: we want someone to…
JOINs
…we want to JOIN across this fortuneCookies property over to the
FortuneCookie entity.
Let's do it! Back over in CategoryRepository... we can add the join anywhere in
the query. Unlike SQL, the QueryBuilder doesn't care what order you do things.
Add ->leftJoin() because…
Accessing Data on a ManyToMany
…droid names
in two spots, so let's add a smart method for this in the Starship class. This
could go anywhere, but I'll stick it at the bottom with the other droid methods.
Create a public function getDroidNames(): string. To return a comma…
Validation
…when it hits the database because
some of the columns are null.
And, we expected this! We're missing validation. Adding validation to our API
is exactly like adding validation anywhere in Symfony. For example, find the
name property. We need name to be required…
Filters: Automatically Modify Queries
…it is a two-step process.
First, in config/packages/doctrine.yaml, we need to tell Doctrine that the
filter exists. Anywhere directly under the orm key, add filters and then
fortuneCookie_discontinued. That string could be anything... and you'll see
how we use…
PHP Namespaces in under 5 Minutes
…creates a... sort of... "shortcut". Anywhere else in this file, we can now
just type SomeClassFoo:
and PHP will know that we're really referring to the long class name: Acme\Tools\Foo.
Or... if you leave off the as part, PHP will assume you…
Asset Mapper
…and paste that in.
Since this new files lives inside the assets/ directory, we should be able to
reference it publicly. Let's do that in our base layout: templates/base.html.twig.
Anywhere, say
, {{ and then use the normal asset() function…
x
512