プログラミング

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ポケモン 102
プログラミング
PHP,PHPポケモン,ポケモン
進化の石編(構成) PHPポケモン 102

進化の石 ピカチュウさんもそろそろ進化したがっているので、β版の公開に向けて進化の石を実装していきます。しかし、イーブイなど特別な進化先や条件を持ったポケモンを考慮すると、少し実装が手間取りそうだったので、今回は構成部分のみのまとめとなっておりますので、ご了承ください。   アイテムクラスの作...

構成見直し編(クラス名) PHPポケモン49
プログラミング
PHP,PHPポケモン,ポケモン
構成見直し編(クラス名) PHPポケモン49

構成の見直し 今回は全体構成の見直しをします。ディレクトリについては変更ありませんが、ファイル名とクラス名について大幅な修正をかけていきます。   クラス名の重複回避 まず、クラス名の重複についてです。状態異常・状態変化の子クラスでは重複回避のために接頭語を着けて管理していましたが、他にも重複...

トレーナー戦編 バトルシステムへの追加 PHPポケモン 98
プログラミング
PHP,PHPポケモン,ポケモン
トレーナー戦編 バトルシステムへの追加 PHPポケモン 98

トレーナー戦闘の追加 前回トレーナー情報を作成したので、今回はその情報をバトルシステムへ組み込んでいきます。 現在、野生ポケモンとの戦闘では「battle」という値actionの値で受け取っています。同じサービス内で分岐を作ると複雑になってしまうので、battle_trainerという新しい分岐を使ってサービス分けをし...

【脱初心者向けプログラミング学習】処理を追え!「今、変数には何が入ってる?」
プログラミング
HTML,PHP,プログラミング学習
【脱初心者向けプログラミング学習】処理を追え!「今、変数には何が入ってる?」

  初心者から中々抜け出せない 1から処理をかけない   そんな悩みを抱えたプログラミング学習者に向けて、「脱初心者のためのプログラミング学習」についてPHPを例にまとめました。 やり方自体は同じですので、他の言語をメインとしている人は自分の環境に置き換えながら学習して、初心者から抜け出しましょ...

PHPポケモン「レスポンス機能編」メッセージの返却 12
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「レスポンス機能編」メッセージの返却 12

  第12回PHPポケモンは「レスポンス機能編」です。 メッセージやデータのやり取り部分を、よりシステム風に作成していきます。   第1回はコチラ   レスポンス(Response)の実装  今までは結果(メッセージ等)はechoを使って出力していましたが処理が行われたタイミングで出力されてしまうため...

たった2日で200万円!フリーランスが簡単に仕事を受注できる方法とは
マーケティング
コロナ,フリーランス,ホームページ制作,助成金
たった2日で200万円!フリーランスが簡単に仕事を受注できる方法とは

  仕事の依頼が全然来ない・・・ 営業しても話を聞いてくれない・・・   その多くが営業力以上に、営業をすべきタイミングがわかっていない人がほとんどです。 実は助成金等を活用することで、行政書士などの職業以外でも仕事を受注することは可能になります。   今回は筆者が、たった2日で200万...

進化アニメーション 後編 PHPポケモン 60
プログラミング
PHP,PHPポケモン,ポケモン
進化アニメーション 後編 PHPポケモン 60

ポケモンの進化演出 前回に続いて、ポケモンの進化演出を実装していきます。バックエンドの処理はざっと説明をしたので、今回はフロントエンド(JavaScript)側の処理を作成していきましょう。   進化画面は新しく設けたので、こちらにもバトル画面で使っているメッセージ用JSを作成していきます。処理自体はほとん...

PHPポケモン「バトルシステム編〜努力値の獲得〜」33
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜努力値の獲得〜」33

努力値の実装 今回はポケモンのやりこみ要素の一つ、努力値システムを導入します。既に努力値の項目は「ピカチュウで学ぶオブジェクト指向」の段階で実装し、ステータス計算にも判定済みですが、肝心な「努力値を獲得する仕組み」自体は出来ていませんでした。なので、バトルシステムも終盤となったこのタイミングで...

カテゴリ

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