カテゴリー : Symfony

[Symfony2] DB の Master/Slave(マスタースレーブ)構成について

Symfony2 での DB の Master/Slave 構成について調べたのでメモ。

symfony1系には sfDoctrineMasterSlavePlugin があるのですが、Symfony2でも同じようなものがないかなと思っていたら、ありました。

Doctrine の DBAL2.16 から実装された MasterSlaveConnection を使えばできるみたいです。

lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php at master from doctrine/dbal – GitHub はてなブックマーク - lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php at master from doctrine/dbal - GitHub
 

DBAL2.16 以上が使えないようでしたら、下記記事を参考に「データベース接続ごとのEntityManagerを明示的に切り替えるような方法」で対応するしかなさそうです。

Symfony2を利用してのDBのMaster/Slave構成について – Google グループ はてなブックマーク - Symfony2を利用してのDBのMaster/Slave構成について - Google グループ

複数のエンティティマネージャと連携する方法 | Symfony2日本語ドキュメント はてなブックマーク - 複数のエンティティマネージャと連携する方法 | Symfony2日本語ドキュメント

以上です。

PHPFog + Symfony2 でステージング環境を作る方法:Symfony Advent Calender 2011 JP – 13日目 –

こんにちは!「Symfony Advent Calendar JP 2011」 はてなブックマーク - Symfony Advent Calendar JP 2011 : ATND13日目です。

昨日の @77webさんからバトンタッチで、今日は「PHPFog + Symfony2 でステージング環境を作る方法」をワタクシ、バコラー (@bakorer) がご紹介します。
 


 

PHPFog と Symfony2 って何?

さて、今日のブログのテーマですが、タイトル通り PHPFog に Symfony2 が動作する環境を作る手順をめっちゃ丁寧に書いていきたいと思います。

みんな大好き Symfony については説明するまでもありません、PHP5向けのウェブアプリケーションフレームワークです。

・公式:High Performance PHP Framework for Web Development – Symfony はてなブックマーク - High Performance PHP Framework for Web Development - Symfony
 

「PHP fog」はPHPの実行環境を提供しているPaaS型クラウドです。先日、3つのアプリケーションまで永久無料にすると発表されたPHPerに優しいサービスなのです。

・詳しくはこちらの記事を参考:ずっと無料で使えるPaaS型クラウドのまとめ。2011年版 - Publickey はてなブックマーク - ずっと無料で使えるPaaS型クラウドのまとめ。2011年版 - Publickey

・公式:PHP Fog — Rock Solid Cloud Platform for PHP はてなブックマーク - PHP Fog — Rock Solid Cloud Platform for PHP
 

Heroku を使うとステージング環境がカンタンに作れて素敵だったから、Symfony2 用のステージング環境をサクッと作りたかったんだ。

ところで、皆さんステージング環境ってどうされていますか?

  • ステージング用の VPS を契約してる
  • 開発環境で確認したら、即、本番アップだぜ!
  • ステージング環境なにそれ?おいしいの?

色々とあると思います。

僕は少し前から、Heroku + Ruby on Rails でも開発しているのですが、本番環境だけでなくステージング環境も簡単に作れることに感動しておりました。

じゃあ、Symfony2 でもPaas使えばできるんじゃない?

ということでやってみました。

(Heroku + Rails でステージング環境を作りたいって方はこちらの記事もどうぞ)

・参考:Heroku + Rails の認証付きステージング(staging)環境を構築する方法 | CodeNote.net はてなブックマーク - Heroku + Rails の認証付きステージング(staging)環境を構築する方法 | CodeNote.net
 

最初は、Heroku で最近 PHP も使えるようになったし、Herokuで作るか!と思ったけど無理でした

あまり知られていないようですが、少し前からHerokuでもPHPが動作するようになりました。

なので、使い慣れた Heroku でやってみよう!と思い Try しましたが、Symfony2 の動作環境としては以下の通り無理でした。

http://symfony2.herokuapp.com/
 

Symfony2 なんだし PHP Fog を使ってみよう!

Heroku が使えないので、他の Paas を検討することに。

