[OpenPNE3]管理画面付きプラグイン(opFreepagePlugin)#3 管理画面編集フォーム作成

Posted under OpenPNE3,php,symfony by uechoco on 木曜日 19 2月 2009 at 22 : 46 : 10

 前回はopFreepagePluginの管理画面の一覧表示部分を作ってみました。今回はそこにデータを追加するための新規作成・編集削除の2画面を一気に作ります。symfonyを使ったことある人ならば、「propel:generate-crud的な感じ」と言えばソースコードの構成が伝わるかもしれません。

まずはactions.class.phpに以下の6つのメソッドを追加します。

php:
  1. public function executeNew(sfWebRequest $request)
  2.   {
  3.     $this->form = new FreepageForm();
  4.   }
  5.  
  6.   public function executeCreate(sfWebRequest $request)
  7.   {
  8.     $this->forward404Unless($request->isMethod('post'));
  9.  
  10.     $this->form = new FreepageForm();
  11.  
  12.     $this->processForm($request, $this->form);
  13.  
  14.     $this->setTemplate('new');
  15.   }
  16.  
  17.   public function executeEdit(sfWebRequest $request)
  18.   {
  19.     $this->forward404Unless($freepage = FreepagePeer::retrieveByPk($request->getParameter('id')), sprintf('Object freepage does not exist (%s).', $request->getParameter('id')));
  20.     $this->form = new FreepageForm($freepage);
  21.   }
  22.  
  23.   public function executeUpdate(sfWebRequest $request)
  24.   {
  25.     $this->forward404Unless($request->isMethod('post') || $request->isMethod('put'));
  26.     $this->forward404Unless($freepage = FreepagePeer::retrieveByPk($request->getParameter('id')), sprintf('Object freepage does not exist (%s).', $request->getParameter('id')));
  27.     $this->form = new FreepageForm($freepage);
  28.  
  29.     $this->processForm($request, $this->form);
  30.  
  31.     $this->setTemplate('edit');
  32.   }
  33.  
  34.   public function executeDelete(sfWebRequest $request)
  35.   {
  36.     $request->checkCSRFProtection();
  37.  
  38.     $this->forward404Unless($freepage = FreepagePeer::retrieveByPk($request->getParameter('id')), sprintf('Object freepage does not exist (%s).', $request->getParameter('id')));
  39.     $freepage->delete();
  40.  
  41.     $this->redirect('opFreepagePlugin/list');
  42.   }
  43.  
  44.   protected function processForm(sfWebRequest $request, sfFormPropel $form)
  45.   {
  46.     $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
  47.     if ($form->isValid())
  48.     {
  49.       $freepage = $form->save();
  50.       $this->redirect('opFreepagePlugin/list');
  51.     }
  52.   }

これでもうアクションの追加は終わりです。あとは対応するビューの作成とフォームの調整です。

templates/ディレクトリにnewSuccess.phpを作成し、以下のコードを入力します。

php:
  1. <?php slot('submenu') ?>
  2. <?php include_partial('submenu') ?>
  3. <?php end_slot() ?>
  4.  
  5. <h2><?php echo __('フリーページの新規作成') ?></h2>
  6.  
  7. <?php include_partial('form', array('form' => $form)) ?>

続いて、editSuccess.phpを作成し、以下のコードを入力します。

php:
  1. <?php slot('submenu') ?>
  2. <?php include_partial('submenu') ?>
  3. <?php end_slot() ?>
  4.  
  5. <h2><?php echo __('フリーページの編集') ?></h2>
  6.  
  7. <?php include_partial('form', array('form' => $form)) ?>

この2つのビューは新規作成と編集画面に対応するものですが、非常に似ていますし、短いですね。というのも、肝心のフォームの描画は部分テンプレートとして分離しています。templares/ディレクトリに_form.phpを作成して、以下のコードを追加します。

