-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# RESTful Webservices in Symfony | ||
|
||
## Coding Challenge 2 - Serialization | ||
|
||
### Tasks | ||
|
||
- use Symfony's Serializer to transform the workshop and attendee entities into a JSON representation | ||
- use `make tests` to check if the api endpoints still work as expected | ||
- make sure that all JSON property names are formatted in _snake_case_ | ||
- add an attendee to one of the workshops and use the PostMan collection to test the endpoints | ||
|
||
### Solution | ||
|
||
- require the Symfony Serializer component: `composer req serializer` | ||
- inject the Serializer into your controllers | ||
- serialize your entities | ||
- create a custom `Normalizer` (implement `ContextAwareNormalizerInterface`) for your Workshop and Attendee entities | ||
- remove the `toArray` method in your entities | ||
- fix the `CircularReferenceException` | ||
|
||
#### Problem 1: No snake_case property names anymore | ||
|
||
```yaml | ||
# config/packages/framework.yaml | ||
|
||
framework: | ||
# ... | ||
serializer: | ||
name_converter: 'serializer.name_converter.camel_case_to_snake_case' | ||
``` | ||
#### Problem 2: Fixing the `CircularReferenceException` | ||
|
||
Adding an attendee to a workshop and accessing this attendee, or the respective workshop results in a `CircularReferenceException`. | ||
|
||
```php | ||
// AttendeeNormalizer | ||
$defaultContext = [ | ||
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => fn ($object, $format, $context) => $object->getFirstname().' '.$object->getLastname(), | ||
]; | ||
``` | ||
|
||
```php | ||
// WorkshopNormalizer | ||
$customContext = [ | ||
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => fn ($object, $format, $context) => $object->getTitle(), | ||
]; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
App\Entity\Attendee: | ||
attendee_1: | ||
__construct: [ '02d47053-4034-4818-97d1-299c4cd7168d', 'Ferdinand', 'Hale', '[email protected]' ] | ||
attendee_2: | ||
__construct: [ '6047c255-593f-4fa8-888b-f919fafd904f', 'Abraham', 'Noel', '[email protected]' ] | ||
attendee_3: | ||
__construct: [ '92e06a4b-19ac-4e67-b988-00e7250929c6', 'Bertha', 'Tucker', '[email protected]' ] | ||
attendee_4: | ||
__construct: [ 'c153c6c3-c43b-449d-8f5a-2bfb627f9822', 'Melodie', 'Perkins', '[email protected]' ] | ||
attendee_5: | ||
__construct: [ 'f5e2c329-f5b8-4e4b-860d-b5a0189ef35f', 'Keegan', 'Mcpherson', '[email protected]' ] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Controller\Attendee; | ||
|
||
use App\Entity\Attendee; | ||
use App\Repository\AttendeeRepository; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\Routing\Annotation\Route; | ||
|
||
#[Route('/attendees', name: 'list_attendee', methods: ['GET'])] | ||
final class ListController | ||
{ | ||
public function __construct( | ||
private readonly AttendeeRepository $attendeeRepository | ||
) { | ||
} | ||
|
||
public function __invoke(): Response | ||
{ | ||
$allAttendees = $this->attendeeRepository->findAll(); | ||
|
||
$allAttendeesAsArray = array_map( | ||
static fn (Attendee $attendee) => $attendee->toArray(), | ||
$allAttendees | ||
); | ||
|
||
return new Response(json_encode($allAttendeesAsArray), Response::HTTP_OK, [ | ||
'Content-Type' => 'application/json', | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Controller\Attendee; | ||
|
||
use App\Entity\Attendee; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\Routing\Annotation\Route; | ||
|
||
#[Route('/attendees/{identifier}', name: 'read_attendee', methods: ['GET'])] | ||
final class ReadController | ||
{ | ||
public function __invoke(Attendee $attendee): Response | ||
{ | ||
return new Response(json_encode($attendee->toArray()), Response::HTTP_OK, [ | ||
'Content-Type' => 'application/json', | ||
]); | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Tests\Controller\Attendee; | ||
|
||
use App\Tests\ApiTestCase; | ||
|
||
class ListControllerTest extends ApiTestCase | ||
{ | ||
public function test_it_should_list_all_attendees(): void | ||
{ | ||
$this->loadFixtures([ | ||
__DIR__.'/fixtures/list_attendee.yaml', | ||
]); | ||
|
||
$this->browser->request('GET', '/attendees'); | ||
|
||
static::assertResponseIsSuccessful(); | ||
|
||
$this->assertMatchesJsonSnapshot($this->browser->getResponse()->getContent()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Tests\Controller\Attendee; | ||
|
||
use App\Tests\ApiTestCase; | ||
|
||
class ReadControllerTest extends ApiTestCase | ||
{ | ||
public function test_it_should_show_requested_attendee(): void | ||
{ | ||
$this->loadFixtures([ | ||
__DIR__.'/fixtures/read_attendee.yaml', | ||
]); | ||
|
||
$this->browser->request('GET', '/attendees/17058af8-1b0f-4afe-910d-669b4bd0fd26'); | ||
|
||
static::assertResponseIsSuccessful(); | ||
|
||
$this->assertMatchesJsonSnapshot($this->browser->getResponse()->getContent()); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
...ller/Attendee/__snapshots__/ListControllerTest__test_it_should_list_all_attendees__1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[ | ||
{ | ||
"identifier": "803449f4-9a4c-4ecb-8ce4-cebc804fe70a", | ||
"firstname": "Jan", | ||
"lastname": "Sch\u00e4dlich", | ||
"email": "[email protected]" | ||
} | ||
] |
6 changes: 6 additions & 0 deletions
6
...Attendee/__snapshots__/ReadControllerTest__test_it_should_show_requested_attendee__1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"identifier": "17058af8-1b0f-4afe-910d-669b4bd0fd26", | ||
"firstname": "Jan", | ||
"lastname": "Sch\u00e4dlich", | ||
"email": "[email protected]" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
App\Entity\Attendee: | ||
attendee_1: | ||
__construct: [ '803449f4-9a4c-4ecb-8ce4-cebc804fe70a', 'Jan', 'Schädlich', '[email protected]' ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
App\Entity\Attendee: | ||
attendee_1: | ||
__construct: [ '17058af8-1b0f-4afe-910d-669b4bd0fd26', 'Jan', 'Schädlich', '[email protected]' ] |