Symfony2 は PHP製のフレームワークですし、お寿司。

PHP Fog を使ってみよう!

ということで、名前に惹かれて PHP Fog に決定。

他の候補は、fluxflex はてなブックマーク - fluxflexとかも日本人がやってて、かなり良さそうだったけどまた別の機会に。
 

PHP Fog + Symfony2 でステージング環境を作る手順

さて、やっと手順です。

  1. PHP Fog で新規アプリ作成
  2. Symfony2 アプリケーションを PHP Fog に Pushする
  3. PHP Fog App を Symfony2 用に設定する
  4. Symfony2 に Basic認証を設定する

ここから飛ばしていきます!
 

1. PHP Fog で新規アプリ作成

まず、PHP Fog で新しくアプリケーションを作成します。


 

次に、アプリケーション選択の画面で、「Custom App」をクリックします。

(Cake、Zend、CodeIgniterとかあるのにSymfonyがないじゃないか!)


 

”MySQLのパスワード”と”ドメインの設定”をします。

独自ドメインを使わない場合は、phpfogapp.com のサブドメインが使えます。


 

PHP Fog 上でのアプリ作成完了です。


 

最後に、SSH公開鍵の設定をします。


 

2. Symfony2 アプリケーションを PHP Fog に Pushする

PHP Fog上にアプリを作って、次はいよいよ Symfony2 アプリケーションを設置します。

まず、git clone で PHP Fog からローカルにリポジトリを複製して、初期ファイルを削除します。

$ git clone git@git01.phpfog.com:symfony2.phpfogapp.com
Cloning into symfony2.phpfogapp.com...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
 
$ cd symfony2.phpfogapp.com
$ git rm index.php

 
 
また、新しいリモート Git リポジトリにアクセスしやすいように phpfog という名前をつけて追加します。

$ git remote add phpfog git@git01.phpfog.com:symfony2.phpfogapp.com

 

次に、Symfony2 のファイル一式を設置して、app_dev.php, config.php を編集して、IPアクセス制限の部分をコメントします。

$ vim web/app_dev.php 
$ vim web/config.php

・参考:Symfony2 ドキュメント日本語版 | Symfony2日本語ドキュメント はてなブックマーク - Symfony2 ドキュメント日本語版 | Symfony2日本語ドキュメント
 

編集したら、PHP Fog 上に Symfony2 アプリを設置します。

$ git add .
$ git commit -m 'symfony2 init'
$ git push phpfog master
Counting objects: 3975, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3781/3781), done.
Writing objects: 100% (3974/3974), 3.75 MiB | 290 KiB/s, done.
Total 3974 (delta 1060), reused 0 (delta 0)
remote:  -----> Deploying to the cloud
To git@git01.phpfog.com:symfony2.phpfogapp.com
   5708d64..adab3a0  master -> master

 

Symfony2 の動作環境を /config.php から確認します。

タイムゾーンの設定を app/AppKernel.php に書きます。

ini_set('date.timezone', 'Asia/Tokyo');

PHP アクセラレータはインストールできないのでスルーします。

同様に、short_open_tag の設定も変更できないのでスルー。
 

3. PHP Fog App を Symfony2 用に設定する

PHP Fog では console からコマンドを叩くことができないので、cache:clear などのコマンドをWebアプリ経由で実行できるようにする必要があります。

$ vim web/clean_prod_cache.php
<?php
system('php ../app/console env=prod cache:clear');
system('php ../app/console env=prod cache:warm');
?>

 

また、ドキュメントルートの設定もしておきます。

これにより、http://symfony2.phpfogapp.com/web/app_dev.php/ というURLが

http://symfony2.phpfogapp.com/app_dev.php/

と web を省略できるので、やっておきましょう。
 

最後に、cache, logs ディレクトリに書込み権限を与えておきます。


 

Symfony2 に Basic認証を設定する

ステージング環境ということで、Basic認証ぐらいは設定しておきたいですよね。

security.yml にサクッと書いてしまいましょう。

