ECWorks Blog

ECWorks Blog

CakePHPを中心としたサイト開発情報をメインに公開。新しもの好きなので時々製品レポートなんかも。

【CakePHP】CakeFestで発表された「Media Plugin for CakePHP」のスライドを翻訳してみました

cake-logoyandodさんCake Festのレポートの中に興味深いセッションが紹介されていました。
「Media Plugin for CakePHP」というものなのですが、これはこれからやろうとしていた制作物にまさに搭載しようとしていた機能で、作るのが面倒なのでどうしようかと考えていたところでした!

で、とりあえずソースを落としてきたのですが、それと一緒にセッション中で使われた(と思われる)スライド(PDF)も公開されていましたので、超ダメ翻訳をしてみました。変な翻訳が間違いなくあると思いますが、その辺ご容赦ください(^^;;;。

————————————————————

CakePHP メディア・プラグイン

Marius Wilms (David Persson)

2009/7/12

————————————————–
【イントロダクション】
————————————————–

自己紹介

■Braunschweig芸術大学の学生です
■PHP歴は8年です
■CakePHP歴は2年半です
■3月から、CakePHPのコアデベロッパーをしています

—————————————-

このトークは…

■アップロードファイルのハンドリング
■異なったバージョンのファイル生成
■埋め込みのためのマークアップの作成
■いくつかの上級向けの使い方

—————————————-

このプラグインは?

23通りの、ファイルの「転送」「操作」「埋め込み」を可能にするCakePHPプラグイン。

■なぜ?
■安定版:0.50 / 開発版 : 0.60alpha
■CakePHP 1.2.x.x とPHP5.2以上に対応
■ソース : https://github.com/davidpersson/media/tree
■ドキュメント : http://wiki.github.com/davidpersson/media

—————————————-

セットアップ

最新版の一式を入手

git clone git ://github.com/davidpersson/media.git app/plugins/media

「app/config/bootstrap.php」にてコンフィグレーションの読み込み


require APP . ’plugins/media/config/core.php’;

ディレクトリの初期化

cake/console/cake media init
chmod -R a+rwX app/webroot/media/{transfer,filter}

————————————————–
【転送】
————————————————–

導入

■沢山のコンポーネント・ビヘイビア・ライブラリ
■正しく処理がされなかったら:潜在的なセキュリティホール
■(他の人が)考えるよりも巧妙

HTMLフォームとアップロード

テンプレートの編集

app/views/movies/add.ctp


echo $form.>create(’Movie’, array(’type’ => ’file ’ )) ;
// ...
echo $form.>input(’file’ , array( ’type’ => ’file ’ )) ;
// ...

—————————————-

リクエスト例

POST /movies/add

Header:
Content-Type: multipart/form-data; boundary=12591
Content-Length: 32888
Body:
–12591
Content-Disposition: form-data; name=”‘_method”’
POST
–12591
Content-Disposition: form-data; name=”‘data[Movie][title]”’
Demo
–12591
Content-Disposition: form-data; name=”‘data[Movie][file]”’ ; filename=”‘clipboard . jpg”’
Content-Type: image/jpeg
… data …
–12591–
200 OK

—————————————-

データのリザルト

MoviesController::$data


Array
(
[Movie] => Array
(
[ title ] => Demo
[ file ] => Array
(
[name] => clipboard.jpg
[type] => image/jpeg
[tmp_name] => /private/var/tmp/php4zN7BY
[ error ] => 0
[ size ] => 32405
)
)
)

—————————————-

バリデーション

(下記を)信用するべきではない

■元のファイル名(変な文字列)
■元のファイル拡張子
■送信MIMEタイプ

—————————————-

実行可能ファイルのアップロード : リクエスト

POST /movies/add

Header:
Content-Type: multipart/form.data; boundary=cAkePhPrUlEz
Content-Length: 32888
Body:
–cAkePhPrUlEz
Content-Disposition: form-data; name=”‘_method”’
POST
–cAkePhPrUlEz
Content-Disposition: form-data; name=”‘data[Movie][title]”’
Fake
–cAkePhPrUlEz
Content-Disposition: form-data; name=”‘data[Movie][file]”’ ; filename=”‘ex.php”’
Content-Type: image/jpeg
<?php echo “‘Hello PHP.”’ ?>
–cAkePhPrUlEz–
200 OK

—————————————-

実行可能ファイルのアップロード : 結果データ

MoviesController::$data


Array
(
[Movie] => Array
(
[ title ] => Fake
[ file ] => Array
(
[name] => ex.php
[type] => image/jpeg
[tmp_name] => /private/var/tmp/phpn4BPKr
[ error ] => 0
[ size ] => 26
)
)
)

—————————————-

レッスンで学んだこと

■送信データを信じるな。バリデート!
■アップロードファイルをwebrootの外側に保存
■応答限定。言い換えれば「リサイズした画像」
■推測不可能な場所へのアップロードの作成。言い換えれば「UUIDの使用」

—————————————-

転送ビヘイビア

私に何をしてくれる?

■いくつもの種類のアップロードを処理
■HTTP POST
■HTTP経由のリモートファイル
■ローカルファイル
■転送のバリデート(8つの新しいバリデーションルール)

—————————————-

使い方

モデルの編集

app/models/movie.php


class Movie extends AppModel {
var $actsAs = array(’Media.Transfer’ ) ;
}

—————————————-

転送ディレクトリの再設置

設定のアップデート

app/config/bootstrap.php


define( ’MEDIA_TRANSFER’, APP . ’transfer’ . DS);
define( ’MEDIA_TRANSFER_URL’, false);
require APP . ’plugins/media/config/core.php’;

ディレクトリの再初期化

cake/console/cake media init
chmod -R a+rwX app/transfer

—————————————-

バリデーション

種類
■location
■size
■pixels
■extension
■MIME type
■あと3つ(それほど興味深くないもの)…

—————————————-

ルールの追加

app/models/movie.php


class Movie extends AppModel {
var $actsAs = array(’Media.Transfer’ ) ;
var $validate = array(
’ file ’ => array(
’mimeType’ => array(
’rule ’ => array(’checkMimeType’, false, array( ’image/jpeg’, ’image/png’))
) ,
’size ’ => array(
’rule ’ => array(’checkSize’ , ’5M’)
)
)) ;
}

—————————————-

Reloca Transfer デモ

(省略)

————————————————–
【バージョン生成】
————————————————–

導入

■共通タスク
■一般的なインターフェースの無い複数ライブラリを必要とする
■セキュアな転送ファイルの手助けをする(言い換えれば コメントタグの除去)

—————————————-

メディアビヘイビア

何をしてくれる?

■改作ファイルの作成
■見透かしたファイルメタデータの回収(カバーできない)
■データベースレコードを用いてファイルの組(後ほど)

—————————————-

使い方

ビヘイビアの追加(連結)

app/models/movie.php


class Movie extends AppModel {
var $actsAs = array(
’Media.Transfer’ ,
’Media.Media’
) ;
// ...
}

—————————————-

デフォルトフィルター設定の上書き

app/config/bootstrap.php


define( ’MEDIA_TRANSFER’, APP . ’transfer’ . DS);
define( ’MEDIA_TRANSFER_URL’, false);
require APP . ’plugins ’ . DS . ’media’ . DS . ’ config ’ . DS . ’ core .php’;
Configure :: write ( ’Media. filter .image’, array(
’s ’ => array(’convert’ => ’image/png’, ’fitCrop ’ => array(100, 100)),
’m’ => array(’convert’ => ’image/png’, ’ fit ’ => array(300, 300)),
)) ;
Configure :: write ( ’Media. filter . video ’ , array(
’s ’ => array(’convert’ => ’image/png’, ’fitCrop ’ => array(100, 100)),
’m’ => array(’convert’ => ’video/ogg’, ’ fit ’ => array(300, 300)),
)) ;

—————————————-

媒体クラス

単一の媒体ファイルの提供インスタンス

■Manipulation
■Information

有効なアダプター

■Gd
■Imagick (ネイティブ & シェル)
■Ffmpeg (ネイティブ)
■GetId3
■PearMp3 & -Text

他のアダプターを提案してください!

—————————————-

Manipulation

…高機能です

なぜ?

■同期(アップロードに)
■非同期
■混合

可能な特徴

■バージョン
■メディアタイプ
■ファイルサイズ

—————————————-

更に他のコールバック:beforeMake

■いつ生成したものかのバージョン入手のコントロール
■代理世代の利用。言い換えればメッセージキュー
■カスタムManipulationメソッドの利用

—————————————-

モデルの更新

app/models/movie.php


class Movie extends AppModel {
// ...
function beforeMake( $file , $process) {
extract($process) ;
if ( $version == ’m’) {
return ClassRegistry :: init ( ’Queue.Job’)->put(compact(’file’, ’process ’ )) ;
}
}
}

戻り値
true: ハンドル済み, バージョンは既に作られている
false or null: 未ハンドル, ビヘイビアがバージョンを作りました

————————————————–
【マークアップ】
————————————————–

導入

■複数のメディアタイプ
■似通ったニーズの異なったマークアップ
■長いパス

—————————————-

何をしてくれる?

■簡単な埋め込みとリンク用の統合されたインターフェース
■部分、あるいは絶対パス
■転送ディレクトリの保護を守る

—————————————-

部分パスのサポート

■全てのヘルパーメソッドのための仕組み
■ダイナミックな拡張

css/cake.generic    /full/path/to/static/css/cake.generic.css
s/img/logo            /full/path/to/filter/s/static/img/logo.png
transfer/img/cern    /full/path/to/transfer/img/cern.jpg
m/transfer/img/cern    /full/path/to/filter/m/transfer/img/cern.png

—————————————-

収集マークアップの作成

ヘルパーを追加


class MoviesController extends AppController {
var $helpers = array(’Media.Medium’);
// ...
}

—————————————-

テンプレートの編集

app/views/movies/view.ctp


<h2>Movie</h2>
<dl>
<dt>Id</dt>
<dd><?php echo $movie[’Movie’][’id’]; ?></dd>
<dt>Title</dt>
<dd><?php echo $movie[’Movie’][’title’ ]; ?></dd>
<dt>File</dt>
<dd><?php echo $medium->file($movie[’Movie’]); ?></dd>
<dt>Preview</dt>
<dd><?php echo $medium->embed($medium.>file(’filter/s’, $movie[’Movie’])); ?></dd>
</dl>

————————————————–
【拡張】
————————————————–

導入

全てのことが一緒にやってきます

—————————————-

添付モデル

何を与えてくれる?

■添付ファイルのための中央場所
■データベースレコードを用いてファイルの組
■バリデーションルールを既に用意
■他の(複数)モデルが結合できる(多型)

—————————————-

使い方

モデルを供給

app/plugins/media/models/attachment.php


class Attachment extends AppModel {
var $actsAs = array(
// ...
’Media.Transfer’ => array(
’ trustClient ’ => false,
’ baseDirectory ’ => MEDIA_TRANSFER,
’ destinationFile ’ => ’:Medium.short::DS::Source.basename:’,
’ createDirectory ’ => true,
) ,
’Media.Media’ => array(
’metadataLevel’ => 2,
’makeVersions’ => true,
’ filterDirectory ’ => MEDIA_FILTER,
) ,
) ;
// ...
}

cake schema run create -path app/plugins/media/config/sql/ -name Media

—————————————-

結合(アソシエーション)

app/models/movie.php


class Movie extends AppModel {
var $hasMany = array(
’Attachment’ => array(
’className’ => ’Media.Attachment’,
’ foreignKey’ => ’foreign_key’,
’ conditions ’ => array(’model’ => ’Movie’),
’dependent’ => true,
)) ;
}

—————————————-

コントローラ・アクションの編集

app/controllers/movies_controller.php


class MoviesController extends AppController {
// ...
function add() {
if (!empty($this->data)) {
$this.>Movie->create();
if ( $this->Movie->saveAll($this->data, array(’validate’ => ’first’))) {
$this->flash(’Movie saved.’, array( ’ action ’=>’index’));
// ...
}

—————————————-

添付エレメント

何?

■HTMLオンリーのソリューション
■ファイルの添付と取り外しのためのフォームフィールド
■あなた独自のソリューションを構築するためのプロトタイプ(もっと言えばflashベース)
■ヘルパーの内部構造を利用

—————————————-

使い方

テンプレートの編集

app/views/movies/add.ctp


echo $form->create(’Movie’, array(’type’ => ’file ’ )) ;
// ...
echo $this->element(’attachments’, array(’plugin ’ => ’media’));
// ...

—————————————-

拡張デモ

(省略)

————————————————–
【終わり】
————————————————–

将来

■新しいCakePHPのリリースについて行く
■安定版にする
■いくつかの新しい特徴

—————————————-

これで終わりです、みなさん。

ご質問は?

————————————————————

実際に動かしていないのでよく分からないのですが、「version」というのはソースコードで言う世代管理みたいなものというよりは、画像サイズの大中小等、1要素中の複数の異なるメディアを管理できるような仕組みにも感じます(解説中に「m」「s」と書かれているので)。gdとかが出てくるので1ファイルのフォーム入力で勝手に生成するような機能であれば、まさにやりたいことが出来そう!
とりあえずテストがてら組み込んでみて、簡単に動くようであれば是非本番にも組み込みたいと思います。ちょっと忙しいのでレポートは詳細に出来ないかもしれませんが、ご紹介できたら、ということで。

現地にいるcakephperさんと少しSkypeしましたが、う~ん…お金と時間があったら行きたかったなぁ。とっても楽しそうでした。次回は是非チャレンジしたいと思います。


Tagged as: , , ,

Comments are closed.