PHPのMVCフレームワークの中では、Githubリポジトリのスターの数がLaravel, CodeIgniter, Symfonyに次いでくらい多いのに、国内では書籍でも紹介されることがないマイナーなフレームワークYii。
最近2.0がリリースされてモダンになったらしいので、雰囲気を掴むためにプロジェクトのセットアップからScaffoldingツール GiiによるCRUDコードの生成を試してみました。

Yiiの特徴としては、まずOracleにやMongoDBなど他のフレームワークでは対応していないDBまでサポートしていることがあります。
SQLServerは最近どのフレームワークでも対応してきましたが、Oracleでちゃんと動くのはYiiとSymfonyくらいではないでしょうか。

また、これからフレームワークを選定するならLaravelとの比較になると思いますが、LaravelはフロントエンドにAngularJSやReactJSなどのSPAフレームワークと組み合わせて使うことを考慮しているのに対して、どちらかというとYiiは昔ながらのMVCフレームワークでシンプルです。
また、Scaffoldingツール Giiが便利で、ささっとDBのフロントアプリを立ち上げたいとかに向いてそうです。

インストール

Vagrantを利用して環境を構築してみます。
Ubuntu 14.04のVagrant boxにLAMPをインストールし、Yii 2.0のプロジェクトを生成、動作を確認するところまでまず解説していきます。

Vagrant環境のセットアップ

プロジェクト用ディレクトリyii2-helloを作成して、Ubuntu 14.04のVagrant環境を用意

$ mkdir yii2-hello && cd yii2-hello
$ vagrant init ubuntu/trusty64


Vagrantfileを以下のように設定します。

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"

  config.vm.network "forwarded_port", guest: 80, host: 8080

  config.vm.synced_folder ".", "/var/www/html", group: "www-data", mount_options: ["dmode=775,fmode=664"]

  config.vm.provision "shell", inline: <<-SHELL
    sudo apt-get update
    sudo apt-get install tasksel -y
    sudo tasksel install lamp-server
  SHELL
end

Vagrantfileの各設定については以下の通り

ホストからのApacheへのアクセスはポートフォワードを利用

  config.vm.network "forwarded_port", guest: 80, host: 8080

Vagrantfileに共有ディレクトリを/var/www/htmlに設定して、Apacheから参照できるように権限を付与

  config.vm.synced_folder ".", "/var/www/html", group: "www-data", mount_options: ["dmode=775,fmode=664"]

Vagrantのフォルダ共有についてはこちらが参考になります: Synced Folders

プロビジョンで、LAMPをインストール

  config.vm.provision "shell", inline: <<-SHELL
    sudo apt-get update
    sudo apt-get install tasksel -y
    sudo tasksel install lamp-server
  SHELL

Vagrantfileが用意出来たら、Vagrantを起動します。

$ vagrant up

Yii 2.0プロジェクトの作成

Installing YiiにしたがってYii2プロジェクトを作成していきます。

まずVagrantにログイン

$ vagrant ssh

Yii2はプロジェクトの生成にComposerを利用します。
以下のコマンドでインストール

$ curl -s http://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

ComposerでYiiのプロジェクトを作成します。
たいていの場合はGithubのTokenのプロンプトが表示されるので、https://github.com/settings/tokensよりトークンを発行して指定する必要があります。

$ cd /var/www/html
$ composer global require "fxp/composer-asset-plugin:~1.1.1"
$ composer create-project --prefer-dist yiisoft/yii2-app-basic basic
...
Could not fetch https://api.github.com/repos/RobinHerbots/jquery.inputmask/commits/d180082aa1ba98c85f85b2c4eebbfa195fd25613, please create a GitHub OAuth token to go over the API rate limit
Head to https://github.com/settings/tokens/new?scopes=repo&amp;description=Composer+on+vagrant-ubuntu-trusty-64+2015-06-15+1326
to retrieve a token. It will be stored in "/home/vagrant/.composer/auth.json" for future use by Composer.
Token (hidden): 
...

Apacheの設定

次はWebサーバーの設定です。

Apacheをインストールしたので、Recommended Apache ConfigurationのとおりにApacheを設定してみます。

ApacheのDocumentRootを/var/www/html/basic/webに設定

DocumentRoot /var/www/html/basic/web

(※ Rewriteの設定については後述)

設定ファイルをリロードします。

$ sudo service apache2 reload

動作確認

Vagrantで8080にポートフォワードしているのでhttp://localhost:8080でアクセスして以下のページが表示されればOKです。
Yii2.0welcome

ScaffoldingツールGiiを試す

動作が確認できたら、次にScaffoldingツールGiiを試してみます。

Giiは、データベースに定義されたテーブルからカラムを参照してモデルのコードを生成します。

