読者です 読者をやめる 読者になる 読者になる

Yii Framework 2.0 リリース記念勉強会 資料

第19回関西PHP勉強会 Yii Framework 2.0 リリース記念勉強会 の資料はこちらです。

だいぶあおり気味なのは、一般公開を意識せずに書いているためです。その場にいる人向けに、今日はこういう勉強会なので空気読んでね、というのが入っているのをご了承ください。

Yii 2.0 とは

ベータリリース記念 第一回勉強会の資料

https://gist.github.com/tanakahisateru/cf8ef578d7ea24ea429a ※ イベントまわりでちょっとオススメじゃない書き方があります

過去の発表やブログなど

http://www.slideshare.net/tanakahisateru/phpcon-2014yii

http://image.slidesharecdn.com/yii-121012040114-phpapp01/95/yii-31-728.jpg?cb=1350032550

http://tanakahisateru.hatenablog.jp/entry/2014/06/16/040047

http://tanakahisateru.hatenablog.jp/entry/2013/12/22/030817

ユーザーガイド

http://www.yiiframework.com/doc-2.0/guide-README.html

Yii の立ち位置

開発規模の想定

開発に必要な前提知識

Symfony との類似点

  • 適切なオブジェクト指向を前提にしていてIDEフレンドリー
  • 設定の項目がオブジェクトのプロパティと完全に対応する
  • デバッグツールを標準装備
  • アセットをPHPライブラリのパッケージ内で管理、Webにパブリッシュして使う (Assetic, Laravelのpublishも似てる)
  • POSTをフォーム オブジェクト で受け取りバリデーションする設計 (Laravelは5で入るあれ)

Symfony に対する大きな違い

  • SymfonyのようなフルDI設計を指向せず、グローバルに参照できるサービスロケーターを良しとする
  • Requestが独立したインスタンスではなくアプリケーションインスタンスと1:1になっていて、リクエストごとにメモリが全破棄される挙動に最適化されている
  • アノテーション等の高度な記述をさらに高度な高速化技法で上塗りするのではなく、遅くなるならメカニズムを捨て、あくまで「ありのままで速い」ことを指向
  • クラスがPOJO(?フレームワークの知識と独立したドメインモデル)であることにこだわらない
  • ORMのインスタンスがフォームを兼任できる (Struts型なのがRails風になる) = ActiveRecord
  • DIされないと作れない制約感 (エンタープライズでは下請けが下手しないための安全策として有効) がない
  • ちょっとしたカスタマイズならクロージャでさっと済ませられる

かつてSymfonyをやめてYii2-alphaを採用した理由

Symfonyでだいぶ作っていたものを、残り2ヶ月でYii2(当時alpha)に変更してイチから作りなおしたことがありました。

  • Doctrineはパッシブレコード、ただの入れ物で小さなロジックを持てるArray。そこからはSQLを実行できる層が見えない。モデルの設計が別途必要だった。
  • 自力で 自由に 設計する必要があるということは、引き継いだ人のOO設計力を問われる。真似する雛形がフレームワークから与えられない
  • Twigで再利用可能な部品を書くのが大変すぎる
  • サードパーティー製ライブラリがないと変わったことが何もできない。その選定の負担が大きい

要するにちゃんとしようとした場合の開発コストです。

他と異なる特徴

基本

  • すべてのコンポーネントが一貫して、getter/setterやビヘイビアをサポートする基底クラスを継承している
    • 名前によるプロパティ参照を活かして、実装がpublicフィールドなのかgetterなのかDBのカラムなのかを区別しない
    • どこにでもイベントとビヘイビアが差し込める
    • イベントフックを利用していろんなものができている
  • すべてのコードがPHPの文法、Yiiの基底クラスのルールを知ればいいだけ => 学習コストの低さ
  • ブラウザから使えるコード生成ツールが便利 = Gii

ビュー

  • ビューがPHPスクリプトである積極的な理由 = ウィジェット
  • フレームワークのサポート範囲にJavaScriptを含む (jQuery等フロント側で必要なライブラリを初期インストール/パッケージバージョン管理下に)
  • 削除の確認などで積極的にJavaScriptのconfirm()を使うなど
  • アセットバンドルによるCSS/JSの依存順序解決
  • わざわざ artisan xyz:publish しなくても自動パブリッシュ

ページャーフレームワーク

  • DataProvider (未評価のQueryのインスタンスにorderとlimitをかけて範囲内のデータを得るオブジェクト)
  • ListView (DataProviderをビューでイテレーションするウィジェット)
  • 任意のSearchForm (フィルタ条件を預かりDataProviderを生成)

