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


デザインパターンとは

ウィキペディア〜デザインパターン (ソフトウェア)

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

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

学ぶ理由

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

これだけで十分です。

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

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

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

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

Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - 目次

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

自分の備忘録として書いているため多少わかりにくい点もありますが、ご容赦ください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 [email protected]:shimooka/PhpDesignPattern.git
  • ディレクトリ内にcomposer.jsonがあるので、必要なファイル群を生成します。
$ composer install

予備知識

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

オートロード

こちらが気になりました。 
/vendor/autoload.phpが見当たらなかったので・・・

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

PHPのオートロード(autoload)
これで理解できるComposerを使ったオートロード

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

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

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

このような意味です。

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

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

$ composer install

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

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

require

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

dirname

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

__DIR__

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

namespace

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

php.net〜名前空間の概要

【PHP超入門】名前空間(namespace・use)について

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

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

use

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

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

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

php.net〜名前空間の使用法: エイリアス/インポート
【PHP超入門】名前空間(namespace・use)について~use キーワードについて
クラスの名前空間とuse宣言

ファイル内で確認する

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

ディレクトリ構成

$ 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;

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