プログラミング

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

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

 

前回実装したオートローダーの使い方が盛大に間違っていたので、今回その間違いの説明をしながら、正しい実装方法をご紹介します。

申し訳ありません。(誠意)

  

オートロードについて(再)

 必要なタイミングで必要なファイルをrequireまたはincludeするあれです。

 

前回spl_autoload_registerの関数を使用した簡易オートローダーを作成したのですが、呼び出していないのに必要なクラスを呼び出してインスタンス化されているという現象がタイプの取得部分で起こっていたため、再度公式(PHP.net)や他の紹介記事を参考にしたところ、この関数は一度登録すれば毎回呼び出す必要が無いということが発覚しました。

※よくみればregisterってなってますからね・・・

 

ということで、前回トレイトで作成したオートローダーはなかったことにしてしっかりと理解した上で作り込んでいきます。

 

オートローダーの作成

 1度実行すれば良いのであれば、トレイトである必要はありません。なのでクラスとして作成します。

 

オートローダー(/Classes/AutoLoader.php
<?php
 
class AutoLoader
{
 
    /**
    * 検索するクラスが格納されているフォルダ
    * @return void
    */
    private $folders = [
        'Move', 'Pokemon', 'Type',
    ];
 
    /**
    * オートローダー
    *
    * @return void
    */
    public function __construct()
    {
        spl_autoload_register([$this, 'autoLoader']);
    }
 
    /**
    * コールバック用メソッド
    *
    * @return void
    */
    private function autoLoader($class_name)
    {
        // クラス名からファイルを検索
        foreach($this->folders as $folder){
            $path = __DIR__ . '/../Classes/'.$folder.'/'.$class_name.'.php';
            if(file_exists($path)){
                // 見つかった場合は読み込み実行
                require $path;
            }
        }
    }
}

 

まず、プロパティに注目しましょう。

/**
* 検索するクラスが格納されているフォルダ
* @return void
*/
private $folders = [
    'Move', 'Pokemon', 'Type',
];

 

技(Move)、ポケモン(Pokemon)、タイプ(Type)のClassesに設置した3フォルダを指定しています。もしクラスが見つからなかった際は、ここから探してくれます。もしアイテムなどが増えた際は、ここに必要フォルダを増やしていきましょう。

 

次にコンストラクタを見てみましょう。

/**
* オートローダー
*
* @return void
*/
public function __construct()
{
    spl_autoload_register([$this, 'autoLoader']);
}

 

spl_autoload_registerは処理の前半に1度だけ呼び出しておけば良いので、オートローダーのクラスをインスタンス化した時点で動くようにしました。中にはメソッドを用意して、インスタンス化→メソッド実行という手順をとっているものもありましたが、今の所一括で出来たほうが良いだろうという判断なのでこの仕様にしています。

もし、セキュリティ面や挙動がおかしくなるなど問題が発生したら、適宜修正していきます。

 

コールバック関数は、前回のように無名関数にせず、可視性がよくなるためにもメソッドへ分けて作成しました。

/**
* コールバック用メソッド
*
* @return void
*/
private function autoLoader($class_name)
{
    // クラス名からファイルを検索
    foreach($this->folders as $folder){
        $path = __DIR__ . '/../Classes/'.$folder.'/'.$class_name.'.php';
        if(file_exists($path)){
            // 見つかった場合は読み込み実行
            require $path;
            break;
        }
    }
}

 

読み込まれていないクラスを呼び出そうとしたタイミングで、spl_autoload_registerは起動して、コールバック関数の第1引数に、そのクラス名が渡されます。以下の例を見てみましょう。 

  1. オートローダーをインスタンス化

    spl_autoload_registerが登録される

  2. ピカチュウのクラスを呼び出そうとする

    ピカチュウのクラスはincludeまたはrequireされていない

  3. spl_autoload_registerが動き、コールバック関数(autoLoader)の第1引数($class_name)にPikachu(ピカチュウのクラス名)が渡される

 

上記の流れになります。

そして、コールバック関数内ではforeachを使ってプロパティに設定したフォルダから順番にピカチュウのクラスを検索させています。

 

これだけです。一度登録していれば、見つからないクラスが呼び出された時点で勝手に探してくれるというのが、前回の説明で漏れていた(というより理解できていなかった)部分です。composerの素晴らしさがわかると同時に、頼り切りだと知らないことがいっぱいだということを改めて教えられました。

namespaceを使用していない関係上、一発で該当フォルダへたどり着くことができないため、無駄な動きは発生していますが、膨大な量ではないので今回は無視します。

 

class_existsの挙動について

次に、class_existsの関数について見ていきましょう。これが今回良くも悪くも気づきをくれました。 

 

第2引数でautoloadをデフォルトでコールするかしないかを指定できます。省略すればtrueになるのでコールしてくれます。

最初は関係ないと思ってスルーしていましたが、オートローダーを実装した途端これが大きな意味を成してきました。

 

技の習得や、進化をする際にclass_existsを何度か使用しています。これは、クラスが不正なものでは無いか(または名称間違いになっていないか)を判別するぐらいで使用していたのですが、オートローダーを導入した関係上、基本的にはクラスは存在しない(読み込まれていない状態)ものをチェックすることになります。その際に、それをオートロードを実行してからチェックするかどうかというのが、class_existsの第2引数の役割です。

通常のclass_existsを使う場合、第2引数にはfalseを指定することが多いです。その理由は、基本的にはクラスは読み込んでいることが前提だからです。しかし、今回のPHPポケモンの現段階で使用しているclass_existsは、基本的に読み込んでいないクラスを探してもらうため、第2引数は省略(true)のままで進めていきます。

 

では、実際に修正箇所を見ていきましょう。

 

コントローラー(/Classes/Controller.php
/**
* @return void
*/
public function __construct($post, $session)
{
    // オートローダーの起動
    new AutoLoader();

 

まず、コントローラーの最初にオートローダーをインスタンス化します。これで、spl_autoload_registerが登録されたことになります。

※AutoLoader.phpは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();
        }
    }
 
}

 

