ぷぎがぽぎ このページをアンテナに追加 RSSフィード

2008-11-29

[][][]jpSimpleMailPluginリリース

時間ができたので、openpearを使ってsymfonyプラグインをリリースしてみました。

jpSimpleMailPlugin (openpear.org)

どんなプラグインなのかは以下のwikiを参照してください。

jpSimpleMailPluginについて

要するに、日本語のメールを簡単に送信するためのラッパークラスのライブラリなだけです。

openpearを利用させてもらっているので、チャンネルを追加する必要があります。

あとは、通常のプラグインのインストールと同じです。

$ ./symfony plugin:add-channel openpear.org
$ ./symfony plugin:install --force-license --release=0.1.1 openpear.org/jpSimpleMailPlugin

*1

*2

plugin:listで確認してみます。

f:id:brtRiver:20081130032901p:image

おー。ちょっと感動。

パッケージの作成がWebから行えるのはやっぱり大きいですね。

このような環境を提供してくれている運営の方々に感謝感謝です。

symfonyのプラグインも公開できちゃうopenpear。オススメです。

[][]テストファーストで作成するsymfonyプラグイン

昨日はsymfony懇親会が開催されました。参加された皆様おつかれさまでした。

また、場所を提供してくださったディノさんありがとうございました。

さて、昨日の自己紹介時にsymfonyのプラグイン作成が充実してきた的なことを言ったのですが、簡単にまとめておきます。

といっても、本家のブログで紹介されています。

The sfTaskExtraPlugin is a plugin maintained by the symfony core team. It adds a number of useful tasks to your symfony command line to help streamline your workflow.

symfony | Web PHP Framework | Blog | Additional tasks to streamline your workflow

なので、ここでは上記ブログのテスト部分の補足です。

まず、sfTaskExtraPluginはsymfonyのプラグインを作るためのプラグインです。

インストールすることで

* generate:plugin (空のプラグインを作成)

* generate:plugin-module (モジュールを含む空のプラグインを作成)

* plugin:package (作成したファイルからプラグインを作成)

のコマンドが利用できるようになります。

ただし、空のプラグインを作成するといっても、標準ではテストディレクトリも作成してくれます。

それも中途半端なテストディレクトリではありません。

myPluginというプラグインを作ってみます。

$ ./symfony generate:plugin myPlugin

すると、以下のようなファイル群が作成されます。

plugins/myPlugin
|-- LICENSE
|-- README
|-- config
|   `-- myPluginConfiguration.class.php
|-- package.xml.tmpl
`-- test
    |-- bin
    |   `-- prove.php (全てのテストを実行するためのスクリプト)
    |-- bootstrap
    |   |-- functional.php(機能テストのときに読み込ませるファイル。test/fixtures以下を実行)
    |   `-- unit.php(単体テストのときに読み込ませるファイル)
    `-- fixtures
        `-- project(プラグインのテストのために用意されたsymfonyプロジェクトファイル群)
            |-- apps
            |   `-- frontend
            |       |-- config
            |       |   |-- app.yml
            |       |   |-- cache.yml
            |       |   |-- factories.yml
            |       |   |-- filters.yml
            |       |   |-- frontendConfiguration.class.php
            |       |   |-- routing.yml
            |       |   |-- security.yml
            |       |   |-- settings.yml
            |       |   `-- view.yml
            |       |-- i18n
            |       |-- lib
            |       |   `-- myUser.class.php
            |       |-- modules
            |       `-- templates
            |           `-- layout.php
            |-- cache
            |-- config
            |   |-- ProjectConfiguration.class.php
            |   |-- databases.yml
            |   |-- propel.ini
            |   |-- properties.ini
            |   |-- rsync_exclude.txt
            |   `-- schema.yml
            |-- data
            |   `-- fixtures
            |       `-- fixtures.yml
            |-- doc
            |-- lib
            |-- log
            |-- plugins
            |-- symfony
            |-- test
            |   |-- bootstrap
            |   |   |-- functional.php
            |   |   `-- unit.php
            |   |-- functional
            |   `-- unit
            `-- web
                |-- css
                |   `-- main.css
                |-- images
                |-- js
                |-- robots.txt
                `-- uploads
                    `-- assets

