Amazon Linux – PostgreSQL・Nginx・FuelPHP


インストール

参考:
Amazon Linux AMIにpostgresqlをインストールする
チュートリアル: Amazon Linux への LAMP ウェブサーバーのインストール

yumをアップデートして、phpとgitとvimとnginx入れた。アパッチとMySQLも入れた。

sudo yum update -y
$ sudo yum install -y httpd24 php56 mysql55-server php56-mysqlnd
$ sudo yum install -y git
$ sudo yum install -y vim
$ sudo yum install -y nginx

postgresql入れた。

$ sudo yum install -y postgresql
$ sudo yum install -y postgresql-server postgresql-libs php-pgsql

エラーでた

$ sudo yum install -y postgresql-server postgresql-libs php-pgsql                                                                   
読み込んだプラグイン:priorities, update-motd, upgrade-helper
パッケージ postgresql92-libs-9.2.15-1.57.amzn1.x86_64 はインストール済みか最新バージョンです
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ php-pgsql.x86_64 0:5.3.29-1.8.amzn1 を インストール
--> 依存性の処理をしています: php-pdo(x86-64) = 5.3.29-1.8.amzn1 のパッケージ: php-pgsql-5.3.29-1.8.amzn1.x86_64
---> パッケージ postgresql92-server-compat.x86_64 0:9.2.15-1.57.amzn1 を インストール
--> 依存性の処理をしています: postgresql92-server(x86-64) = 9.2.15-1.57.amzn1 のパッケージ: postgresql92-server-compat-9.2.15-1.57.amzn1.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ php-pdo.x86_64 0:5.3.29-1.8.amzn1 を インストール
--> 依存性の処理をしています: php-common(x86-64) = 5.3.29-1.8.amzn1 のパッケージ: php-pdo-5.3.29-1.8.amzn1.x86_64
---> パッケージ postgresql92-server.x86_64 0:9.2.15-1.57.amzn1 を インストール
--> トランザクションの確認を実行しています。
---> パッケージ php-common.x86_64 0:5.3.29-1.8.amzn1 を インストール
--> 衝突を処理しています: php56-common-5.6.19-1.123.amzn1.x86_64 は php-common < 5.5.22-1.98 と衝突しています
--> 衝突を処理しています: php56-pdo-5.6.19-1.123.amzn1.x86_64 は php-pdo < 5.5.22-1.98 と衝突しています
--> 依存性解決を終了しました。
エラー: php56-pdo conflicts with php-pdo-5.3.29-1.8.amzn1.x86_64
エラー: php56-common conflicts with php-common-5.3.29-1.8.amzn1.x86_64
 問題を回避するために --skip-broken を用いることができます。
 これらを試行できます: rpm -Va --nofiles --nodigest

php56と指定しないといけないっぽい。

$ sudo yum install -y postgresql-server postgresql-libs php56-pgsql

これで必要なの入った。

postgreSQLの設定する

postgresユーザにパスワード設定

$ sudo passwd postgres

postgresユーザに切り替える

$ su - postgres

基本データベース生成とサービス開始

$ initdb --encoding=UTF8 --no-locale
$ pg_ctl start
$ exit
$ chkconfig postgresql on

データベース作成する

$ psql -U posgres
postgres=# create database hoge;

NginxでPHP使えるようにする

参考:nginxでphpを使う(CentOS6.5)

php-fpmをインストールする

$ sudo yum install -y php56-fpm

php-fpmの設定をする

下記のwww.confのuserとかgroupがapacheになっているので、nginxに変更します。

$ sudo vim /etc/php-fpm.d/www.conf

NginxでFuelphpが動くようにする

下記、nginx.confを修正していく。

$ sudo vim /etc/nginx/nginx.conf

下記箇所を、/usr/share/nginx/hoge/publicとかにする。

root         /usr/share/nginx/html

参考:http://fuelphp.jp/docs/1.8/installation/instructions.html
下記のように変更する。

location / {
    index index.php;
    try_files $uri $uri/ /index.php$is_args$args;
}

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param FUEL_ENV "production";
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

nginxとphp-fpmを再起動する

$ sudo service php-fpm restart
$ sudo service nginx restart

FuelPHPをcloneする

FuelPHPはローカルで作ってるやつをcloneする。

$ cd /usr/share/nginx/
$ sudo git clone https://hogehoge.git

FuelPHPのcomposer installする

$ cd /usr/share/nginx/hoge
$ ./composer.phar install

phpPgAdminインストール