php:
  1. <?php include_stylesheets_for_form($form) ?>
  2. <?php include_javascripts_for_form($form) ?>
  3.  
  4. <form action="<?php echo url_for('opFreepagePlugin/'.($form->getObject()->isNew() ? 'create' : 'update').(!$form->getObject()->isNew() ? '?id='.$form->getObject()->getId() : '')) ?>" method="post" <?php $form->isMultipart() and print 'enctype="multipart/form-data" ' ?>>
  5. <?php if (!$form->getObject()->isNew()): ?>
  6. <input type="hidden" name="sf_method" value="put" />
  7. <?php endif; ?>
  8.   <table>
  9.     <tfoot>
  10.       <tr>
  11.         <td colspan="2">
  12.           <?php echo $form->renderHiddenFields() ?>
  13.           &nbsp;<a href="<?php echo url_for('opFreepagePlugin/index') ?>">キャンセル</a>
  14.           <?php if (!$form->getObject()->isNew()): ?>
  15.             &nbsp;<?php echo link_to('削除', 'opFreepagePlugin/delete?id='.$form->getObject()->getId(), array('method' => 'delete', 'confirm' => '本当に削除しますか?')) ?>
  16.           <?php endif; ?>
  17.           <input type="submit" value="<?php echo $form->getObject()->isNew() ? '作成' : '更新' ?>" />
  18.         </td>
  19.       </tr>
  20.     </tfoot>
  21.     <tbody>
  22.       <?php echo $form->renderGlobalErrors() ?>
  23.       <tr>
  24.         <th><?php echo $form['title']->renderLabel() ?></th>
  25.         <td>
  26.           <?php echo $form['title']->renderError() ?>
  27.           <?php echo $form['title'] ?>
  28.         </td>
  29.       </tr>
  30.       <tr>
  31.         <th><?php echo $form['body']->renderLabel() ?></th>
  32.         <td>
  33.           <?php echo $form['body']->renderError() ?>
  34.           <?php echo $form['body'] ?>
  35.         </td>
  36.       </tr>
  37.       <tr>
  38.         <th><?php echo $form['app_type']->renderLabel() ?></th>
  39.         <td>
  40.           <?php echo $form['app_type']->renderError() ?>
  41.           <?php echo $form['app_type'] ?>
  42.         </td>
  43.       </tr>
  44.       <tr>
  45.         <th><?php echo $form['auth']->renderLabel() ?></th>
  46.         <td>
  47.           <?php echo $form['auth']->renderError() ?>
  48.           <?php echo $form['auth'] ?>
  49.         </td>
  50.       </tr>
  51.     </tbody>
  52.   </table>
  53. </form>

この_form部分テンプレートは、新規作成と編集の両方に対応しているテンプレートですので、ところどころで三項演算子の分岐で新規作成時と編集時の描画内容を分けています。このようにフォームの描画部分を1つのファイルにまとめることで、効率の良いコード保守ができるわけです。

 一応これでフォームは表示できるのですが、symfonyが自動で生成したフォームは余計なフィールドが混ざっているので、たいていはカスタマイズが必要です。今回もcreated_atやupdated_atを表示させないようにしたり、app_typeやauthの表示方法を変更するために、フォームファイルをカスタマイズします。/plugins/opFreepagePlugin/lib/form/FreepageForm.class.phpを開いて、クラスの中身を以下のように書き換えます。

php:
  1. protected static $auths = array('0' => 'なし', '1' => 'あり');
  2.   protected static $app_types = array('pc' => 'pc', 'mobile' => 'mobile');
  3.  
  4.   public function configure()
  5.   {
  6.     unset($this['created_at'], $this['updated_at']);
  7.  
  8.     $this->widgetSchema['body'] = new sfWidgetFormTextarea(array(), array('cols' => 50, 'rows' => 20));
  9.  
  10.     $this->widgetSchema['app_type'] = new sfWidgetFormSelect(array('choices' => self::$app_types));
  11.     $this->validatorSchema['app_type'] = new sfValidatorChoice(array('choices' => array_keys(self::$app_types)));
  12.  
  13.     $this->widgetSchema['auth'] = new sfWidgetFormChoice(array('choices' => self::$auths, 'multiple' => false, 'expanded' => true));
  14.     $this->validatorSchema['auth'] = new sfValidatorChoice(array('choices' => array_keys(self::$auths)));
  15.  
  16.     $this->widgetSchema->setLabels(array(
  17.       'app_type' => 'アプリケーションタイプ',
  18.       'auth'     => '認証が必要',
  19.     ));
  20.   }

