PHPのお勉強４


概念・言語仕様・補完的な実装（の続き）
================================

参考:

	PHP: 言語リファレンス - Manual
	http://goo.gl/TFWYSf
	メニューバーが見やすいリファレンスがあったのでメモ（5.4までと古いけど）
	http://i.cmaas.net/php/

## プロトコル/ラッパー

http://php.net/manual/ja/wrappers.php

> file:// — ローカルファイルシステムへのアクセス
http:// — HTTP(s) URL へのアクセス
ftp:// — FTP(s) URL へのアクセス
php:// — さまざまな入出力ストリームへのアクセス
zlib:// — 圧縮ストリーム
data:// — データ (RFC 2397)
glob:// — パターンにマッチするパス名の検索
phar:// — PHP アーカイブ
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — オーディオストリーム
expect:// — 対話的プロセスストリーム

・zlib://は曖昧さがあるから、compress.zlib://file.gzを使う
・data://はbase64とurlencodedとつかえるみたい
・glob://はDirectoryIteratorクラスでも使う。
　pearのfile_find使わなくてもいいのかな。
<?php
// ext/spl/examples/ ディレクトリのすべての *.php ファイルについて、
// そのファイル名とサイズを表示します

```test.php
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
    printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
```

・ssh2://でsshもできるのか。。
・rar://はつかうことなさそうだな。
・ogg://はajaxでストリーミング再生とかにつかえたりするのかな。
・expect://は標準出力へアクセスか。面白そうだけど使いどころあるのかな。たくさんコマンド打つときとか？

## ストリーム

うん、基礎から理解してない。
バケット(bucket)って何？パケットと違う？
brigadeってなに？ググっても出てこない。
音声通信とかストリーミングとかは理解しておいたら便利そうだけど、
PHPで実装してもいいものなのかな。できるのかな。

http://php.net/manual/ja/intro.stream.php

単に使い方としては下記のような概要。。
なのだけど、ストリーム関数の一覧をみると、stream_bucket_appendというのがあり、詳細がわからない。

> カスタムラッパーをstream_wrapper_register() を利用して PHP スクリプトの内部から、あるいはストリーム API を用いて、 直接拡張モジュールの内部から追加できます (ストリーム API については ストリームの作成 を参照ください)。 あらゆる種類のラッパーが PHP に追加できるので、 特にラッパーでできることの限界はありません。 現在登録されているラッパーの種類を知るには、 stream_get_wrappers() を使います。

http://ja.wikipedia.org/wiki/%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%83%90%E3%82%B1%E3%83%83%E3%83%88

> なお、バケット (bucket) とは、バケツのことであり、転送すべきネットワークトラフィックを集積する抽象化されたコンテナである（実装は例えばバッファやキュー）。

http://dancingmammoth.com/2009/08/29/php-stream-filters-unchunking-http-streams/

httpでUnchunkingしてるサンプルコードがあった。

http://php.net/manual/ja/stream.streamwrapper.example-1.php

グローバル変数の読み書きやPDOでのDB操作をストリームラッパーのクラスで実装した例がある。

## トレイト

http://php.net/manual/ja/language.types.resource.php

リソースは特別な変数であり、外部リソースへのリファレンスを保持している。 
データベースの持続的接続は（接続や切断が減るので）効率をあげることができる。

http://blog.tojiru.net/article/242054875.html

呼んでるとトレイトが便利なことが伝わってくる。使ってみようという気になりました。
この記事は2011年のものだが、現状で、トレイトはフレームワークでどのように実装されているのだろうか。
（fuelPHPのcoreとかパッケージに検索をかけてみると、Loggerの部分に2カ所、発見されただけだった。）

> 多重継承が解禁されたことにより、フレームワークの設計を根幹から変えてしまう可能性を秘めています。
> 予想) mixin再現ライブラリが必要なくなる
> 予想) 抽象クラスがオワコン化する？
> 予想) 無尽蔵にメソッドを増やせることを前提にした設計が可能に
> そのうち固まってくるだろうモノ
> traitを使ったデザインパターン定石
traitの命名規則どうするの
退避用の一時メソッドの命名規則どうするの(補足参照)
> 元の実装を呼び出したい場合、別名で退避させておく必要があります。その際、無意味にpublicメソッドが増えないよう、privateに差し替えておくとベターですかね。

```test.php
class ChildKlass {
  use SomeTrait {
    doSomething as private _SomeTrait_doSomething;
  }
 
  public function doSomething() {
    $this->_SomeTrait_doSomething();
  }
}
```

http://www.infiniteloop.co.jp/blog/2014/08/php54-traits/

・図もあるし、コード例があっていろんな使い道のイメージがわきやすかった。
・traitを利用するときに気をつけることは、実装クラス側で設定して欲しいプロパティは、 trait 側で宣言してしまうと実装クラス側で再宣言出来ないのでgetterメソッドや定数を用意。

> 3. どのようなケースで実装するか
> 3-a. デザインパターンの実装
> 3-b. interface の基本実装として実装
> 3-c. アクセサの実装
> ここでご紹介した以外にも、特定のDIコンテナ要素への getter メソッドや、SQLクエリ生成の補助、バリデーションなど、幅広い要素に trait が活用出来るでしょう。

http://blog.anatoo.jp/entry/20110707/1310045371