参考:phpPgAdminのインストール – CentOS6.5(Vagrant)

とりあえず、ローカルで上記サイトに記載のURLから、ダウンロードして、展開して、gitリポジトリに追加して、pullした。常時使える必要はなかったので、nginxのrootを変更してちょっとだけ使った。

FFmpeg – mac・PHPで使う

macのバージョンは、10.11.4。El Capitan。

参考: Mac OS XでFFmpegのインストールとWebM動画の作り方

brewでインストールした。ここまで長いオプションは必要ないのかもしれない。

brew install automake celt faac fdk-aac git lame \
libass libtool libvorbis libvpx \
libvo-aacenc opencore-amr openjpeg \
opus sdl schroedinger shtool speex texi2html \
theora wget x264 xvid yasm

FFmpegとは?

FFmpeg(エフエフエムペグ)は動画と音声を変換することのできるUNIX系OS生まれのフリーソフトウェアであり、libavcodec(動画/音声のコーデックライブラリ)、libavformat(動画/音声のコンテナライブラリ)、libswscale(色空間・サイズ変換ライブラリ)、libavfilter(動画のフィルタリングライブラリ)などを含む。ライセンスはコンパイル時のオプションによりLGPLかGPLに決定される。コマンドラインから使用することができる。対応コーデックが多く、多彩なオプションを使用可能なため、幅広く利用されている。

引用:FFmpeg

PHP-FFMpegを使う

最初ffmpeg-phpを使おうとしたけど、エラーでインストールできなかった。2012年で開発終了しているらしい。

PHPでffmpegを利用するには、PHP-FFMpegがおすすめです。Composer対応のモダンなPHP実装なので、PHP5.3以上のコードベースではとても扱いやすいです。

ffmpeg-phpというPHP拡張もありますが、2012年で開発が止まっているのであまりおすすめしません。

引用:FFmpegによる動画エンコードの基本

PHP-FFMpegを使ってみる。

PHP-FFMpeg

上記のREADMEに詳しく書いてあった。composerに追加してupdateしたら下記のような感じで使えるようになる。

composer.json

{
    "require": {
        "php-ffmpeg/php-ffmpeg": "~0.5"
    }
}

fuelphpのコントローラ内でテスト。保存されている動画を取得して、jpgのサムネイル画像を作成して保存している。その後、fuelphpのImageクラスでリサイズして保存した。

//ffmpegテスト
$ffmpeg = FFMpeg\FFMpeg::create(array(
	'ffprobe.binaries' => '/usr/local/bin/ffprobe',
	'ffmpeg.binaries' => '/usr/local/bin/ffmpeg'
));
$video = $ffmpeg->open(DOCROOT.'assets/movie/'.$movie['file_name']);
//		$video
//			->filters()
//			->resize(new FFMpeg\Coordinate\Dimension(320, 180))
//			->synchronize();
$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(15));
$img_path = DOCROOT.'assets/movie/thumb/'.$movie['id'].'.jpg';
$frame->save($img_path);

//画像のリサイズ
//ffmpegのリサイズが効かない為
Image::load($img_path)->resize(320, null, true, true)->save($img_path);

fuelphp1.8 – コアクラスのカスタマイズ

参考:http://fuelphp.jp/docs/1.8/general/extending_core.html#extend_and_replace

type=”file”のformに、「required」というバリデーションルールを適用しても、うまく動作しない。ファイルをアップロードしても、ファイルがアップロードしたことにならない。だから、requiredというルールを適用するのをやめたんだけど、そうすると、form.phpで設定できる、required_markの表示がなくなるので、それも嫌だ。required_markというのは、requiredルールを設定してあるFieldをview等でbuildした時に、勝手に必須項目であることを示す文字列等を表示してくるものであります。なので、Fieldをbuild関数をいじって、required_markを表示する条件を変更してみようと思った。

fuel/core/classes/fieldset/field.phpの591行目に、下記があります。

$required_mark = $this->get_attribute('required', null) ? $form->get_config('required_mark', null) : null;

get_attributeで「required」があれば、form.phpのrequired_markに設定している文字列を返しています。なので、get_attributeに渡すものを「required」だけではなく、array(‘required’, ‘required_upload’)にしてみます。でも、fuel/core内を勝手にいじってはダメなので、下記のようにします。

コアクラスを継承したクラスを作成する

fuel/app/classes/fieldset/field.phpを下記のように作成する。

<?php