上から順番に処理の内容を言うと、bodyフィールドのcols・rowsの設定、app_typeフィールドをセレクトボックスとし選択肢を限定、authフィールドをオプションボタンとし選択肢を限定、いくつかのフィールドのラベルを変更、となっています。実は最初authフィールドをチェックボックスとして実装したのですが、0と1で判断するauthフィールドとはなぜか相性が良くないらしく、編集時にauth=0のはずがチェックがされた状態で描画されてしまいました。とりあえずオプションボタンにすることで回避できました。

以上で管理画面側は全て出来上がりました。実際に編集画面を見てみるとこんな感じになります。
02_opfreepage_edit

次回はPC/mobileの実際の表示画面の作成をやります。次回の内容でプラグインの機能部分は終わって、それ以降はプラグインの微調整と、プラグインのリリースなどが待っています。あともう少しでプラグインの完成です!


[OpenPNE3]管理画面付きプラグイン(opFreepagePlugin)#2 管理画面の作成

Posted under OpenPNE3,php,symfony by uechoco on 火曜日 17 2月 2009 at 09 : 22 : 26

 前回はopFreepagePluginの初期設定として、ディレクトリの作成とDBスキーマの作成を行いました。今回は管理画面内のプラグイン独自の設定画面を開発方法を学びます。開発を行う前に、OpenPNE3のプラグイン設定画面の仕組みを説明します。

 OpenPNE3では、プラグインごとに設定画面が持てるような仕組みを持っていて、設定画面がある場合はプラグイン一覧からリンクが張られています。

00_plugin_list

 プラグイン独自の設定画面を作成するには、プラグイン内にpc_backendアプリケーション用のディレクトリを用意し、そこにプラグインと同名のモジュールを追加します。つまり、プラグインと同名のモジュールがあるかないかで設定画面の有無を判断しています。例えば、opFreepagePluginであれば、/plugins/opFreepagePlugin/apps/pc_backend/modules/opFreepagePlugin/actionsディレクトリを持っていれば「設定画面あり」とみなされます。

 では具体的にopFreepagePluginに設定画面を追加してみます。まずはターミナルで

BASH:
  1. ./symfony opGenerate:app opFreepagePlugin pc_backend

を実行し、/plugins/opFreepagePlugin/apps/pc_backend/modulesディレクトリを作成します。続いて

BASH:
  1. ./symfony opGenerate:module opFreepagePlugin pc_backend opFreepagePlugin

を実行し、pc_backendアプリケーション用のopFreepagePluginモジュールを追加します。デフォルトでactions.class.phpとindexSuccess.phpも作られます。また、この時点で既にプラグイン一覧にはopFreepagePluginの設定画面へのリンクが表示されています。

/actions/actions.class.phpにはexecuteIndex()メソッドが最初から記述されています。これを下記のように書き換え、さらにexecuteList()メソッドを追加します。

php:
  1. public function executeIndex($request)
  2.   {
  3.     $this->redirect('opFreepagePlugin/list');
  4.   }
  5.  
  6.  /**
  7.   * Executes list action
  8.   *
  9.   * @param sfRequest $request A request object
  10.   */
  11.   public function executeList($request)
  12.   {
  13.     $this->freepage_list = FreepagePeer::doSelect(new Criteria());
  14.     return sfView::SUCCESS;
  15.   }

上記記述で追加したlistアクションはフリーページの一覧を表示するアクションで、opFreepagePluginの設定画面を開くと最初に表示されることを想定しています。このlistアクションに対応するビューとして、/templates/listSuccess.phpを作成します。

