超PHPerになろう

Enjoy PHP Programming

すごいPHPerになるためにいろいろやってた

すごいPHPer(ぺちぱー)になりたいと思っていろいろやってたんですが、ちょっと慌しいのが重なって報告わすれてました ヾ(〃><)ノ゙☆

PHP BLT #3でしゃべってきた

PHP BLT #2は参加できなかったけど、#3には参加してました ヾ(〃><)ノ゙

PhpStormはすごいんですけど、Emacsの実力もこんなもんじゃないんで、がんばっていきたい…!

インスパイヤされて掲示板を作りたくなってた

qiita.com

しばらく更新できてなかったけど、そろそろ再開できるかな…!

WEB+DB Press Vol. 92にHTTPの話を書いた

gihyo.jp

PHPからHTTPを叩く方法はいろいろあるんだけど、とりあへずguzzle/guzzle: Guzzle, an extensible PHP HTTP clientの6.xを使っとけばいいんじゃないの、みたいなことを書きました。

PHPカンファレンス北海道2016でComposerについてしゃべってきた

関係者から招待いただいたとかじゃなくて、インターネットで見掛けたのでCFPを送ったら通ってしまったので、喋らせていただいた次第です。

phpcon.sapporo-php.net

私は地元が北海道だったので、大学生じゃなくなってぷらぷらしてた時期にはRuby札幌とかPython札幌で活動してた頃もあるので、かなり懐かしい感じでしたね!

PHP BLT #4でしゃべってきた

この話に関してはQiitaあたりに、もうちょっと詳しく書きます!

適当なライブラリ

クラス名のエイリアスはるやつ

github.com

なんかファイルごとにuseとかするのめんどいじゃん? ってときに使へるやつですね。動作原理を解説してもいいんですけど、ずこーって感じがします。

クラスの擬似動的ロード/モンキーパッチをするやつ

二ヶ月くらゐ前に書いてGitHubに上げてた気がするんだけど、幻覚だったようだ… 動いてはあるので、近々ちょっと直して公開するかも。

この期間での知見

やりたいことなんでも手をひろげていった揚句にどれも完成度いまいち、みたいなのって割と最悪に近いので、ほどほどにがんばります ヾ(〃><)ノ゙

すごいPHPerになるためにオートローディングについて調べて記事書いた

Composerとかでインストールしたライブラリではなにげなく使ってる名前空間オートローディングについて詳しく書いてます。まあ、PHP: 名前空間 - Manualとか読めば書いてあるんですが、Composerとかオートローディングと組合せてきちんと説明してる記事はWebでもあんまりないと思ふので、会社での布教などにぜひご利用くださいヾ(〃><)ノ゙

gihyo.jp

PHP BLT #1で「たのしい独自フレームワーク」を発表しました

PHP BLT #1PHP界隈のTipsについて5分で話すLT大会です。

phpblt.connpass.com

コンセプトとしてはもっと気軽な内容を意図されてたはずなのですが、このスライドでは20分枠で話すような内容を説明不足に任せて駆け足でLTにした感じです!

www.slideshare.net

独自フレームワークの設計の具体的なところについては、このblogでもきちんと書いていきたいですね ヾ(〃><)ノ゙

User-Agent文字列を解釈するには [woothee/woothee]

User-Agent/UA文字列はブラウザなどのユーザーエージェントが自己申告する識別子のことです。この値は歴史的経緯から複雑怪奇で、付け焼刃の実装では正確な判定が困難です。

Project Wootheeプログラミング言語に依存しないUA文字列パーサーを開発するプロジェクトです。言語を横断してテストを共有して居り、同じバージョンを利用すれば、どの言語実装を利用しても同じ結果が得られることが保障されます。

公式サイト Woothee: User-Agent parser/classifier for multi languages by woothee
概要 Cross-language UserAgent classifier library, PHP implementation
パッケージ名 woothee/woothee - Packagist
作者 tagomoris (TAGOMORI "moris" Satoshi)
yuya-takeyama (Yuya Takeyama)
ライセンス Apache License, Version 2.0
バージョン v1.2.0 (2015-08-14)