/**
 * Fieldset Class
 *
 * カスタムバリデーションルールのrequired_uploadが設定されている場合に、
 * required_markが表示されるようにFieldset_Fieldクラスを修正
 */
class Fieldset_Field extends \Fuel\Core\Fieldset_Field
{

	protected function template($build_field)
	{
		$form = $this->fieldset()->form();

		//下記を修正
		//$required_mark = $this->get_attribute('required', null) ? $form->get_config('required_mark', null) : null;
		$required_mark = $this->get_attribute(array('required', 'required_upload'), null) ? $form->get_config('required_mark', null) : null;
		$label = $this->label ? $form->label($this->label, null, array('id' => 'label_'.$this->name, 'for' => $this->get_attribute('id', null), 'class' => $form->get_config('label_class', null))) : '';
		$error_template = $form->get_config('error_template', '');
		$error_msg = ($form->get_config('inline_errors') && $this->error()) ? str_replace('{error_msg}', $this->error(), $error_template) : '';
		$error_class = $this->error() ? $form->get_config('error_class') : '';

		if (is_array($build_field))
		{
			$label = $this->label ? str_replace('{label}', $this->label, $form->get_config('group_label', '<span>{label}</span>')) : '';
			$template = $this->template ?: $form->get_config('multi_field_template', "\t\t<tr>\n\t\t\t<td class=\"{error_class}\">{group_label}{required}</td>\n\t\t\t<td class=\"{error_class}\">{fields}\n\t\t\t\t{field} {label}<br />\n{fields}\t\t\t{error_msg}\n\t\t\t</td>\n\t\t</tr>\n");
			if ($template && preg_match('#\{fields\}(.*)\{fields\}#Dus', $template, $match) > 0)
			{
				$build_fields = '';
				foreach ($build_field as $lbl => $bf)
				{
					$bf_temp = str_replace('{label}', $lbl, $match[1]);
					$bf_temp = str_replace('{required}', $required_mark, $bf_temp);
					$bf_temp = str_replace('{field}', $bf, $bf_temp);
					$build_fields .= $bf_temp;
				}

				$template = str_replace($match[0], '{fields}', $template);
				$template = str_replace(array('{group_label}', '{required}', '{fields}', '{error_msg}', '{error_class}', '{description}'), array($label, $required_mark, $build_fields, $error_msg, $error_class, $this->description), $template);

				return $template;
			}

			// still here? wasn't a multi field template available, try the normal one with imploded $build_field
			$build_field = implode(' ', $build_field);
		}

		// determine the field_id, which allows us to identify the field for CSS purposes
		$field_id = 'col_'.$this->name;
		if ($parent = $this->fieldset()->parent())
		{
			$parent->get_tabular_form() and $field_id = $parent->get_tabular_form().'_col_'.$this->basename;
		}

		$template = $this->template ?: $form->get_config('field_template', "\t\t<tr>\n\t\t\t<td class=\"{error_class}\">{label}{required}</td>\n\t\t\t<td class=\"{error_class}\">{field} {description} {error_msg}</td>\n\t\t</tr>\n");
		$template = str_replace(array('{label}', '{required}', '{field}', '{error_msg}', '{error_class}', '{description}', '{field_id}'),
			array($label, $required_mark, $build_field, $error_msg, $error_class, $this->description, $field_id),
			$template);

		return $template;
	}

}

これを、fuel/app/bootstrap.phpを設定して、読み込めるようにします。

bootstrap.phpの設定

\Autoloader::add_classes(array(
	// Add classes you want to override here
	// Example: 'View' => APPPATH.'classes/view.php',
	'Fieldset_Field' => APPPATH.'classes/fieldset/field.php',
));

fuelphp 1.8 – カスタムバリデーション

どうも、Uploadをすると、Uploadクラスのバリデーションを使うことになりますが、これとfieldsetのValidationクラスとの連動がいまいちうまくできない。Fieldsetはform.phpの、inline_errorsをtrueにすると勝手にエラーを表示してくれるが、このエラーに自動的にuploadのエラーも連動するようにしたい。他にやり方があるかもしれないが、Upload関連のエラーをValidationのカスタマイズルールとして作成することで、実現してみる。

モデルでFieldsetを作成する

fileというフィールドに、uploadというルールを設定している。これはデフォルトではないので、カスタマイズルールになります。引数は、フィールド名。あとでこのuploadというルールを作成します。