インスタンス化用のトレイトも、前回まではポケモンや技など種類分けをしていましたが、その必要が無くなったので簡潔なものに戻しています。

あとは、インスタンス化したい際に使用すれば、class_existsで勝手にクラスを探して読み込んでくれるという仕様です。

 

ポケモンデータの引き継ぎ

 これでタイプや技に関しては上手く行きましたが、ポケモンクラスで問題が発生しました。

今まではコントローラーで各ポケモンのクラスを読み込んでいたのですが、これをオートローダーに変更したところメソッド等が呼び出せなくなりました。原因を確認したところ、セッション内に以下のようなものが入力されていました。 

__PHP_Incomplete_Class Object

 

そもそも、インスタンスはセッションで渡すべきでは無いそうです。よくよく考えたら、セキュリティの関係からも当たり前と納得です。なので、こちらも修正します。

 

いままでは、ポケモンをインスタンス化する際に「捕まえた」「進化前」だけを判定していました。ですが、前画面から同じポケモンの引き継ぎという判定を追加しなければいけません。必要なデータだけを配列としてセッションに渡し、コントローラーの最初でその引き継ぎデータ(配列)を使って新しくポケモンをインスタンス化します。

 

ではまずポケモンクラスの修正版から見ていきましょう。

 

ポケモンクラス(/Classes/Pokemon.php
<?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 ResponseTrait;
    use InstanceTrait;
    use SetTrait;
    use GetTrait;
 
    /**
    * ニックネーム
    * @var string(min:1 max:5)
    */
    protected $nickname;
 
    /**
    * 現在のレベル
    * @var integer(min:2 max:100)
    */
    protected $level;
 
    /**
    * 覚えている技
    * @var array(min:1 max:4)
    */
    protected $move = [];
 
    /**
    * 経験値
    * @var integer
    */
    protected $exp;
 
    /**
    * 個体値
    * @var array(value min:0 max:31)
    */
    protected $iv = [
        'HP' => null,
        'Attack' => null,
        'Defense' => null,
        'SpAtk' => null,
        'SpDef' => null,
        'Speed' => null,
    ];
 
    /**
    * 努力値
    * @var array
    */
    protected $ev = [
        'HP' => 0,
        'Attack' => 0,
        'Defense' => 0,
        'SpAtk' => 0,
        'SpDef' => 0,
        'Speed' => 0,
    ];
 
    /**
    * インスタンス作成時に実行される処理
    *
    * @param object|array|null
    * @return void
    */
    public function __construct($before=null)
    {
        switch (gettype($before)) {
            /**
            * 捕まえた際の処理
            * @var null $before
            */
            case 'NULL':
            $this->setLevel();
            $this->setDefaultExp();
            $this->setDefaultMove();
            $this->setIv();
            $this->setMessage($this->name.'をゲットした', 'success');
            break;
            /**
            * 前の画面からの引き継ぎ
            * @var array $before
            */
            case 'array':
            $this->takeOverAbility($before);
            break;
            /**
            * 進化した際の処理
            * @var object $before
            */
            case 'object':
            // 進化前のポケモンと一致しているかチェック
            if(is_a($before, $this->before_class ?? null)){
                $this->takeOverAbility($before);
                // メッセージの引き継ぎ
                $this->setMessage($before->getMessages());
                $this->setMessage($this->name.'に進化した', 'success');
                $this->checkMove();
            }
            break;
        }
    }
 
    /**
    * レベルアップ処理
    *
    * @return void
    */
    protected function actionLevelUp()
    {
        // レベルアップ
        $this->level++;
        $this->setMessage($this->getNickName().'のレベルは'.$this->level.'になった!', 'success');
        // 現在のレベルで習得できる技があるか確認
        $this->checkMove();
    }
 
    /**
    * 進化
    *
    * @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');
        }
    }
 
    /**
    * 現在のレベルで覚えられる技があるか確認する処理
    *
    * @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];
            // 覚えようとしている技(クラス)が存在かつ重複していないか
            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');
            }
        }
    }
 
    /**
    * 現在インスタンスを出力
    *
    * @return array
    */
    public function export()
    {
        return [
            'class_name' => get_class($this),   # クラス名
            'nickname' => $this->nickname,    # ニックネーム
            'level' => $this->level,          # レベル
            'ev' => $this->ev,                # 努力値
            'iv' => $this->iv,                # 個体値
            'exp' => $this->exp,              # 経験値
            'move' => $this->move,            # 技
        ];
    }
 
    /**
    * 進化時の能力引き継ぎ処理
    *
    * @param object $before 進化前
    * @return void
    */
    protected function takeOverAbility($before)
    {
        if(is_object($before)){
            $this->nickname = $before->nickname;    # ニックネーム
            $this->level = $before->level;          # レベル
            $this->ev = $before->ev;                # 努力値
            $this->iv = $before->iv;                # 個体値
            $this->exp = $before->exp;              # 経験値
            $this->move = $before->move;            # 技
        }elseif(is_array($before)){
            $this->nickname = $before['nickname'];    # ニックネーム
            $this->level = $before['level'];          # レベル
            $this->ev = $before['ev'];                # 努力値
            $this->iv = $before['iv'];                # 個体値
            $this->exp = $before['exp'];              # 経験値
            $this->move = $before['move'];            # 技
        }
    }
}

 

コンストラクタ内でswitchを使い、引数で受け取ったbeforeの型をgettype関数を使ってチェックしています。 

 NULL → ゲット

array → 引き継ぎ

object → 進化

 

上記3つの判定になります。ただ、分岐が多くなりすぎるのも良くないので、そろそろメソッド分けする必要がありそうですが、一旦はこのまま押し通します。

 

次に新しく追加したexportというメソッドを見てみましょう。

/**
* 現在インスタンスを出力
*
* @return array
*/
public function export()
{
    return [
        'class_name' => get_class($this),   # クラス名
        'nickname' => $this->nickname,    # ニックネーム
        'level' => $this->level,          # レベル
        'ev' => $this->ev,                # 努力値
        'iv' => $this->iv,                # 個体値
        'exp' => $this->exp,              # 経験値
        'move' => $this->move,            # 技
    ];
}

 

これは、現在のポケモンの引き継ぎ用情報を出力するためのメソッドです。これを使い、セッションに必要なデータを渡します。引き継ぎ後はクラスを呼び出す必要があるため、クラス名をget_classで取得して配列に格納しています。

 

変更が加えられた、能力の引き継ぎメソッド(takeOverAbility)についても見てみましょう。

/**
* 進化時の能力引き継ぎ処理
*
* @param object $before 進化前
* @return void
*/
protected function takeOverAbility($before)
{
    if(is_object($before)){
        $this->nickname = $before->nickname;    # ニックネーム
        $this->level = $before->level;          # レベル
        $this->ev = $before->ev;                # 努力値
        $this->iv = $before->iv;                # 個体値
        $this->exp = $before->exp;              # 経験値
        $this->move = $before->move;            # 技
    }elseif(is_array($before)){
        $this->nickname = $before['nickname'];    # ニックネーム
        $this->level = $before['level'];          # レベル
        $this->ev = $before['ev'];                # 努力値
        $this->iv = $before['iv'];                # 個体値
        $this->exp = $before['exp'];              # 経験値
        $this->move = $before['move'];            # 技
    }
}

 

前回までは進化の際にしか能力値を引き継いでいませんでしたが、今回からは画面移管でも引き継ぐ必要があるので、配列で受け取った場合の処理を追加しました。これで、どちらのパターンでも同じメソッドを使った能力の引き継ぎが可能です。

 

それではコントローラーの修正箇所(コンストラクタ)を見ていきましょう。

 

コントローラー(/Classes/Controller.php
/**
* @return void
*/
public function __construct()
{
    $post = $_POST;
    $session = $_SESSION;
    // オートローダーの起動
    new AutoLoader();
    /**
    * 初期画面
    */
    if(empty($post)){
        $_POST = [];
        $_SESSION = [];
        return;
    }
    /**
    * ポケモンが選択された
    */
    if(isset($post['pokemon'])){
        $this->checkPokemon(htmlspecialchars($post['pokemon']));
        return;
    }
    /**
    * アクションが実行された
    */
    if(isset($post['action']) && class_exists($session['pokemon']['class_name'] ?? null)){
        // 引き継いだデータを引数にポケモンをインスタンス化
        $this->pokemon = new $session['pokemon']['class_name']($session['pokemon']);
        // アクションメソッドの実行
        $this->action(htmlspecialchars($post['action']), htmlspecialchars($post['param'] ?? null));
    }
}

 

前回までは引数でpostsessionを受け取っていましたが、正直グローバルでとっても問題なさそうなので変更しました。ただ、そのままは使用せずに一度変数に格納してから使っています。

 大きく変更されたのは、アクションが実行された際の処理です。今まではそのままpokemonのプロパティに渡していましたが、class_existsでチェックしてからインスタンス化するという手順を踏んでいます。

あと追加で、申し訳程度にhtmlspecialcharsを使ってサニタイズしています。

 

コントローラーの仕様に合わせて出力画面も修正します。

 

出力画面(/index.php
<?php
 
require_once(__DIR__.'/Classes/Controller.php');
require_once(__DIR__.'/Resources/Lang/Translation.php');
 
session_start();
 
$controller = new Controller();
$action_path = '/';
 
?>
<!DOCTYPE html>
<html lang="jp" dir="ltr">
<head>
    <meta charset="utf-8">
    <title>PHPポケモン</title>
    <meta name="robots" content="noindex, nofollow" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <link rel="stylesheet" href="Resources/Assets/css/style.css">
</head>
<body>
    <header>
        <div class="container">
            <section>
                <div class="row">
                    <div class="col-12">
                        <h1>PHPポケモン</h1>
                    </div>
                </div>
            </section>
        </div>
    </header>
    <main>
        <div class="container">
            <?php if(isset($controller->pokemon)): ?>
                <section>
                    <div class="row">
                        <div class="col-12 col-sm-6 col-md-4">
                            <?php # 詳細 ?>
                            <table class="table table-bordered table-hover">
                                <thead class="thead-light">
                                    <tr>
                                        <th scope="col" colspan="2">詳細</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php foreach($controller->pokemon->getDetails() as $key => $val): ?>
                                        <tr>
                                            <th scope="row" class="w-50"><?=transJp($key)?></th>
                                            <td><?=$val?></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                        <div class="col-12 col-sm-6 col-md-4">
                            <?php # ステータス ?>
                            <table class="table table-bordered table-hover">
                                <thead class="thead-light">
                                    <tr>
                                        <th scope="col" colspan="2">ステータス</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php foreach($controller->pokemon->getStats() as $key => $val): ?>
                                        <tr>
                                            <th scope="row" class="w-50"><?=transJp($key)?></th>
                                            <td><?=$val?></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                        <div class="col-12 col-sm-6 col-md-4">
                            <?php # 覚えている技 ?>
                            <table class="table table-bordered table-hover">
                                <thead class="thead-light">
                                    <tr>
                                        <th scope="col">覚えている技</th>
                                        <th scope="col">タイプ</th>
                                        <th scope="col">PP</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php foreach($controller->pokemon->getMove() as $move): ?>
                                        <tr>
                                            <th scope="row" class="w-50"><?=$move->getName()?></th>
                                            <td><?=$move->getType()->getName()?></td>
                                            <td><?=$move->getPp()?>/<?=$move->getPp()?></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </section>
            <?php endif; ?>
            <section>
                <div class="row">
                    <div class="col-12 col-sm-6 mb-5">
                        <h2 class="mb-3">メソッドの実行</h2>
                        <?php if(is_object($controller->pokemon ?? null)): ?>
                            <?php $_SESSION['pokemon'] = $controller->pokemon->export(); # ポケモンの情報をセッションに格納 ?>
                            <?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 include('Resources/Partials/Forms/select_pokemon.php'); ?>
                        <?php endif; ?>
                    </div>
                    <div class="col-12 col-sm-6 mb-5">
                        <h2 class="mb-3">実行結果</h2>
                        <div class="result-box border p-3 mb-3">
                            <?php foreach($controller->getMessages() as list($msg, $status)): ?>
                                <?php if($status == 'error') $class = 'text-danger'; ?>
                                <?php if($status == 'success') $class = 'text-success'; ?>
                                <p class="<?=$class ?? ''?>"><?=$msg?></p>
                            <?php endforeach; ?>
                            <?php if(!empty($controller->getResponses())): ?>
                                <pre><?php var_export($controller->getResponses()); ?></pre>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </main>
</body>
</html>

 

 

日本語化の実装(おまけ)

 先程のindex.phpにも記述していますが、一部分だけ日本語化を実装しました。とは言っても、英語をキーとした日本語を配列として用意し、それを関数で呼び出してチェックしているだけです。

 

翻訳ファイル(/Resources/Lang/Translation.php
<?php
 
function transJp($str)
{
    $array = [
        'attack' => 'こうげき',
        'defense' => 'ぼうぎょ',
        'spatk' => 'とくこう',
        'spdef' => 'とくぼう',
        'speed' => 'ぼうぎょ',
        'name' => '正式名称',
        'nickname' => 'ニックネーム',
        'type' => 'タイプ',
        'level' => 'レベル',
        'exp' => '経験値',
        'nextlevel' => '次のレベルまで',
        'physical' => '物理',
        'special' => '特殊',
        'status' => '変化',
    ];
    // 小文字変換して配列から取得、存在しなければそのまま返却
    return $array[mb_strtolower($str)] ?? $str;
}

 

今まで日本語キーだった部分を英語に置き換え、それに合わせてtransJpという関数を呼び出す仕様です。もし技やポケモンの名前も、わざわざインスタンス化してgetNameをするのが面倒であれば、同じように用意して関数で置き換えるという方法をとっても構いません。

  

まとめ

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

今回のPHPポケモンでは、前回実装したオートローダーの不備を修正し、正しい使い方をご紹介しました。

ぜひオートローダーを使う人は、しっかり公式マニュアルや書籍を読み込んでから実装するようにしておきましょう。

パーフェクトPHP パーフェクトPHP

ワイがPHPを勉強した一冊や! というより、書籍はこれしか読んでないで! ちなみに、最初からこれに挑むとほぼ100%挫折するので、ある程度PHPを理解してからの方がいいぞ   オブジェクト指向がよく分かってなくて、関数がなんとなく理解出来てたあたりで読み出して、理解を深めた一冊や。 古い本やけど、...

 

注目の記事

短期間でライティングスキルを高める虎の巻!7日間集中トレーニング法
ライティング
ブロガー,ブログ
短期間でライティングスキルを高める虎の巻!7日間集中トレーニング法

  毎日のんびり続けていると、気づけば結果につながっている   そんな幸せな理想を多くの人は抱いてしまいますが、そう甘いものではありません。ブログ収益化などコンテンツ配信業におけるライティングスキルを高めるためにも、夏合宿のような集中トレーニング法が存在し、一定期間で本格的な結果を求める...

PHPポケモン「タイプ実装編」15
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「タイプ実装編」15

ポケモンのタイプについて  2020年剣盾シリーズでのポケモンでは、全18タイプが実装されています。初代では15タイプ(あく、はがね、フェアリーを除く)からスタートして、たった3つのタイプしか増えていない、と感じる方もいるかも知れませんが、この追加に関してもバトルの歴史を大きく動かしてきたのです...

連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57
プログラミング
PHP,PHPポケモン,ポケモン
連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57

セッション経由でのオブジェクト引き継ぎ 技習得の処理が整ってきたので、ここで連続技習得・連続レベルアップ時にも問題なく動作するように作り込んでいきます。ですが、現状のモーダルをレスポンスやメッセージと同様に、そのまま引き継いだとしてもエラーが発生します。 その原因がセッション経由でのオブジェク...

PHPポケモン(α)攻略wiki「稼ぎ方特集」
雑記
PHP,PHPポケモン,ポケモン
PHPポケモン(α)攻略wiki「稼ぎ方特集」

前回に引き続き、連続wiki投稿でPHPポケモン溺愛ユーザーにとっては歓喜の2日間です。   という冗談も踏まえつつ、今回は「稼ぐ」ということについて真面目に考察してみたいと思います。もしリアル世界での「稼ぐ」を目的に来た人は、盛大にブラウザバックしてください。   PHPポケモンにおける「稼ぐ」...

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

  第13回のPHPポケモンは「UI編」ということで、CSSの大人気フレームワークBootstrapさんにお手伝いいただきます。 また、前回実装したレスポンス機能により進化のアクションに一部不具合が出ていたので、このあたりも合わせて修正をしながら進めていきましょう。   Bootstrapを導入するにあたり、今までin...

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

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

進化の石編(構成) PHPポケモン 102
プログラミング
PHP,PHPポケモン,ポケモン
進化の石編(構成) PHPポケモン 102

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

へんしん編 PHPポケモン 74
プログラミング
PHP,PHPポケモン,ポケモン
へんしん編 PHPポケモン 74

へんしんとは 今回はサムネイルに合わせて、特別技の1つ「へんしん」を実装します。  へんしん https://wiki.ポケモン.com/wiki/へんしん   へんしんを使うことで、相手ポケモンをコピーすることができますが、その全てをコピーするわけではありません。コピーできる項目とそうでない項目は以下の通りで...

カテゴリ

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