PHPのお勉強３


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

参考:

	PHP: 言語リファレンス - Manual
	http://goo.gl/TFWYSf

## コンテキスト

用語としては抽象的で曖昧な模様。
文脈と解釈して時々にあわせて、それがどういう意味合いの文脈なのか判断する感じか。

（多分、ストリームについて理解をしないとここの理解も浅い理解になっていそうな気がする。ひとまずストリームについては後回し。）

http://www.sophia-it.com/content/%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88

プログラムの実行コンテキスト（プログラムの実行に必要な各種情報）という場合であったり、
コンテキストメニューやコンテキストスイッチなど、複合語として使用される場合。
（コンテキストメニューとは、操作の場面に応じてメニューを表示することである。また、コンテキストスイッチとは、CPUのレジスタの情報をコンテキストとして保持して、プログラムの実行に応じてコンテキストを切り替えることである。）
アクセスコンテキストとか、後述のストリームコンテキストとか。。

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

PHPではストリームコンテキストのことをコンテキストと呼ぶことがスタンダードっぽい。

## コンテキストオプションとパラメータ

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

・コンテキストでくくるのは何という概念だったり記法だったりするのか。基礎？

http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%A0_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)
http://www.lifeaether.com/overtaker/blog/wp-content/uploads/2008/10/stream.html

コンテキストってのはあくまで属する概念で、ストリーム (プログラミング)ってことかな？

http://otndnld.oracle.co.jp/document/products/wls/docs90/programming/context.html

コンテキストの伝播という概念もあるのね。
コンテキストを再利用するような場合には有効な記述法って事かしら。（ちゃんと読んでない。）

・全般的にコンテキスト関数をつかうほうが効率よく処理できるのかどうなのか。
・正規化されたりして視認性が高いコードになるのか。
・「ストリームコンテキスト php 視認性」でググってもわからず。

マニュアルに例文が載ってなかったりするのでググる。

> ソケットコンテキストオプション — ソケットコンテキストオプション一覧
HTTP コンテキストオプション — HTTP コンテキストオプションの一覧
FTP コンテキストオプション — FTP コンテキストオプションの一覧
SSL コンテキストオプション — SSL コンテキストオプションの一覧
CURL コンテキストオプション — CURL コンテキストオプションの一覧
Phar コンテキストオプション — Phar コンテキストオプション一覧
MongoDB context options — MongoDB context option listing
コンテキストパラメータ — コンテキストパラメータの一覧

#### HTTP コンテキストオプション

http://blog.mach3.jp/2010/12/21/use-curl-for-filegetcontents.html

2010年の記事ですが、file_get_contentsでHTTP コンテキストオプションを利用するメリットがあるか
と考えてみると簡単と言うことくらいですかね。現状を知りたければ自分でベンチマークした方がいいかも。
CURL コンテキストオプションを使うのと通常のcurlとの比較とか。

> モバイル回線のノートでYahoo!のトップページを取得してざっくり計測したところ、
file_get_contents : 4秒前後
cURL : 2秒前後

```test.php
function curl_get_contents( $url, $timeout = 60 ){
    $ch = curl_init();
    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_HEADER, false );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
    $result = curl_exec( $ch );
    curl_close( $ch );
    return $result;
}

// test
$result = curl_get_contents( "http://www.example.com", 120 );
```

#### FTP コンテキストオプション

レジュームやプロキシーを使える。
ftp,ftpsの基盤のプロトコルのであるtcp,sslのコンテキストオプションも使える

http://php.net/manual/ja/transports.inet.php

#### SSL コンテキストオプション

https://gist.github.com/padraic/8743811

```test.php
$context = stream_context_create(array(
    'ssl' => array(
        'ciphers' => $ciphers,
        'verify_peer' => true,
        'cafile' => '/etc/ssl/certs/ca-certificates.crt', // <-- EDIT FOR NON-DEBIAN/UBUNTU SYSTEMS
        'CN_match' => $domain,
        'verify_depth' => 3,
        'disable_compression' => true,
        'SNI_enabled' => true,
        'SNI_server_name' => $domain
    )
));
 
if (!$usecurl) {
    if ($reconfigure) {
        $html = file_get_contents($url, null, $context);
    } else {
        $html = file_get_contents($url); // This default will be BAD!
    }
} else {
    $ch = curl_init($url);
    if ($reconfigure) {
        curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $html = curl_exec($ch);
    curl_close($ch);
}
```

#### CURL コンテキストオプション

コンパイル時に --with-curlwrappers オプションを指定。