public static function fieldset()
{
	//大カテゴリー取得
	$big_categories = Model_Category::get_big_category_list();

	$fset = Fieldset::forge();
	$fset->add('file', '動画ファイル', array('type' => 'file'))->add_rule('upload', 'file');
	$fset->add('title', 'タイトル')->add_rule('required')->add_rule('max_length', 150);
	$fset->add('description', '説明', array('type' => 'textarea'))->add_rule('required')->add_rule('max_length', 500);
	$fset->add('big_category_id', '大カテゴリー', array('type' => 'select', 'options' => $big_categories));
	$fset->add('category_id', '小カテゴリー', array('type' => 'select'))->add_rule('required');
	$fset->add('order_no', '表示順')->add_rule('required')->add_rule('numeric_between', 1, 100);
	return $fset;
}

カスタムバリデーションのクラスファイルを作成する

fuel/app/classes/model/validation/upload.phpというのを作成してみる。

<?php
class Model_Validation_Upload
{
	public static function _validation_upload($field_name)
	{
		if(Upload::is_valid())
		{
			Upload::save();
			return true;
		}
		else
		{
			$error = Upload::get_errors($field_name);
			if(!empty($error['errors'][0]['message']))
			{
				Validation::active()->set_message('upload', $error['errors'][0]['message']);
			}else{
				Validation::active()->set_message('upload', 'ファイルのアップロードでエラーが発生しました');
			}
			return false;
		}
	}
}

コントローラを作成する

フィールドセットを作って、Upload:processを走らせて、フィールドセットからバリデーションを取りだして、バリデーションにuploadルールを読めるように設定する。

public function action_add()
{
	//フィールドセットの取得
	$fset = Model_Movie::fieldset();

	if (Input::post()){
		Upload::process();

		// バリデーションチェック
		$val = $fset->validation();
		$val->add_callable('Model_Validation_Upload');

		if( $val->run() ){
			//動画情報をデータベースに登録
			$file = Upload::get_files( 0 );
			if( Model_Movie::add( Input::post(), $file ) ){
				Session::set_flash( 'msg', '動画を登録しました。' );
				return Response::redirect( 'admin/movies/' );
			}else{
				//保存ファイルの削除
				File::delete( DOCROOT . 'assets/movie/' . $file[ 'saved_as' ] );
			}
		}

		//小カテゴリのoptionsの取得・設定
		$big_id = Input::post( 'big_category_id' );
		$fset   = Model_Category::set_small_cat_options( $big_id, $fset );

		$fset->repopulate();

		Session::set_flash( 'msg', '動画が登録できませんでした。恐れ入りますが、再度お試しください。' );
	}

	//set view
	$this->template->content = View::forge('admin/movies/add');
	$this->template->content->set_safe('fset', $fset);
}

View

uploadは、enctypeの表示が必要。Fieldsetのフィールドをbuildしてるだけ。bootstrapを使っているので、set_attributeでform-controlクラスを設定している。

<?php echo Form::open(array('enctype' => 'multipart/form-data'))?>
<?php echo $fset->field('file')->set_attribute('class', 'form-control')->build()?>
<?php echo $fset->field('title')->set_attribute('class', 'form-control')->build()?>
<?php echo $fset->field('description')->set_attribute('class', 'form-control')->build()?>
<?php echo $fset->field('big_category_id')
	->set_attribute('class', 'form-control')
	->set_attribute('onchange', 'get_small_cat("' . Uri::create('rest/admin/categories/small_cat.json') . '");')
	->build()?>
<?php echo $fset->field('category_id')->set_attribute('class', 'form-control')->build()?>
<?php echo $fset->field('order_no')->set_attribute('class', 'form-control')->build()?>
<button type="submit" class="btn btn-primary">登録</button>
<?php echo Html::anchor('admin/movies/', 'キャンセル', array('class' => 'btn btn-default'))?>
<?php echo Form::close()?>

fuelphp1.8 – Formとバリデーション

fieldsetを使うと、入力した内容を保持できるし、バリデーションチェックも簡単に行える。エラーも自動で表示できる。core/config/form.phpにformを表示する際のHTMLの設定が書いてあるので、これをシンプルにすることで、多様なデザインにもデザイナがviewの設定のみで大体対応できるようになるかなと思った。

form.phpの設定項目

引用:FuelPHPのFieldsetクラスをまとめてみた。1