テストのためにこれでもかというぐらい用意してくれます。

(ただプロジェクトの雛形をコピーしているだけですが。)

とくに、機能テストを行うときに参照するプロジェクト、アプリケーション、モジュールもtest/fixturesディレクトリに作成することができ、なおかつコマンドから簡単に実行することができるのです。

テストを作成するのも簡単です。

test/unit, test/functionalディレクトリを作成し、そこにテストファイルをファイル名がTest.phpで終わるように作成するだけです。

そして、それぞれのbootstrapのファイルをincludeしておきます。

test/unit/sampleTest.phpの場合

<?php
include(dirname(__FILE__) . '/../bootstrap/unit.php');
$t = new lime_test(1, new lime_output_color());
$t->diag('check method');
....

また、汎用的になるようにsymfonyのlibディレクトリへのパスは$_SERVER['SYMFONY']で参照するようになっています。なのでLinux系であれば以下のように環境変数をセットしておく必要があります。

$ export SYMFONY=/path-to-symfony/lib

ローカル環境、テスト環境などでパスが異なる場合でもハードコーディングせずに済むというメリットがあります。

あとは、テストを実行するだけです。

$ php ./plugin/myPlugin/test/unit/sampleTest.php

全てのテストを実行する場合は

$ php ./plugin/myPlugin/test/bin/prove.php

このsfTaskExtraPluginの良いところはテストを自動生成するのではなく、テストするための環境を作ってくれるということです。

テストファーストで開発を行いたいけどテスト開発するための準備が面倒だと感じている方も多いのではないでしょうか?

そういう私のような人間にはぴったりなプラグインによる開発についてでした。

また、plugin:packageを叩いたときに、このテストディレクトリは含まれないようにパッケージされます。

*1:--force-licenceをつけないとエラーになってしまいます

*2:openpear.orgで指定しないとRESTをサポートしていないと怒られてしまいました。

2008-11-28

[][]sfFormで確認画面を作るためのhidden作成

テンプレート内では、通常の要素表示(sfFormField->renderが呼び出される)の記述のまま、freezeされた場合はinputタグなどの表示から、入力値+hiddenタグの表示に自動的に切り替わるようにしてみました。

Symfonyと格闘・・・ - iNNX Life - real side

やっぱり皆やることは同じですねw

Ajaxが使える場合はUIを巧く利用することで確認画面を無くしても問題ないことが多いですが、案件内容によっては確認画面が必須だったりしますよね。

[追記]

確認画面部分をsfFormに拡張できるプラグインがあることをコメントいただきました。

Openforce

こちらを使ったほうが簡単に実装できそうです。

で、私の場合は以下のようなメソッドをフォームクラスに追加することでHTML_QuickFormのfreeze,unfreezeを実装してみました。

  /**
   * for freeze feature
   */
  public $isFreeze = false;
  protected static $valuesBeforeFreeze = array();
  protected static $widgetSchemaBeforeFreeze = null;
  public function setHiddenAll()
  {
    self::$valuesBeforeFreeze = $this->getValues();
    self::$widgetSchemaBeforeFreeze = clone $this->getWidgetSchema();
    foreach ($this->getWidgetSchema()->getFields() as $id => $v) {
      // CSRF token is set by automate, so except !
      if ($this->getCSRFFieldName() == $id) continue;
      $this->widgetSchema[$id] = new sfWidgetFormInputHidden(array(), array('value' => $this->getValue($id)));
    }
  }
  public function unfreeze()
  {
    $this->setwidgetSchema(self::$widgetSchemaBeforeFreeze);
    $this->setDefaults(self::$valuesBeforeFreeze);
    $this->isFreeze = false;
  }
  public function freeze()
  {
    $this->setHiddenAll();
    $this->isFreeze = true;
   }

やっていることは既に定義したsfWidgetSchemaをcloneでコピーしておき、各フィールドをsfWidgetFormInputHiddenで再作成するようにしています。そして、unfreeze時にはコピーしたスキーマを再セットしています。

これでアクション側で

$this->form->freeze();

とすればテンプレートで

echo $this->form;

とするだけで全てhiddenで書き出されます。

freezeされているかどうかは

$this->form->isFreeze

で確認できるはず。

というわけで、晒しておきますがおかしなところがあればご指摘ください。。