$ vim app/config/security.yml
security:
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
 
    providers:
        in_memory:
            users:
                admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
 
    firewalls:
        secured_area:
            pattern:    ^/
            http_basic:
                realm: "Secured Area"
 
    access_control:
        - { path: ^/, roles: ROLE_ADMIN }

ここまでで作ったアプリは下記のリンクから ID: admin / PASS: adminpass でアクセスできます。

http://symfony2.phpfogapp.com/app_dev.php/

以上です。

MVCのどれも全く作ってないのでアレな感じはしますが、とりあえず今日はここまでということで。

「Symfony2のステージング環境ならこれがオススメ!」というのがあれば是非、Twitterやブコメでアドバイス頂ければ嬉しいです。

他の言語でも、「ステージング環境はこうしてるよ!」というアドバイスも絶賛募集中でございます。
 

ちなみに本記事は、先日開催された「第5回 Symfony2 勉強会」のLTで発表したネタを書き起こしたものです。

・参考:人生初のLTを第5回 Symfony2 勉強会でしてきました [ #Symfony2study] – バコラー日記 はてなブックマーク - 人生初のLTを第5回 Symfony2 勉強会でしてきました [ #Symfony2study] - バコラー日記
 

次回予告

さて、明日、2011/12/14(水)は@ganchiku はてなブックマーク - Shin Ohno (ganchiku) は Twitter を利用していますこと、大野さんです。

・大野さんのプロフィールページ:GANCHIKU.com はてなブックマーク - GANCHIKU.com

きっと、めっちゃためになる内容だと思うので乞うご期待です!
 

—-

参考文献

PHP Fog – Supported Frameworks はてなブックマーク - PHP Fog - Supported Frameworks

Using Symfony2 on PhpFog now. – Developly はてなブックマーク - Using Symfony2 on PhpFog now. - Developly

Assetの管理にどうやってAsseticを使うか? | Symfony2日本語ドキュメント はてなブックマーク - Assetの管理にどうやってAsseticを使うか? | Symfony2日本語ドキュメント

セキュリティ | Symfony2日本語ドキュメント はてなブックマーク - セキュリティ | Symfony2日本語ドキュメント

Symfony2の認証を色々試してみる(前編) – 覇王色を求めて はてなブックマーク - Symfony2の認証を色々試してみる(前編) - 覇王色を求めて

[資料] ”PHPFog + Symfony2でステージング環境を作ってみた” at 第5回 Symfony2 勉強会

第5回 Symfony2 勉強会の LT で「PHPFog + Symfony2でステージング環境を作ってみた」というタイトルで発表しました。

そのときの資料を公開します。良ければご覧下さい。

当日の詳しい様子は、プライベートブログをご覧下さい。

人生初のLTを第5回 Symfony2 勉強会でしてきました [ #Symfony2study] – バコラー日記

以上です。

[Doctrine] SQLを直接実行する方法 [Symfony1.4]

Symfony1.4にて、SQLを直接実行する方法を調べたのでメモ。

以下の記事を参考にしました。

・参考:DoctrineでSQLを直接実行する – ゆっくり*ゆっくり

以上です。

[Doctrine] サブクエリ(副問合せ)を使う方法 [Symfony1.4]

Symfony1.4にて、Doctrineでサブクエリ(副問合せ)を使う方法を調べたのでメモ。

Doctrineでサブクエリを使う : アシアルブログ

The symfony Cookbook | データをDoctrineで読み取る | symfony | Web PHP Framework

なるほど、createSubquery()を使えばいいんですね。

MySQLのサブクエリについてはこちら。

MySQL :: MySQL 5.1 リファレンスマニュアル :: 12.2.8 サブクエリ構文

以上です。

[Symfony1.4] 認証(authentication)と承認(authorization)のチェックは security.yml で設定する

Symfony1.4にて、ログイン認証していないユーザは特定のアクションを実行できないような処理をするのに、preExecute に認証チェックをしていました。

認証チェックが必要なモジュールのアクションファイルに全てに下記のような preExecute メソッドを記述していたのですが、認証・承認の処理はsecurity.ymlで設定を変更すれば一括でできるみたいです…。

/**
 * アクション実行前にログイン認証が通っているか確認
 * 認証が通っていない場合、ログインページにリダイレクト
 **/
public function preExecute() {
	if (!$this->getUser()->isAuthenticated()) {
		$this->redirect('@user_login');
	}
}

認証・承認の処理の設定ですが以下のように、security.yml を変更します。

■ /project/apps/frontend/config/security.yml

# You can find more information about this file on the symfony website:
# http://www.symfony-project.org/reference/1_4/en/08-Security
 
#default:
#  is_secure: false

all:
  is_secure:   true
  credentials: login

security.yml を修正後、忘れずに symfony cc します。

これでウェブサイトにアクセスすると認証していない場合、ログイン処理のページにリダイレクトされます。

ログイン処理に対応するモジュールとアクションを settings.yml に書いていない場合、デフォルトが ‘action’ => ‘login’, ‘module’ => ‘default’ となっているみたいで500エラーが返ってきました。

500 | Internal Server Error | sfConfigurationException
Unable to find a matching route to generate url for params “array ( ‘action’ => ‘login’, ‘module’ => ‘default’,)”.

ログイン処理に対応するモジュール、アクションの設定は以下のように書きます。

(この場合、UserLoginモジュールのLoginアクションにログイン処理をさせています。)

■ /project/apps/frontend/config/settings.yml (一部のみ抜粋)

all:
  .actions:
    login_module:  UserLogin
    login_action:   Login

これで認証前にログインページ以外のページにアクセスしても、ログイン処理の画面が表示されるようになりました。

ログイン処理はこれで大丈夫なのですが、これでは新規ユーザ登録のページにアクセスした場合にもログイン処理のページが表示されてしまいます。

これは使えないので、新規ユーザ登録の処理をしているモジュールの認証チェックを外してやります。

モジュール以下のディレクトリに新たに /config/security.yml を作成します。

■ /project/apps/frontend/modules/UserRegister/config/security.yml

all:
  is_secure:   false

また、モジュール内の特定のアクションに対して認証チェックをする、しないという切り分けを設定することもできます。

例えば、NewアクションとCompleteアクションは認証チェックをしないで、Confirmアクションには認証チェックをするという場合は以下のように書きます。

new:
  is_secure:   false
confirm:
  is_secure:   true
complete:
  is_secure:   false

security.yml 、settings.yml を編集後は、symfony cc をするのをお忘れなく。
 

以上です。
 

【参考】

The symfony Reference Book | security.yml 設定ファイル | symfony | Web PHP Framework

security.yml 設定ファイル | 日本Symfonyユーザー会

settings.yml 設定ファイル | 日本Symfonyユーザー会

symfony book 日本語ドキュメント ユーザー証明の管理方法

[Symfony1.4] PostValidatorで個別のフィールドにバリデーションエラーを設定する方法

Symfony1.4にて、PostValidatorで個別のフィールドにバリデーションエラーを設定する方法を調べたのでメモ。

・参考:postValidatorから個別のフィールドにエラーを設定 – ゆっくり*ゆっくり はてなブックマーク - postValidatorから個別のフィールドにエラーを設定 - ゆっくり*ゆっくり

最初は、単純に sfValidatorError を使って、バリデーションエラーメッセージを表示させていたのですが、この書き方だとGlobalErrorになります。

// ログインIDの重複チェックをするバリデータ
class ValidatorSameLoginId extends sfValidatorBase{
	protected function doClean($value){
		// DBから同じログインIDのレコードを取得
		$user = UserTable::getInstance()->getOneByLoginId($value['login_id']);
		// 同じログインIDのレコードが既に存在する場合、バリデーションエラー
		if($user != false){
			throw new sfValidatorError($this, '同じログインIDが既に登録されています', array('value' => $value));
		}
		return $value;
	}
}

これを単一のフィールドに対するエラーであるNamedErrorにするには、

if($user != false){
	throw new sfValidatorError($this, '同じログインIDが既に登録されています', array('value' => $value));
}

の部分を、sfValidatorErrorSchema を使って以下のように書き換えると、個別のフィールドにバリデーションエラーを表示させることができます。

symfony API » sfValidatorErrorSchema Class | symfony | Web PHP Framework はてなブックマーク - symfony API » sfValidatorErrorSchema Class | symfony | Web PHP Framework

class ValidatorSameLoginId extends sfValidatorBase{
	protected function doClean($value){
		// DBから同じログインIDのレコードを取得
		$user = UserTable::getInstance()->getOneByLoginId($value['login_id']);
		// 同じログインIDのレコードが既に存在する場合、バリデーションエラー
		if($user != false){
			throw new sfValidatorErrorSchema($this, array(
				'login_id' => new sfValidatorError($this, '同じログインIDが既に登録されています'),
			));
		}
		return $value;
	}
}

以上です。

[Symfony1.4] メール配信処理の実装

Symfony1.4にて、メール配信処理を実装しました。

参考にした公式サイトのリンクをメモ。

Practical symfony | 16日目: メーラー | symfony | Web PHP Framework

The More with symfony book | メール | symfony | Web PHP Framework

A Gentle Introduction to symfony | 第11章 – Eメール | symfony | Web PHP Framework

実用的な「クラスとしてメールメッセージを使う」を特に参考にしました。

クラスとしてメールメッセージを使う | A Gentle Introduction to symfony | 第11章 – Eメール | symfony | Web PHP Framework

以上です。

[Symfony1.4] 同じテーブルのカラムへの複数リレーションを持たせる方法

Symfony1.4にて、schema.yml を作成しているときに、同じテーブルのカラムへの複数リレーションを持たせるのに苦労したのでメモ。

本の情報を登録したユーザと変更したユーザの情報を持つために、registry_user_id と edit_user_id というレコードを Book テーブルに持たせています。

それぞれ、User テーブルのid とリレーションを持たせたいのですが、下記のように書くと、後ろの edit_user_id しかリレーションを持てません。

Book:
  actAs:
    Timestampable: ~
    Sluggable: ~
  columns:
    .
    .
    registry_user_id:
      type:             integer
      notnull:          true
    edit_user_id:
      type:             integer
    .
    .
  relations:
    User:
      onDelete:         CASCADE
      local:            registry_user_id
      type:             one
      alias:            RegistryUser
      foreign:          id
      foreignType:      one
    User:
      onDelete:         CASCADE
      local:            edit_user_id
      type:             one
      alias:            EditUser
      foreign:          id
      foreignType:      one

これを下記のように、クラス名を直接指定するのではなく、それぞれに名前を持たせて class: User と指定すればOKです。

    RegistryUser:
      onDelete:         CASCADE
      class:            User
      local:            registry_user_id
      type:             one
      foreign:          id
      foreignType:      one
    EditUser:
      onDelete:         CASCADE
      class:            User
      local:            edit_user_id
      type:             one
      foreign:          id
      foreignType:      one

以上です。

[Symfony1.4] テンプレートの変更:setTemplate

Symfony1.4にて、テンプレートの変更について調べたのでメモ。テンプレートの変更には、setTemplateメソッドを使います。

■ テンプレートファイルのパスを直接指定する方法

$this->setTemplate('テンプレートファイルの絶対パス、または、相対パス');

■ アクションに対応するテンプレートを指定する方法

$this->setTemplate('Edit');

この場合、Editアクションに対応するテンプレートを呼び出しています。

■ return sfView::SUCCESS

アクションの処理が全て終わったら、何も書かれていない場合、sfView::SUCCESS がreturnされる。

他にも、sfView::NONE, sfView::ERROR などがある。

■ テンプレートについて調べるときに読む記事。

(公式)

A Gentle Introduction to symfony | 第6章 – コントローラーレイヤーの内側 | symfony | Web PHP Framework

Practical symfony | 14日目: フィード | symfony | Web PHP Framework
 

(ブログ記事など)

例外発生時のテンプレートの変更 – ゆっくり*ゆっくり

symfonyでsymfuldaze

WEBアプリケーション研究室 開発ノート [symfony] 特定のテンプレートを強制的に表示