php:
  1. <?php slot('submenu') ?>
  2. <?php include_partial('submenu') ?>
  3. <?php end_slot() ?>
  4.  
  5. <h2><?php echo __('一覧') ?></h2>
  6.  
  7. <table>
  8.   <thead>
  9.     <tr>
  10.       <th>ID</th>
  11.       <th><?php echo __('Title') ?></th>
  12.       <th><?php echo __('Body') ?></th>
  13.       <th><?php echo __('AppType') ?></th>
  14.       <th><?php echo __('Auth') ?></th>
  15.       <th><?php echo __('Created At') ?></th>
  16.       <th><?php echo __('Updated At') ?></th>
  17.     </tr>
  18.   </thead>
  19.   <tbody>
  20.     <?php foreach ($freepage_list as $freepage): ?>
  21.     <tr>
  22.       <td><?php echo link_to($freepage->getId(), 'opFreepagePlugin/edit?id='.$freepage->getId()) ?></td>
  23.       <td><?php echo $freepage->getTitle() ?></td>
  24.       <td><?php echo '(' . strlen($freepage->getBody()) . __('文字') . ')' ?></td>
  25.       <td><?php echo $freepage->getAppType() ?></td>
  26.       <td><?php echo ($freepage->getAuth() ? 'あり' : 'なし') ?></td>
  27.       <td><?php echo $freepage->getCreatedAt() ?></td>
  28.       <td><?php echo $freepage->getUpdatedAt() ?></td>
  29.     </tr>
  30.     <?php endforeach; ?>
  31.   </tbody>
  32. </table>
  33. <?php echo link_to(__('新規追加'), 'opFreepagePlugin/new') ?>

listSuccess.phpの冒頭でsubmenuという名前の部分テンプレートをスロットとして読み込んでいます。この冒頭3行は管理画面のビューの典型的なパターンですので覚えて損はないです。そのほかの部分はfreepageテーブルの内容を表形式に出力し、編集や新規作成へのリンクを加えています。

 最後に先ほど触れたsubmenuという名前の部分テンプレートを/templates/_submenu.phpに作成します。

php:
  1. <li><strong><?php echo __('フリーページ') . __('プラグイン') ?></strong></li>
  2. <li><?php echo link_to(__('一覧'), 'opFreepagePlugin/list') ?></li>
  3. <li><?php echo link_to(__('新規追加'), 'opFreepagePlugin/new') ?></li>

とりあえずこれでフリーページの一覧は表示できるようになりました。まだ新規作成や編集のリンクは動いていませんが、試しにフリーページをデータベースに直接登録してみると、以下のような画面になります。

01_opfreepage_list

 今回はここまでです。おさらいですが、管理画面にプラグイン独自の設定画面を追加するには、プラグイン名と同名のモジュールを作成すればよいということを忘れないでください。

 次回は管理画面の残りの機能として、新規作成・編集・削除画面を作ります。フォームの使い方勉強にもなりそうです。


[OpenPNE3]管理画面付きプラグイン(opFreepagePlugin)#1 開発準備、DBスキーマの設定

Posted under OpenPNE3,php,symfony by uechoco on 日曜日 15 2月 2009 at 22 : 22 : 33

OpenPNE3のプラグインの作り方は公式ページにもありますが、あちらは管理画面を使わないプラグインでした。今回は管理画面側の設定画面も込みのプラグインのサンプルとしてopFreepagePlugin(フリーページプラグイン)を作ってみたいと思います。フリーページはOpenPNE2からある機能ですが、現時点ではOpenPNE3の開発ロードマップには含まれていないため、当分、公式には作られないと思われる機能です。方針としてはOpenPNE2のフリーページと同等の機能をOpenPNE3で実装していきたいと思います。

プラグイン作成の参考としてこの記事をご覧になる方もいると思いますので、この連載記事で学べること、を先に列挙しておきます。

  • 一般的なOpenPNE3プラグインの作成手順(opGenerateコマンドなどを使用する方法)が学べます。
  • 独自にDBテーブルを持つプラグインの作成方法が学べます。
  • 独自のDBテーブルをフォームから操作する方法が学べます。
  • 管理画面にプラグイン独自の設定画面を追加する方法が学べます。
  • PC、モバイルの両方に独自のページを追加する方法が学べます。
  • プラグイン独自にルーティングを拡張する(プラグイン内からrouting.ymlと同等の定義をする)方法が学べます。
  • OpenPNE3プラグインのパッケージングの方法が学べます。