2008-11-27

[][]jpMailPluginのsymfony1.2対応

昨日の続きです。

さすがに、ライブラリのソース晒して「使ってみてください」は悲しいので、パッケージにしました。

対応したといっても、getPresentationForが使えるようにしたというだけです。

また、symfony1.2でしか確認していませんが。。大丈夫かな。

jpMailPlugin

ちなみに、PHPMailerは同梱してませんので別途とってきてください。

2008-11-26

[][]jpMailPluginをsymfony1.1以降で使う場合

symfony1.2でaskeet実践のための準備としてsymfonyでメール送信ネタが続きます。

すでに周知の事実としてjpMailPluginはそのままではsymfony1.1以降では動きません。

これは、sfMailクラスがバンドルされなくなったことが一番の原因なのですが、それ以外にも色々とハマります。

とりあえず現状分かっている範囲をまとめます。

symfony1.1で利用する場合

spanstyle::monologさんところが実際に使えるようになるまでを紹介してくれています。

ref: jpMailPluginをsymfony1.1.5に対応してみた(暫定)

getPresentationForの所属クラスが変更になっている

symfony1.0のころとの違いはgetPresentationForメソッドはコントローラークラスに移動しているので注意

$this->getController()->getPresentationFor(...)

getPresentationForで第3引数でビュークラスを指定してもsfPHPに上書きされてしまう

手元のsymfony1.2での現象なのですが(バグのような気もしますが)、jpMailと指定してもsfPHPViewクラスでレンダー処理されるという悲しい結果になってしまいます。

これは引数で渡した値よりも設定ファイル(module.yml)の方が強く効くためのようです。

なので、getPresentationForで利用する専用のモジュールを作成しmodule.ymlでview_classを指定しなければ意図した動作になりませんでした。

アプリケーション/modules/モジュール名/config/module.yml

all:
  view_class: jpMail
  is_internal: on

symfony1.2でjpMailViewクラスを使いたい

新規プロジェクトで使うのであればgetPresentationForを利用せずにgetComponentかgetPartialを使うのが自然かと思います。

もし、symfonyを1.0からアップグレードして使いたい場合は以下の手順でjpMailPluginを使うことができる(みたい)です

  1. symfony1.1以降で不足しているsfMail.class.phpをsymfony1.0からもってくる(アップグレードの場合はもともとあるので必要ないと思いますが。。)
  2. jpMailView.class.phpをsymfony1.2に対応した以下のクラスに置き換える

*1

<?php

/**
 *
 * @package    jpMail.plugin
 * @subpackage view
 * @author     brt river <brt.river@gmail.com>
 */
class jpMailView extends sfPHPView
{
  /**
   * Retrieves the template engine associated with this view.
   *
   * @return string sfMail
   */
  public function getEngine()
  {
    return 'jpMail';
  }

  /**
   * Configures template for this view.
   *
   * @throws <b>sfControllerException</b> If the configure fails
   */
  public function configure()
  {
    // view.yml configure
    parent::configure();

    // require our configuration
    $moduleName = $this->moduleName;
    
    if ($file = sfContext::getInstance()->getConfigCache()->checkConfig('modules' . sfConfig::get('sf_app_module_dir_name').'/'.$this->moduleName.'/config/mailer.yml',true)) {
      require(sfContext::getInstance()->getConfigCache()->checkConfig('modules' . sfConfig::get('sf_app_module_dir_name').'/'.$this->moduleName.'/config/mailer.yml'));
    }
  }

