PHP 初めてプログラミングを勉強するならCLIアプリ！

# はじめに
初めてプログラミングを勉強するってときに、環境構築は心折れるポイントだと思う。
PHPを選択した場合、WEBアプリ開発が主な用途なので、XAMPPやらVagrantやらでウェブサーバーを立てなきゃってイメージが挫折ポイントかな。サーバーとか「HTTP」の知識も必要になってくる。
ウェブアプリを作るには避けて通れないけど、まずはプログラミングの面白さを体験したいならウェブサーバーはいらないよって話。

#環境
PHP 7.1.14
OSはMac想定。PHPが標準で入ってる。
Windowsの人は上手く読み替えて。あとPHPのインストールが必要だと思う。

# CLI（Command Line Interface）アプリとは？
コマンドラインから実行するアプリケーション。
PHPだけど、ブラウザは使わない。コマンドラインで入出力。
MacならPHPは最初から入っているのですぐ実行できる。

実際、仕事でもよく作られます。ウェブアプリの裏方で働くアプリです。
定期的にデータベースをクリーニングしたり、データ解析したり、開発用便利ツールなどなど。
ちなみに私はウェブアプリよりCLIアプリの方が作ってて楽しいです。

# まずは動かしてみよう

やっぱり動かすとこまで行かないとモチベーションも上がらないよね！
ということでサンプルを作ったので動かしてみよう。

## 動かし方

1. 下のサンプルプログラムをコピーして保存。<br>ここでは /User/path/cli.phpで保存したものとする。
2. Macのターミナルを起動（黒い画面）
3. ターミナルに「php」と入力し、スペースを押す。
4. そのまま保存したファイルをターミナルにドラッグ
5. Enterを押して実行

```
# こんな感じになればok
php /User/path/cli.php
年齢を入力してください：20
あなたは大人です。
```

## サンプルプログラム
年齢を聞いて、二十歳以上か判断するだけのアプリです。

```cli.php
<?php

/*
|--------------------------------------------------------------------------
| サンプルプログラム
|--------------------------------------------------------------------------
|
| 勉強用のCLI（Command Line Interface）アプリのサンプル
| 年齢を入力させて、20歳以上かを判定するだけのものです。
|
*/

// アプリケーション本体の「インスタンス」を生成
$app = new SampleApp();

// アプリケーション実行
$app->execute();


/*
|--------------------------------------------------------------------------
| 以下、クラス定義
|--------------------------------------------------------------------------
|
*/

/**
 * アプリケーションのベースとなる「抽象クラス」
 * メッセージ表示・入力受付などの基本的なメソッドが用意されています。
 */
abstract class App
{

    /**
     * アプリケーション実行メソッド
     * 「抽象メソッド」です。「継承」したクラスで、このメソッドを定義しないとエラーになります。
     *
     * @return void
     */
    abstract public function execute();


    /*
    |--------------------------------------------------------------------------
    | 以下、汎用的な「メソッド」を定義
    |--------------------------------------------------------------------------
    |
    */

    /**
     * 画面に文字を表示：末尾に改行なし
     *
     * @param string $message
     */
    protected function message(string $message)
    {
        // 危険な文字はエスケープする（HTMLエスケープのシェル版みたいなもの）
        echo escapeshellcmd($message);
    }

    /**
     * 画面に文字を表示：末尾に改行あり
     *
     * @param string $message
     */
    protected function line(string $message)
    {
        echo escapeshellcmd($message) . "\n";
    }

    /**
     * 画面に文字を表示して、入力を受け付ける
     *
     * @param string $message
     * @return string
     */
    protected function ask(string $message)
    {
        // メッセージを表示し、「標準入力」の受け付け待ち。
        // 前後のスペースなど、入力ミスと思われるものを除外（trim）してあげるのは優しさ。
        $this->message($message);
        return trim(fgets(STDIN));
    }

}

/**
 * アプリケーション本体
 *
 * Appクラスを「継承」して、アプリケーションに必要なロジックをここに記述します。
 */
class SampleApp extends App
{
    /**
     * アプリケーション実行メソッド
     * アプリケーション独自の処理を記述する
     *
     * @return void
     */
    public function execute()
    {
        // 年齢を聞く
        $age = $this->listen();
        // 年齢として正しくない値が返ってきたら、メッセージを出力して終了する。
        if (false === $age) {
            $this->line('年齢を入力して！！');
            return;
        }
        // 大人かどうかで処理わけ
        if ($this->isAdult($age)) {
            $this->line('あなたは大人です。');
        } else {
            $this->line('お子ちゃまですね。');
            $this->line('早く寝なさい！！');
        }
    }

    /**
     * 年齢を聞きます
     * 年齢としておかしい値の場合はfalseを返します。
     *
     * @return false|int
     */
    protected function listen()
    {
        $input = $this->ask('年齢を入力してください：');

        // 優しさ。もし全角数値が入力されたら、半角数値に変換してあげる。
        $value = mb_convert_kana($input, 'n');

        // 年齢として扱えない：数値として扱えない文字列
        if (!is_numeric($value)) {
            return false;
        }
        // is_numeric()は、小数とかも許容してしまう。「キャスト」して無理やり整数にする。
        // 正確にやるなら、「正規表現」を使いますが、理解が難しいと思うのでここでは手抜き。
        $age = (int)$value;
        if (200 < $age) {
            // 200歳より大きかったら人間じゃないよね・・ということでfalseを返す
            return false;
        }
        // 入力された年齢を返す。
        return $age;
    }

    /**
     * 大人（20歳以上）ならtrueを返す。
     *
     * @param int $age
     * @return bool
     */
    protected function isAdult(int $age)
    {
        return (20 <= $age);
    }

}
```

# 解説

とりあえず、ちょこちょこっと自分で何か書いてみたいなら、SampleAppクラスの中身を書き換えてください。
「継承」元のAppクラスに表示や入力受付の「メソッド」を用意してあるので、上手く使ってexecuteメソッドを実装すれ良いです。

コメントは多めに書いてあるし、わからない時にググるべしキーワードは「」で囲ったやつなので、頑張って勉強してください！
（眠くなってきたので雑になってきた！！）

## 補足１
わかってると思うけど、実業務では使わないでくださいね。（テキトーに作ったやつなんで）
「フレームワーク」の機能を使うなり、ライブラリ使うなり、安心できるメジャーな方法を選択してください。

## 補足2
サンプルでは一つのファイルにまとめて書いてますが、実際に業務で作るときは、たくさんのファイルに分割されることになります。「名前空間」だとか「オートロード」だとか色々勉強すべきことはいっぱいです！

## 補足３
プログラマの重要スキルの一つは検索スキルだと思う。
検索（勉強）するためのキーワードは覚えていこう。

## 補足４
とりあえず作ってみたら？？な課題例。

- [fizzbuzz](https://ja.wikipedia.org/wiki/Fizz_Buzz)
- [アナグラム](https://www.softantenna.com/wp/software/fizzbuzz-alternatives/#3)
- トランプゲームのハイ＆ロー
- トランプゲームのブラックジャックとか

ブラックジャックはいい課題だと私も思う。
[プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし](https://qiita.com/hirossyi73/items/cf8648c31898216312e5)