Link Search Menu Expand Document

Moduulit

Edellisessä tutoriaalissa Hello World! asensit Piken, ja loit projektiokansion uudelle applikaatiolle. Tässä tutoriaalissa jatkat projektia laajentamalla sen peliaiheiseksi REST-API:ksi.

Sisällysluettelo

  1. Johdanto
  2. Step 1. Luo kontrollerit ja moduulit
    1. Päivitä index.php, composer.json ja testaa
  3. Step 2. Luo peleille ja genreille DAO-luokat
    1. Luo datatiedostot ja testaa
  4. Step 3. Bundlaa moduulit yhden luokan alle
  5. Yhteenveto

Johdanto

Tässä tutoriaalissa luot REST-backendin kuvitteelliselle peliaiheiselle applikaatiolle. Tutoriaalissa luot API:in kaksi moduulia:

  • Game: käsittelee peleihin liittyvät HTTP-pyynnöt
  • Genre: käsittelee peligenreihin liittyvät HTTP-pyynnöt

Step 1. Luo kontrollerit ja moduulit

Luo kopio edellisen tutoriaalin projektikansiosta (tut1-hello-pike) ja anna kopioidulle kansiolle nimeksi tut2-modules. Luo kansioon kansio tut2-modules/src, ja sen sisälle kaksi uutta kansiota - src/Game ja src/Genre. Luo kumpaankin kansioon kaksi uutta tiedostoa:

src/Game/GamesModule.php

<?php declare(strict_types=1);

namespace Me\MyApp\Game;

use Pike\AppContext;

final class GamesModule {
    public function init(AppContext $ctx): void {
        $ctx->router->map('GET', '/games/[w:genreSlug]',
            [GamesController::class, 'listGamesByCategory']
        );
    }
}

src/Game/GamesController.php

<?php declare(strict_types=1);

namespace Me\MyApp\Game;

use Pike\{Request, Response};

final class GamesController {
    public function listGamesByCategory(Request $req, Response $res): void {
        $games = ["@todo pelit kategorialle {$req->params->genreSlug}"];
        $res->json($games);
    }
}

src/Game/GenresModule.php

<?php declare(strict_types=1);

namespace Me\MyApp\Genre;

use Pike\AppContext;

final class GenresModule {
    public function init(AppContext $ctx): void {
        $ctx->router->map('GET', '/genres',
            [GenresController::class, 'listGenres']
        );
    }
}

src/Game/GenresController.php

<?php declare(strict_types=1);

namespace Me\MyApp\Genre;

use Pike\Response;

final class GenresController {
    public function listGenres(Response $res): void {
        $genres = [
            (object) ['name' => 'Real time tactics', 'slug' => 'real-time-tactics'],
            (object) ['name' => 'Role playing game', 'slug' => 'role-playing-game'],
            (object) ['name' => 'First person shooter', 'slug' => 'first-person-shooter'],
            (object) ['name' => 'Point-and-click', 'slug' => 'point-and-click'],
            (object) ['name' => 'Racing', 'slug' => 'racing'],
        ];
        $res->json($genres);
    }
}

Päivitä index.php, composer.json ja testaa

Konfiguroi composerin autoloader lataamaan projektimme nimiavaruus Me\MyApp.

Päivitä composer.json

     "name": "me/my-app",
     "require": {
         "ut4/pike": "0.9.0"
+    },
+    "autoload": {
+        "psr-4": {"Me\\MyApp\\": "src/"}
     }
 }

… ja aja tämän jälkeen komento composer update (projektikansion juuressa /tut2-modules).

Lisää Pike-applikaation luontikutsuun edellä luomasi moduulit.

Päivitä index.php

<?php declare(strict_types=1);

$loader = require __DIR__ . '/vendor/autoload.php';

$app = new \Pike\App([new \Me\MyApp\Game\GamesModule,
                      new \Me\MyApp\Genre\GenresModule]);
$app->handleRequest($_GET['q'] ?? '/');

Avaa tämän jälkeen selaimesi osoitteissa http://<devausYmpäristösiOsoite>/tut2-modules/index.php?q=/games/real-time-tactics ja http://<devausYmpäristösiOsoite>/tut2-modules/index.php?q=/genres, joka pitäisi listata kontrollerien palauttaman kovakoodatun datan.

Step 2. Luo peleille ja genreille DAO-luokat

Korvataan konrollereihin kovakoodattu data luokilla, jotka lukee ne json-tiedostoista:

Luo uusi tiedosto src/Game/GamesDao.php

<?php declare(strict_types=1);

namespace Me\MyApp\Game;

use Pike\{ArrayUtils, FileSystem};

final class GamesDao {
    /** @var \Pike\FileSystem */
    private $fs;
    public function __construct(FileSystem $fs) {
        $this->fs = $fs;
        $this->dataFilePath = dirname(__DIR__, 2) . '/data/games.json';
    }
    public function listByGenreSlug(string $genreSlug): array {
        $all = json_decode($this->fs->read($this->dataFilePath));
        $filtered = ArrayUtils::filterByKey($all, $genreSlug, 'genreSlug');
        return $filtered;
    }
}

