concrete5.7 ブロックタイプ（最少）に入力値を保存する機能を追加する

# はじめに

[前回作ったブロックタイプ](http://qiita.com/yorozuone/items/41ba5497e34f218138db)は、エリアに配置すると既定の文字列(Hello, World!) が表示されるだけでした。今回は、ブロックの編集画面で入力した文字列を表示するように改造したいと思います。

# 画面イメージ

## 編集画面
![010.png](https://qiita-image-store.s3.amazonaws.com/0/1154/504f50bf-f613-6d01-ea87-546446f71953.png)

## 公開画面
![020.png](https://qiita-image-store.s3.amazonaws.com/0/1154/69afd7a5-71f8-925b-de41-09f097772747.png)

# 仕様

- 文字列を１行入力できる input を作成して、表示できるようにします。
- `SingleLine` という名前にします。
- `/application/blocks/single_line/` に作成します。
- 今回作成するのは、以下の5ファイルです。

```
db.xml
controller.php
add.php
edit.php
view.php
```

各ファイルの説明は、concrete5 japan の [ディレクトリ構造とコンセプト](http://concrete5-japan.org/help/5-7/developer/working-with-blocks/directory-structure-and-concepts/) が参考になります。

# db.xml

編集画面で入力した情報を保存するテーブルの構造を記述します。
テーブル名は、名前の競合を極力避けるため、`bt` というプリフィックスを先頭につける慣習があります。
フィールドに指定できる型などの詳細は、concrete5.org の [db.xml in the Doctrine XML Format](http://documentation.concrete5.org/developers/packages/custom-database-tables-in-packages/db-xml-doctrine-xml-format) ページをご覧ください。

```lang:/application/blocks/single_line/db.xml
<?xml version="1.0" encoding="UTF-8"?>
<schema
  xmlns="http://www.concrete5.org/doctrine-xml/0.5"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.concrete5.org/doctrine-xml/0.5 http://concrete5.github.io/doctrine-xml/doctrine-xml-0.5.xsd">

  <table name="btSingleLine">
    <field name="bID" type="integer">
      <unsigned/>
      <key/>
    </field>
    <field name="content" type="text"/>
  </table>

</schema>
```

ブロックタイプをインストールした時点で、データベース上にテーブルが作成されます。

```
CREATE TABLE `btSingleLine` (
	`bID` INT(10) UNSIGNED NOT NULL,
	`content` LONGTEXT NULL COLLATE 'utf8_unicode_ci',
	PRIMARY KEY (`bID`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;
```

作成されてたテーブルは、MySQL で、こんな構造になっていました。

# controller.php

いくつかの修正が必要ですが、設定関係が主になります。

```lang:/application/blocks/single_line/controller.php
<?php
namespace Application\Block\SingleLine;
use \Concrete\Core\Block\BlockController;

class Controller extends BlockController {

	// db.xml で指定したテーブル名を記述します。
	protected $btTable = 'btSingleLine';

  // キャッシュに関する設定を行います。
  // キャッシュするには true を、しない場合は false を指定。
  protected $btCacheBlockRecord = true;
  protected $btCacheBlockOutput = true;
  protected $btCacheBlockOutputOnPost = true;
  protected $btCacheBlockOutputForRegisteredUsers = true;

  // ブロックタイプの説明を出力
  public function getBlockTypeDescription() {
    return t("１行のテキストを表示します。");
  }

  // ブロックタイプのタイトルを出力
  public function getBlockTypeName() {
    return t("１行テキスト");
  }

}
```

`protected $btTable = 'btSingleLine';`
db.xml で指定したデータベース名を指定します。

`namespace Application\Block\SingleLine;`
フォルダと名前を整えます。

`public function getBlockTypeDescription()`
`public function getBlockTypeName()`
ブロックタイプに合わせて変更します。

# add.php

ブロックタイプをエリアにドラッグ＆ドラッグしたときの HTML を記述します。今回は、１行文字列を入力できるようにします。
`<?php echo $form->text('content') ?>`
第一引数に指定されている `'concent'` は、db.xml で指定したフィールド名と一致させてください。

```lang:/application/blocks/single_line/add.php
<?php
    // おまじない
    defined('C5_EXECUTE') or die(_("Access Denied."));
    // フォームヘルパー読み込み
    $form = Core::make('helper/form');
?>
<label class="control-label"><?php echo t('１行テキスト')?></label>
<?php echo $form->text('content') ?>
```

# edit.php

ブロックを編集したときの HTML を記述します。add.php とほとんど同じです。
`<?php echo $form->text('content', $content) ?>`
違いは、の第二引数に、db.xml で指定した、content フィールドを指定している点です。
これで、編集時にテーブルに保存されている情報を既定値として表示するようになります。

```lang:/application/blocks/single_line/edit.php
<?php
    // おまじない
    defined('C5_EXECUTE') or die(_("Access Denied."));
    // フォームヘルパー読み込み
    $form = Core::make('helper/form');
?>
<label class="control-label"><?php echo t('１行テキスト')?></label>
<?php echo $form->text('content', $content) ?>
```

# view.php

表示用のHTMLを記載します。h() でくくっているのは、エスケープです。

```lang:/application/blocks/single_line/view.php
<?php
    // おまじない
    defined('C5_EXECUTE') or die(_("Access Denied."));
?>
<div><?php echo h($content) ?></div>
```

# さいごに

開発中 db.xml を作成する前に、ブロックタイプをインストールして、あとから、db.xml を作成すると、データベース回りでエラーが出るようになります。ブロックタイプの削除すら難しくなってしまいました。
対策としては、db.xml をリネームして、ブロックタイプを削除します。その後、db.xml に名前を戻して、再度インストールすると改めてテーブルが作成されるので、うまく動くようになります。

複数のファイルを作りますが、ファイル間で名前を統一する必要がある部分が多いので、うまく動かない場合は、タイプミスがないか念入りに見るといいと思います。