インストール

Composerでインストール可能です。

composer.phar require woothee/woothee

UA文字列とは

以前、勉強会で発表するために作成したスライドを紹介します。

www.slideshare.net

ブラウザ業界は常に渾沌として居り、現在はMozilla Firefoxを除く多くのブラウザは「WebKitだ」と名乗ります^1

# Chrome 
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2560.0 Safari/537.36
# Mozilla Firefox
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:42.0) Gecko/20100101 Firefox/42.0
# Safari
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/601.2.7 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.7
# Microsoft Edge
Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586
# Opera(OPR)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 OPR/33.0.1990.58

これらの変化する情勢について自前で解釈するのは不毛なので、WootheeのようなUAパーサーを利用することは有効です。

UAを分岐する目的

とは言っても現在の多くのブラウザの挙動は標準化されて居り、サーバーサイドのレベルでブラウザの種類そのものを判定することが必要な処理は、ほとんどありません。

実用例を挙げるならば、次のような用途があります。

  • UAスマートフォンかどうかを判定し、モバイル向けサイトにリダイレクトする
  • セキュリティを目的に、著しく古いブラウザ(IE8以下など)での利用を抑制する
  • TwitterFacebookクローラーなどに、TwitterカードOGPを出力する
  • OSごとに異なるファイルをダウンロードさせる

それ以外の目的で不用意に判定を追加すると、将来登場する新しい環境で意図しない挙動をするおそれがあるので、本当に必要な処理かどうか検討してください。

また、GooglebotなどのUAに対して通常のブラウザと著しく異なるレスポンスを返した場合、検索結果に想定できない悪影響がある場合があります。単にGooglebotからのアクセスを拒否することは問題ありませんが、その場合はrobots.txtを利用することを推奨します。詳細はGooglebot - Search Console ヘルプを参照ください。

UAの取得方法

標準のPHPでは、以下のような方法でUser-Agent文字列を取得できます。

<?php
$UA = isset($_SERVER['HTTP_ USER_AGENT']) ? $_SERVER['HTTP_ USER_AGENT'] : '';

$woothee = new \Woothee\Classifier;
$result = $woothee->parse($UA);

ただし、Webフレームワークを利用する場合はテスタビリティを確保するため、フレームワーク推奨の方法で取得しましょう。

以下はLaravelのファサードを利用した記法です。

<?php
$UA = Request::server('HTTP_USER_AGENT');

$woothee = new \Woothee\Classifier;
$result = $woothee->parse($UA);

解析結果

本稿執筆時点でのWoothee 1.2.0では、以下のような出力が得られます。

<?php
$woothee = new \Woothee\Classifier;

# Twitterのクローラー
$woothee->parse("Twitterbot/1.0");
# => [
#     "name" => "twitter",
#     "category" => "crawler",
#     "os" => "UNKNOWN",
#     "version" => "UNKNOWN",
#     "vendor" => "UNKNOWN",
#     "os_version" => "UNKNOWN",
# ]

$woothee->parse("facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)");
# => [
#     "name" => "facebook",
#     "category" => "crawler",
#     "os" => "UNKNOWN",
#     "version" => "UNKNOWN",
#     "vendor" => "UNKNOWN",
#     "os_version" => "UNKNOWN",
# ]

$woothee->parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2560.0 Safari/537.36");
# => [
#     "name" => "Chrome",
#     "vendor" => "Google",
#     "version" => "48.0.2560.0",
#     "category" => "pc",
#     "os" => "Mac OSX",
#     "os_version" => "10.10.5",
# ]

$woothee->parse("Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586");
# => [
#     "name" => "Edge",
#     "vendor" => "Microsoft",
#     "version" => "13.10586",
#     "category" => "pc",
#     "os" => "Windows 10",
#     "os_version" => "NT 10.0",
# ]