項目名 説明
form_method formのmethod属性の値
form_template formを作る際のテンプレートです。{open}がformの開始、{fields}がフィールド部分、{close}がformの終了です。こちらはFormクラスで使用されます。
fieldset_template ↑のfieldset版。
field_template fieldのテンプレート。そのままですね。
multi_field_template fieldが複数だった時のテンプレート。{fields}から{fields}までが項目のループ部分。セレクトボックスはどうやってるのかは不明
error_template エラーのテンプレート。$user_form->validation()->error()メソッドで使われている模様。
required_mark {required}に対応する値を指定。
inline_errors エラーを表示するかどうか。
error_class エラー表示に使うクラス名。デフォルトではtdに指定しているのでこのクラスに対してエラーだった時のbackground-color等を指定することになる。

バリデーションエラーメッセージの日本語化

・core/lang/en/validation.phpを、app/lang/ja/にコピーして編集する。
・app/config/config.phpの「language」を「ja」に設定する。

モデルの例

/**
 * フィールドセット
 */
public static function fieldset()
{
	$fset = Fieldset::forge();
	$fset->add('name', '名前')
		->add_rule('required')
		->add_rule('max_length', 30);
	$fset->add('order_no', '並び順')
		->add_rule('required')
		->add_rule('numeric_between', 1,100);
	return $fset;
}

app/config/form.phpのfield_templateの例

'field_template' => "<div class='form-group'>{label}{required}{field}<p class='err_msg'>{error_msg}</p></div>",

コントローラの例

/**
 * 管理 - 大カテゴリー登録
 */
public function action_add_big()
{
	//フィールドセットの取得
	$fset = Model_Category::fieldset();

	if (Input::post())
	{
		// バリデーションチェック
		$val = $fset->validation();
		if ($val->run())
		{
			//カテゴリ登録
			if(Model_Category::add_big(Input::post('name'), Input::post('order_no')))
			{
				Session::set_flash('msg', '大カテゴリーを登録しました。');
				return Response::redirect('admin/categories/');
			}
		}
		$fset->repopulate();
		Session::set_flash('msg', '大カテゴリーが登録できませんでした。恐れ入りますが、再度お試しください。');
	}

	//set view
	$data['menu_tab'] = View::forge('elements/admin/categories/menu_tab', array('active' => 'big'));
	$this->template->content = View::forge('admin/categories/add_big', $data);
	$this->template->content->set_safe('fset', $fset);
}

fuelphp 1.8 – Auth – simpleauthで使うデフォルトのusersテーブル

参考:[FuelPHP] FuelPHPで作るログイン管理

CREATE TABLE `users` (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `username` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
    `password` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
    `group` INT NOT NULL DEFAULT 1 ,
    `email` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
    `last_login` VARCHAR( 25 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
    `login_hash` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
    `profile_fields` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
    `created_at` INT( 11 ) UNSIGNED NOT NULL ,
    UNIQUE (
        `username` ,
        `email`
    )
) 

fuelphp – メール送信

参考:
Email パッケージの使用方法
Fuelphp:Fuelphpで基本的なメール送信処理

コントローラーで下記を読み込むらしい。

\Package::load('email');

下記みたいな感じでとりあえずできた。日本語文字化け対策で、上記参考サイトの、■ Emailクラスの設定ファイルというところの対策をやった方がいいらしい。

public function get_index()
{
	$this->template = View::forge('public/template');

	$data = array();
	$this->template->title = 'お問い合わせ';
	$this->template->content = View::forge('public/contact/index', $data);
}

public function post_index(){
	$this->template = View::forge('public/template');
	$this->template->title = 'お問い合わせ';

	$data = Input::post();
	if(!$data || empty($data['name']) || empty($data['mail']) || empty($data['content'])){
		$data = array('error_msg' => '全項目を入力してください。');
		$this->template->content = View::forge('public/contact/index', $data);
		return;
	}

	$result = $this->send_mail($data);
	switch($result){
		case 1:
			$data = array('mail_success' => true);
			break;
		case 2:
			$data = array('error_msg' => '正しいメールアドレスを入力してください');
			break;
		case 3:
			$data = array('error_msg' => 'メールが送信できませんでした。恐れ入りますが、再度お試しください。');
			break;
	}

	$this->template->content = View::forge('public/contact/index', $data);
}

/**
 * メール送信関数(通常のお問合せ)
 */
private function send_mail($data){
	$admin_email = $this->make_mail($data, true);
	$user_email = $this->make_mail($data, false);

	try
	{
		$user_email->send();
		$admin_email->send();
		return 1;
	}
	catch(\EmailValidationFailedException $e)
	{
		// バリデーションが失敗したとき
		return 2;
	}
	catch(\EmailSendingFailedException $e)
	{
		// ドライバがメールを送信できなかったとき
		return 3;
	}
}

/**
 * メール作成関数
 */
private function make_mail($data, $admin = false){
	$admin_mail = __('site_info.admin_mail');
	$subject = __('site_info.contact_mail_subject');

	$email = \Email::forge('jis');
	$email->from($admin_mail);

	if($admin){
		$email->subject('[管理]' . $subject);
		$email->to(array(
			$admin_mail,
		));
	}else{
		$email->subject($subject);
		$email->to(array(
			$data['mail'],
		));
	}

	$body = \View::forge('public/email/contact', $data);
	$email->body(mb_convert_encoding($body, 'jis'));
	return $email;
}

fuelphp – csvインポート

下記をformat.phpにつくった。

/**
 * アップロードされたCSVファイルを配列に変換する
 * @param arrray $csv ($_FILEのデータ)
 * @return array $array
 */
static function csv_to_array($csv = null){
	if(empty($csv['file'])) return null;

	$csv_data = file_get_contents($csv['file']);
	$csv_data = mb_convert_encoding($csv_data, 'UTF-8', 'sjis-win');

	$fp = fopen('php://memory', 'r+');
	fwrite($fp, $csv_data);
	rewind($fp);
	$current_locale = setlocale(LC_ALL, '0');
	setlocale(LC_ALL, 'ja_JP.UTF-8');

	while($values = fgetcsv($fp)){
		$data[] = $values;
	}
	setlocale(LC_ALL, $current_locale);
	fclose($fp);

	return $data;
}

コントローラで、Uploadを使ってアプッロードファイルのチェックをしてから、上記関数を呼び出し、CSVデータを配列化した。

fuelphp – csv出力

参考:FuelPHPでCSVの出力

app/classes/format.php を作成

上記参考サイトどおりにやる

<?php
class Format extends Fuel\Core\Format {
	/**
	 * CSV出力をSJIS-WINで返す
	 * @access public
	 * @param mixed $data
	 * @return string csv(sjis-win)
	 */
	public function to_csv($data = null, $delimiter = null){
		$csv = parent::to_csv($data, $delimiter);
		$csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8');
		return $csv;
	}
}

app/bootstrap.php の一部を修正

上記参考サイトどおりにやる

Autoloader::add_classes(array(
	// Add classes you want to override here
	// Example: 'View' => APPPATH.'classes/view.php',
	'Validation_Error' => APPPATH.'classes/validation/error.php',
	'Format' => APPPATH . 'classes/format.php',
));

コントローラーにPDF出力アクションを追加

例えばcompanyコントローラーにaction_pdfを追加する

/**
 * 事業者情報のPDFダウンロード
 */
public function action_pdf(){
	$data = array(
		array('会社名', '郵便番号', '住所', '代表者名', 'URL'),
		array('Logicky', '123', '東京都', 'きむたく', 'http://google.com'),
		array('電通', '123', '東京都', 'つまぶききん', 'http://google.co.jp'),
	);

	$this->template = null;
	$this->response = new Response();
	$this->response->set_header('Content-Type', 'application/csv');
	$this->response->set_header('Content-Disposition', 'attachment; filename="company.csv"');
	$this->response->send(true);
	echo Format::forge($data)->to_csv();
	return;
}

fuelphp – マイグレーション

cakePHPのmigrationsプラグインはありがたいものではあるものの微妙だと思っていたのですが、あれの場合、データベースを色々いじってから、現状のschemaファイルとデータベースの現状との差分を勝手に確認してくれるというものでした。どうもfuelphpのマイグレーションというのはそういう機能はないのかなあと、今思っております。

参考:fuelPHP での Migration の使い方

カラムの追加をoilのmigrationを使って実行できます。

oil generate migration add_{カラム名}_to_{データベース名} <fieldname1>:<type1>

例えば、oil generate migration add_hoge_to_shops hoge:varcharといった感じでやります。
これにより、カラムを追加する為の新しいマイグレーションファイルが作成されます。

databaseを最新の状態にするのは、

oil r migrate

のようです。これによって作成したマイグレーションファイルの内容が、databaseに反映されます。

できたのですが、nullがNGになっておりました。nullをOKにしたり、varcharの最大文字数設定の方法とかが分かりません。

参考:
Generate
マイグレーション

まあ、migrationsファイルを直接編集すればいいのかなと思いますが、oilコマンドでもできるようです。
参考:fuelPHP での Migration の使い方 (2)

$ oil g migration create_table1 title:string[50]:null

便利でした