  /**
   * Renders the presentation and send the email to the client.
   *
   * @return mixed Raw data of the mail
   */
  public function render($templateVars = null)
  {

    $template         = $this->getDirectory().'/'.$this->getTemplate();
    $actionStackEntry = sfContext::getInstance()->getActionStack()->getLastEntry();
    $actionInstance   = $actionStackEntry->getActionInstance();

    $retval = null;

    // execute pre-render check
    $this->preRenderCheck();

    if (sfConfig::get('sf_logging_enabled'))
    {
      $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('{sfView} render "%s"', $template))));
    }

    // get sfMail object from action
    $mail = $actionInstance->getVarHolder()->get('mail');
    if (!$mail)
    {
      $error = 'You must define a sfMail object named $mail ($this->mail) in your action to be able to use a sfMailView.';
      throw new sfControllerException($error);
    }

    // assigns some variables to the template
    //$this->attributeHolder->add($this->getGlobalVars());
    //$this->attributeHolder->add($actionInstance->getVarHolder()->getAll());

    // render main template
    $retval = $this->renderFile($template);
  

    // render main and alternate templates
    $all_template_dir  = dirname($template);
    $all_template_regex = preg_replace('/\\.php$/', '\..+\.php', basename($template));
    $all_templates = sfFinder::type('file')->name('/^'.$all_template_regex.'$/')->in($all_template_dir);
    $all_retvals = array();
    foreach ($all_templates as $templateFile)
    {
      if (preg_match('/\.([^.]+?)\.php$/', $templateFile, $matches))
      {
        $all_retvals[$matches[1]] = $this->renderFile($templateFile);
      }
    }

    // send email
    if (sfConfig::get('sf_logging_enabled'))
    {
      $this->dispatcher->notify(new sfEvent($this, 'application.log', array('{sfView} send email to client')));
    }

    // configuration prefix
    $config_prefix = 'sf_mailer_'.strtolower($this->moduleName).'_';

    $vars = array(
      'mailer',
      'priority', 'content_type', 'charset', 'encoding', 'wordwrap',
      'hostname', 'port', 'domain', 'username', 'password'
    );
    $defaultMail = new jpMail();
    foreach ($vars as $var)
    {
      $setter = 'set'.sfInflector::camelize($var);
      $getter = 'get'.sfInflector::camelize($var);
      $value  = $mail->$getter() !== $defaultMail->$getter() ? $mail->$getter() : sfConfig::get($config_prefix.strtolower($var));
      $mail->$setter($value);
    }
    $mail->setBody($retval);

    // alternate bodies
    $i = 0;
    foreach ($all_retvals as $type => $retval)
    {
      if ($type == 'altbody' && !$mail->getAltBody())
      {
        $mail->setAltBody($retval);
      }
      else
      {
        ++$i;
        $mail->addStringAttachment($retval, 'file'.$i, 'base64', 'text/'.$type);
      }
    }

    // preparing email to be sent
    $mail->prepare();

    // send e-mail
    if (sfConfig::get($config_prefix.'deliver'))
    {
      $mail->send();
    }
    return $mail->getRawHeader().$mail->getRawBody();
  }
}

とりあえず、エラーが出ていた箇所をsymfony1.2で動くように書き換えてみました。(例外処理の変更、ログの出力変更などなど)

小論

getPresentationForを使うのはなにかと面倒なことになりそう(引数でViewクラスを書き換えることができないため)。

getComponentかgetPartialを使うように実装した方が良いと思われる。

追記

getPresentationForを使わずに、もっとシンプルにPHPMailer, Swift Mailer, Qdmailで簡単に日本語メールを送るためのプラグイン(jpSimpleMailPlugin)を作成中です。

どんな感じになるかはjpSimpleMailPluginを見てもらえればわかるかと。

まだ公開していないのは公開場所をopenpearにしたいからその準備が週末でないとできないということなんですが。

でも、アンダーバー区切りのパッケージの中にいきなりキャメルケースのsymfonyプラグインを入れるのに抵抗を感じてるのですが。。

*1:テスト不足感があるので後日ちゃんと対応します。

2008-11-20

[][]Swift Mailerをiso-2022-jpで送信するための自前ヘッダークラス

symfonyでは1.0系ではPHPMailerというライブラリをメール送信で利用できるようにコアに含めてくれていました。

しかし、symfony1.1以降はコアにメール送信のライブラリを含めなくなってしまいました。

これは、symfonyが他のライブラリへの依存をできる限り排除しようとするポリシーになったからだと思われます。

そして、symfonyのcook bookではSwift Mailerというライブラリを使ったメール送信方法が紹介されています。

何故PHPMailerではなくSwift Mailerかというところの詳しい説明はありませんが、よりオブジェクト指向としてしっかり作られているという点ではないかと個人的には思っています。


しかし、日本語(iso-2022-jp)を扱うことが簡単ではありません。

詳しくは以下のアシアルさんところの記事を読んでみてください。