Päivitä src/GamesController.php

 use Pike\{Request, Response};

 final class GamesController {
-    public function listGamesByCategory(Request $req, Response $res): void {
-        $games = ["@todo pelit kategorialle {$req->params->genreSlug}"];
+    public function listGamesByCategory(Request $req,
+                                        Response $res,
+                                        GamesDao $gamesDao): void {
+        $games = $gamesDao->listByGenreSlug($req->params->genreSlug);
         $res->json($games);
     }
 }

Luo uusi tiedosto src/Genre/GenresDao.php

<?php declare(strict_types=1);

namespace Me\MyApp\Genre;

use Pike\FileSystem;

final class GenresDao {
    /** @var \Pike\FileSystem */
    private $fs;
    public function __construct(FileSystem $fs) {
        $this->fs = $fs;
        $this->dataFilePath = dirname(__DIR__, 2) . '/data/genres.json';
    }
    public function listAll(): array {
        $all = json_decode($this->fs->read($this->dataFilePath));
        return $all;
    }
}

Päivitä src/GenresController.php

 use Pike\Response;

final class GenresController {
-    public function listGenres(Response $res): void {
-        $genres = [
-            (object) ['name' => 'Real time tactics', 'slug' => 'real-time-tactics'],
-            (object) ['name' => 'Role playing game', 'slug' => 'role-playing-game'],
-            (object) ['name' => 'First person shooter', 'slug' => 'first-person-shooter'],
-            (object) ['name' => 'Point-and-click', 'slug' => 'point-and-click'],
-            (object) ['name' => 'Racing', 'slug' => 'racing'],
-        ];
+    public function listGenres(Response $res, GenresDao $genresDao): void {
+        $genres = $genresDao->listAll();
         $res->json($genres);
     }
 }

Luo datatiedostot ja testaa

Luo uusi kansio tut2-modules/data ja sinne kaksi uutta tiedostoa:

data/games.json

[
    {"name":"Desperados III","genreSlug":"real-time-tactics"},
    {"name":"Shadow Tactics: Blades of the Shogun","genreSlug":"real-time-tactics"},
    {"name":"Cyberpunk 2077","genreSlug":"role-playing-game"},
    {"name":"The Elder Scrolls V: Skyrim","genreSlug":"role-playing-game"},
    {"name":"Wasteland 3","genreSlug":"role-playing-game"},
    {"name":"Doom","genreSlug":"first-person-shooter"},
    {"name":"Control","genreSlug":"first-person-shooter"},
    {"name":"Beautiful Desolation","genreSlug":"point-and-click"},
    {"name":"Life Is Strange","genreSlug":"point-and-click"},
    {"name":"Wreckfest","genreSlug":"racing"},
    {"name":"Trials Evolution","genreSlug":"racing"},
    {"name":"Ridge Racer Unbounded","genreSlug":"racing"}
]

data/genres.json

[
    {"name":"Real time tactics","slug":"real-time-tactics"},
    {"name":"Role playing game","slug":"role-playing-game"},
    {"name":"First person shooter","slug":"first-person-shooter"},
    {"name":"Point-and-click","slug":"point-and-click"},
    {"name":"Racing","genreSlug":"racing"}
]

Tämän jälkeen REST-reittimme pitäisi palauttaa kovakoodatun datan sijaan json-tiedostojen sisältämä data. Cool!

Step 3. Bundlaa moduulit yhden luokan alle

Tehdään applikaatiostamme testattavampi irroittamalla se index.php -tiedostosta omaksi luokakseen.

Luo uusi tiedosto src/MyGamingSiteApp.php

<?php declare(strict_types=1);

namespace Me\MyApp;

use Pike\App;
use Me\MyApp\Game\GamesModule;
use Me\MyApp\Genre\GenresModule;

final class MyGamingSiteApp {
    public static function create(): App {
        return new App([
            new GamesModule,
            new GenresModule
        ]);
    }
}

Päivitä index.php

 $loader = require __DIR__ . '/vendor/autoload.php';
 
-$app = new \Pike\App([new \Me\MyApp\Game\GamesModule,
-                      new \Me\MyApp\Genre\GenresModule]);
+$app = \Me\MyApp\MyGamingSiteApp::create();
 $app->handleRequest($_GET['q'] ?? '/');

Yhteenveto

Tässä tutoriaalissa:

  • Korvasit yhden tiedoston Hei Maailma -applikaation melkein oikealla REST-API-applikaatiolla
  • Konfiguroit composerin automaattisesti lataamaan applikaation src-kansiossa sijaitsevat luokat
  • Huomasit miten Pike injektoi automaattisesti luokistasi (GamesDao, GenresDao) instansseja kontrollereihin

Seuraavaksi Tutoriaali #3: Testaus.


Copyright © 2019-2021 ut4