SprintPHPをCloud9で使ってみた。

#SprintPHPについて

[SprintPHP](http://sprintphp.com/)

> Blazing fast Web Application development with SprintPHP. Fully baked and ready to rock.

詳細は略

#Cloud9、composerでSprintPHPのインストール

composerを使ってSprintPHPのインストールを実行しますが、Cloud9の端末上で実行しようとするとアップデートを勧められるので実行します。

```bash
$ composer create-project sprintphp/sprintphp sprintphp dev-develop
  Warning: This development build of composer is over 60 days old. It is recommended to update it by running "/usr/bin/composer self-update" to get the latest version.

$ sudo composer self-update
```

アップデートが完了したらSprintPHPをインストール。
今回はsprintphpというディレクトリに配置することにします。

```bash
$ pwd
/home/ubuntu/workspace
$ composer create-project sprintphp/sprintphp sprintphp dev-develop
```

インストールが完了したらsprintphpディレクトリに移動してsprintコマンドが実行できるか確認

```bash
$ cd sprintphp
$ php sprint
You must pass a valid command to sprint.
```

#Cloud9の公開ディレクトリの変更

このままだとURLに余分なディレクトリが入ったままになるので公開ディレクトリを変更します。
以下のファイルを編集すればよいみたいです。

```bash
$ sudo vi /etc/apache2/sites-enabled/001-cloud9.conf
```

`DocumentRoot`を変更します。

```/etc/apache2/sites-enabled/001-cloud9.conf
    DocumentRoot /home/ubuntu/workspace
↓
    DocumentRoot /home/ubuntu/workspace/sprintphp
````

#SprintPHPのconfig変更とデータベース接続

SprintPHPはほとんどCodeigniter3のままなのでいつもの場所にあるconfigを変更すればデータベースに接続できるようになります。

```~/workspace/sprintphp/application/config/config.php
$config['base_url'] = '';
↓
$config['base_url'] = 'https://sprintphp-test-youhei-nakagawa.c9users.io';
```

同じくconfigファイルだけど`encryption_key`は一応変更

```~/workspace/sprintphp/application/config/config.php
$config['encryption_key'] = hex2bin( '23e1f843dc67509597fe17b8372de916' );
↓
$config['encryption_key'] = hex2bin( 'eafbb3fb57df1828c68b51f99cd793be' );
```

```~/workspace/sprintphp/application/config/database.php
        'hostname' => 'localhost',
        'username' => 'root',
        'password' => 'root',
↓
        'hostname' => getenv('IP'),
        'username' => getenv('C9_USER'),
        'password' => '',
```

via: [Cloud9でMySQLを使う](http://qiita.com/ao_love/items/31b660ab53bee959c940)


#Cloud9、MySQLの起動とデータベースの作成

Cloud9は手動でMySQLを起動する必要があるみたいです。
オリジナルの起動コマンド？

```bash
$ mysql-ctl start
$ mysql-ctl cli
```

MySQLにこれから使うデータベースを作成し中身を確認

```mysql
mysql> create database sprint;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| c9                 |
| mysql              |
| performance_schema |
| sprint             |
+--------------------+
5 rows in set (0.00 sec)

mysql> use sprint;
Database changed
mysql> show tables;
Empty set (0.00 sec)

```

#SprintPHPのマイグレーションの実行

via: [Installing SprintPHP](https://www.youtube.com/watch?v=OYWwm8nKxg0)

SprintPHPには標準的なログイン機能が提供されていて必要なテーブルの作成を行ってくれます。

```bash
$ php sprint database migrate
Migration group to refresh? [ Default: "app" ]: 
Migrate to the latest available version? [ y, n ]: y

        Successfully migrated database from version 0 to 20160111121139.
```

上記sprintコマンド実行後MySQLにテーブルが入ったことが確認できます。

```mysql
mysql> show tables;
+-------------------------+
| Tables_in_sprint        |
+-------------------------+
| auth_groups             |
| auth_groups_permissions |
| auth_groups_users       |
| auth_login_attempts     |
| auth_logins             |
| auth_permissions        |
| auth_tokens             |
| ci_sessions             |
| mail_queue              |
| migrations              |
| settings                |
| user_meta               |
| users                   |
+-------------------------+
13 rows in set (0.00 sec)
```

この状態でCloud9の公開URLにアクセスしてみます。

`https://{プロジェクト名など}.c9users.io/login`
![sprintphp_login.png](https://qiita-image-store.s3.amazonaws.com/0/111110/cbc51560-7dc7-2618-af80-b2df2f90a025.png)

ユーザー登録などが実行できるようになっています。

#SprintPHPのforge機能、modelの作成

via: [SprintPHP - Using the Forge Generators](https://www.youtube.com/watch?v=CANFdCR5NKo)

以下のコマンドでmodelファイルの作成ができます。

```bash
$ php sprint forge model
Invoked ModelGenerator
Model name: rabbit_model
Table name [ Default: "rabbits" ]: 
Primary Key [ Default: "id" ]: 
Set Created date? [ y, n ]: y
Set Modified date? [ y, n ]: y
Date Format? [ datetime, date, int ]: datetime
Log User actions? [ y, n ]: n
Use Soft Deletes? [ y, n ]: y
        created models/Rabbit_model.php
```

`Rabbit_model.php`がありますね。

```bash
$ ls application/models/
Rabbit_model.php  User_model.php  index.html
```

しかしMySQLの中にはrabbitsテーブルは存在していないことを確認。

```mysql
mysql> show tables;
+-------------------------+
| Tables_in_sprint        |
+-------------------------+
| auth_groups             |
| auth_groups_permissions |
| auth_groups_users       |
| auth_login_attempts     |
| auth_logins             |
| auth_permissions        |
| auth_tokens             |
| ci_sessions             |
| mail_queue              |
| migrations              |
| settings                |
| user_meta               |
| users                   |
+-------------------------+
13 rows in set (0.00 sec)
```

#SprintPHPのforge機能、既存テーブルからmodelの作成

forge機能を使ってみます。まずは既存のテーブルからmodelを作成します。
既存のmail_queurテーブルを使ってみます。
まずは存在確認。

```mysql
mysql> desc mail_queue;
+---------+------------------+------+-----+---------+----------------+
| Field   | Type             | Null | Key | Default | Extra          |
+---------+------------------+------+-----+---------+----------------+
| id      | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| mailer  | varchar(255)     | NO   |     | NULL    |                |
| params  | text             | YES  |     | NULL    |                |
| options | text             | YES  |     | NULL    |                |
| sent    | tinyint(1)       | NO   | MUL | 0       |                |
| sent_on | datetime         | YES  |     | NULL    |                |
+---------+------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
```

modelを生成。
テーブル名を指定します。

```bash
$ php sprint forge model
Invoked ModelGenerator
Model name: mail_queue_model
Table name [ Default: "mail_queues" ]: mail_queue
Set Created date? [ y, n ]: n
Set Modified date? [ y, n ]: n
Date Format? [ datetime, date, int ]: datetime
Log User actions? [ y, n ]: n
Use Soft Deletes? [ y, n ]: n
        created models/Mail_queue_model.php
```

ファイルがテーブルの内容と同期して生成されたことを確認します。

```bash
$ cat application/models/Mail_queue_model.php
```

一部抜粋。

```application/models/Mail_queue_model.php
    /**
     * An array of validation rules. This needs to be the same format
     * as validation rules passed to the Form_validation library.
     */
    protected $validation_rules = [
                [
                        'field' => 'id',
                        'label' => 'Id',
                        'rules' => 'integer|max_length[11]',
                ],              [
                        'field' => 'mailer',
                        'label' => 'Mailer',
                        'rules' => 'alpha_numeric_spaces|max_length[255]',
                ],              [
                        'field' => 'params',
                        'label' => 'Params',
                        'rules' => 'alpha_numeric_spaces',
                ],              [
                        'field' => 'options',
                        'label' => 'Options',
                        'rules' => 'alpha_numeric_spaces',
                ],              [
                        'field' => 'sent',
                        'label' => 'Sent',
                        'rules' => 'integer|max_length[1]',
                ],              [
                        'field' => 'sent_on',
                        'label' => 'Sent On',
                        'rules' => '',
                ],
```

#SprintPHPのforge機能、存在しないテーブルからcontrollerの作成

まずは単純なcontrollerの作成

```bash
$ php sprint forge controller
Invoked ControllerGenerator
Controller name: Rabbit
Model Name? (empty is fine): 
Is a Themed Controller? [ y, n ]: n
        created controllers/Rabbit.php
```

Rabbitコントローラが生成されているのを確認

```bash
$ ls application/controllers
Home.php  Rabbit.php  index.html
```

Rabbitコントローラに紐づくモデルがないことを確認

```bash
$ cat application/controllers/Rabbit.php
```

```application/controllers/Rabbit.php
    // If set, this model file will automatically be loaded.
    protected $model_file      = null;
```

rabbitモデルと紐づくようにします。
先ほどのコントローラ作成のコマンドの後ろに既存コントローラを指定すると再設定が可能に。しかし上書きができない。

```bash
$ php sprint forge controller rabbit
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        exists: controllers/Rabbit.php
```

-overwriteオプションを追加して再度実行

```bash
$ php sprint forge controller rabbit -overwrite
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        overwrote controllers/Rabbit.php
```

モデルが指定されていることを確認

```bash
$ cat application/controllers/Rabbit.php
```

```application/controllers/Rabbit.php
    // If set, this model file will automatically be loaded.
    protected $model_file      = 'rabbit_model';
```

#SprintPHPのforge機能、存在しないテーブルと既存モデル及びコントローラからviewの作成

先ほどのモデルと紐づけるコマンドに -create_view オプションをつけることで作成可能。
しかしデータベースエラーが発生。そもそもテーブルが存在していない。

```bash
$ php sprint forge controller rabbit -overwrite -create_views
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        overwrote controllers/Rabbit.php
        created views/rabbit/index.php

        A PHP Error was encountered
        Severity: Warning
        Message: Invalid argument supplied for foreach()
        Filename: /home/ubuntu/workspace/sprintphp/myth/_generators/Controller/view_create.tpl.php
        Line Number: 14
```

テーブルを作りますがマイグレーションファイルを生成してそこからテーブルを生成したいと思います。

```bash
$ php sprint forge migration create_rabbit_table -fields "name:string id:id created_on:datetime modified_on:datetime age:int:2"
Invoked MigrationGenerator
        created database/migrations/20160128042421_Create_rabbit_table.php
```

先ほど作成したマイグレーションファイルを実行します。

```bash
$ php sprint database migrate
Migration group to refresh? [ Default: "app" ]: 
Migrate to the latest available version? [ y, n ]: y

        Successfully migrated database from version 20160111121139 to 20160128042421.
```

テーブルが生成されているのを確認します。

```mysql
mysql> show tables;
+-------------------------+
| Tables_in_sprint        |
+-------------------------+
| auth_groups             |
| auth_groups_permissions |
| auth_groups_users       |
| auth_login_attempts     |
| auth_logins             |
| auth_permissions        |
| auth_tokens             |
| ci_sessions             |
| mail_queue              |
| migrations              |
| rabbits                 |
| settings                |
| user_meta               |
| users                   |
+-------------------------+
14 rows in set (0.00 sec)

mysql> desc rabbits;
+-------------+-----------------+------+-----+---------+----------------+
| Field       | Type            | Null | Key | Default | Extra          |
+-------------+-----------------+------+-----+---------+----------------+
| name        | varchar(255)    | YES  |     |         |                |
| id          | int(9) unsigned | NO   | PRI | NULL    | auto_increment |
| created_on  | datetime        | NO   |     | NULL    |                |
| modified_on | datetime        | NO   |     | NULL    |                |
| age         | int(2)          | NO   |     | 0       |                |
+-------------+-----------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
```

テーブルができたところで再度viewファイルを生成、エラーが発生しないことを確認

```bash
$ php sprint forge controller rabbit -overwrite -create_views
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        overwrote controllers/Rabbit.php
        overwrote views/rabbit/index.php
        overwrote views/rabbit/create.php
        overwrote views/rabbit/show.php
        overwrote views/rabbit/update.php
```

#SprintPHPのforge機能、存在するテーブルからマイグレーションファイルを生成

`migration`に`-fromdb`をつけるだけ
この例では最初からつく荒れていたusersテーブルのマイグレーションファイルを生成します。

```bash
$ php sprint forge migration create_users_table -fromdb
Invoked MigrationGenerator
        created database/migrations/20160128043525_Create_users_table.php
```

ファイルの中身を確認

```bash
$ cat application/database/migrations/20160128043525_Create_users_table.php
```

```php
        $fields = [
                'id' => [
                        'type' => 'int',
                        'constraint' => 11,
                        'auto_increment' => true,
                        'unsigned' => true,
                ],              'email' => [
                        'type' => 'varchar',
                        'constraint' => 255,
                ],              'username' => [
                        'type' => 'varchar',
                        'constraint' => 30,
                ],              'password_hash' => [
                        'type' => 'varchar',
                        'constraint' => 255,
                ],              'reset_hash' => [
                        'type' => 'varchar',
                        'constraint' => 40,
                ],              'activate_hash' => [
                        'type' => 'varchar',
                        'constraint' => 40,
                ],              'created_on' => [
                        'type' => 'datetime',
                        'default' => '0000-00-00 00:00:00',
                ],              'status' => [
                        'type' => 'varchar',
                        'constraint' => 255,
                ],              'status_message' => [
                        'type' => 'varchar',
                        'constraint' => 255,
                ],              'active' => [
                        'type' => 'tinyint',
                        'constraint' => 1,
                ],              'deleted' => [
                        'type' => 'tinyint',
                        'constraint' => 1,
                ],              'force_pass_reset' => [
                        'type' => 'tinyint',
                        'constraint' => 1,
                ],      ];
```

#SprintPHPのforge機能、存在するテーブルからmigration,model,controller,view,seedファイルを生成する

全部一括して作られるのを確認するために、rabbitテーブルを残してこれまで作成したmodel、migration、controller、view、seedファイルを削除します。
seedは作られてないかな？

そしてscaffoldを実行。何でもかんでもテーブルを参照して作ってくれます。

```bash
$ php sprint forge scaffold rabbit -fromdb -overwrite
Invoked ScaffoldGenerator
Invoked MigrationGenerator
        created database/migrations/20160128044044_Create_rabbit_table.php
Invoked SeedGenerator
        created database/seeds/RabbitSeeder.php
Invoked ModelGenerator
        created models/Rabbit_model.php
Invoked ControllerGenerator
        created controllers/Rabbit.php
        created views/rabbit/index.php
        created views/rabbit/create.php
        created views/rabbit/show.php
        created views/rabbit/update.php


Before your new module can be successfully used, you must run the migration to
get the database current.
You can do this with the following line:

    php sprint database migrate

If you have scaffolded this as part of a module, then pass the module name after
that, like:

    php sprint database migrate {module_name}
```


実際にできた画面をのぞいてみると・・・

![sprintphp_scaffold.png](https://qiita-image-store.s3.amazonaws.com/0/111110/762bbceb-5698-35fd-42c5-a63a5ea4fd65.png)


なぜか新規追加画面と編集画面がテーブルの内容とあっていない。

しかたないので、controllerとviewだけ再度生成するために`forge controller -create_views`をするとよくなる。

```bash
$ php sprint forge controller rabbit -overwrite -create_views
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        overwrote controllers/Rabbit.php
        overwrote views/rabbit/index.php
        overwrote views/rabbit/create.php
        overwrote views/rabbit/show.php
        overwrote views/rabbit/update.php
```

![sprintphp_scaffold_fix.png](https://qiita-image-store.s3.amazonaws.com/0/111110/02be5fbc-7905-31a9-e055-5310e7b66d9a.png)


できた！

#SprintPHPを簡単に使うには？

1. データベース上に対象となるテーブルをさくっと作成。
 migrationで作成してもいいかも。好みの問題かも。

2. scaffoldでテーブルに紐づく必要なファイルを一挙に生成
  テーブル名とクラス名の対応には注意！クラス名は単数形、テーブル名は複数形

3. viewがテーブルの内容とあっていないのでcontrollerとviewだけ再生成
  モデル名の指定だけ気を付ける

単純なコマンドにすると・・・

```bash
$ php sprint forge migration create_rabbit_table -fields "name:string id:id created_on:datetime modified_on:datetime age:int:2"
Invoked MigrationGenerator
        created database/migrations/20160128051003_Create_rabbit_table.php

$ php sprint database migrate
Migration group to refresh? [ Default: "app" ]: 
Migrate to the latest available version? [ y, n ]: y

$ php sprint forge scaffold rabbit -fromdb -overwrite
Invoked ScaffoldGenerator
Invoked MigrationGenerator
        created database/migrations/20160128051045_Create_rabbit_table.php
Invoked SeedGenerator
        overwrote database/seeds/RabbitSeeder.php
Invoked ModelGenerator
        created models/Rabbit_model.php
Invoked ControllerGenerator
        created controllers/Rabbit.php
        created views/rabbit/index.php
        created views/rabbit/create.php
        created views/rabbit/show.php
        created views/rabbit/update.php


Before your new module can be successfully used, you must run the migration to
get the database current.
You can do this with the following line:

    php sprint database migrate

If you have scaffolded this as part of a module, then pass the module name after
that, like:

    php sprint database migrate {module_name}

$ php sprint forge controller rabbit -overwrite -create_views
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        overwrote controllers/Rabbit.php
        overwrote views/rabbit/index.php
        overwrote views/rabbit/create.php
        overwrote views/rabbit/show.php
        overwrote views/rabbit/update.php

```

#使ってみて気になったところとまだわからないところ。

- 日本語が入らない
- 編集画面で前のデータが反映されていない
- 項目の表示/非表示はどうするんだろう？
- joinテーブル対応はどうするか？
- 検索画面とかできるのか？

##日本語が入らない

validationの問題でした。

```bash
$ vi application/models/Rabbit_model.php
```

とりあえず下記のようにrulesから半角英数字空白縛りを外すと動きます。

```application/models/Rabbit_model.php
    protected $validation_rules = [
		[
			'field' => 'name',
			'label' => 'Name',
			//'rules' => 'alpha_numeric_spaces|max_length[255]',
			'rules' => 'max_length[255]',
```

##編集画面で前のデータが反映されていない

###**修正されました！**

[SprintPHPのGithubの修正差分](https://github.com/ci-bonfire/Sprint/commit/1ef776667cb429f8cc4f458b0002de39392182d7#diff-aceb138e7f9163cf6030781570bbe76d)

全然わからない英語でIssueを書きましたが対応してもらえて嬉しかったです。

[No data is displayed in the edit screen. #162](https://github.com/ci-bonfire/Sprint/issues/162)

でもこれって`array`のほうがよく使われているからそうしたみたいに読み取れるけどどうなんだろう？生成されるviewファイルを変更したほうがいいのかな？

##以下は解決済みの内容です

テンプレートはオブジェクトを参照、しかしデータベースから取り出したときは配列になるようになっていたのが原因でした。
forgeされると以下のようなコードに。

```bash
vi application/models/Rabbit_model.php
```

```application/models/Rabbit_model.php
    protected $return_type = 'array';
```

このコードを`'object'`にすれば済むんだけどmodelのテンプレートから変更してforgeするたびに変更する手間を省きます。

```bash
vi myth/_generators/Model/model.tpl.php
```

```myth/_generators/Model/model.tpl.php
    protected \$return_type = 'array';
    ↓
    protected \$return_type = 'object';
```

再度viewファイルを生成

```bash
$ php sprint forge controller rabbit -overwrite -create_views
Invoked ControllerGenerator
Model Name? (empty is fine): rabbit_model
        overwrote controllers/Rabbit.php
        overwrote views/rabbit/index.php
        overwrote views/rabbit/create.php
        overwrote views/rabbit/show.php
        overwrote views/rabbit/update.php
```

しっかりと反映されるようになりました！

![sprintphp_edit_fix.png](https://qiita-image-store.s3.amazonaws.com/0/111110/f6d7f38a-000d-57e6-b199-8b504e8a3837.png)