No Time For a REST

Phew, it’s been another red hot, football-filled week here in the UK. I’m sure for some of you, 29°C is positively chilly. But for me, it’s been baking. Not helped by an evil selection of naughty wasps making camp outside my window, forcing me to work without fresh air. Lovely.

Anyway, I’m sure you don’t tune in for weather updates, or for my views on the Sports Ball. Let’s get back to the good stuff.

Do You GraphQL?

One of the most interesting bits of tech about at the moment, in my opinion, is GraphQL.

GraphQL, briefly, is an alternative to REST. The main difference between ‘REST’ and GraphQL being that we – as consumers – can specify exactly which bits of data we want / need, and the server returns just the things we care about, and nothing more.

Also, you only need one endpoint with GraphQL, as often opposed to many with ‘REST’.

Now, I put REST in inverted commas as the typical RESTful API’s that I both create, and work with, are not truly RESTful. Pragmatism, and all that. That’s why I’ve more typically started referring to these types of API’s as JSON APIs.

But I digress.

Like every new piece of tech, there are often a bunch of advocates shouting loudly, particularly on sites like Twitter, about how if you’re not using GraphQL then you’re basically a dinosaur.

how-to-graphqlThen recently – I think maybe a few weeks ago – I came across a really interesting website about GraphQL. It’s called How To GraphQL.

Why I like the site is that there are some generic introduction tutorials, and then some more language specific tutorials. There’s React for the front end, along with Node and Elixir on the back end. No PHP, mind. More on that in a second. I chose the Elixir tutorial, and enjoyed playing around with it.

After playing around with the Elixir back end implementation I’d created, I wondered how this might translate into PHP. I was already aware that the API Platform can support GraphQL so used that as a starting point. I kept my implementation identical (well, as close as) to the setup in the How To GraphQL Elixir tutorial. The idea being that I could switch out the two, and the front end shouldn’t care.

It turned out to be a really interesting exercise. I’d be happy to share my code if anyone has any interest? There’s nothing fancy there, but it was a fun learning experience for me.

What I did find most interesting was in that Dunglas, the creator of the API Platform (and many other cool things – very clever guy, well worth following), isn’t quite the GraphQL advocate I expected. These two tweet threads are interesting reading:

and:

I’d be really interested to hear about your experiences with GraphQL.

Video Update

This week saw three new videos added to the site:

GET’ting Multiple Resources [API Platform]

I mentioned last week that in many ways I’ve been doing the API Platform a disservice.

In taking as many videos as I have to show a single end point API I may have made things look more difficult than they really are.

We’ve used this setup as an excuse to cover some interesting, and useful / commonly needed things such as customisation of your route paths, and defining custom operations (the Health check).

If you don’t need to customise anything, getting an API up and running using the API Platform is really remarkably rapid.

All that said, I stand by this approach. We’ve played around with some cool features. This is all stuff that will help you in the real world.

PUT to Update Existing Data [API Platform]

The API Platform takes an interesting approach to the process of updating existing data.

There’s no implementation of PATCH , the most controversial / complex HTTP Verb. And that’s fine. Less controversy is always a good thing, imo. Besides which, the more I work with the front end, the less I find any use for PATCH  anyway. Typically I will have the full resource, so making full updates to that resource is easy enough.

We cover a little potential gotcha in the way that API Platform differs from the Symfony 4 JSON API, and Symfony 4 with FOSRESTBundle approaches. This is in the status code returned by the API Platform, and why they may choose to do this.

DELETE to Remove Data [API Platform]

Adding an implementation for DELETE  is probably the easiest of the whole lot. This is partly because we’ve done all the hard work already. But also because deleting stuff just works. There’s very little to it.

Now, in the real world you’d probably want to restrict who can and can’t delete, and things get a little more complex. But the underlying operation itself is very straightforward.

There’s just one thing left to do with our API Platform setup, and that’s handle the error paths. We’ll get on to that in the final video in this part of the series.

