diff --git a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/index.md b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/index.md index 8383459..c05eb94 100644 --- a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/index.md +++ b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/index.md @@ -14,7 +14,7 @@ L'objectif est alors de sortir en production notre nouvelle version, et que chaq En revanche, si un client, lors de sa requête, spécifie une version (comme `1.1.0` par exemple), alors il doit continuer à récupérer le même modèle de données que précédemment. -D'un point de vu technique, notre API devra alors appliquer une transformation sur le modèle de sortie afin d'assurer la rétro-compatibilité sur cette version. +D'un point de vu technique, notre API devra alors appliquer une transformation sur le modèle de sortie afin d'assurer la rétro-compatibilité sur cette version. C'est vraiment la réponse de notre API qui sera versionnée. # Gestion du numéro de version @@ -22,6 +22,16 @@ Pour la suite de cet article, j'ai choisi de partir sur un numéro de version sp À vous de choisir ce qui vous conviendra le mieux mais je trouve la solution du header plus simple à maintenir et surtout, lorsque vous décidez de ne plus supporter une version, cela n'a pas d'impact sur les endpoints d'appel à votre API, vous renvoyez simplement la dernière version de votre API. +# Pré-requis + +Avant de débuter l'implémentation technique, il vous faut disposer d'une instance Symfony. Vous pouvez vous rendre sur [http://symfony.com/download](http://symfony.com/download) pour installer une version de Symfony. + +Cet article n'est pas spécifique à Symfony 4, cependant, si vous souhaitez installer cette dernière version, vous pouvez directement utiliser composer : + +``` +$ composer create-project symfony/skeleton api-versioning +``` + # Prochaine étape Une fois la logique claire, nous pouvons commencer à implémenter la configuration des changements en fonction du numéro de version dans notre application Symfony. diff --git a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step1.md b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step1.md index 21320e0..3249ae4 100644 --- a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step1.md +++ b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step1.md @@ -17,6 +17,8 @@ parameters: Nous spécifions une liste de la version la plus récente à la plus ancienne. +**Note** : La version actuelle (1.2.0) n'apparaît pas dans cette liste car il s'agit ici uniquement de la liste des versions sur lesquels nous souhaitons appliquer une rétro-compatibilité. + Les changements de rétro-compatibilité seront alors appliqués dans ce même ordre. Ainsi, dans le cas ou un client ajoute un header `X-Accept-Version: 0.9.0` dans ses requêtes, alors, les changements de rétro-compatibilité des versions seront joués respectivement dans l'ordre `1.1.0`, `1.0.0` puis `0.9.0`. diff --git a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step2.md b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step2.md index 91c886e..14ad254 100644 --- a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step2.md +++ b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step2.md @@ -34,7 +34,8 @@ class VersionChangesListener * @param RequestStack $requestStack * @param ChangesFactory $changesFactory */ - public function __construct(RequestStack $requestStack, ChangesFactory $changesFactory) { + public function __construct(RequestStack $requestStack, ChangesFactory $changesFactory) + { $this->requestStack = $requestStack; $this->changesFactory = $changesFactory; } diff --git a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step3.md b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step3.md index c7ff09a..16c488d 100644 --- a/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step3.md +++ b/_posts/codelabs/2018-03-04-api-versioning-et-retro-compatibilite-avec-symfony/step3.md @@ -65,7 +65,7 @@ Cette classe prend donc en entrée le tableau de versions déclaré dans en tant Notez que, par la suite, vous pourrez avoir besoin d'injecter Doctrine, par exemple, afin de récupérer des données en base de données, et pas simplement de les re-modeler. -Nous avons également écris deux méthodes `has($version)` et `get($version)` assez simples, pour retourner une version. +Nous avons également écrit deux méthodes `has($version)` et `get($version)` assez simples, pour retourner une version. Cependant, les yeux les plus aguéris auront remarqués la présence dans le constructeur de l'appel à la méthode `prepare()` qui va nous permettre d'instancier les namespaces fournis dans la configuration en classes PHP utilisables. @@ -74,8 +74,8 @@ La méthode à ajouter est la suivante : ```php /** * Prepares class instances from class name. - * - * @throws \RuntimeException When version changes class does not exist. + * + * @throws \RuntimeException When version changes class does not exist or does not implement VersionChangesInterface. */ protected function prepare() { @@ -84,6 +84,10 @@ La méthode à ajouter est la suivante : throw new \RuntimeException(sprintf('Unable to find class "%s".', $class)); } + if (!$class instanceof VersionChangesInterface) { + throw new \RuntimeException(sprintf('Class "%s" does not implement VersionChangesInterface.', $class)); + } + $instance = new $class($this->requestStack); $this->versions[$version] = $instance; @@ -117,6 +121,92 @@ Nous ajoutons donc la méthode : Ainsi, dans le cas ou une version `1.0.0` est demandée, seuls les fichiers de changements `1.0.1` et `1.0.0` seront joués. Les versions précédentes tel que `0.0.9` seront ignorées. +Pour vous aider à mieux comprendre la façon dont cet historique de version est récupéré, voici comment serait testé unitairement (avec PHPUnit) cette méthode : + +```php +request = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack') + ->disableOriginalConstructor() + ->getMock(); + + $this->versions = [ + '1.1.0' => 'Acme\VersionChanges\VersionChange110', + '1.0.0' => 'Acme\VersionChanges\VersionChange100', + '0.9.0' => 'Acme\VersionChanges\VersionChange090', + '0.8.0' => 'Acme\VersionChanges\VersionChange080', + ]; + + $this->changesFactory = new ChangesFactory($this->versions, $this->requestStack); + } + + /** + * {@inheritdoc} + */ + protected function tearDown() + { + $this->request = null; + $this->versions = null; + $this->changesFactory = null; + } + + /** + * Test getHistory() when version 1.1.0 + */ + public function testGetHistoryWithVersion110() + { + $history = $this->versionChanges->getHistory('1.1.0'); + + $this->assertCount(1, $history); + $this->assertInstanceOf('Acme\VersionChanges\VersionChange110', $history[0]); + } + + /** + * Test getHistory() when version 1.0.0 + */ + public function testGetHistoryWithVersion100() + { + $history = $this->versionChanges->getHistory('1.0.0'); + + $this->assertCount(2, $history); + $this->assertInstanceOf('Acme\VersionChanges\VersionChange110', $history[0]); + $this->assertInstanceOf('Acme\VersionChanges\VersionChange100', $history[1]); + } +} +``` + +Aussi, pour rappel, même si nous n'écrivons pas de tests unitaires dans ce tutoriel, principalement afin d'en simplifier sa lecture, vous devriez en ajouter afin de vous assurer du comportement de vos méthodes. + # Ajout du service Symfony Afin que ce service soit injecté par l'injection de dépendance de Symfony, nous devons également déclarer le service : diff --git a/src/assets/scss/objects/_course-page.scss b/src/assets/scss/objects/_course-page.scss index 1023b66..d8a4118 100644 --- a/src/assets/scss/objects/_course-page.scss +++ b/src/assets/scss/objects/_course-page.scss @@ -52,7 +52,7 @@ width: em(70px, $context); height: em(70px, $context); .-current & { - background-color: #b8b8b8; + background-color: $brand-yellow; } } @@ -86,9 +86,10 @@ &__button { background-color: $brand-yellow; - border-radius: 50%; - width: em(110px); - height: em(110px); + border: none; + border-radius: 30%; + width: em(70px); + height: em(70px); &[disabled] { visibility: hidden; }