Laravelとの類似点 (yii2)

  • ActiveRecordはEloquentとかなり似ている。クエリのしかた、リレーションのやりかた。後発なのでよりちゃんとした設計になってる。
  • 世界的な人気は同クラス (どっちが強いかというよりは、今のPHPにどういうニーズが高いか)

Laravelとの相違点

まずはこれ

f:id:tanakahisateru:20141119203616p:plain

※ LaravelのEloquentはコンクリートなModelとBuilderの2つでできていて、生SQL用のBuilderはメソッド体系が似た別の実装になっています。つまりこの図に対応させると関係線のないクラスが3つ登場するだけ。

で、結果

$firstAdminId = (new Query())->from('user')
    ->where(['admin' => true])->orderBy('create_time')
    ->select('id')->scalar();

というコードとほとんどの内部フローを共有してこれ

$firstAdmin = User::find()->where(['admin' => true])->orderBy('create_time')->one();

が動く。ActiveRecordでのイベント/ビヘイビアとバリデーションは、ComponentとModel(フォーム)から継承している。

で、MongoDBのActiveRecordもまったく同じ継承構造。なのでこのぐらいのクエリならほぼ名前空間を変えるだけで MongoDB に切り替えられる。それでも 〜Trait とModel継承の部分は実装を共有できてて半分ぐらいは完全に同じ動きをする。

  • というように、全体的に一貫したオブジェクト指向設計がある。
  • 内部設計の追跡しやすさ、カスタマイズしやすさは段違い。
  • ライフサイクルイベントのあるヘビーウェイトなMVC構造に見えて、実はLaravelよりも速く、キャッシュ効率が高い(PHPに素直なことへの恩恵)

CakePHPとの類似点 (yii1,2)

  • 適用するプロジェクト規模がわりと近い印象
  • データベースの編集画面を最速で作れる系

CakePHPとの相違

  • 1.1の頃からすでにActiveRecordがだいぶ先行している
  • 規約ベースで動いてないので自由な設計がしやすい
  • OOP的に素直で全体の一貫性がある(ビヘイビアのサポートはより基底なクラスにあってどこでも使える)
  • イベントのおかげで無理せずファットコントローラを避けられる(経験上)
  • メジャーバージョンを上げるときのポリシー = 下位互換なしでいい、旧バージョンを長くサポートすればいい

特徴的なコンセプト

  • コードをかっこよくするために遅くなるような選択はしない (プログラマーの満足を満たすより、PHPで適切に動くコードはどうか、という意識)
  • いまどきのPHP、真面目にやれば速さは落ちない、かっこよさは結果ついてくるもの
  • フレームワーク固有な記述方法 (Yamlを使ったりアノテーションを使ったり裏ワザみたいなArray記法だったり) がないのでわかりやすく、自分独自のカスタマイズも容易
  • とにかくものすごくアプリケーション開発者目線。個々の部品をどういう使い方しても動くという完全性より、現場目線で「あー自分だったらこれ変えられるようにしておくのになぁ」と思ったところは、だいたい開発者の自己責任で変更できるようにしてある。

Railsと比べて何が良いか ← この視点で見るのが適切

  • もっともRailsと比較されることの多いPHPフレームワーク
  • PHPランタイムで動くということ。これはでかい
  • PhpStormのPHPは型(docコメント)のあるLL、動的すぎない安心感
  • requireとか暗黙で生まれるオブジェクトより、名前空間をuseするクラスローダーのほうが好き
  • ActiveRecordのフィールドはデフォルトでホワイトリスト (デフォルトでMassive Assignmentを防げる)
  • TurboLinkやらCoffeeScriptやらSassやらHamlやら、フレームワークの仕事はそういうことじゃない感
  • どこに何が入っているのかが単純明解で、自分独自なプロジェクト構成も作りやすい
  • 理想 (生き字引きなRubyエキスパートが現場に常駐してくれるという仮定) より現実 (普通の人がそこそこ調べたらどうにか動くものが作れること) を重視

Yii2で採用された新技術など

1 Composer

いまどき当たり前な Composer によるプロジェクト作成。

composer create-project --prefer-dist yiisoft/yii2-app-basic basic

yiisoft/yii2-app-basic は Packagist の登録名。公開されていればどんなテンプレートからでも生成可能。

ってだけならよくある話で、アプリケーション構造はPSR-4に準拠していて名前空間で浅いディレクトリから任意のクラスをオートロード。

2 composer-asset-plugin

https://github.com/francoispluchino/composer-asset-plugin

BowerやNPMからパッケージをインストールできるComposer拡張

インストール

composer global require "fxp/composer-asset-plugin:1.0.0-beta4"

vendorの下にダウンロードされ、Yiiのアセットバンドルの機能で動的にweb公開場所にパブリッシュされます。

3 Twitter Bootstrap