curl_verify_ssl_host,curl_verify_ssl_peerとかでgoogle検索してもほぼ情報が無い。
突き詰めれば便利でもないし初心者が使いやすくもないから誰も使ってないとか？
それともコンパイルオプションがネック？

http://sourceforge.jp/users/tutty/pf/php_tutty/scm/blobs/af10e698a24e0e624920ea4c4b72a2bc3c647cef/ext/curl/streams.c

```test.c
                 if (SUCCESS == php_stream_context_get_option(context, "http", "curl_verify_ssl_host", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 2);
                 } else {
                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
                 }
                 if (SUCCESS == php_stream_context_get_option(context, "http", "curl_verify_ssl_peer", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
                 } else {
                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
                 }
 ```

phpのソースからのフォークっぽいものをみるとcurl関数と同じようなことをしていそう。
内部的な処理はどうなのだろう。他手法と比較して効率はどうなのだろう。
処理パフォーマンスだけでの、検証と根拠なしの勝手な想像としては下記。

	curl関数 > curlコンテキスト > fsockopen > file_get_contents

ストリームコンテキストの書き方をすること自体はメリットがあるのかな。

#### Phar コンテキストオプション

Pharってなに？

http://php.net/manual/ja/phar.using.intro.php
http://php.net/manual/ja/phar.using.object.php

ssl証明書で検証したり、ファイル操作の関数などでPharの中身を扱える。
Pharクラスを使うともっと高度なことが出来るとのことなのでPharを書き込みで扱うならクラスつかったほうがよいとのこと。
でも読み込みを考えてもちょっと手の込んだことをする場合はクラスの方が便利なのかな。

> Phar クラスは Phar アーカイブの読み込みや操作をサポートしています。 また RecursiveDirectoryIterator クラスを継承しているため、順次処理も可能です。 ArrayAccess インターフェイスをサポートしているので、 Phar アーカイブ内のファイルに対して、 それがまるで連想配列であるかのようにアクセスすることができます。

> Phar::interceptFileFuncs() は、 fopen() や file_get_contents()、opendir() そしてすべての stat 系関数 (file_exists()、is_readable() など) のコールを Phar が横取りして、相対パスを phar アーカイブ内の適切な位置に変換するようにします。

> phar 拡張モジュールは、PHP アプリケーション全体をひとつの "phar" (PHP Archive) ファイルにまとめてしまい、配布やインストールを容易にするためのものです。

http://qiita.com/rana_kualu/items/d868604a1f54c2f93a7c

中間コード的な圧縮とかじゃないのか。。じゃあ、速度的にはどうなんだろう。

> ちなみにメモ帳に突っ込めばわかりますが基本的に単なるテキストなので、プログラムの隠蔽には使えません。

http://www.sharkpp.net/blog/2013/12/01/fuelphp-advent-calendar-2013-1st-day.html

なるほ、fuelPHPもpharにできるのか。

#### MongoDB context options

複数台のサーバー構成でのセッションなどで有用なMongoDBのコンテキストオプション

## モックとスタブ

自分でつくることがすくないのであまり理解が進んでない。
Pharのところでローダスタブという用語が出てきたので検索。

http://d.hatena.ne.jp/devbankh/201002

相互作用中心か状態中心か。

http://techtipshoge.blogspot.jp/2014/02/blog-post.html

> スタブとはテスト対象の間接入力をテストシナリオに合わせて都合よく書き換えるためのもの。モックとはテスト対象の間接出力が正しいことを確認するためのもの。

## チャンク通信

マニュアルにあった注意書きから検索してチャンク通信にたどり着く。

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

> 注意:
5.3.0 より前のバージョンの PHP では chunked transfer decoding を実装していません。 この値を 1.1 に設定するなら、 1.1 準拠にするのは自分の責任となります。

Content-Length ヘッダは出力されないのだそう。perlのサンプルコードがチャンクについてわかりやすい。

http://d.hatena.ne.jp/kiririmode/20100606/p1

> Chunked は HTTP/1.1 で定義されている方式です。RFC 2068 には以下のような記述があり、Chunked と Content-Length を共存させてはいけない (MUST NOT) ことが分かります。)
> ...
> RFC では、HTTP の特徴として「メッセージボディのサイズを決定することが難しいこと」があり、メッセージボディをチャンク(Chunk) に分け、チャンク毎のサイズとともに送信することで、受信側でそのサイズを確認できるというようなことが書かれています。

```test.pl
#!/usr/bin/perl
print <<EOF;
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked

6
hello 
5
world
0

EOF
```