プログラミング

PHPポケモン「オートローダー編」16

PHP PHPポケモン ポケモン
PHPポケモン「オートローダー編」16

 

今までは技やタイプを一括requireという荒業で対応していましたが、フシギダネ系列の技を実装した際に「こんなん全部読み込んでられるか!」と流石になったので、簡易ながらオートローダーを実装していきます。

そして、実装したらしたで色々と問題も浮かび上がってきたので、このあたりは回を進めて行きながら修正予定です。

 

それでは今回はPHPのオートローダー(autoloader)についてご紹介します。

 

一部解釈ミスがあったので、本記事の修正版を挙げています。本記事も参考にしながら本格的且つ簡易的なオートローダーは次記事をご参考ください

PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化 PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化

  前回実装したオートローダーの使い方が盛大に間違っていたので、今回その間違いの説明をしながら、正しい実装方法をご紹介します。 申し訳ありません。(誠意)    オートロードについて(再)  必要なタイミングで必要なファイルをrequireまたはincludeするあれです。   前回spl_autoload_reg...

 

オートローダーとは

簡単に言えば、必要な時に必要なファイルを自動的に読み込む便利な機能のことです。

 

PHPであればspl_autoload_registerという関数使って、指定したファイルをrequireincludeすることができます。 

  

簡易オートローダーの作成

とは言っても、今回は全てのファイルをオートローダーを使って読み込むようなことはしません。あくまで使用するのは「ポケモン」「」「タイプ」というデータベースの用にしているファイルのみです。

※現段階は上記3つですが、必要に応じて増やしていきます

 

通常オートローダーはクラスで作成されますが、インスタンス化するのも面倒なので今回はトレイトで作成します。

※もし都合が悪くなればクラスに変更予定です

 