> traitは、クラスに適用できるメソッドとプロパティの集合である
traitの適用は、そのクラスの型に影響しない
クラスの継承とインターフェイスの実装だけでは困るケースが存在する
traitメソッドの衝突を解決するには、優先順位を設定する

## 依存性の注入(Dependency Injection)

http://ja.wikipedia.org/wiki/%E4%BE%9D%E5%AD%98%E6%80%A7%E3%81%AE%E6%B3%A8%E5%85%A5

依存性を疎にするために、あとから依存性を注入するデザインパターンということかな。

> プログラムに依存性を注入する方法としては、以下のような手法が存在する。
インタフェース注入 注入用のインタフェースを定義して注入を行う方法
setter 注入 setter メソッドを定義して注入を行う方法
コンストラクタ注入 コンストラクタを定義して注入を行う方法

## デザインパターン

http://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)

適切な場合分けでデザインパターンを頭に前提条件としていれておいて実装できればよりよいモノがつくれそうだ。

・設計の型紙のこと。
・なので、プログラムコードの記述のパターン化したものという意味のときもあるかと。
・主要なデザインパターンの一覧にいろんなパターンが列挙されている。
・デザインパターンの型紙に頼りすぎるのは誤りに繋がるということもあるみたい。

> 注意および批判[編集]
デザインパターンは、よく使われる設計を一般化された形でまとめたものに過ぎない。具体的な実装を提供するものではなく、あくまでもコンセプトとして参照されることが意図されている。サンプルコードは実装例に過ぎない。
デザインパターンはすべての状況における最善の設計では決してない。「Code Complete」は、デザインパターンを紹介している書籍の１つであるが、デザインパターンをむやみに適用するのは不適切であり、不適切な使用はコードの複雑さを無意味に高めてしまうと注意している。[1]
一部のデザインパターンは、プログラミング言語（例: Java, C++）の機能の欠損の印であると主張されることがある。計算機科学者のピーター・ノーヴィグは、GoFによるデザインパターン本の23パターンのうち16パターンは、言語によるサポートによって単純化または除去できることをLispやDylanを用いて実演した。[3]

## シングルトンパターン

生成に関するパターンの一種で、あるクラスについて、インスタンスが単一であることを保証する。
PHPではDB接続の効率化で使われることが多い。

## Observerパターン

振る舞いに関するパターンの一種で、インスタンスの変化を他のインスタンスから監視できるようにする。Listenerとも呼ばれる。

## 遅延静的束縛 (Late Static Bindings)

ルールが複雑で混乱しそうだからあまりつかわないのほうがいいのかなと思ってしまう。もやもやする。
仕組みとして多用したり依存するのは避けて、コメントを添えてピンポイントで使うとかはあるかもな。
まだあまり理解していないけど、リフレクションの概念には必要なのかな。

・遅延して呼び出したときにstatic::を解決する情報を保存する。
・静的束縛はstaticな呼び出しで利用するため。（そして、staticじゃなくても適用されるらしい。。）
・$this->を使っても遅延静的束縛は提供されない。
・インスタンスからメソッドを呼び出した場合は遅延静的束縛が適用される。
・静的コールで呼び出した場合には、コール元の情報が転送されないので遅延静的束縛は適用されない。
・（起点がインスタンスである）parent::やself::で呼び出した場合にはコール元の情報が転送されるので適用される。

http://php.net/manual/ja/language.oop5.late-static-bindings.php

> 遅延静的束縛は直近の "非転送コール" のクラス名を保存します。
静的メソッドの場合、これは明示的に指定されたクラス (通常は :: 演算子の左側に書かれたもの) となります。
静的メソッド以外の場合は、そのオブジェクトのクラスとなります。
"転送コール" とは、self:: や parent::、static:: による静的なコール、 あるいはクラス階層の中での forward_static_call() によるコールのことです。

http://blog.fagai.net/2014/02/17/php54_singleton_pattern/

シングルトンパターンの実装例があった。

> こんな感じです。traitと、Reflection、遅延静的束縛を必要とします。

```test.php
trait TraitSingleton
{
    /**
     * get instance.
     */
    public static function getInstance() {
        static $instance; // 静的なinstanceを保持するための変数
         
        // インスタンスが存在しない時だけインスタンスを作る
        if(! $instance)
        {
            // 遅延静的束縛
            $reflection = new ReflectionClass(get_called_class());
            $construct = $reflection->getConstructor();
            $construct->setAccessible(true);
             
            // インスタンスをコンストラクタ無しで作成
            $instance = $reflection->newInstanceWithoutConstructor();
             
            // コンストラクタを実行する
            $construct->invokeArgs($instance ,func_get_args());
        }
         
        return $instance;
    }
     
    /**
     * the instance clone is not allowd
     * @throws RuntimeException
     */
    public final function __clone()
    {
        throw new RuntimeException('Clone is not allowed against ' . get_called_class($this));
    }
}
```

http://blog.anatoo.jp/entry/20110707/1310045371

上記のものよりシンプルなつくりだがどっちがいいのだろう。
やってることは同じだが遅延静的束縛の実装の仕方に違いがある。
下でやってて不都合があれば上にすればいっかあ。。

```test.php
<?php

trait Singleton
{
    protected function __construct() { }
    static function getInstance()
    {
        static $obj = null;
        return $obj ?: $obj = new static;
    }

    function __clone()
    {
        throw new RuntimeException("You can't clone this instance.");
    }
}
```