これはこれで、データベースを設計するエンジニアがプログラマーとは別に居たりするプロジェクトなどは便利ですし、
普通にマイグレーションを利用してコードでテーブルを管理することもできます。

データベース接続設定

まず、データベース接続の準備をします。
設定はconfig/db.phpに記述

<?php

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=yii2basic',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
];

動作確認用なので、デフォルト設定のままデータベース yii2basic を作成してみます。

mysql> create database yii2basic;

Giiの表示

Giiへのアクセスは、デフォルトでは制限されています。
Vagrantからは、ホストからのアクセスは10.0.2.2に見えるので、allowedIPsに設定します。

    $config['modules']['gii'] = [
        'class' => 'yii\gii\Module',
        'allowedIPs' => ['127.0.0.1', '10.0.2.2'] // adjust this to your needs
    ];

設定後、http://localhost:8080/index.php?r=gii にアクセスすると以下のページが表示されます。
Yii2.0_Gii

モデルの生成

モデルの基になるサンプルテーブルをデータベースに定義します。

CREATE TABLE articles (
  id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  text TEXT,
  PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

[Model Generator]を開き、[Table Name]作成したテーブル名を、[Model Class]にモデルのクラス名を入力します。
Yii2.0_generate_model_with_Gii
[Preview]をクリックして生成されるファイルを確認後、[Generate]ボタンをクリックすると以下のようにテーブル情報を読み込んで自動でモデルのコードが生成されます

<?php

namespace app\models;

use Yii;

/**
 * This is the model class for table "articles".
 *
 * @property integer $id
 * @property string $title
 * @property string $text
 */
class Article extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'articles';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['title'], 'required'],
            [['text'], 'string'],
            [['title'], 'string', 'max' => 255]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'title' => 'Title',
            'text' => 'Text',
        ];
    }
}

バリデーションルールなども自動で追加されて気が利いていますね。

CRUD画面の生成

CRUDの画面は、対象のモデル(上記で作成したもの)を指定し、CRUDアクションを含むコントローラーと各アクションに対応するビューを生成します。

[CRUD Generator]を開き以下のように設定します。
Yii2.0_generate_cRUD_with_Gii

Model Class
作成してモデルを完全修飾(名前空間付)クラス名で指定する

テーブルに主キーが定義されていない場合は、モデルに主キーの定義が必要
モデルにprimaryKeyメソッドを追加しておく

Search Model Class
検索フォーム用モデルを完全修飾クラス名で入力

Controller Class
コントローラのクラス名を完全修飾クラス名で入力

View Path
[View Path]は、ディレクトリを指定、区切り文字は’\’じゃなくて’/’なので注意。
[Controller Class]に入力したコントローラ名が例えば”BookCategoryController”のように途中に大文字を含む場合は、”@app/views/book-category”のようにハイフンを入れて指定します。

参照: Controller IDsController Class Naming

[Preview]をクリックすると、以下のファイルが生成されることが確認できます。
Yii2.0_generate_cRUD_with_Gii_review
[Generate]をクリックするとコードが生成されます。

http://localhost:8080?r=article/indexにアクセスすると以下のように表形式のビューが表示されます。
Yii2.0_CRUD_with_gii

ルーティング

ここまで説明してきて、ルーティングが?r=<コントローラID>/<アクションID> (Controllers Routes)なのが気になると思います。

ルーティングについては、Handring RequestのRouting and URL Creationに説明されていますので、それにしたがって設定してみます。

config/web.phpへの設定

デフォルトの?r=<コントローラID>/<アクションID>といったパラメータ形式のルーティングを/<コントローラID>/<アクションID>といったURL形式にするには、componentsurlManagerを追加し、enablePrettyUrltrueにします。

<?php

$params = require(__DIR__ . '/params.php');

$config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'components' => [
        ...
        'urlManager' => [
          'enablePrettyUrl' => true,
        ],
    ],
]

これで、まず先ほど作成したArticleControllerに/index.php/article/indexのようにアクセスできるようになります。
Yii2.0_enablePrettyUrl

ApacheにRewriteの設定を追加

さらにエントリースクリプトの/index.phpも消したい場合は、ApacheにRewriteの設定を追加する必要があります。

<Directory "/var/www/html/basic/web">
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]
</Directory>

mod_rewriteを有効にして、Apache2をリスタートします。

$ sudo a2enmod rewrite
$ sudo service apache2 restart

以下の通り/article/indexでアクセス可能になりました。
Yii2.0_hide_entryscript

参考

Envato Tuts+ Code Tutorial
How to Program with Yii2: Getting Started
How to Program With Yii2: Working With the Database and Active Record