プログラミング

PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

PHP PHPポケモン ポケモン
PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

 

第13回のPHPポケモンは「UI編」ということで、CSSの大人気フレームワークBootstrapさんにお手伝いいただきます。

また、前回実装したレスポンス機能により進化のアクションに一部不具合が出ていたので、このあたりも合わせて修正をしながら進めていきましょう。

 

Bootstrapを導入するにあたり、今までindex.phpに書き込んでいたものを分割するため、新しくResourcesの階層を追加しています。

 

 最後にはコード配布デモページを用意しているので、ぜひ最後まで読んでからご活用ください。

  

Bootstrapの導入

 まずは見た目から見直しをしていきます。ただ、整えるためにCSSを打ち込んでいけばそれだけでかなりの量になってしまうため、前述したとおり今回は大人気CSSのフレームワーク「Bootstrap」のお力を借ります。

とはいっても、線を引いたり余白を整えたりフォームのデザインをお借りするなど、単純なクラスだけしか利用しない(予定)なので、Bootstrapを学習目的の方はその旨ご理解ください

 

出力ファイル(/index.php
# head内に記述
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

  

ステータス詳細の常時表示化

ステータスや詳細を表示するのに、今まではアクションで選択していましたが、これらは常時確認できるに越したことはありません。なので、もし既にポケモンを選択済みであれば出力するようにしましょう。

 

出力ファイル(/index.php
<?php if(isset($controller->pokemon)): ?>
    <section>
        <div class="row">
            <div class="col-12 col-sm-6">
                <?php foreach($controller->pokemon->getDetails() as $key => $val): ?>
                    <dl class="row">
                        <dt class="col-4"><?=$key?></dt>
                        <?php if(is_array($val)) $val = implode(',', $val); ?>
                        <dd class="col-8"><?=$val?></dd>
                    </dl>
                <?php endforeach; ?>
            </div>
            <div class="col-12 col-sm-6">
                <?php foreach($controller->pokemon->getStats() as $key => $val): ?>
                    <dl class="row">
                        <dt class="col-4"><?=$key?></dt>
                        <dd class="col-8"><?=$val?></dd>
                    </dl>
                <?php endforeach; ?>
            </div>
        </div>
    </section>
<?php endif; ?>

 

技一覧の出力には、再度implodeを使用しています。出力結果は以下のとおりです。

 

 

 

これで選択しているポケモンの詳細がひと目で分かるようになりました。

 

 

フォームの分割 

次にフォーム部分を見直ししていきます。前回は配列として項目やメソッドを用意しましたが、増えていけば自由度が制限されてしまい、それこそ保守性が悪くなってしまうため。ファイルを分割して管理していきます。 

さらに、今までは全データをポストしていましたが、メソッドごとにフォームを用意することで解決ができるということが判明したので、こちらも合わせて実装していきます。

 

ポケモンの選択フォーム(/Resources/Parcials/Forms/select_pokemon.php
<form action=" <?=$action_path?>" method="post">
    <p>ポケモンを選択してください</p>
    <div class="input-group">
        <select class="form-control" id="select_pokemon" name="pokemon">
            <option>--選択してください--</option>
            <?php foreach($controller->getPokemonList() as $class => $pokemon): ?>
                <option value="<?=$class?>"><?=$pokemon?></option>
            <?php endforeach; ?>
        </select>
        <div class="input-group-append">
            <button type="submit" class="btn btn-primary">ゲット</button>
        </div>
    </div>
</form>

 

ニックネームの変更フォーム(/Resources/Parcials/Forms/change_nickname.php
<form action="<?=$action_path?>" method="post">
    <input type="hidden" name="action" value="setNickname">
    <div class="input-group mb-3">
      <input type="text" class="form-control" placeholder="最大5文字" name="param" aria-describedby="submit-setNickname">
      <div class="input-group-append">
          <input class="btn btn-primary" type="submit" id="submit-setNickname" value="ニックネームを変更">
      </div>
    </div>
</form>

 

経験値の取得フォーム(/Resources/Parcials/Forms/add_exp.php
<form action="<?=$action_path?>" method="post">
    <input type="hidden" name="action" value="setExp">
    <div class="input-group mb-3">
      <input type="number" class="form-control" min="1" name="param" aria-describedby="submit-setExp">
      <div class="input-group-append">
          <input class="btn btn-primary" type="submit" id="submit-setExp" value="経験値を取得">
      </div>
    </div>
</form>

 

リセットフォーム(/Resources/Parcials/Forms/reset.php
<form action="<?=$action_path?>" method="post">
    <input type="hidden" name="action" value="reset">
    <input class="btn btn-danger" type="submit" value="リセット">
</form>

 

出力用ファイル(/index.php
<?php
 
require_once(__DIR__.'/Classes/Controller.php');
 
session_start();
 
$controller = new Controller($_POST, $_SESSION);
$action_path = '/';
 
?>
 
--省略
 
<div class="col-12 col-sm-6">
    <h2 class="mb-3">メソッドの実行</h2>
    <?php if(is_object($controller->pokemon ?? null)): ?>
        <?php $_SESSION['pokemon'] = $controller->pokemon; # ポケモンのインスタンスをセッションに格納 ?>
        <?php include('Resources/Partials/Forms/change_nickname.php'); # ニックネームの変更?>
        <?php include('Resources/Partials/Forms/add_exp.php'); # 経験値の取得 ?>
        <?php include('Resources/Partials/Forms/reset.php'); # リセット ?>
    <?php else: ?>
        <?php
        // ポストとセッションをリセット
        $_POST = [];
        $_SESSION = [];
        ?>
        <?php include('Resources/Partials/Forms/select_pokemon.php'); ?>
    <?php endif; ?>
</div>

 

それぞれのフォームのアクションパス($action_path)はindex.phpで指定しています。現在はフォームの使いまわしをしていませんが、後々使い回す際に役立つために変数で管理しています。

 

それぞれにフォームを割り当てることで、パラメーターの指定が楽になりましたね。

  1. アクションが選択不要になったため、hiddenで隠しパラメーターとして用意
  2. パラメーターのメソッド判定が不要になったため、nameparamに変更

 

この仕様に合わせてコントローラー側も修正しましょう。

 

コントローラー(/Classes/Controller.php
/**
* @return void
*/
public function __construct($post, $session)
{
    if(get_parent_class($session['pokemon'] ?? null) === 'Pokemon'){
        // Pokemonのインスタンスに溜まったメッセージとレスポンスデータを初期化
        $session['pokemon']->resetMessage();
        $session['pokemon']->resetResponse();
    }
    if(isset($post['pokemon'])){
        // ポケモンをゲットした
        $this->checkPokemon($post['pokemon']);
    }
    if(isset($post['action'])){
        // アクションを選択した
        $this->pokemon = $session['pokemon'] ?? null; # 更新時エラー回避用にnullをセット
        // アクションメソッドの実行
        $this->action($post['action'], $post['param'] ?? null);
    }
}
 
--省略
 
/**
* アクション
*
* @param string $action(method_name)
* @param mixed $param
* @return void
*/
private function action($action, $param)
{
    if($action === 'reset' || is_null($this->pokemon)){
        // 初期化
        $this->pokemon = null;
        return;
    }
    // 呼び出せるメソッドか判別
    if(is_callable([$this->pokemon, $action])){
        // メソッド実行結果を$resultに格納
        $result = $this->pokemon
        ->$action($param);
        switch ($action) {
            // 経験値の取得
            case 'setExp':
            $this->pokemon = $result;
            break;
        }
        // Pokemonクラスに溜まったメッセージを取得
        $this->setMessage($this->pokemon->getMessages());
    }else{
        $this->setMessage('このアクションは使用できません', 'error');
    }
}

 

パラメーター($param)の判別が無くなった分、簡易化することができました。表示を確認してみましょう。

 

 

  

Bootstrapのおかげで大分使いやすくなりましたUIの重要性を改めて感じます。

 

進化アクションの見直し 

次に進化アクションを一部見直したいと思います。前回の仕様で行くと「進化してもメッセージが引き継がれない」という問題がありました。なので、進化後にメッセージを引き継ぐ処理を追加します。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* インスタンス作成時に実行される処理
*
* @param object|null
* @return void
*/
public function __construct($before=null)
{
    // 進化前のポケモンと一致しているかチェック
    if(is_a($before, $this->before_class ?? null)){
        // 進化した際の処理
        $this->takeOverAbility($before);
        // メッセージの引き継ぎ
        $this->setMessage($before->getMessages());
        $this->setMessage($this->name.'に進化した', 'success');
        $this->checkMove();
    }else{
        // 捕まえた際の処理
        $this->setLevel();
        $this->setDefaultExp();
        $this->setDefaultMove();
        $this->setIv();
        $this->setMessage($this->name.'をゲットした', 'success');
    }
}

 

進化メッセージの前に、進化前($before)からのメッセージを引き継ぎさせます。これで進化後にメッセージが消えてしまうという不具合を解消することができました。

 

進化前プロパティの設定

各ポケモンに割り当てていた 進化メソッド(evolve)についても少し見直しをしましょう。

evolveというメソッドはポケモン共通項目です。もちろん進化条件などは様々ですが、現状では特に分けておく必要性もないためポケモンクラスへ移動させましょう。そしてそのためには、進化先を判別できる必要があるので、各ポケモンに進化先のプロパティを用意します。リザードのクラスを例に見てみましょう。

 

リザードのクラス(/Classes/Pokemon/Lezardo.php)
/**
* 進化前(クラス名)
* @var string
*/
protected $before_class = 'Hitokage';
 
/**
* 進化後(クラス名)
* @var string
*/
protected $after_class = 'Lizardon';

※前回までは進化前のクラス用プロパティをchild_classとしていましたが、そうなると進化先のクラス用プロパティを「parent_class」とする必要があり、意味が異なってしまうため、before_classに名称変更しました

 

最終進化のリザードンやライチュウなどは不要のプロパティです。では、ポケモンクラスに移動したevolveメソッドを見直していきましょう。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* 進化
*
* @return Classes\Pokemon\$after_class
*/
protected function evolve()
{
    if(class_exists($this->after_class ?? null)){
        $pokemon = new $this->after_class($this);
        // 進化後のインスタンスを返却
        return $pokemon;
    }else{
        $this->setMessage('このポケモンは進化できません', 'error');
    }
}

 

進化前の判別と同じように、class_existsを使って正しい進化先かどうかを判定しています。これで各ポケモンに設定しているevolveメソッドは不要になりましたので、削除しておきましょう。

 

コードの配布

 出力用ファイルを階層分けした関係で大幅な変更が出ているので、第13回終了時点でのコードをGitHubより配布します。ぜひご活用ください。

 

デモページ

UIの変更により大分遊びやすくなったので、興味ある人はぜひデモページで遊んでみてください。

デモページ

 

まとめ

いかがだったでしょうか。

今回のPHPポケモンは「UIの変更(Bootstrapの導入)」についてご紹介しました。

ゲームは見た目が重要です。PHPではバックエンドの処理がメインとなるため、どうしてもJavascriptCSSの力に頼ることが多くなるでしょう。これらは状況に合わせて活用しながら、あくまでPHPでの処理をメインとして紹介していく予定です。

Webプログラミングに興味がある方は、ぜひ参考にしてくださいね。

 

注目の記事

簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】
ライティング
ブロガー,ブログ
簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】

  ブログの毎日のテーマ決めが大変・・・ そもそも良質な記事をどうやって書けるようになるのかわからない   こんな悩みを抱えていませんか? 始めたばかりで伸び悩んでいる人には多いのではないでしょうか。 今回はブログで収益化や、アクセス数を伸ばそうと考えている人へ向けて「簡単に良質なブログ...

迷惑メールはなぜ届く?amazonや楽天を騙る悪質メールへの対処法とは
ネットワーク
amazon,スパム,メール,楽天
迷惑メールはなぜ届く?amazonや楽天を騙る悪質メールへの対処法とは

「いきなり迷惑メールが届くようになった」 「Amazonや楽天を装ったメールはどうやって見分ければいいの?」   知らない人からいきなり連絡が届いたり、登録もしていないようなサービスからメールが届けば、それは詐欺メールかも知れません。 スマホやパソコンが一般的に普及して、ネットでの買い物やサービスを利用...

反動技編(はかいこうせん・とびひざげり)PHPポケモン40
プログラミング
PHP,PHPポケモン,ポケモン
反動技編(はかいこうせん・とびひざげり)PHPポケモン40

反動技とは ポケモンでは反動技というものがあります。反動によっても様々で、現在の仕組みのままでも実装可能なものや、新たに処理が必要なものまであります。なので、一律で反動技という同じ処理は出来ません。  反動技(ポケモンwiki) https://wiki.ポケモン.com/wiki/反動技 反動技(はんどうわざ...

今からできる!ブログのアクセスを爆UPさせる3大SNS活用法
マーケティング
Facebook,Instagram,Twitter,ブロガー,ブログ
今からできる!ブログのアクセスを爆UPさせる3大SNS活用法

  ブログを収益化させたいけど、なかなかアクセス数が増えない 記事の質は高いのに、その良さをどうやって伝えれば良いかわからない   SEO対策をする上でも、収益化するためにも記事のクオリティは重要です。 しかし、せっかく良い記事を書いていても、そのブログや記事の存在を伝えることができなけれ...

ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4

  ピカチュウから学ぶオブジェクト指向の第4弾は「トレイト(trait)の活用」についてです。更に、レベルシステムを導入すれば欠かせない経験値システムも合わせて実装します。 第3回からの続きとなりますので、もし前回をまだ見ていない人は是非ご参考ください。   それでは今回もピカチュウと一緒に、...

パーティー実装編 トレーナーの作成 PHPポケモン 63
プログラミング
PHP,PHPポケモン,ポケモン
パーティー実装編 トレーナーの作成 PHPポケモン 63

パーティーとは ポケモンでは、ゲーム・アニメ共に最大6匹のパートナーポケモンと旅をすることができます。7匹以上は持ち歩くことができず、ボックスに転送されてしまうという仕組みです。そして、その6匹のパートナーポケモンの構成をパーティーと呼んでいます。 現在のPHPポケモンでは1匹のポケモンしか管理で...

投稿タイトルを自動生成する方法【WordPressを便利にカスタマイズ】
プログラミング
PHP,WordPress
投稿タイトルを自動生成する方法【WordPressを便利にカスタマイズ】

  カスタムフィールドを含む投稿の場合、わざわざタイトルを設定する必要がないものもあります。 そういったときに、カスタムフィールド値を使ってタイトルを自動生成してくれると楽ですし、一覧で見てもわかりやすい状態にすることができます。   今回はWordPressで「投稿タイトルを自動生成する方法」につ...

ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか
プログラミング
amazon,AWS,Honeycode,NoCode,プログラミング学習
ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか

  近年、プログラミングの需要は増え勢いを増していますが、それ以上にノーコードというソースコードを打たなくでもアプリ開発ができるというソフトウェアやプラットフォームが普及してきました。 これにより一部の期待感とは別に、プログラマーという職業は今後不要になるのではないかと危機感を抱く人が出て...

カテゴリ

SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO SEO対策 Sequel Pro Skype SNS SSH Symfony TCP/IP title Toastr Trait Twig Twitter UCC V系 WAN WebSub Wi-Fi wiki Windows WordPress XAMPP xml Xserver YouTube YouTuber Zoom アーティスト アウトプット アクセス層 アニメーション アフィリエイト イーブイ インターネット インプット エンジニア オブジェクト指向 お金配り クリック単価 クリック数 コミュニケーション能力 コロナ コンサルティング サムネイル システムエンジニア スタートアップ スタイルシート スパム データベース ディープフェイク デザイナー デザイン テレワーク ナンパ ニュース ネットワークモデル ノマドワーク バナー ピカチュウ ビジネス フィード フリーランス ブロガー ブログ プログラマー プログラミング プログラミング学習 プログラミング教育 プロトコル ホームページ制作 ポケモン マークアップ マーケティング メール リモートワーク レンダリング 三井住友 三宮 仕事依頼 児童デイ 児童デイサービス 児童発達支援 公開鍵 初心者 助成金 勉強法 営業 広告 広告収入 必勝マニュアル 放課後等デイサービス 朝活 楽天 深層学習 無線LAN 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力