$woothee->parse('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)');
# => [
#     "name" => "Internet Explorer",
#     "vendor" => "Microsoft",
#     "version" => "6.0",
#     "category" => "pc",
#     "os" => "Windows XP",
#     "os_version" => "NT 5.1",
# ]

$woothee->parse("Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)");
# => [
#     "name" => "Internet Explorer",
#     "vendor" => "Microsoft",
#     "version" => "8.0",
#     "category" => "pc",
#     "os" => "Windows UNKNOWN Ver",
#     "os_version" => "NT 5.2",
# ]

php.netのひみつ(1) 短縮URL

php.netPHPの公式サイトです。ダウンロードやリリースノートがあるのは当然なのですが、その中でもPHP: Documentationには技術文書が網羅されてます。

RubyPythonのドキュメントが各バージョンごとや英語とその他の言語(日本語を含む)の断片化が著しいのに対し、php.netはきちんと国際化されてます。

さて、あなたは関数/メソッドの仕様を知りたくなったとき、どうやってその文書まで辿りつくでしょうか。

例としてstrtotimeの日本語版記事のURLは http://php.net/manual/ja/function.strtotime.php です。こんな長いURLを打ち込むわけにもいかないのでGoogleなどの検索エンジンに頼るでしょうか。

それもひとつの選択肢ではありますが、ブラウザにphp.net/strtotimeと打ち込みます。

このようにphp.net/xxxxxのようなURLに対して、さまざまなショートカットが設定されてます。

ただし最近はDash for OS X - API Documentation Browser, Snippet Manager - Kapeliのようなドキュメントツールがあるので、そちらの話は後日また。

PHPとMIT Licenseについて

Webにはフリーソフトウェアとして公開された多くのPHPライブラリがあります。しかし、多くのスクリプトには「ライセンス」と呼ばれる利用条件が設定されて居り、利用者はこれを遵守する必要があります。

今回は多くのPHPライブラリのライセンスとして採用される MIT License について紹介します。

ライセンス名 The MIT License
SPDX Identifier MIT
分類 フリーソフトウェア / 寛容なライセンス
原文 MIT License - Choose a License
必須事項 ライセンスと著作権の表示
許可されること 商用利用、修正、配布、派生作品に別のライセンスを課す
禁止事項 作者に責任を求めること
同等のライセンス Expat License
BSD 2-Clause License

要点

MIT Licenseは「寛容なライセンス」であると呼ばれます。業務利用もしやすいライセンスで、利用者が遵守しなければならない条件も非常に少なく簡潔です。

  • ソースコードか添付文書に著作権表示とライセンスをぜったい記載してね (除去したらだめ)
  • このソフトを使って損害が生じても作者に責任はないからね (免責事項)
  • ↑ これを守ってくれる限り、無制限に使っても配ってもいいよ!

あなたが守らねばならないこと

改造して利用する場合

自由に改造して、再配布することができます。有料で販売したり、別の利用条件(ライセンス)を課しても問題ありません。

ただし、大前提となる著作権表示とライセンス文は必ず含まねばなりません

Composerで依存する場合

MIT Licenseが設定されたライブラリをComposerでrequireする場合、自作のソフトウェアの配布物の複製を含まず利用者に個別にダウンロードさせるため、特に何もすることはありません。READMEなどの文章に著作権表示や謝辞を記載する必要もありません。

業務で利用する場合

営利目的であっても問題なく業務利用できます。ただし、利用したPHPコードにバグがあり障害が発生したとしても、保障や損害賠償を要求することはできません。何か問題があれば自分で原因を調査して解決する覚悟を持って利用してください^1

サーバーで利用する場合

ソースコードを他者に配布せずサーバーでPHPを動作させて利用する場合、著作権表示やライセンス文を記載する必要はありません^2

JavaScriptを利用する場合

WebサービスでのJavaScriptソースコードを利用者にダウンロードさせるため、著作権表示を除去しない限りは何もせずに商用利用・再配布が可能です。

