プログラミング

グローバル&ヘルパー関数編 PHPポケモン 61

PHP PHPポケモン ポケモン
グローバル&ヘルパー関数編 PHPポケモン 61

進化や技習得、HPバーや経験値バーの演出ができているのに、なぜ状態異常の演出はされていないの?

 

そう感じている方が少なからずいるはずです。

現段階では、状態異常になっても次の画面に移管しなければ表示されません。これは、PHP側で内部処理は行われているが、メッセージに合わせた動的な変更がされていないからです。

 

実は、この実装を妨げている原因が「レスポンストレイト」なのです。

今回のPHPポケモンは、よりよいシステム構成にするための「グローバル関数」と「ヘルパー関数」の実装方法についてご紹介します。

 

グローバル関数

グローバル変数という名称はよく聞くかも知れませんが、グローバル関数という言葉にはあまり聞き馴染みがない人が多いはずです。なぜなら、あくまでこれは仮名称で、どこからでも呼び出せる関数ということを表現しているだけだからです。

 

例えば、tranJpという日本語置き換えの関数を序盤に実装しましたよね。これは、ページの最初に読み込んでおくことで、どこからでも呼び出すことが可能です。

これを、レスポンス(メッセージ・モーダルを含む)関係で活用できるようにするのが、今回のグローバル関数の目的です。

 

グローバル変数の活用

作成するグローバル関数と合わせて使いたいのが「グローバル変数」です。セッションやポストなどもグローバル変数(スーパーグローバル変数)ですが、今回はこれとは別のグローバル変数を用意します。

 

例えば、以下の例を見てみましょう。

<?php
$global = 'グローバル変数';
 
function test(){
    return $global;
}
 
var_dump(test());

 

上記のコードでは、test関数内で宣言している$globalは「見つかりません」となりエラーが吐き出されてしまいます。関数内では、あくまでその関数内で作成された変数や引数しか使うことができません。

 

ですが、これをグローバル宣言することで、testという関数内でも$globalを使うことができます。

<?php
$global = 'グローバル変数';
 
function test(){
    global $global;
    return $global;
}
 
var_dump(test());

 

関数内で、globalという宣言をして変数を記述します。こうすることで「この関数で使う$globalは、関数外で使っているglobalのことだよ」ということを知らせてやることができるのです。

 

レスポンスのクラス化と一元化

それでは、原因となっているレスポンストレイトについてです。

現在は、どのクラスでも活用できるようにトレイトとしてレスポンス関係を管理していましたが、こうすることでそれぞれのクラス内にレスポンスが含まれてしまうことになります。そのせいで、引き継ぎ処理などがややこしくなってしまい、混乱や機能制限を招く結果となっています。

なのでそれを解決するためにも、レスポンスはクラスとして用意することで、一元管理しましょう。

 

レスポンスクラス(/Classes/Response.php
<?php
class Response
{
    /**
    * メッセージの格納用
    * @var array
    */
    private $messages = [];
 
    /**
    * レスポンスデータの格納用
    * @var array
    */
    private $responses = [];
 
    /**
    * モーダルの格納用
    * @var array
    */
    private $modals = [];
 
    /**
    * メッセージIDの発行
    *
    * @return string
    */
    public function issueMsgId()
    {
        // IDを生成
        $id = 'msg'.substr(bin2hex(random_bytes(16)), 0, 16);
        // ユニークになるようにチェック
        while(in_array($id, $_SESSION['__message_ids'] ?? [], true)){
            $id = 'msg'.substr(bin2hex(random_bytes(16)), 0, 16);
        }
        $_SESSION['__message_ids'][] = $id;
        return $id;
    }
 
    /**
    * 全リセット
    *
    * @return void
    */
    public function resetResponsesAll()
    {
        $this->messages = [];
        $this->responses = [];
        $this->modals = [];
    }
 
    /**==================================================================
    * メッセージ関係の処理
    ==================================================================**/
    /**
    * メッセージの取得
    *
    * @return array
    */
    public function getMessages()
    {
        return $this->messages;
    }
 
    /**
    * メッセージの格納
    *
    * @param string|array $msg
    * @param mixed $param
    * @return array
    */
    public function setMessage($msg, $param=null)
    {
        if(empty($msg)){
            // 空の場合はスキップ
            return;
        }
        if(is_array($msg)){
            // 一括登録
            $this->messages = array_merge($this->messages, $msg);
        }else{
            // 単発登録
            $this->messages[] = [$msg, $param, ''];
        }
    }
 
    /**
    * アニメーション用の自動メッセージの格納
    *
    * @param mixed $param
    * @return array
    */
    public function setAutoMessage($param)
    {
        $this->messages[] = ['', $param, 'auto'];
    }
 
    /**
    * 空メッセージの格納
    *
    * @param string $param
    * @return array
    */
    public function setEmptyMessage(string $param='')
    {
        $this->messages[] = ['', $param, ''];
    }
 
    /**
    * メッセージの初期化
    *
    * @return void
    */
    public function resetMessage()
    {
        $this->messages = [];
    }
 
    /**
    * メッセージの最初のキーを取得
    *
    * @return void
    */
    public function getMessageFirstKey()
    {
        return array_key_first($this->messages);
    }
 
    /**
    * メッセージの最後のキーを取得
    *
    * @return void
    */
    public function getMessageLastKey()
    {
        return array_key_last($this->messages);
    }
 
    /**==================================================================
    * レスポンス関係の処理
    ==================================================================**/
    /**
    * 指定したレスポンステータの取得
    *
    * @param string|integer
    * @return mixed
    */
    public function getResponse($param)
    {
        if(isset($this->responses[$param])){
            return $this->responses[$param];
        }
    }
 
    /**
    * レスポンステータの全取得
    *
    * @return array
    */
    public function getResponses()
    {
        return $this->responses;
    }
 
    /**
    * レスポンステータの格納
    *
    * @param mixed $response
    * @param mixed $key
    * @return array
    */
    public function setResponse($response, $key=null)
    {
        if(empty($response)){
            // 空の場合はスキップ
            return;
        }
        if(is_null($key)){
            // キー指定無し
            if(is_array($response)){
                // $responseが配列の場合の処理
                $this->responses = array_merge($this->responses, $response);
            }else{
                // $responseが配列ではない場合の処理
                $this->responses[] = $response;
            }
        }else{
            // キー指定有り
            $this->responses[$key] = $response;
        }
    }
 
    /**
    * 指定されたプロパティをレスポンスにセット(出力)
    *
    * @return void
    */
    public function exportProperty(...$properties)
    {
        foreach($properties as $property){
            $this->setResponse($this->$property, $property);
        }
    }
 
    /**
    * レスポンステータの初期化
    *
    * @return void
    */
    public function resetResponse()
    {
        $this->responses = [];
    }
 
    /**==================================================================
    * モーダル関係の処理
    ==================================================================**/
    /**
    * モーダルテータの取得
    *
    * @return array
    */
    public function getModals()
    {
        return $this->modals;
    }
 
    /**
    * モーダル用テータの格納
    *
    * @param array $param
    * @param boolean $merge
    * @return array
    */
    public function setModal(array $param, bool $merge=false)
    {
        if(empty($param)){
            // 空の場合はスキップ
            return;
        }
        if($merge){
            // 結合(引き継ぎ)
            $this->modals = array_merge($this->modals, $param);
        }else{
            // モーダル格納
            $this->modals[] = $param;
            // モーダル起動時用のからメッセージをセット
            $this->messages[] = ['', '', ''];
        }
    }
 
    /**
    * モーダル情報の初期化
    *
    * @return void
    */
    public function resetModal()
    {
        $this->modals = [];
    }
 
}

 

トレイトの内容を、そのままクラスに置き換えました。このクラスにメッセージを格納することで一元管理をしていきましょう。

 

ヘルパー関数

さて、前項で説明したグローバル関数と、新しく作成したレスポンスクラスを使って一元管理をするとしましたが、実際にどのように紐付けていくかがネックです。

例えばポケモンクラス内でレスポンスクラスにアクセスするためには、メソッド内でグローバル関数の宣言が必要になります。

/**
* 正式名称を取得する
* @return string
*/
public function getName()
{
    global $global;
    return $this->name;
}

 

これを全メソッドに行うとなれば、明らかに非効率的です。なので、グローバル宣言をしなくても呼び出せるグローバル関数を経由することで、グローバル変数に用意されたレスポンスのインスタンスにアクセスし、メソッドを呼び出す方法を取ります。

これを、フレームワークなどで名称活用されている「ヘルパー関数」としましょう。

 

全クラス内から共通インスタンスへのアクセス

それでは、全クラス内からアクセスできるレスポンスインスタンスを作成しましょう。

レスポンス関係のヘルパー関数を格納するファイル(ResponseGlobal.php)を作成し、これをページの最初で読み込んでおきます。

require_once(__DIR__.'/App/Globals/ResponseGlobal.php');

 

それでは、ヘルパー関数の作成方法を見ていきましょう。以下、メッセージを取得するためのヘルパー関数です。

<?php
// レスポンス用グローバル関数
$root_path = __DIR__.'/../..';
// クラス読み込み
require_once($root_path.'/Classes/Response.php');
$global_responses = new Response;
 
/**
* メッセージの取得
* @return array
*/
function getMessages()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}

 

ポイントは、関数名とレスポンスのメソッド名を合わせているという点です。こうしておくことで、__FUNCTION__で現在の関数名が取得できるので、そのままグローバル変数のメソッド名として使用することができます。

もし他のインスタンスに対して用意する際に、メソッド名が重複する場合は、関数名を取得せず、メソッド指定で呼び出すようにしておきましょう。

 

次に、引数指定があるメッセージの格納用のヘルパー関数を見ていきましょう。

/**
* メッセージの格納
* @param string|array $msg
* @param mixed $param
* @return void
*/
function setMessage($msg, $param=null)
{
    global $global_responses;
    $name = __FUNCTION__;
    $global_responses->$name($msg, $param);
}

こちらは、引数をそのまま指定するだけでOKです。この要領で、レスポンス用のヘルパー関数を作成していきましょう。

 

レスポンス用ヘルパー関数
<?php
// レスポンス用グローバル関数
$root_path = __DIR__.'/../..';
// クラス読み込み
require_once($root_path.'/Classes/Response.php');
$global_responses = new Response;
 
/**
* メッセージIDの発行
* @return string
*/
function issueMsgId()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**
* 全リセット
* @return void
*/
function resetResponsesAll()
{
    global $global_responses;
    $name = __FUNCTION__;
    $global_responses->$name();
}
 
/**==================================================================
* メッセージ関係の処理
==================================================================**/
/**
* メッセージの取得
* @return array
*/
function getMessages()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**
* メッセージの格納
* @param string|array $msg
* @param mixed $param
* @return void
*/
function setMessage($msg, $param=null)
{
    global $global_responses;
    $name = __FUNCTION__;
    $global_responses->$name($msg, $param);
}
 
/**
* アニメーション用の自動メッセージの格納
*
* @param mixed $param
* @return void
*/
function setAutoMessage($param)
{
    global $global_responses;
    $name = __FUNCTION__;
    $global_responses->$name($param);
}
 
/**
* 空メッセージの格納
*
* @param string $param
* @return void
*/
function setEmptyMessage(string $param='')
{
    global $global_responses;
    $name = __FUNCTION__;
    $global_responses->$name($param);
}
 
/**
* メッセージの初期化
* @return void
*/
function resetMessage()
{
    global $global_responses;
    $name = __FUNCTION__;
    $global_responses->$name();
}
 
/**
* メッセージの最初のキーを取得
*
* @return mixed
*/
function getMessageFirstKey()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**
* メッセージの最後のキーを取得
*
* @return mixed
*/
function getMessageLastKey()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**==================================================================
* レスポンス関係の処理
==================================================================**/
/**
* 指定したレスポンステータの取得
*
* @param string|integer
* @return mixed
*/
function getResponse($param)
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name($param);
}
 
/**
* レスポンステータの全取得
*
* @return array
*/
function getResponses()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**
* レスポンステータの格納
*
* @param mixed $response
* @param mixed $key
* @return array
*/
function setResponse($response, $key=null)
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name($response, $key);
}
 
/**
* レスポンステータの初期化
*
* @return void
*/
function resetResponse()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**==================================================================
* モーダル関係の処理
==================================================================**/
/**
* モーダルテータの取得
*
* @return array
*/
function getModals()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}
 
/**
* モーダル用テータの格納
*
* @param array $param
* @param boolean $merge
* @return array
*/
function setModal(array $param, bool $merge=false)
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name($param, $merge);
}
 
/**
* モーダル情報の初期化
*
* @return void
*/
function resetModal()
{
    global $global_responses;
    $name = __FUNCTION__;
    return $global_responses->$name();
}

 

一元化したことにより、セッションを活用したメッセージIDの重複チェックは不要かなと思っています。現在は支障が無いので、合間を見て修正をかけていきます。

また、現段階では可変長引数への対応ができないのと、プロパティへのアクセスができないため、exportPropertyメソッドは不要になりました。

 

あとは、全コードのメッセージやレスポンスの格納方法を変更するだけです。

例として、レベル技習得確認メソッド(checkeLevelMove)の記述を見てみましょう。

/**
* 現在のレベルで覚えられる技があるか確認する処理
*
* @return void
*/
protected function checkLevelMove()
{
    // レベルアップして覚えられる技があれば習得する
    $level_move_keys = array_keys(
        array_column($this->level_move, 0),
        $this->level
    );
    foreach($level_move_keys as $key){
        $move_class = $this->level_move[$key][1];
        // 覚えようとしている技(クラス)が存在かつ重複していないか
        if(!in_array($move_class, array_column($this->move, 'class'), true)){
            // インスタンス化
            $move = new $move_class;
            if(count($this->move) < 4){
                /**
                * 技が4つ未満なら即習得
                */
                // 技クラスをセット
                $this->setMove($move);
                setMessage($move->getName().'を覚えた!');
            }else{
                /**
                * 技選択用モーダルの返却
                */
                // メッセージIDを生成
                $msg_id = issueMsgId();
                // レベルアップメッセージ
                setMessage($this->getNickName().'は'.$move->getName().'を覚えたい');
                setMessage('しかし技を4つ覚えるので精一杯だ');
                setMessage($move->getName().'の代わりに他の技を忘れさせますか?', $msg_id);
                // レスポンスデータをセット
                setResponse([
                    'toggle' => 'modal',
                    'target' => '#'.$msg_id.'-modal',
                    'move' => $move_class
                ], $msg_id);
                // モーダル用のレスポンスをセット
                setModal([
                    'id' => $msg_id,
                    'modal' => 'selectmove',
                    'new_move' => $move
                ]);
                // 諦めメッセージを事前に用意しておく
                setMessage($this->getNickName().'は'.$move->getName().'を覚えるのを諦めた');
            }
        }
    }
}

 

大分スマートになりました。また、今まで引き継ぎ処理としていたメッセージを取得してコントローラーのメッセージに格納、その後取得先のメッセージをリフレッシュするという処理をなくすことができました。

  

まとめ

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

今回のPHPポケモンでは内部の修正として、グローバル・ヘルパー関数を活用した「レスポンスの一元化」の方法をご紹介しました。

この変更を本番環境に反映させる際には、再度セーブデータの全リセットを行う予定です。ご了承ください。

また、この変更に合わせて状態異常の演出に取り欠かれるので、こちらは近日中に実装します。

 

現在プログラミング学習に取り組んでいる方、興味を持たれている方は、ぜひ参考にしてみてくださいね。

 

注目の記事

