【PHPデザインパターン】サンプルコードのクローン〜オートロードと名前空間の予備知識

# デザインパターンとは

>[ウィキペディア〜デザインパターン (ソフトウェア)](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))

過去のソフトウェア開発者が発見した設計ノウハウを、他の開発者が再利用できるようにまとめたものです。

成り立ちがフレームワークと似ていますね。

# 学ぶ理由

- 職場で使えそうだから
- トレンドに左右されないベースとなる知識を身につけたかったから
- ~~年末年始の連休が暇だったから!~~

これだけで十分です。

ネットで``「PHP　デザインパターン」``と検索すると、こちらの本にたどり着くかと思います。

- 秀和システム「PHPによるデザインパターン入門」

本当はこの本が欲しかったのですが、既に絶版になっていました・・・（しかも中古品でかなりの高値というレア本）

しかし、著者の一人である下岡秀幸さんが、その内容をネットで公開してくださっています！
さらに、GitHubのリポジトリにサンプルコードも公開されているという神対応です。

>[Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - 目次](http://d.hatena.ne.jp/shimooka/20141211/1418298136)

ブログを拝見してみると、説明もコードも理解しやすかったので、渡りに船と活用させていただくことにしました。
そして、せっかくなら内容を自分なりにまとめて記事にしてみようと思いました。

自分の備忘録として書いているため多少わかりにくい点もありますが、ご容赦くださいm(_ _)m
 
# My環境
- macOS mojave 10.14.1
- PHP 7.1.21
- Composer 1.6.5
- Apache 2.4.33

# サンプルコードをクローン

サンプルコードは手直しがされているため、ブログに掲載されているソースコードと若干異なります。

- ``Apache``を使用するため、``htdocs``へ移動します。

```
$ cd /usr/local/var/www/htdocs
```

- そこで対象のディレクトリをクローンします。

```
$ git clone git@github.com:shimooka/PhpDesignPattern.git
```

- ディレクトリ内に``composer.json``があるので、必要なファイル群を生成します。

```
$ composer install
```

# 予備知識
ファイル内で使用されている用語の理解がゆるふわだったので、再確認しました。

## オートロード
こちらが気になりました。　
`/vendor/autoload.php`が見当たらなかったので・・・

```php
require dirname(__DIR__) . '/vendor/autoload.php';
```

>[PHPのオートロード(autoload)](https://qiita.com/atwata/items/5ba72d3d881a81227c2a)
>[これで理解できるComposerを使ったオートロード](https://reffect.co.jp/php/composer-autoload)

まず、クローンした``PhpDesignPattern``は、デザインパターンの名前がつけられた23のディレクトリと、その他のファイルで構成されています。

そして、その他のファイルである``composer.json``に以下の記述があります。

```composer.json
{
    "autoload": {
        "psr-4": {
            "DoYouPhp\\PhpDesignPattern\\": "."
        }
    }
}
```

このような意味です。

- PSR-4というルールでオートロードを行う。
- 今いる場所``/usr/local/var/www/htdocs/PhpDesignPattern``を``DoYouPhp\PhpDesignPattern\``という名前空間で扱う。

現在、``composer.json``はクローンしたばかりで新規ファイルのような状態です。
この場合、``installコマンド``で必要なファイル群を生成することができます。

```sh
$ composer install
```

コマンド実行後に``vendor``ディレクトリが作成されます。
そして``require``を使用して``/vendor/autoload.php``が読み込まれるという流れです。

その他の用語の意味もメモしておきます。

### require
指定されたファイルを読み込み、評価する制御構造

### dirname
親ディレクトリのパスを返す関数

### \_\_DIR\_\_
そのファイルの存在するディレクトリを表す定数

## namespace

``namespace（名前空間）``とは、シンボル名（変数名、メソッド名、クラス名など）の衝突を避けるための仕組みです。

>[php.net〜名前空間の概要](http://php.net/manual/ja/language.namespaces.rationale.php)

>[【PHP超入門】名前空間（namespace・use）について](https://qiita.com/7968/items/1e5c61128fa495358c1f)

名前空間を分けておけば、同一ファイル内で同一シンボル名があったとしても、それぞれの名前空間内で呼び出して実行されるそうです。

``namespace``はファイルの一番初めに呼び出されます。

## use
最初、``namespace``との違いがよくわかりませんでした。

- 名前空間などの別名（エイリアス）をつける。
- クラスや変数などをインポートする。

今回は、ファイル内でクラスの継承やオブジェクトの生成を行なっています。
なので、後者の機能を使ってクラスをインポートする必要がありました。

>[php.net〜名前空間の使用法: エイリアス/インポート](http://php.net/manual/ja/language.namespaces.importing.php)
>[【PHP超入門】名前空間（namespace・use）について~use キーワードについて](https://qiita.com/7968/items/1e5c61128fa495358c1f#use-%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
>[クラスの名前空間とuse宣言](https://qiita.com/shosho/items/f51fcc5395a37aa65aa4)

## ファイル内で確認する

`PhpDesignPattern/TemplateMethod`ディレクトリ内で、実際に確認してみます。

### ディレクトリ構成

```sh
$ tree -L 2
.
├── AbstractClass
│   └── AbstractDisplay.php
├── ConcreteClass
│   ├── ListDisplay.php
│   └── TableDisplay.php
└── client.php
```

### 各ファイルの説明

#### client.php
- クライアント（呼び出し側）となるファイルです。
- 名前空間を指定しています。
- ``autoload.php``を読み込んでいます。
- この中で``ListDisplayクラス``と``TableDisplayクラス``のオブジェクトが生成され、メソッドが実行されます。そのため、``use``を使用してクラスのインポートが行われています。
- ``require``の前に``namespace``が使われている？（オートロードで名前空間を設定しているはずなのに、先に読み込んで良いのでしょうか？）
- ``namespace``の記述を削除しても動きます。

```client.php
namespace DoYouPhp\PhpDesignPattern\TemplateMethod;

require dirname(__DIR__) . '/vendor/autoload.php';

use DoYouPhp\PhpDesignPattern\TemplateMethod\ConcreteClass\ListDisplay;
use DoYouPhp\PhpDesignPattern\TemplateMethod\ConcreteClass\TableDisplay;
```

#### AbstractDisplay.php
- ``ListDisplayクラス``と``TableDisplayクラス``の親クラスです。
- クラスの継承などは行われていないので、名前空間のみ指定されています。

```AbstractDisplay.php
namespace DoYouPhp\PhpDesignPattern\TemplateMethod\AbstractClass;
```

#### ListDisplay.php
- ``AbstractDisplayクラス``の子クラスです。
- 名前空間が指定されています。
- 親クラスをインポートするため、``use``が使われています。

```ListDisplay.php
namespace DoYouPhp\PhpDesignPattern\TemplateMethod\ConcreteClass;

use DoYouPhp\PhpDesignPattern\TemplateMethod\AbstractClass\AbstractDisplay;
```

#### TableDisplay.php
- 同じく、``AbstractDisplayクラス``の子クラスです。
- 名前空間が指定されています。
- 親クラスをインポートするため、``use``が使われています。


```TableDisplay.php
namespace DoYouPhp\PhpDesignPattern\TemplateMethod\ConcreteClass;

use DoYouPhp\PhpDesignPattern\TemplateMethod\AbstractClass\AbstractDisplay;
```

かなり脱線しましたが、次からはデザインパターンを実際に使ってみます。