Swift_Mailer の内部的な処理としてヘッダーのエスケープ処理(Swift_Message_Headers)が記述されているので、mb_encode_mimeheader()を使用してエンコードする処理に変更する必要があります(もしくはSwift_Message_Headersを直接変更してしまいます)。

symfonyでSwift Mailerを使用する際の注意点 : アシアルブログ

ただ、Swift Mailerでコアクラスに修正せずにiso-2022-jpで送信することはできたのでメモとして残しておきます。

まず、どうしても外部から変更が不可能なのがSubjectのエンコード処理でした。

なので、以下のようなファイルをコアライブラリの階層をまねて作成します。

* <アプリケーションルート>/lib/vender/SwiftMailer/Swift/Message/jpHeaders.php

<?php
Swift_Classloader::load('Swift_Message_Headers');
class Swift_Message_jpHeaders extends Swift_Message_Headers
{
  public function __construct()
  {
    $this->setCharset('iso-2022-jp');
  }
  public function getEncoded($name)
  {
    if ($this->getCharset() == 'iso-2022-jp' && (strtolower($name) == "subject")) {
      $encoded_value = (array)$this->get($name);
      foreach ($encoded_value as $key => $value ) {
        $encoded_value[$key] = mb_encode_mimeheader($value, $this->getCharset(), 'B', "\n");
      }
      //If there are multiple values in this header, put them on separate lines, cleared by commas
      $lname = strtolower($name);
      //Append attributes if there are any
      $this->cached[$lname] = implode("," . $this->LE . " ", $encoded_value);
      if (!empty($this->attributes[$lname])) $this->cached[$lname] .= $this->buildAttributes($this->cached[$lname], $lname);
      return $this->cached[$lname];
    } else {
      return parent::getEncoded($name);
    }
  }
}

subjectの時だけ自前のencode処理を行うようにしています。それ以外の$this->cachedやらなんやらはよく調べていないのですが、親メソッドではごにょごにょしていたので合わせて処理するようにしてあります。

そして、この自前Headerを使ってメール送信を行うように以下のようなアクションを使います。

  public function executeSendSwiftMailer(sfWebRequest $request)
  {
    // Create the mailer and message objects
    mb_language('ja');
    $charset = 'iso-2022-jp';
    $mailer = new Swift(new Swift_Connection_NativeMail());
    $message = new Swift_Message();
    // Send
    $subject = 'メール送信テストです';
    $type = 'text/plain';
    $encoding = '7bit';
    $to = new Swift_Address('hoge@example.com', mb_encode_mimeheader('ほげ', $charset, 'B', "\n"));
    $from = new Swift_Address('huga@example.com', mb_encode_mimeheader('ふが', $charset, 'B', "\n"));
    $body = mb_convert_encoding('本文です!', $charset, mb_internal_encoding());

    $message->setHeaders(new Swift_Message_jpHeaders()); // <= 自前ヘッダークラスを指定する
    $message->setContentType($type);
    $message->setSubject($subject);

    $message->setEncoding($encoding);
    $message->setCharset($charset);
    $message->setBody($body);
    $mailer->send($message, $to, $from);
    $mailer->disconnect();
    return sfView::NONE;
  }

$message->setHeadersで自前のヘッダークラスを指定しています。

また、ヘッダークラスを上書きした場合はsetContentTypeも再度指定する必要がありました。

この辺りの内部構造を理解しきれていません。。


その他のmb_convert_encoding処理も自前クラスを作りカプセル化してしまおうかと思ったのですが、かなりややこしい事になりそうだったので諦めました...orz


これでSwiftMailerでも日本語メールが送信できましたが、私自身の結論はPHPMailerQdmailの利用を検討することにしますw


また、近いうちにPHPMailerを使ったjpMailPluginをsymfony1.1以降に対応するように修正したいと思います。

基本的な送信ぐらいであればPHPMailerとQdmailを同じインターフェースで使えるようにできるといいな。そうしよう。

2008-11-18

[][][] parent::setName($value)は使わずに$this->_set('name', $value)を使え

昨日の続き。

まず、現象の再現方法。

現在某ブログでaskeetをsymfony1.2で実践中なのですが、

