プログラミング

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を理解してからの方がいいぞ   オブジェクト指向がよく分かってなくて、関数がなんとなく理解出来てたあたりで読み出して、理解を深めた一冊や。 古い本やけど、...

 

注目の記事

あばれる編(あばれる・はなびらのまい)PHPポケモン52
プログラミング
PHP,PHPポケモン,ポケモン
あばれる編(あばれる・はなびらのまい)PHPポケモン52

あばれる状態とは 技を使うと、しばらくの間その技のみしか使用できなくなる技があります。その状態を「あばれる状態」と言います。 あばれる状態(ポケモンwiki) https://wiki.ポケモン.com/wiki/あばれる_(状態変化) あばれるの効果 2~3ターンの間攻撃し続け、交換したり、他の指示を出すことが出...

PHPポケモン「オートローダー編」16
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「オートローダー編」16

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

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

  ※前回(第6回)で意味不明な場所に空変数が入っており、ステータスが一部しか出力できないという問題がありました。修正しています。犯人は「$stats = [];」です。(GetTrait.php)   今回はポケモンのゲームでは欠かせない、楽しみの一つとなる「進化システム」を導入していきます。これからPHPポ...

TwitterでYouTubeのリンク付きサムネイルを表示させる方法【超実践的Webプログラミング活用法】
プログラミング
HTML,JavaScript,PHP,Twitter,YouTube
TwitterでYouTubeのリンク付きサムネイルを表示させる方法【超実践的Webプログラミング活用法】

  Twitter(ツイッター)をブログや商品、イベントの宣伝目的で使用している人は多いです。そして、そのためのマーケティング方法や戦略は数多く練られています。 今回は、その中でもYouTubeの告知をするために特化させた内容をまとめました。   一般的な方法と、プログラミングの知識(HTMLやJavascript等)があ...

フレンドリィショップ編 開店準備 PHPポケモン 75
プログラミング
PHP,PHPポケモン,ポケモン
フレンドリィショップ編 開店準備 PHPポケモン 75

アイテム(どうぐ) PHPポケモンもバトル機能が一通り揃ってきたので、新機能として「アイテム」の実装に取り掛かります。 アイテムにも色々ありますが、技やポケモンのクラス同様に、初代で登場したアイテムから順番に取り揃えていきましょう。   キズぐすりの実装 ポケモンのどうぐ、一番手は「キズぐすり」...

PHPポケモン「わざ編〜チャージ技の実装〜」34
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「わざ編〜チャージ技の実装〜」34

チャージ技とは ポケモンの技は数多く存在していて、その中でも特別な処理が必要なものがいくつかあります。その1つが「チャージ技」です。 ※チャージ技とはポケモン上で用いられている用語ではありません   現在実装している初代御三家+ピカチュウの初代レベルアップ技の中では以下の2つがあります。 ロ...

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

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

PHPポケモン「わざ編〜わるあがき〜」35
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「わざ編〜わるあがき〜」35

わるあがき そろそろ技のPPを実装段階にきたので、その前に「わるあがき」という技を作成しましょう。「わるあがきって何?」という人のために、どういった技なのか簡単に説明します。 全ポケモン使用可能。ただし、レベルアップなどで普通のわざとして覚えることはできず、自分の技がすべて選択不能になった場合...

カテゴリ

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

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach fortify function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jetstream 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力