連載記事のボリュームとしては、6?7回の分量を想定しています。作り方には興味ないけどプラグインだけ欲しいという方は、opFreepagePlugin-0.9.0.tgzをダウンロードしてください。勝手プラグイン(非公式プラグイン)ですので、動作保証は致しません。フィードバックは歓迎しますが、トラブルが発生してもその責任は負えません。OpenPNE3.0.0で動作確認をしています。

プラグインの作成方法を学ぶ前に、これからどんなプラグインを作るのかを知っておいたほうが良いので、関連のあるサムネイルを列挙します。

さて、いよいよプラグイン作りの開始です。第1回目はプラグインの初期設定として、opFreepagePlugin用のディレクトリの作成とDBスキーマの作成、そのDBスキーマに対応したモデルなどのファイルの作成を行います。

まずはプラグインのディレクトリを作ります。ターミナル上でOpenPNE3のルートディレクトリまで移動して以下のコマンドを実行します。以降そのルートディレクトリを基準に話を進めます。

BASH:
  1. ./symfony opGenerate:plugin opFreepagePlugin

すると、/plugins/opFreepagePluginディレクトリが作成され、apps、config、i18n、libの4つの空ディレクトリが作成されます。

次に、DBスキーマを作成します。/plugins/opFreepagePlugin/config/schema.ymlファイルを作成し、

TEXT:
  1. propel:
  2.   _attributes: { package: plugins.opFreepagePlugin.lib.model }
  3.   freepage:
  4.     id: ~
  5.     title:      { type: longvarchar }
  6.     body:       { type: longvarchar }
  7.     app_type:   { type: varchar(16), required: true, default: 'pc'}
  8.     auth:       { type: tinyint, required: true, default: 1}
  9.     created_at: ~
  10.     updated_at: ~

と入力します。今回はfreepageというテーブルをの中に、idカラム(PRIMARY KEY・AUTO_INCREMENT)、titleカラム(TEXT型)、bodyカラム(TEXT型)、app_type(VARCHAR型、'pc'と'mobile'を想定)、auth(BOOL型、ログイン認証のあり=1と、なし=0を想定)、created_at(DATETIME型)、updated_at(DATETIME型)といったカラムを定義しています。

 DBスキーマのファイルを作成したら、スキーマを元にモデルやフォーム、フィルタを自動生成させます。

BASH:
  1. ./symfony openpne:install

を行い、指示に従ってDB情報を入力するとOpenPNE3内のすべてのDB関連ファイルが一新され、その過程でopFreepagePlugin用のファイルも作成されます。しばらくしてコマンドが完了すると、/plugins/opFreepagePlugin/libディレクトリの中にmodel、form、filterなどのディレクトリが作成されていて、それぞれ自動生成された以下のクラスファイルが格納されています。

├─form
│  │  FreepageForm.class.php
│  └─base
│          BaseFreepageForm.class.php
├─model
│  │  Freepage.php
│  │  FreepagePeer.php
│  ├─om
│  │      BaseFreepage.php
│  │      BaseFreepagePeer.php
│  └─map
│          FreepageMapBuilder.php
└─filter
    │  FreepageFormFilter.class.php
    └─base
            BaseFreepageFormFilter.class.php

 これでプラグイン開発の準備が整いました。次回は管理画面のプラグイン独自の設定ページの作成に移ります。


[OpenPNE3]3.0.0のindex.phpを消す

Posted under OpenPNE3,php by uechoco on 日曜日 1 2月 2009 at 20 : 28 : 37

prod環境のno_script_nameがonになってるのにindex.phpが消えないOpenPNE3ですが、果てしない旅の結果、ただのバグでした。

