Lucky you! You found an early release chapter - it will be fully polished and published shortly!
Rest assured, the gnomes are hard at work
completing this video!
We're going to start doing more with our API... so it's time to bring this thing to life with some data fixtures!
For this, I like to use Foundry along with DoctrineFixturesBundle. So, run
composer require foundry orm-fixtures --dev
to install both as dev
dependencies. Once that finishes, run
php bin/console make:factory
If you haven't used Foundry before, for each entity, you create a factory class
that's really good at creating that entity. I'll hit zero to generate the one for
DragonTreasure
.
The end result is a new src/Factory/DragonTreasureFactory.php
file.
This class is just really good at creating DragonTreasure
objects. It even
has a bunch of nice random data ready to be used!
To make this even fancier, I'm going to paste over with some code that I've
dragon-ized. Oh, and we also need a TREASURE_NAMES
constant... which I'll also
paste on top. You can grab all of this from the code block on this page.
Ok, so this class is done. Step two: to actually create some fixtures, open
src/DataFixtures/AppFixtures.php
. I'll clear out the load()
method. All we need
is: DragonTreasureFactory::createMany(40)
to create a healthy trove of 40
treasures.
Let's try this thing! Back at your terminal, run:
symfony console doctrine:fixtures:load
Say "yes" and... it looks like it worked! Back on our API docs, refresh...
then let's try the GET
collection endpoint. Hit execute.
Oh, so cool! Look at all those beautiful treasures! Remember, we added 40. But if
you look closely... even though the IDs
don't start at 1, we can see that there
are definitely less than 40 here. The response says hydra:totalItems: 40
,
but it only shows 25.
Down here, this hydra:view
kind of explains why: there's built-in pagination!
Right now we're looking at page 1.. and we can also see the URLs for the last page
and the next page.
So yes, API endpoints that return a collection need pagination... just like a website. And with API Platform, it just works.
To play with this, let's go to /api/treasures.json
. This is page 1... and then
we can add ?page=2
to see page 2. That's the easiest thing I'll do all day.
Now if you need to, you can change a bunch of pagination options. Let's see if we can tweak the number of items per page from 25 to 10.
To start digging into the config, open up your terminal and run:
php bin/console debug:config api_platform
There are a lot of things that you can configure on API Platform. And this
command shows us the current configuration. So for example,
you can add a title
and description
to your API. This becomes part of the
OpenAPI Spec... and so it shows up on your documentation.
If you search for pagination
- we don't want the one under graphql
... we
want the one under collection
- we can see several pagination-related options.
But, again, this is showing us the current configuration... it doesn't necessarily
show us all possible keys.
To see that, instead of debug:config
, run:
php bin/console config:dump api_platform
debug:config
shows you the current configuration. config:dump
shows you a full
tree of possible configuration. Now... we see pagination_items_per_page
.
That sounds like what we want!
This is actually really cool. All of these options live under something called
defaults
. And these are snake-case versions of the exact same options that you'll
find inside the ApiResource
attribute. Setting any of these defaults
in the config
causes that to be the default value passed to that option for every ApiResource
in your system. Pretty cool.
So, if we wanted to change the items per page globally, we could do it with this config. Or, if we want to change it only for one resource, we can do it above the class.
Find the ApiResource
attribute and add paginationItemsPerPage
set to 10.
Again, you can see that the options we already have... are included in the defaults
config.
Move over and head back to page 1. And... voilà! A much shorter list. Also, there are now 4 pages of treasure instead of 2.
Oh, and FYI: you can also make it so that the user of your API can determine how many items to show per page via a query parameter. Check the documentation for how to do that.
Ok, now that we have a lot of data, let's add the ability for our Dragon API users to search and filter through the treasures. Like maybe a dragon is searching for a a treasure of individually wrapped candies among all this loot. That's next.
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^3.0", // v3.0.8
"doctrine/annotations": "^1.0", // 1.14.2
"doctrine/doctrine-bundle": "^2.8", // 2.8.0
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
"doctrine/orm": "^2.14", // 2.14.0
"nelmio/cors-bundle": "^2.2", // 2.2.0
"nesbot/carbon": "^2.64", // 2.64.1
"phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
"phpstan/phpdoc-parser": "^1.15", // 1.15.3
"symfony/asset": "6.2.*", // v6.2.0
"symfony/console": "6.2.*", // v6.2.3
"symfony/dotenv": "6.2.*", // v6.2.0
"symfony/expression-language": "6.2.*", // v6.2.2
"symfony/flex": "^2", // v2.2.4
"symfony/framework-bundle": "6.2.*", // v6.2.3
"symfony/property-access": "6.2.*", // v6.2.3
"symfony/property-info": "6.2.*", // v6.2.3
"symfony/runtime": "6.2.*", // v6.2.0
"symfony/security-bundle": "6.2.*", // v6.2.3
"symfony/serializer": "6.2.*", // v6.2.3
"symfony/twig-bundle": "6.2.*", // v6.2.3
"symfony/ux-react": "^2.6", // v2.6.1
"symfony/validator": "6.2.*", // v6.2.3
"symfony/webpack-encore-bundle": "^1.16", // v1.16.0
"symfony/yaml": "6.2.*" // v6.2.2
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
"symfony/debug-bundle": "6.2.*", // v6.2.1
"symfony/maker-bundle": "^1.48", // v1.48.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/stopwatch": "6.2.*", // v6.2.0
"symfony/web-profiler-bundle": "6.2.*", // v6.2.4
"zenstruck/foundry": "^1.26" // v1.26.0
}
}