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

忍び歩く男 - SLYWALKER

大阪のこっそりPHPer

初めてのプラグイン フォームメール - CakePHP1.2RC2 その1モデル編

CakePHP1.2RC2でプラグインをつくってみた

お題は「フォームメール」


まず、プラグイン作成の際にはココを熟読しておく!
(自分はハマリかけてあきらめかけてしまいました)
The Cookbook :: 1.2 Collection :: マニュアル :: CakePHPによる開発 :: Plugins

どんなものつくるの?

  • フォーム項目を設定できるようにしたい。
  • なるべくCake流で(Validate等を最大限そのまま使う)
  • プラグイン名(form_mail)

bakeで

$ cake bake plugin form_mail

これでプラグインのスケルトンができる

データベースの準備

-- --------------------------------------------------------

--
-- テーブルの構造 `form_mail_elements`
--

CREATE TABLE `form_mail_elements` (
  `id` int(11) NOT NULL auto_increment,
  `form_mail_form_id` int(11) NOT NULL,
  `label` varchar(255) collate utf8_unicode_ci NOT NULL,
  `type` varchar(255) collate utf8_unicode_ci NOT NULL,
  `options` varchar(255) collate utf8_unicode_ci NOT NULL,
  `rule` varchar(255) collate utf8_unicode_ci NOT NULL,
  `required` tinyint(1) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `form_mail_form_id` (`form_mail_form_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- --------------------------------------------------------

--
-- テーブルの構造 `form_mail_forms`
--

CREATE TABLE `form_mail_forms` (
  `id` int(11) NOT NULL auto_increment,
  `title` varchar(255) collate utf8_unicode_ci NOT NULL,
  `email` varchar(255) collate utf8_unicode_ci NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

モデル

フォームのValidate用のモデルは、テーブルを使わずに
動的に Model::_schemaにコントローラからセットするようにする。
Validateも同様、設定された値からセットする。

app/plugin/form_mail/models/form_mail_view.php

<?php
class FormMailView  extends FormMailAppModel {
    public $name = 'FormMailView';
    public $useTable = false;

    public $_schema = array('id' => array('type' => 'primary'));
    public $validate = array();

    function setSchema($name, $type)
    {
        $map = array(
            'text'     => 'string',
            'textarea' => 'text',
            'datetime' => 'datetime',
            'date'     => 'date',
            'time'     => 'time',
            'select'   => 'string',
            'radio'    => 'string',
            'checkbox' => 'boolean',
        );
        $schema = array($name => array('type' => $map[$type]));
        $this->_schema = am($this->_schema, $schema);
        return true;
    }

    function setValidate($field, $options = 'required', $allowEmpty = false)
    {
        $rule = $options;
        if (is_array($options)) {
            $rule = $options[0];
        }
        $validate = array();
        if ($allowEmpty) {
            $validate['allowEmpty'] = true;
        }
        switch ($rule) {
            case 'required':
                $validate['rule'] = VALID_NOT_EMPTY;
                $validate['message'] = '必須項目です';
                break;
            case 'numeric':
                $validate['rule'] = $options;
                $validate['message'] = '半角数字で入力してください';
                break;
            case 'alphaNumeric':
                $validate['rule'] = $options;
                $validate['message'] = '半角英数字で入力してください';
                break;
            case 'email':
                $validate['rule'] = $options;
                $validate['message'] = 'メールアドレスの形式を確認してください';
                break;
            case 'url':
                $validate['rule'] = $options;
                $validate['message'] = 'URLの形式を確認してください';
                break;
        }

        $this->validate[$field][] = $validate;
        return true;
    }
}
?>

あとは、先ほど作ったテーブル用のモデル
プラグインで使用するモデル名には注意を!

プラグイン名.モデル名

これを忘れてもエラーがでず、変な動きしだすだけなので大変です。
(ここにハマって投げ出しそうになりました)

2008-09-09 追記
アソシエーションのオプションを指定する場合は、
またコツがいりました。

public $hasMany = array(
    'FormMailElement' => array(
        'className' => 'FormMail.FormMailElement',
        'dependent' => true,
    ),
);

のように、classNameにプラグイン名.モデル名を指定します。

app/plugin/form_mail/models/form_mail_element.php

<?php
class FormMailElement extends FormMailAppModel {
    public $name = 'FormMailElement';

    public $validate = array(
        'label' => array(
            'rule' => VALID_NOT_EMPTY,
            'message' => 'ラベルを入力してください',
        ),
    );

    public $types = array(
        'text'     => 'テキスト',
        'textarea' => 'テキストエリア',
        'datetime' => '日付 時刻',
        'date'     => '日付',
        'time'     => '時刻',
        'radio'    => 'ラジオボタン',
        'select'   => 'セレクトボックス',
        'checkbox' => 'チェックボックス',
    );

    public $rules = array(
        'numeric'      => '半角数字',
        'alphaNumeric' => '半角英数字',
        'email'        => 'Email形式',
        'url'          => 'URL形式',
    );

    public $belongsTo = array('FormMail.FormMailForm');
}
?>

app/plugin/form_mail/models/form_mail_form.php

<?php
class FormMailForm extends FormMailAppModel {
    public $name = 'FormMailForm';
    public $validate = array(
        'title' => array(
            array(
                'rule' => VALID_NOT_EMPTY,
                'message' => 'タイトルを入力してください',
            ),
        ),
        'email' => array(
            array(
                'rule' => array('email'),
                'message' => 'メールアドレスの形式を確認してください',
            ),
            array(
                'rule' => VALID_NOT_EMPTY,
                'message' => 'メールアドレスを入力してください',
            ),
        ),
    );

    // 2008-09-09 修正
    public $hasMany = array('FormMailElement' => array(
        'className' => 'FormMail.FormMailElement',
        'dependent' => true
    ));
    // 2008-09-09 修正
}
?>

その2送信編に続く