Live Stream Update

I’ve recorded the first “live stream”. It’s on my laptop, waiting for a touch of editing. I need to mask a few bits of config due to security reasons.

I also hit on a proper issue. The domain I was planning to launch under has expired. And worse, because I let it expire and didn’t renew it, it’s gone into grace period. And now Namecheap want $108 to reactivate it. Silly me.

Ok, so this may delay the launch of the thing in the real world. It’s not going to stop me writing the code. I wanted to get this video out this week. It will slip into next week. Fortunately (depending on how you look at it), I have a couple of long train journeys on Monday and Tuesday evening next week. The perfect time to edit videos – even if it does draw a few funny looks.

As a reminder, the live stream stuff will not be getting a write up. These will be video only, but you’re more than welcome to raise questions, or ask to see more detail etc. I’ll share all that via the forum.

Ok, that about wraps it up from me this. As ever, have a great weekend, and happy coding.

Chris

Renaming Routes in DunglasApiBundle

Let’s say you have defined a new Resource  entry for your SocialMediaAccount  Entity:

# app/config/services.yml

    resource.social_media_account:
        parent:    "api.resource"
        arguments: [ "AppBundle\\Entity\\SocialMediaAccount" ]
        tags:      [ { name: "api.resource" } ]

Now, when we run php app/console debug:router we see the following:

dunglas-api-bundle-rename-routes

Ack. Underscores in our URLs.

Most likely not what we want.

Thankfully, changing this is really easy:

# app/config/services.yml

    resource.social_media_account:
        parent:    "api.resource"
        arguments: [ "AppBundle\\Entity\\SocialMediaAccount" ]
        calls:
            - method: "initShortName"
              arguments: [ 'social-media-account' ]
        tags:      [ { name: "api.resource" } ]

Success:

dunglasapibundle-custom-route-names

But, how did I know to add in that specific method in the calls block?

This line: parent: “api.resource” tells us that we are using a Parent Service.

Parent services are something of a trade off.

They decrease the amount of configuration you are required to write, but increase the technical complexity of comprehending the configuration.

The idea is that if we have two or more classes that are being configured as Symfony Services, and that they share identical setup requirements, then we can extract the common / shared requirements to a parent class, and tell our child services to use the configuration from the parent.

We can now remove the duplicated service setup / configuration.

However, newer or less experienced developers who read our code / configuration will have a harder time understanding what is happening.

But back to DunglasApiBundle!

We are using api.resource as our Parent service. This service definition must live somewhere, and as Symfony Bundles tend to follow a common structure, the best place to start looking would be in:

/vendor/dunglas/api-bundle/Resources/config/

There’s a fair few files in here:

dunglas-api-bundle-resources

If unsure, do a quick search for ‘api.resources’ in that folder, or resort to the old school method of opening them one-by-one and eye balling the service definitions until you find the one you want.

In our case, it lives inside api.xml , nice and easy:

<service id="api.resource" class="Dunglas\ApiBundle\Api\Resource" public="false" abstract="true" lazy="true" />

Now we have the class name so we know exactly where to look.

With the file found (/vendor/dunglas/api-bundle/Api/Resource.php ), all we need to know are the available method names. Thankfully, PHPStorm can provide us with a nice list of them:

dunglas-api-bundle-resource-php-methods

Sorry about the truncating. If you want to see that view then hit cmd / ctrl + 7, and then cmd / ctrl + 1 to return to ‘normal’ when you are done.

Now we have our list of methods, we can simply add the required methods, along with their parameters to our calls block in our concrete Resource setup:

# app/config/services.yml

    resource.social_media_account:
        parent:    "api.resource"
        arguments: [ "AppBundle\\Entity\\SocialMediaAccount" ]
        calls:
            - method: "initShortName"
              arguments: [ 'social-media-account' ]
        tags:      [ { name: "api.resource" } ]

Be sure to read up on Symfony Parent Services to understand this further.

Happy Dunglas’ing! 🙂