symfony+Doctrineでレコード(Doctrine_Record)のプロパティ(body)のセッター部分をハックし、html_bodyというプロバティにMarkdown形式で上書きたい場合のお話です。

本家チュートリアルのように、意識せずPropelのコードと同様に以下のようなaskeetのコードを書いてブラウザから登録を行うと。。

class Question extends BaseQuestion
{
  ....
  public function setBody($v)
  {
    require_once('markdown.php');
    parent::setBody($v); // <= ここで落ちる
    // strip all HTML tags
    $v = htmlentities($v, ENT_QUOTES, sfConfig::get('sf_charset'));
    $this->setHtmlBody(markdown($v));
  }

見事にセグメンテーションエラー。(PHP5.2.6)

[notice] child pid 23191 exit signal Segmentation fault (11)

しかも、不思議なことにdoctrine:data-loadの場合はエラーで落ちずにちゃんと読み込んでくれます。

parent::setBodyメソッド部分で落ちているのはわかったのですが、原因がわからない。。

確かにDoctrineはマジックメソッドを多用しているので、Propelのように親クラスにはsetBodyというメソッドはありません。

でもそれで動くのがマジックメソッドのはずなのに。。。

で、公式ドキュメントみても該当するものが無いと諦めかけていたときにようやく見つけました。まさにこの現象についての記事を。

The _set() and _get() methods must be used to avoid a infinite loop when overriding accessors and mutators.

symfony | Web PHP Framework | Blog | New in symfony 1.2: Doctrine goodies

アクセッサを上書きすると無限ループになっちゃうと。なので、アクセッサとしてDoctrine_Recordに用意された_set()メソッドと_get()メソッドを使えと。

というかまぢですか。

とりあえず、以下のコードがプロパティを上書きするための正しいDoctrineのコード。

class Question extends BaseQuestion
{
  ....
  public function setBody($v)
  {
    require_once('markdown.php');
    $this->_set('body', $v);
    // strip all HTML tags
    $v = htmlentities($v, ENT_QUOTES, sfConfig::get('sf_charset'));
    $this->_set('html_body', markdown($v));
  }

これは知らないとはまる。

2008-11-17

[][]これだからbetaは。。。

1011         public function updateObject()

1012         {

1013          $object = parent::updateObject();

    1011     public function updateObject($values = null)

    1012     {

    1013      $object = parent::updateObject($values);

Changeset 13055 - symfony - Trac

うは。sfFormのupdateObjectに$valuesなんて引数がいつの間に。

ただ、これでいちいち$object->setHoge('XXX')なんてしなくても$valuesに渡してあげればfromArrayで自動でアサインしてくれるぽい。

でも、今困ってるのはupdateObjectを叩くと画面が真っ白でapacheのログにはセグメンテーションエラーが。。。

[notice] child pid 23191 exit signal Segmentation fault (11)
[notice] child pid 23146 exit signal Segmentation fault (11)

んー。。。気になって寝れない。

2008-11-12

[][]symfony懇親会のお知らせ

普段の勉強会だと特定の人が発表、それをみんなで聞く、というのが多いのでもっと気軽に交流する場ということでsymfony懇親会を開催します。

基本的にビール(など)を楽しみながら気軽にsymfonyやその他技術のことを話す集まりなので、お気軽にご参加ください。

events.php.gr.jp - symfony懇親会

参加表明済み。

symfonyに限らずですが、技術系の情報ってこういう集まりが色々話が聞くことができるので一番いいんですよね。

ちょっとでも気になる方は参加してみませんか?

2008-11-11

[][]symfony1.2 beta2 リリース

We are very happy to announce the symfony 1.2 beta 2 release, which now supports the admin generators for both Doctrine and Propel

symfony | Web PHP Framework | Blog | symfony 1.2 beta2 - The Doctrine Admin Generator is here

symfony1.2から標準でサポートされるようになったDoctrineが新しいアドミンジェネレータに対応というのがbeta2の一番の特徴のようです。

更新されたドキュメントによると、

アドミンジェネレータの設定ファイルであるgenerator.ymlは互換性があるので、propel:init-adminを再度実行するだけで新しいアドミンジェネレータを利用できるとのこと。

そして、今まで新規と更新が同じ画面でしたが、新しいバージョンからはnew,とeditと別々の設定が行えるようになったとのこと。

今までに増して使いやすいものになってそうですね。

本家

Upgrading Projects from 1.1 to 1.2

What's new in symfony 1.2

日本語

Upgrading Projects from 1.1 to 1.2

What's new in symfony 1.2

2008-11-10

[][]sfSimplePagePlugin

本家にsfSimplePagePluginというプラグインを登録してみました。

別に新しいものでもなく、以前からsfBasicCMSPluginとして勝手プラグインとして公開していたものに手直ししたものです。

といっても、何なのこのプラグインってことで簡単に説明をば。


その名のとおり、シンプルなページを表示するためのプラグインです。

たとえば

http://example.com/frontend.php/static/page.html

というリクエストであれば、PATH_INFOからプラグインが判断して

<プロジェクト>/data/static/page.html

テンプレートとして表示してくれます。

なので、以下のような

http://example.com/frontend.php/static/hoge/page.html

ディレクトリが指定されていれば

<プロジェクト>/data/static/hoge/page.html

をテンプレートとして表示してくれます。

つまりメリットは以下の通りです。

  • アクションファイルを用意しなくてもよい
  • テンプレート名にステータスを表す(Success)文字が不要
  • テンプレートを階層で配置できる
  • ヘッダーやフッターだけを利用したいというほぼ静的なページの作成が簡単

もちろん、画面遷移が伴う(アクションが必要な)処理には不向きです。

symfonyに詳しくないと、「DBアクセスとかできないのでは?」と思われるかもしれませんが大丈夫です。

まず、symfonyの仕組みとしてactionとtemplateがあります。この中でactionは画面遷移部分を担当しています。たとえば、入力画面なのか確認画面なのか、それとも完了画面なのかという感じです。

f:id:brtRiver:20081110114631p:image

DBアクセスはORMを通して行いますが、これはアクションからでも利用できますし、テンプレートではコンポーネントという仕組みを使えば利用できます。*1

というわけで、プラグインを導入したフローは以下のようになります。

f:id:brtRiver:20081110115521p:image

アクション処理をスルーし(実際はプラグインの中で処理しています)テンプレートの処理を行うだけです。シンプルです。


ちなみに、今回はsfTaskExtraPluginというプラグインを作るためのプラグインを使ってひな形とパッケージを作成しました。

ほとんどの作業をタスクでできるので簡単なのでオススメです。

みなさんもプラグインつくってみませんか?

*1:本当はコンポーネントを使わなくても直接ORM呼べますがコンポーネントを使った方が切り分けができます

2008-11-05

[][]symfonyアップグレード

symfony1.2のbeta1がリリースされ、本年度中の正式リリースに向けて開発が進んでいます。

そして、この機会にsymfony1.0からsymfony1.2へ移行していこうという方も多いかと思います。

そういう方のために情報をまとめてみました。

symfony1.0からバージョンアップするために役立つ情報 : エクスギア Blog

どんどん学習コストが増えていくのは気のせいではないはず。。

google codeだと文字が小さいという方のためにもgoogle codeの日本語訳をブログ内にも置きましたのでお役に立てば幸いです。

2008-11-02

[][] symfony 1.2 beta1 リリース

As the release manager of symfony 1.2, I have the pleasure to announce that we released the symfony 1.2 beta today. Head for the installation page to obtain information on how to download this release.

symfony | Web PHP Framework | Blog | symfony 1.2 beta is out the door

ここ数日fabienが凄い勢いでTicketを処理していたのですが、ようやくリリースされました。

f:id:brtRiver:20081102120349j:image

とりあえず実装が完了したという位置づけになるんでしょうか。

なので、バグもあるでしょうけど、実際に使ってフィードバックを返そうと思います。

また、膨大な量のアップグレード情報ファイル(UPGRADE_TO_1_2)ですが、知らない間に

* アップグレードするために必要な情報(UPGRADE_TO_1_2)

* symfony 1.2での新しい機能についての情報(what's new?)

のファイルに分割されました。

その結果

f:id:brtRiver:20081102120350j:image

と大幅にすっきり!

ただし、全体の文量が減ったわけではないんですけどね。。

日本語訳も追随してありますのでご参考になれば幸い

UPGRADE_TO_1_2(日本語)

What's new(日本語)

2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |