はじめに
Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する
(4.PDO使用)の続きです。
前提
下記記事で構築した環境を前提とします。
手順
1. 専用のユーザーを作成
2. プロジェクトディレクトリを作成・slim3インストール
3. 各種設定
4. DocumentRootを変更&表示確認
5. Twigを使ってみよう
6. Loggingしてみよう
7. Controllerを作成しよう
8. PDOを使用してデータベースに接続しよう
9. @nunulkさんのチュートリアルで作成したチケット管理システムをtwigを使って再現しよう
やってみよう
今回の記事では、手順9を行います。
9. @nunulkさんのチュートリアルで作成したチケット管理システムをtwigを使って再現しよう
Repositoryを実装
Repositoryでは、データベースとの通信を行うための、データアクセスロジックを実装します。
下記のようにフォルダ・ファイルを作成してください。
.
├── src/
└── Domain/
└── Ticket/
└── TicketRepository.php
src/Domain/Ticket/TicketRepository.php
には以下のように記述します。
CRUD機能を一通り用意します。
<?php
namespace App\Domain\Ticket;
use DomainException;
use PDO;
final class TicketRepository
{
private $PDO;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function getTicketById(int $id): array
{
$sql = 'SELECT * FROM tickets WHERE id = :id';
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['id' => $id]);
$row = $stmt->fetch();
if (empty($row)) {
throw new DomainException(sprintf('Ticket not found: %s', $id));
}
return $row ?: [];
}
public function getTickets(): array
{
$sql = 'SELECT * FROM tickets';
$stmt = $this->pdo->query($sql);
$tickets = [];
while($row =$stmt->fetch()) {
$tickets[] = $row;
}
if (empty($tickets)) {
throw new DomainException('Tickets not found');
}
return $tickets ?: [];
}
public function insertTicket($subject): bool
{
$sql = 'INSERT INTO tickets (subject) values (:subject)';
$stmt = $this->pdo->prepare($sql);
$result = $stmt->execute(['subject' => $subject]);
if (!$result) {
throw new DomainException('could not save the ticket');
}
return $result;
}
public function updateTicket($ticket): bool
{
$bool_flg = true;
try {
$selectTicket = $this->getTicketById($ticket['id']);
} catch (DomainException $e) {
$bool_flg = false;
}
if ($bool_flg) {
$sql = 'UPDATE tickets SET subject = :subject WHERE id = :id';
$stmt = $this->pdo->prepare($sql);
$stmt->execute($ticket);
}
return $bool_flg;
}
public function deleteTicket(int $id): bool
{
$bool_flg = true;
try {
$ticket = $this->getTicketById($id);
} catch (DomainException $e) {
$bool_flg = false;
}
if ($bool_flg) {
$sql = 'DELETE FROM tickets WHERE id = :id';
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['id' => $ticket['id']]);
}
return $bool_flg;
}
}
Serviceクラスを実装
Serviceクラスにはビジネスロジックを実装します。
ServiceクラスはControllerから呼び出されます。
Serviceクラスでは、Repositoryで実装されたメソッドを使用します。
下記のようにフォルダ・ファイルを作成してください。
.
├── src/
└── Domain/
└── Ticket/
└── TicketRepository.php
└── TicketService.php
src/Domain/Ticket/TicketService.php
には以下のように記述します。
<?php
namespace App\Domain\Ticket;
final class TicketService
{
private $ticketRepository;
public function __construct(TicketRepository $ticketRepository)
{
$this->ticketRepository = $ticketRepository;
}
public function getTicketById(int $id): array
{
$ticketRow = $this->ticketRepository->getTicketById($id);
return $ticketRow;
}
public function getTickets(): array
{
$ticketRows = $this->ticketRepository->getTickets();
return $ticketRows;
}
public function insertTicket($subject): bool
{
$result = $this->ticketRepository->insertTicket($subject);
return $result;
}
public function updateTicket($ticket): bool
{
$result = $this->ticketRepository->updateTicket($ticket);
return $result;
}
public function deleteTicket(int $id): bool
{
$result = $this->ticketRepository->deleteTicket($id);
return $result;
}
}
Controllerクラスを実装
Controllerクラスを実装して、まずは前回実装したチケット一覧画面を表示してみましょう。
Controllerクラスですが、ネーミングはダニエルさんに従ってActionクラスです。
なぜですか。ダニエルさん。
下記のようにフォルダ・ファイルを作成してください。
.
├── src/
└── Domain/
└── Ticket/
└── TicketRepository.php
└── TicketService.php
└── Action/
└── Action.php
└── TicketAction.php
まずは抽象クラスのsrc/Action/Action.php
に以下のように記述します。
<?php
namespace App\Action;
use Psr\Container\ContainerInterface;
use Slim\Views\PhpRenderer;
abstract class Action
{
protected $renderer;
protected $db;
protected $twig;
public function __construct(ContainerInterface $container)
{
$this->renderer = $container['renderer'];
$this->db = $container['db'];
$this->twig = $container['twig'];
}
}
src/Action/Action.php
を継承したsrc/Action/TicketAction.php
以下のように記述します。
<?php
namespace App\Action;
use App\Domain\Ticket\TicketRepository;
use App\Domain\Ticket\TicketService;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Request;
use Slim\Http\Response;
final class TicketAction extends Action
{
public function index(Request $request, Response $response)
{
$repository = new TicketRepository($this->db);
$service = new TicketService($repository);
$tickets = $service->getTickets();
$data = ['tickets' => $tickets];
return $this->twig->render($response, 'tickets/index.twig', $data);
}
}
routes.php修正
config/routes.php
で、前回修正した箇所を削除し、以下の記述を追加します。
$app->get('/tickets', \App\Action\TicketAction::class . ':index');
container.php修正
config/container.php
で、以前追加した箇所を修正します。
$container[Twig::class] = function (Container $container) {
$container['twig'] = function (Container $container) {
動作確認
ブラウザで以下のURLを開いて、チケット一覧画面が表示されればOKです。
http://192.168.33.90/tickets
以前作成したページを表示するための修正
上記変更を行ったので、time.twigとhome-index.twigは表示できなくなりましたので、修正します。
time.twig
以下のようにsrc/Action/TimeAction.php
を追加します。
<?php
namespace App\Action;
use Slim\Http\Request;
use Slim\Http\Response;
final class TimeAction extends Action
{
public function __invoke(Request $request, Response $response)
{
$viewData = [
'now' => date('Y-m-d H:i:s')
];
return $this->twig->render($response, 'time.twig', $viewData);
}
}
次にconfig/routes.phpを修正します。
$app->get('/time', function (Request $request, Response $response) {
$viewData = [
'now' => date('Y-m-d H:i:s')
];
return $this->get(Twig::class)->render($response, 'time.twig', $viewData);
});
$app->get('/time', \App\Action\TimeAction::class);
home-index.twig
home-twig.twig用に設定したcontainer.phpの内容を削除し、
src/Action/HomeIndexAction.php
を以下のように変更します。
<?php
namespace App\Action;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Request;
use Slim\Http\Response;
final class HomeIndexAction extends Action
{
/**
* Action.
*
* @param Request $request the request
* @param Response $response the response
*
* @return ResponseInterface the response
*/
public function __invoke(Request $request, Response $response): ResponseInterface
{
$viewData = [
'name' => 'World',
];
return $this->twig->render($response, 'Home/home-index.twig', $viewData);
}
}
Action.phpを継承することでControllerクラスにTwigの宣言が不要になりましたし、
container.phpに記述する設定も不要になり、実装がシンプルになりました。
参考サイト
Creating your first Slim 3 Framework Application
Creating your first Slim 3 Framework Application Part 2
私家版 Slim Framework チュートリアル (1、2、3、4、5、6)
関連ページ
Windows10にVagrantをを入れてCentOS7をインストールしよう
1. VagrantインストールからVagrantfileを設置まで
2. 仮想マシンの操作
3. WinSCP、Tera Termに秘密鍵でログイン
4. WinSCP、Tera Termにrootユーザーでパスワードログイン
5. zip/unzipをインストール
6. Vagrantにて仮想環境を配布
ローカルでLAMP環境を構築しよう
0. 事前準備
1. Apacheをインストール
2. MySQLをインストール
3. PHPをインストール
4. ファイアウォールとか停止する
Composerをインストール
PHP Slim3フレームワークのサンプルアプリを作ろう
2-1. First Application Walkthrough Getting Set Upまで
Apache
Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する
1. プロジェクト作成~各種設定
2. DocumentRoot変更~Twigを使用
3. LoggingとController
4.PDO使用
5. チケット管理システムを再現➀
6. チケット管理システムを再現➁