コンテンツ配信業でバズるために大切な3つの法則〜『1ヶ月でチャンネル登録者数1000人』は参考にするな
マーケティング
YouTube,YouTuber,ブログ
コンテンツ配信業でバズるために大切な3つの法則〜『1ヶ月でチャンネル登録者数1000人』は参考にするな

  YouTubeやブログを始めたけど思ったように伸びない・・・   こういった人は、チャンネル登録者数を伸ばす方法などの動画を見ても参考にならなく、結果に繋がらないという場合がほとんどです。 その理由は、その人自身に問題があるわけではなく、動画の前提条件がそもそも違っているからです。   今回は「...

手っ取り早く情報強者になる簡単な方法
雑記
アウトプット,インプット,ニュース
手っ取り早く情報強者になる簡単な方法

  ニュースや情報番組、討論番組をみると、出演者の方々の情報量の多さに圧倒されることがあります。 また、ユニークな考え方に共感を得る人も多いでしょう。   どうやって、情報を仕入れているのか? なぜそんなことまで知っているのか?   メディアで取り上げられているような人や、活躍している人の多く...

フリーランスのための値段交渉術!案件はこうやって見極めろ
フリーランス
フリーランスのための値段交渉術!案件はこうやって見極めろ

  「これもっと安くならない?」 「他の人はこれぐらいの金額でやってくれるよ」   こういった値切り交渉を受けたことがある人もいるのではないでしょうか?技術を提供するフリーランスであれば、金額を落とすということは自分の価値を下げているということを理解しておかなければなりません。 値段交渉...

状態異常演出編 PHPポケモン 62
プログラミング
PHP,PHPポケモン,ポケモン
状態異常演出編 PHPポケモン 62

状態異常の演出 今回は「状態異常」にかかった際の動的な変更、演出を実装していきます。 どく状態になれば、メッセージに合わせて「どく」を表記、まひ状態になれば、メッセージに合わせて「まひ」をセットするという単純なものです。   返り値の変更 それではまず、状態異常をセットしてメッセージを生成して...

HPバー色変更編(アニメーション) PHPポケモン53
プログラミング
PHP,PHPポケモン,ポケモン
HPバー色変更編(アニメーション) PHPポケモン53

HPバーの色変更 残りHPの割合に合わせて色クラスをセットしていましたが、ダメージを受けた際の判定処理(動的は変更)が未実装でしたので、今回はコチラを対応します。   残数(割合)の判定 HPの色判定は、HTMLの描画時とJSによるHP変動時に行います。animateメソッド前や後に行うと変更のズレが生じるため、a...

独立するならWordPress理解しておけばOK!プログラミングでフリーランスはこれ一つで成り立ちます
プログラミング
PHP,WordPress,フリーランス,独立
独立するならWordPress理解しておけばOK!プログラミングでフリーランスはこれ一つで成り立ちます

  プログラミングでフリーランスを目指すには、どの言語始めればいいの?   プログラミングの学習を始めたのに、それをどう活かせばよいか分からず、いざフリーランスで活動しようと思ってもイメージできずに断念してしまう人は多いです。 言語にも向き不向きがあるため、フリーランスとして活動するために向...

未経験からWeb系エンジニアとしてフリーランスになる現実的な方法教えます【軌道に乗れば起業も可能】
フリーランス
エンジニア,フリーランス,プログラミング学習,独立,起業
未経験からWeb系エンジニアとしてフリーランスになる現実的な方法教えます【軌道に乗れば起業も可能】

  セカンドキャリアとしてプログラミングやデザインを学習したい   そう考えてスクールを受講したり、独学で始める人が増えていますが、そのほとんどが実らずに挫折してしまいます。 ですが、学習方法と経験の積み方や職の選び方さえ間違えなければ、技術を身につけてフリーランスとして活動することも難しく...

甘い誘惑に気をつけよう「わからないことへの対処法」
雑記
甘い誘惑に気をつけよう「わからないことへの対処法」

  最近は開発記事が多めだったので、今回は気分転換も込めてみんな大好きコラムのコーナーです。開発疲れという理由ももちろんありますが、久々に考えを書き綴りたくなったというのが本音です。   今回のテーマは「甘い誘惑に気をつけよう」です。高校生ぐらいまではあまり縁がなかったことでも、大学生・社会...

カテゴリ

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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力