旅の経路:

  • UrlHelper内link_to()関数
  • UrlHelper内url_for()関数
  • sfWebController->genUrl()メソッド
  • sfPatternRouting->generate()メソッド
  • sfRouting->fixGeneratedUrl()メソッド
  • cache内config_factories.yml.phpファイル
  • sfOpenPNEWebRequest->__construct()メソッド
  • sfRequest->__construct()メソッド
  • sfWebRequest->initialize()メソッド
  • sfOpenPNEWebRequest->initialize()メソッド

で、sfWebRequest->initialize()とsfOpenPNEWebRequest->initialize()を比較した結果、sfOpenPNEWebRequest->initialize()の第4引数がないことに気付きました。第4引数$optionsを追加して、試しに$optionsの内容をprint_rしたところ、

TEXT:
  1. Array (     [logging] =&gt;      [path_info_array] =&gt; SERVER     [path_info_key] =&gt; PATH_INFO     [relative_url_root] =&gt;      [formats] =&gt; Array         (             [txt] =&gt; text/plain             [js] =&gt; Array                 (                     [0] =&gt; application/javascript                     [1] =&gt; application/x-javascript                     [2] =&gt; text/javascript                 )              [css] =&gt; text/css             [json] =&gt; Array                 (                     [0] =&gt; application/json                     [1] =&gt; application/x-json                 )              [xml] =&gt; Array                 (                     [0] =&gt; text/xml                     [1] =&gt; application/xml                     [2] =&gt; application/x-xml                 )              [rdf] =&gt; application/rdf+xml             [atom] =&gt; application/atom+xml         )      [no_script_name] =&gt; 1 )

と、no_script_name => 1が伝搬されてきました。あとは、これをparent::initialize()の第4引数として渡してやると、無事にindex.phpが消えました。

結論:

sfOpenPNEWebRequest.class.phpのsfOpenPNEWebRequest->initialize()メソッドを

php:
  1. public function initialize(sfEventDispatcher $dispatcher, $parameters = array(), $attributes = array())
  2. {
  3. parent::initialize($dispatcher, $parameters, $attributes);
  4.  
  5. require_once 'Net/UserAgent/Mobile.php';
  6. }

から

php:
  1. public function initialize(sfEventDispatcher $dispatcher, $parameters = array(), $attributes = array(), $options = array())
  2. {
  3. parent::initialize($dispatcher, $parameters, $attributes, $options);
  4.  
  5. require_once 'Net/UserAgent/Mobile.php';
  6. }

に変えるだけ。たぶんOpenPNE3.0.1とかでは既に治ってると思います。


[OpenPNE3]新規登録を受け付ける(オープン制)

Posted under OpenPNE3,php by uechoco on 土曜日 31 1月 2009 at 22 : 53 : 31

OpenPNE3を初めてインストールしたときは、管理画面が変わってしまっていて、オープン制にする方法がわからない人もいるかもしれません。

通常、OpenPNE3.0.0をインストールしてアクセスすると、以下のようにメールアドレスとパスワード欄が用意されてはいますが、新規登録ページへのリンクはありません。

index_login_disable

現在のバージョンでは実運用する人はなかなかいないと思いますので、試験設置の方がほとんどだと思います。そういう場合はオープン制の方が便利ですよね。もちろんオープン制にするオプションはあるのですが、プラグイン式になったため分かりにくくなっています。まずは管理画面にアクセスします。デフォルトではadmin/passwordで入れると思います。左メニューから「プラグイン設定」を選択します。

plugin-list

プラグイン一覧の中から「opAuthMailAddressPlugin」を探し、右側の「設定」をクリックします。下図の画面に遷移したら、招待モードを「」にすれば完了です。

opauthmailaddressrequestregisterurl

するとログインフォームの下に「新規登録」というリンクが増えます。

index_login_enable

新規登録方法はおなじみの方法です。メールアドレスを入力すると、そのメールアドレスに新規登録用のURLが記載されたメールが届きます。ブラウザでアクセスしてプロフィールなどを入力すれば新しいメンバーが追加されます。


« 前ページへ次ページへ »

Copyright © 2012 うえちょこ@ぼろぐ. WP Theme created by Web Top.