オートローダー(/Traits/AutoLoaderTrait.php
<?php
 
trait AutoLoaderTrait
{
    /**
    * オートローダー
    *
    * @param string $class_name
    * @param string $folder
    * @return void
    */
    protected function autoLoader($class_name, $folder='')
    {
        if(!empty($folder)){
            // フォルダ指定されていれば最後にスラッシュを付与
            $folder = $folder.'/';
        }
        spl_autoload_register(function($class_name) use($folder){
            // クラス名からファイルを検索
            $path = __DIR__ . '/../Classes/'.$folder.$class_name.'.php';
            if(file_exists($path)){
                // 見つかった場合は読み込み実行
                require $path;
            }
        });
    }
}

 

それではautoLoaderのメソッドを見ていきましょう。

protected function autoLoader($class_name, $folder='')
{
    if(!empty($folder)){
        // フォルダ指定されていれば最後にスラッシュを付与
        $folder = $folder.'/';
    }
    spl_autoload_register(function($class_name) use($folder){
        // クラス名からファイルを検索
        $path = __DIR__ . '/../Classes/'.$folder.$class_name.'.php';
        if(file_exists($path)){
            // 見つかった場合は読み込み実行
            require $path;
        }
    });
}

 

引数の1つ目はクラス名です。渡されたクラス名は読み込む対象となるファイル名として使用されるため、必ず作成したクラス名とファイル名は一致させておきましょう。

第2引数では、フォルダを選べる仕様です。オートローダーでは、指定のクラスがどのパスに存在しているかを探し出さなければなりません。ですが、様々な階層を調べるのはそれだけでも大きな手間になります。今回はオートローダーを使ったファイルの読み込み、現状Classesフォルダ以下に限定されているため、ポケモンであればPokemon、技であればMoveのように選んで読み込みができるようにしています。

※現仕様では上位階層のファイルも読み込めてしまいますが、今回はスルーします。もし参考にシステムへ組み込もうと考えている人はご注意ください。

 

ではsql_autoload_registerについて見てみましょう。

spl_autoload_register(function($class_name) use($folder){
    // クラス名からファイルを検索
    $path = __DIR__ . '/../Classes/'.$folder.$class_name.'.php';
    if(file_exists($path)){
        // 見つかった場合は読み込み実行
        require $path;
    }
});

 

第1引数にはコールバック関数が渡されます。今回は無名関数を引数に記述しています。

コールバック関数の引数にはクラス名が入ります。今回は$folderも使用したいので、useを使ってコールバック関数内で使えるように変数を渡しています。

あとは、パス作成して存在をチェック、もし見つかればrequireするといった単純な仕様になっています。

  

インスタンス化トレイトの修正

 それでは作成したオートローダーを使って、該当クラスのファイルを読み込んでいきましょう。まずは前回作成したインスタンス化トレイトの修正からです。

 

インスタンス化トレイト(/Traits/InstanceTrait.php
<?php
 
trait InstanceTrait
{
 
    /**
    * インスタンス化関数
    * @param string $class_name
    * @return object
    */
    protected function getInstance($class_name)
    {
        // 存在チェックをして読み込み
        if(class_exists($class_name)){
            return new $class_name();
        }
    }
 
    /**
    * ポケモンのインスタンス化関数
    * @param string $class_name
    * @return object
    */
    protected function getPokemonInstance($class_name)
    {
        // ポケモンフォルダを指定してオートローダーを実行
        $this->autoLoader($class_name, 'Pokemon');
        return $this->getInstance($class_name);
    }
 
    /**
    * 技のインスタンス化関数
    * @param string $class_name
    * @return object
    */
    protected function getMoveInstance($class_name)
    {
        // ポケモンフォルダを指定してオートローダーを実行
        $this->autoLoader($class_name, 'Move');
        return $this->getInstance($class_name);
    }
 
    /**
    * タイプのインスタンス化関数
    * @param string $class_name
    * @return object
    */
    protected function getTypeInstance($class_name)
    {
        // ポケモンフォルダを指定してオートローダーを実行
        $this->autoLoader($class_name, 'Type');
        return $this->getInstance($class_name);
    }
}

ポケモン用、技用、タイプ用の3つを追加しました。それぞれに用意したのは、array_mapのコールバック関数で使用している関係上、引数でフォルダを指定するとなれば少し複雑化してしまうため、今回は必要数用意するという方法を取りました。

 

それぞれ、呼び出されたタイプに合わせてオートローダーを実行してからインスタンスの取得をしています。 

これで、数多くのrequire_onceをせずに欲しいクラスのファイルだけを取得することが可能です。

 

ポケモンクラスの修正

 では、技やタイプを呼び出しているポケモン回りから修正を加えていきましょう。

 

ポケモンクラス(/Classes/Pokemon.php
<?php
require_once(__DIR__.'/../Traits/AutoLoaderTrait.php');
require_once(__DIR__.'/../Traits/ResponseTrait.php');
require_once(__DIR__.'/../Traits/InstanceTrait.php');
require_once(__DIR__.'/../Traits/Pokemon/SetTrait.php');
require_once(__DIR__.'/../Traits/Pokemon/GetTrait.php');
 
// ポケモン
abstract class Pokemon
{
    use AutoLoaderTrait;
    use ResponseTrait;
    use InstanceTrait;
    use SetTrait;
    use GetTrait;
 
--省略
 
    /**
    * 現在のレベルで覚えられる技があるか確認する処理
    *
    * @var integer
    */
    protected function checkMove()
    {
        // レベルアップして覚えられる技があれば習得する
        $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];
            // オートローダーを使った技クラスの読み込み
            $this->autoLoader($move_class, 'Move');
            // 覚えようとしている技(クラス)が存在かつ重複していないか
            if(class_exists($move_class) && !in_array($move_class, $this->move, true)){
                // 技クラスをセット
                $this->setMove($move_class);
                // インスタンス化
                $move = new $move_class();
                $this->setMessage($move->getName().'を覚えた!', 'success');
            }
        }
    }
 

 

 まずページの最初で、作成したオートローダーのトレイトを読み込みます。不要になった一括読み込み用のIncludeは削除しました。

次に、技の確認用メソッド(checkMove)です。今まではすべての技ファイルが既に読み込まれていましたが、今回は必要に応じて読み込めば良いので、class_existsの前に技指定でオートローダーを実行させました。

 

次に、タイプの読み込みもしなければならなのでGet関係のメソッドを見直しましょう。

 

Get格納トレイト(/Traits/Pokemon/GetTrait.php
/**
* 覚えている技の一覧を取得する
* @return array
*/
public function getMove()
{
    // array_mapで配列内の技クラスをインスタンス化
    return array_map([$this, 'getMoveInstance'], $this->move);
}
 
--省略
 
/**
* タイプの取得
*
* @param string|array|object $return
* @var void
*/
public function getTypes($return='object')
{
    /**
    * タイプ名の取得用関数
    * @param object
    * @var string
    */
    function getTypesName($obj){
        return $obj->getName();
    }
    // array_mapで配列内のタイプクラスをインスタンス化
    $types = array_map([$this, 'getTypeInstance'], $this->types);
    switch ($return) {
        case 'string':
        // array_mapでタイプ名の配列にしたものを、implodeで文字列に変換
        $types = implode(',', array_map('getTypesName', $types));
        break;
        case 'array':
        // array_mapでタイプ名の配列にして返却
        $types = array_map('getTypesName', $types);
        break;
    }
    return $types;
}

 

技の一覧取得用メソッド(getMove)と、タイプ取得用メソッドにオートロードを追加しました。これでrequire_once地獄から抜け出すことが出来ました。

※現状だと一部class_existsによるオートロードが働いています。こちらは別回で修正予定です。

 

 

まとめ

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

今回のPHPポケモンでは「オートローダーの実装」をご紹介しました。

0からの構築をすると、回を進めて行くごとに粗が目立ったり「こうしておけば良かった」というのがどんどん浮かんできます。本来の開発では設計書や仕様書を作り進めていくことをオススメしますが、学習目的であればプログラミングの理解を深めていくためのきっかけにもなります。

現在学習中の方は、ぜひ参考にしてくださいね。

 

注目の記事

PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化

  前回実装したオートローダーの使い方が盛大に間違っていたので、今回その間違いの説明をしながら、正しい実装方法をご紹介します。 申し訳ありません。(誠意)    オートロードについて(再)  必要なタイミングで必要なファイルをrequireまたはincludeするあれです。   前回spl_autoload_reg...

戦闘用アイテム編 プラスパワー PHPポケモン96
プログラミング
PHP,PHPポケモン,ポケモン
戦闘用アイテム編 プラスパワー PHPポケモン96

戦闘用アイテムとは バトル中に使用できるアイテムはいくつかありますが、その中でも「バトル専用」のアイテムがあります。それが戦闘用アイテムであり、主にドーピングと呼ばれるものです。 アイテムカテゴリとして、プレイヤー対象(スプレーなど)、敵ポケモン対象(ボール類)、味方対象(キズぐすり)の3つに...

PHPポケモン(α)攻略wiki「最初のポケモン」
雑記
PHPポケモン,wiki,ポケモン
PHPポケモン(α)攻略wiki「最初のポケモン」

リリースから一ヶ月、遂にPHPポケモン(α)の攻略Wiki(仮)が公開です!   というのは大嘘で、内部の大幅変更の関係上、今回はPHPポケモンをプレイするにあたってのオススメなどをまとめて見た次第です。 ちなみに、バトルシステム自体は本家に沿って作成しているので、種族値や技性能に精通している人はブラウザ...

PHPポケモン「バトルシステム実装編〜ランク補正〜」22
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム実装編〜ランク補正〜」22

ランク補正とは  ポケモンでは通常ステータスとは違い、バトル中にのみ変化するステータスが存在します。初代仕様であれば、「なきごえ」や「かたくなる」といった変化技により「こうげき」や「ぼうぎょ」の強化や弱体化をさせるものです。これはバトル中であれば引き継がれるものですが、交代やバトルが終了すればリ...

get_template_partで引数を渡す方法(WordPress5.5以降)
プログラミング
PHP,WordPress
get_template_partで引数を渡す方法(WordPress5.5以降)

WordPress5.5へのバージョンアップで、大きく機能が追加されました。中には変更に戸惑っている人もいるかも知れませんが、個人的にはエンジニアの要望を大きく取り入れて自由度がアップした印象があります。 今回はその中でも、多くの方が待ち望んでいた「get_template_part」の変更点についてご紹介します。 ge...

放物線アニメーション編 PHPポケモン 81
プログラミング
PHP,PHPポケモン,ポケモン
放物線アニメーション編 PHPポケモン 81

ボールアニメーション 前回までに作成した捕獲判定処理を使って、ボールのアニメーションを作成します。 捕獲演出は以下の通りです。  味方側から相手に向かってボールを投げる 相手ポケモンの前でボールを開く 捕獲判定で算出した揺れ回数分ボールを揺らす   捕まえた際は、ボールの揺れをストップ...

非公開ディレクトリ画像表示編 PHPポケモン 91
プログラミング
PHP,PHPポケモン,ポケモン
非公開ディレクトリ画像表示編 PHPポケモン 91

非公開ディレクトリの画像を表示する 今回は、β版に向けての取り組みの1つとして、表示させる画像のアクセス先を非公開ディレクトリに変更します。 現在は公開ディレクトリ(Public)内のAssetsフォルダ内に配置していますが、これをルート直下においているStorageに移動させるのが目的となります。   gifのbas...

千利休から学ぶビジネスモデルの作り方3ステップ!守破離とは
ビジネスモデル
千利休から学ぶビジネスモデルの作り方3ステップ!守破離とは

  千利休の利休道歌に以下のような記述があります。 規矩作法 守り尽くして破るとも離るるとても本を忘るな    これは武道や芸道など学びの基礎として考えられ、創造過程のベースとして用いられてきました。これはビジネスモデルを作り上げるという観点から見ても非常に重要かつ、失敗する多くの人が疎...

カテゴリ

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