gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Question: have you ever gone to the store and accidentally bought too much cheese? It's the story of my life. Or maybe you have the opposite problem: you're hosting a big party and you don't have enough cheese! This is our new billion dollar idea: a platform where you can sell that extra chunk of Brie you never finished or buy a truck-load of camembert from someone who go a little too excited at the cheese market. Yep, it's what the world is asking for: a peer-to-peer cheese marketplace. We're calling it: Cheese Whiz.
For the site, maybe we're going to make it an single-page application built in React or Vue... or maybe it'll be a little more traditional: a mixture of HTML pages and JavaScript that makes AJAX requests. And maybe we'll even have a mobile app. It doesn't really matter because all of these options mean that we need to be able to expose our core functionality via an API.
But to start: forget about the API and pretend like this is a normal, boring Symfony project. Step 1 is... hmm, probably do create some database entities.
Let's open up our .env
file and tweak the DATABASE_URL
. My computer uses root
with no password... and how about cheese_whiz
for the database name.
... lines 1 - 30 | |
DATABASE_URL=mysql://root:@127.0.0.1:3306/cheese_whiz | |
... lines 32 - 33 |
You can also create a .env.local
file and override DATABASE_URL
there. Using root
and no password is pretty standard, so I like to add this to .env
and commit it as the default.
Cool! Next, at your terminal, run
composer require maker --dev
to get Symfony's MakerBundle... so we can be lazy and generate our entity. When that finishes, run:
php bin/console make:entity
Call the first entity: CheeseListing
, which will represent each "cheese" that's for sale on the site. Hit enter and... oh! It's asking:
Mark this class as an API Platform resource?
MakerBundle asks this because it noticed that API Platform is installed. Say "yes". And before we add any fields, let's go see what that did! In my editor, yep! This created the usual CheeseListing
and CheeseListingRepository
. Nothing special there. Right now, the only property the entity has is id
. So, what did answering "yes" to the API Platform resource question give us? This tiny annotation right here: @ApiResource
.
... lines 1 - 7 | |
/** | |
* @ApiResource() | |
... line 10 | |
*/ | |
class CheeseListing | |
... lines 13 - 111 |
The real question is: what does that activate? We'll see that soon.
But first, let's add some fields. Let's see, each cheese listing probably needs a title
, string
, 255
, not nullable, a description
, which will be a big text field, price
, which I'll make an integer
- this will be the price in cents - so $10 would be 1000, createdAt
as a datetime
and an isPublished
boolean. Ok: good start! Hit enter to finish.
Congratulations! We have a perfectly boring CheeseEntity
class: 7 properties with getters and setters.
... lines 1 - 11 | |
class CheeseListing | |
{ | |
/** | |
* @ORM\Id() | |
* @ORM\GeneratedValue() | |
* @ORM\Column(type="integer") | |
*/ | |
private $id; | |
/** | |
* @ORM\Column(type="string", length=255) | |
*/ | |
private $title; | |
/** | |
* @ORM\Column(type="text") | |
*/ | |
private $description; | |
/** | |
* @ORM\Column(type="integer") | |
*/ | |
private $price; | |
/** | |
* @ORM\Column(type="datetime") | |
*/ | |
private $createdAt; | |
/** | |
* @ORM\Column(type="boolean") | |
*/ | |
private $isPublished; | |
... lines 45 - 109 | |
} |
Next, generate the migration with:
php bin/console make:migration
Oh! Migrations isn't installed yet! No problem, follow the recommendation:
composer require migrations
But before we try generating it again, I need to make sure my database exists:
php bin/console doctrine:database:create
And now run make:migration
:
php bin/console make:migration
Let's go check that out to make sure there aren't any surprises:
CREATE TABLE cheese_listing...
... lines 1 - 12 | |
final class Version20190508193750 extends AbstractMigration | |
{ | |
... lines 15 - 19 | |
public function up(Schema $schema) : void | |
{ | |
// this up() migration is auto-generated, please modify it to your needs | |
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); | |
$this->addSql('CREATE TABLE cheese_listing (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, description LONGTEXT NOT NULL, price INT NOT NULL, created_at DATETIME NOT NULL, is_published TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB'); | |
} | |
... lines 27 - 34 | |
} |
Yea! Looks good! Close that and run:
php bin/console doctrine:migrations:migrate
Brilliant! At this point, we have a completely traditional Doctrine entity except for this one, @ApiResource()
annotation. But that changes everything. This tells API Platform that you want to expose this class as an API.
Check it out: refresh the /api
page. Woh! Suddenly this is saying that we have five new endpoints, or "operations"! A GET
operation to retrieve a collection of CheeseListings, a POST
operation to create a new one, GET
to retrieve a single CheeseListing
, DELETE
to... ya know... delete and PUT
to update an existing CheeseListing
. That's a full, API-based CRUD!
And this isn't just documentation: these new endpoints already work. Let's check them out next, say hello to something called JSON-LD and learn a bit about how this magic works behind the scenes.
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/api-pack": "^1.2", // v1.2.0
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/doctrine-migrations-bundle": "^2.0", // v2.0.0
"nesbot/carbon": "^2.17", // 2.19.2
"symfony/console": "4.2.*", // v4.2.9
"symfony/dotenv": "4.2.*", // v4.2.9
"symfony/flex": "^1.1", // v1.9.10
"symfony/framework-bundle": "4.2.*", // v4.2.9
"symfony/yaml": "4.2.*" // v4.2.9
},
"require-dev": {
"symfony/maker-bundle": "^1.11", // v1.11.6
"symfony/profiler-pack": "^1.0" // v1.0.4
}
}