gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
To create a programmer, our client needs to send up some data. And while you can send that data as JSON, XML, form-encoded or any insane format you dream up, you'll probably want your clients to send JSON... unless you work for the banking or insurance industry. They love XML.
For the JSON, we can design it to have any keys. But since our Programmer
entity has the properties nickname
, avatarNumber
and tagLine
, let's
use those.
These don't have to be the same, but it makes life easier if you can manage it.
Back in testing.php
, create a $nickname
- but make it a little bit random:
this has a unique index in the database and I don't want everything to blow
up if I run the file twice. Make a $data
array and put everything
in it. The avatarNumber
is which built-in avatar you want - it's a number
from 1 to 6. And add a tagLine
:
... lines 1 - 11 | |
$nickname = 'ObjectOrienter'.rand(0, 999); | |
$data = array( | |
'nickname' => $nickname, | |
'avatarNumber' => 5, | |
'tagLine' => 'a test dev!' | |
); | |
... lines 18 - 25 |
To send this data, add an options array to post
. It has a key called body
,
and it's literally the raw string you want to send. So we need to json_encode($data)
:
... lines 1 - 11 | |
$nickname = 'ObjectOrienter'.rand(0, 999); | |
$data = array( | |
'nickname' => $nickname, | |
'avatarNumber' => 5, | |
'tagLine' => 'a test dev!' | |
); | |
$response = $client->post('/api/programmers', [ | |
'body' => json_encode($data) | |
]); | |
... lines 22 - 25 |
This looks good - so let's move to our controller. To read the data the
client is sending, we'll need the Request
object. So add that as an argument:
... lines 1 - 7 | |
use Symfony\Component\HttpFoundation\Request; | |
... lines 9 - 12 | |
/** | |
* @Route("/api/programmers") | |
* @Method("POST") | |
*/ | |
public function newAction(Request $request) | |
{ | |
... lines 19 - 21 | |
} | |
... lines 23 - 24 |
To get the JSON string, say $body = $request->getContent()
. And to prove
things are working, just return the POST'd body right back in the response:
... lines 1 - 16 | |
public function newAction(Request $request) | |
{ | |
$data = $request->getContent(); | |
return new Response($data); | |
} | |
... lines 23 - 24 |
The client is sending a JSON string and our response is just sending that right back. Try it!
php testing.php
Hey, that's prefect! We get a 200 status code response and its content is the JSON we sent it. Time to pack it up and call it a day. Just kidding.
Now that we've got the JSON, creating a Programmer
is ridiculously simple.
First, json_decode
the $body
into an array:
... lines 1 - 17 | |
public function newAction(Request $request) | |
{ | |
$data = json_decode($request->getContent(), true); | |
... lines 21 - 30 | |
} | |
... lines 32 - 33 |
For now, we'll trust the JSON string has a valid structure. And the second
argument to json_decode
makes sure we get an array, not a stdClass
object.
Now for the most obvious code you'll see $programmer = new Programmer()
,
and pass it $data['nickname']
and $data['avatarNumber']
- I gave this
entity class a __construct()
function with a few optional arguments. Now,
$programmer->setTagLine($data['tagLine'])
:
... lines 1 - 17 | |
public function newAction(Request $request) | |
{ | |
$data = json_decode($request->getContent(), true); | |
$programmer = new Programmer($data['nickname'], $data['avatarNumber']); | |
$programmer->setTagLine($data['tagLine']); | |
... lines 24 - 30 | |
} | |
... lines 32 - 33 |
The only tricky part is that the Programmer
has a relationship to the User
that created it, and this is a required relationship. On the web, I'm logged
in, so that controller sets my User
object on this when I create a Programmer
.
But our API doesn't have any authentication yet - it's all anonymous.
We'll add authentication later. Right now, we need a workaround. Update the
controller to extend BaseController
- that's something I created right
in AppBundle/Controller
that just has some handy shortcut methods. This
will let me say $programmer->setUser($this->findUserByUsername('weaverryan'))
:
... lines 1 - 4 | |
use AppBundle\Controller\BaseController; | |
... lines 6 - 11 | |
class ProgrammerController extends BaseController | |
{ | |
... lines 14 - 17 | |
public function newAction(Request $request) | |
{ | |
$data = json_decode($request->getContent(), true); | |
$programmer = new Programmer($data['nickname'], $data['avatarNumber']); | |
$programmer->setTagLine($data['tagLine']); | |
$programmer->setUser($this->findUserByUsername('weaverryan')); | |
... lines 25 - 30 | |
} | |
} |
So we're cheating big time... for now. At least while developing, that user exists because it's in our fixtures. I'm not proud of this, but I promise it'll get fixed later.
Finish things off by persisting and flushing the Programmer:
... lines 1 - 17 | |
public function newAction(Request $request) | |
{ | |
... lines 20 - 23 | |
$programmer->setUser($this->findUserByUsername('weaverryan')); | |
$em = $this->getDoctrine()->getManager(); | |
$em->persist($programmer); | |
$em->flush(); | |
... lines 29 - 30 | |
} | |
... lines 32 - 33 |
Enjoy this easy stuff... while it lasts. For the Response
, what should we
return? Ah, let's worry about that later - return a reassuring message, like
It worked. Believe me, I'm an API!
:
... lines 1 - 17 | |
public function newAction(Request $request) | |
{ | |
... lines 20 - 27 | |
$em->flush(); | |
return new Response('It worked. Believe me - I\'m an API'); | |
} | |
... lines 32 - 33 |
The whole flow is there, so go back and hit the script again:
php testing.php
And... well, I think it looks like that probably worked. Now, let's add a form.
// composer.json
{
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.6.*", // v2.6.11
"doctrine/orm": "~2.2,>=2.2.3,<2.5", // v2.4.7
"doctrine/dbal": "<2.5", // v2.4.4
"doctrine/doctrine-bundle": "~1.2", // v1.4.0
"twig/extensions": "~1.0", // v1.2.0
"symfony/assetic-bundle": "~2.3", // v2.6.1
"symfony/swiftmailer-bundle": "~2.3", // v2.3.8
"symfony/monolog-bundle": "~2.4", // v2.7.1
"sensio/distribution-bundle": "~3.0,>=3.0.12", // v3.0.21
"sensio/framework-extra-bundle": "~3.0,>=3.0.2", // v3.0.7
"incenteev/composer-parameter-handler": "~2.0", // v2.1.0
"hautelook/alice-bundle": "0.2.*", // 0.2
"jms/serializer-bundle": "0.13.*" // 0.13.0
},
"require-dev": {
"sensio/generator-bundle": "~2.3", // v2.5.3
"behat/behat": "~3.0", // v3.0.15
"behat/mink-extension": "~2.0.1", // v2.0.1
"behat/mink-goutte-driver": "~1.1.0", // v1.1.0
"behat/mink-selenium2-driver": "~1.2.0", // v1.2.0
"phpunit/phpunit": "~4.6.0" // 4.6.4
}
}