あなたがライブラリ作者の場合

  • あなたが作ったライブラリを利用したことが原因で問題が発生しても解決や賠償の義務はありません
  • サーバーに採用されたことを確実に知る手段はありません
  • 派生版を商用販売されたとき、確実に利益を受け取る手段はありません
    • 派生版のライセンスによっては改善をフィードバックできないことがあります
  • ビジネスのライバルに利用されることを阻止する方法はありません

ライセンス本文

非常に短いため、ライセンス全文を掲載します。

原文

Copyright (c) <year> <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

日本語訳

Open Source Group JapanによるMIT Licenseの日本語訳を紹介します。

Copyright (c) <year> <copyright holders>

以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル(以下「ソフトウェア」)の複製を取得するすべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブライセンス、および/または販売する権利、およびソフトウェアを提供する相手に同じことを許可する権利も無制限に含まれます。

上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に記載するものとします。

ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もなく提供されます。ここでいう保証とは、商品性、特定の目的への適合性、および権利非侵害についての保証も含みますが、それに限定されるものではありません。 作者または著作権者は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切の請求、損害、その他の義務について何らの責任も負わないものとします。

さまざまな環境で統一的にファイルを操作する [league/flysystem]

Flysystemは複数ファイルシステムを透過的に操作できるライブラリです。

ローカルのファイルシステム(UNIX系/Windows)はもとより、zip形式のファイル書庫やFTPWebDAVを経由したリモートディスク、Amazon S3DropBoxのようなクラウドサービスなど、さまざまです。

公式サイト Flysystem - Multiple Filesystems, One API
概要 Abstraction for local and remote filesystems
パッケージ名 league/flysystem
作者 The League of Extraordinary Packages
ライセンス MIT License
バージョン v1.0.15 (2015-09-30)

インストール

Composerでインストール可能です。

composer.phar require league/flysystem

また、READMEにはComposerに依存しないインストール方法についても言及があります。

API

どのようなファイルシステムに対しても、以下のようなメソッド呼び出しで利用することができます。

以下は基本的なメソッドを抜萃したもので、すべてのメソッドは公式ドキュメントのAPI - Flysystemを参照してください。

<?php

// ファイルの存在確認
$exists = $filesystem->has('path/to/file.txt');
// ファイルを読み込む
$contents = $filesystem->read('path/to/file.txt');
// ファイルを読み込むストリームを得る
$stream = $filesystem->readStream('something/is/here.ext');
// ファイルに書き込む
$filesystem->write('path/to/file.txt', 'contents');
// ファイルに追記する
$filesystem->put('path/to/file.txt', 'contents');
// ファイルを削除する
$filesystem->delete('path/to/file.txt');
// ファイルを読み込んで削除する
$contents = $filesystem->readAndDelete('path/to/file.txt');
// ファイルをリネーム(移動)する
$filesystem->rename('filename.txt', 'newname.txt');

重要なのはストリームのまま処理できることですかね。数十MB程度ならともかく、数GB以上の巨大なファイルを利用する場合にその全てをメモリに載せてファイルに書き込むのは明らかに非効率なので、stream_copy_to_stream($fs->readStream($f), fopen($target, 'w'));のようなイディオムで記述すれば効率よく処理できる、気がする。

Adapter

Flysytemは「Adapter」と呼ばれる機構で、さまざまなファイルシステム/プロトコルに対応します。

本稿執筆時点でドキュメントに記載のある対応ファイルシステムは以下の通りです。

Local
Azure
AWS S3 V2
AWS S3 V3
Copy.com
Dropbox
FTP
GridFS
Memory
Null / Test
Rackspace
ReplicateAdapter
SFTP
WebDAV
PHPCR
ZipArchive

なほ、Local/Null/FTP以外は別途インストールが必要になります。

Integrations

Flysystemと各フレームワークをつなぎこむためのインターフェイスも、それぞれ別ライブラリとして提供されてゐます。

たとへばGrahamCampbell/Laravel-Flysystemを利用すると、Laravelのファサードとして利用することができます。