Bootstrap3 拡張が最初から組み込み済み。使うか使わないかは名前空間で使い分け。

yii\widgets\* ← → yii\bootstrap\*

Bootstrapを使いたくなければ名前空間を切り替える。(Bootstrap特有のものを使っていない箇所、ActiveFormなど) これでウィジェットが吐くHTMLにbootstrapなクラスが付いたり付かなかったり。

4 SwiftMailer

SwiftMailerもBootstrapのように使い分け可能。デフォルトは組み込み済み。

Transport実装を切り替えて、SMTPなのをAmazon SESに対応したりsendmailにしたりと、ブリッジがSwiftMailerの便利さを活かすインターフェース設計になっている。

useFileTransport (bool型)という開発用のマスタースイッチが便利。

メールテンプレートのレンダラーがはじめからHTMLメールを想定している。

5 Markdown

https://github.com/cebe/markdown

1.1のときの PHPMarkdownExtra に代わって、これが採用された。すでにコアに入ってる。

  • みんなおなじみのGFM (GitHub方言) モードあり
  • シンタックスごとにモジュールを分割して書かれている
  • Traitとして分けられたモジュールを必要なぶん結合し、自分のカスタムパーサーを作ることができる
  • Traitなのでオブジェクト間のメッセージングがなく速度が出る

ベンチマーク https://github.com/kzykhys/Markbench#readme

  • parsedownに匹敵する速度 (ただしparsedownは拡張性なさすぎてPHPMarkdownかというほど)
  • ciconaに匹敵する拡張性 (ただしciconaは凝集度に対して誠実すぎ、もっと実行速度に最適化していいと思う)

ちなみにYiiには以前から HtmlPurifier が初期インストール済みで、デフォルトで適度に Markdown をサニタイズします。

6 最新のPHP関数とかセキュリティ

  • 日時や通過などの国際化がintlベース(polyfillあり)に
  • password_hash() / password_verify() (5.5〜) 推奨
  • なくても互換実装あり (なんも知らんでもセキュア)
  • ちなみにプロジェクト生成時にクッキー暗号化ソルトを自動生成 (なんも知らんでもセキュア)
  • ちなみに何も書かなくてもフォームにCSRF対策が効いていて、わざわざ解除しないかぎり有効 (なんも知らんでもセキュア)

7 Codeception

http://codeception.com/

BDD風のAcceptanceテスト(Webサーバの外からテスト)とFunctionalテスト(フレームワークのリクエスト全体をテスト)

アプリケーションの実装はだいたいが Yii::$app が指すサービスロケーターに依存するので、だったらいっそリクエストまるごとテストする高級なテスティングフレームワークをサポートしよう。

まあSeleniumにもできるけど、デフォルトのPhpBrowserなら、PHPだけあればHTTPをサーバの外からテストできるよ。

もちろんDbUnitっぽいことが可能な単体テストもあるし、任意にPHPUnitを使ってもOK

8 HATEOASなREST

RESTfulなCRUDに特化したコントローラあり

デフォルトでActiveRecord(正確にはModel)への直接読み書きが実装済みのものあり

で、なんとこれまでSpring(Java)とBEAR.Sunday関連でしか聞いたことのなかったHATEOASをサポート http://en.wikipedia.org/wiki/HATEOAS#Implementations

レスポンスに次のアクションの選択肢リンクや現在のページャー状態などを含んで返すやつ。PHPはREST-APIに特化して、フロントはアプリやピュアなAjaxで作ってもいい。

9 その他今っぽいライブラリ

フレームワークと同時並行開発された豊富な拡張ライブラリ。ほぼ標準機能と言ってもいいです。プロジェクトによっては使わない場合もあるので composer.json に書いていないけど。

アルファ版以前から Elasticsearch の実装があるあたり、最新技術に貪欲でいいですね。

OAuthのフレームワークがあるおかげで設計迷わなくて助かりました。これは時代的にとても現実的。

10 コミュニティのライブラリ

などなど、Packagistでyii2で検索。正式リリース1ヶ月で66ページある。fuelやfuelphpで試すと1桁なので...

新しいサービスとのブリッジやウィジェットなど周辺を補助するものがやたら多い。YiiがCSS/JSを含んでのフレームワークであるというのが効いている。

逆に開発手法を変えるようなものは少ない。時期がまだ熟していないからか、それとも、だいたい yiisoft/* 以下でカバーできてるからか。

(Packagistでヒット数が多すぎるフレームワークは、それはそれで、「え、それサードパーティー製なの?!」ってなることはある)

デモに使ったプロジェクト

(追記)

Dropbox - phpkansai-19-yii2-basic.zip

.git 込みです。vendor が入ってないので、 composer install でどうぞ。