伊藤清徳の垂直落下式ムーンサルトプレス

PerlとかPHPとかMySQLとか...がんばっても8割だ。

Category: PHP (page 2 of 6)

Inter-MediatorをCodeigniterから使ってみる

INTER-MediatorというPHPアプリケーションフレームワークがあります。
かなり前から存在は知っていたものの、今回はじめて使ってみました。
普通に使うには、私個人としてメリットがなかったので使って来なかったのですが、
他のフレームワークと一緒に使うと便利なんじゃね?
ってことで、Codeigniterで使ってみることに。
 
え?なんでかって?seezoo cmsのコミッターだからさ!
 


そもそも、INTER-Mediatorってなによ?

 
そもそも、INTER-Mediatorってなによ?ってことなんですが、
従来のPHPやPHPフレームワークでは、
SQLやORMをつかってデータベースのレコードを呼んできて、
 

<table>
<?php foreach( $rows as $row ): ?>
<tr> <td><?php $row['field']; ?></td> </tr> <?php endforeach; ?>
</table>

 
のようなコードを書かなくてはなりませんでした。
(PHPTALをつかうともっとスッキリHTMLのポリシーに近くなりますが)
 
Inter-Mediatorの場合、PHPファイルに規定の書き方で、
呼び出すテーブル・1ページあたりのレコード数などを書き入れ、
そのファイルをjavascriptファイルとして、HTMLから呼び出すだけで、
 

<table>
<tr>
<td class="IM[テーブル名@フィールド名"></td>
</tr>
</table>

 
こんなHTMLを書けば、Javascript制御でclassで指定された
テーブル名/フィールド名のデータを表示してくれます。
また、複数レコードを呼ぶ設定にしている場合は、
テーブルの行数もレコード数分追加してくれます。


定義ファイルの中身

INTER-Mediatorの定義ファイルは
 

<?php
require_once ('INTER-Mediator/INTER-Mediator.php');
IM_Entry(
	//呼び出すレコードの定義
	array(
		array(
			'records' => 1,
			'name' => 'person',
			'key' => 'id',
		),
	),
	//オプション設定
	null,
	//DBへの接続設定
	array('db-class' => 'PDO'),
	//デバッグレベルの設定
	false
);

こんな感じです。詳しくは公式サイトのドキュメントをご覧下さい。
IM_Entry();が、HTMLのクラスセレクタを解析して、
DBのレコード/フィールドを差し込むJavascriptコードを出力してくれる
そんな仕組みになっているようです。
 


Codeignireから使うには?

 
上記の様に、INTER-Mediatorの定義ファイルは実に単純なしくみです。
この定義ファイルを出力するコントローラーをつくれば、
ページの出力がかなり簡単になるのでは?
と思ったわけです。
 
気をつけるポイントとして、
INTER-Mediatorでは、PDOでMySQLなどへの接続を行なっているので、
CodeigniterのDBドライバインスタンスをINTER-Mediatorで使うことはできません。
ただ、CodeigniterでつかっているDBの設定はそのまま引き継ぎたい。
そんなわけで、以下のようなコントローラーを作ってみました。
 

<?php
class im_require extends CI_Controller
{
	public function index()
	{
		//IMをrequire
		require FCPATH.'INTER-Mediator/INTER-Mediator.php';
		
		//データベース設定を呼び出す
		require APPPATH . 'config/database.php';
		$dsn = $db[$active_group];
		
		//第三引数
		$dbset = array();
		$dbset['db-class'] = 'PDO';
		$dbset['dsn'] = 'mysql:dbname=' . $dsn['database'] . ';host=' . $dsn['hostname'];
		$dbset['user'] = $dsn['username'];
		$dbset['password'] = $dsn['password'];
		
		
		IM_Entry(
			array(
					array(
						'records' => 1,
						'paging' => true,
						'name' => 'person'
					)
			),
			null,
			$dbset,
			0
		);
	}
}

 
DB設定ファイルを呼び出して、今アクティブなDB設定を
INTER-MediatorのPDO設定に入れているという簡単なしくみです。
 
あとは、どのテーブルを呼び出すかなどを、
GET/POSTのパラメータなどから呼び出せるようにしたり、
YAMLなどで定義できるようにしておけば、
1つのコントローラーで、複数のINTER-Mediatorの定義を作ることができるようになります。
 


INTER-Mediatorの改造

 
さて、定義ファイルを作成するコントローラーができたわけですが、
これだけでは、ちょっとまずいところがありますので、
INTER-Mediator自体の改造が少し必要です。
GenerateJSCode.phpを改造します。
68行目付近に
 

$pathToMySelf = (isset($scriptPathPrefix) ? $scriptPathPrefix : '')
. $_SERVER['SCRIPT_NAME'] . (isset($scriptPathSufix) ? $scriptPathSufix : '');

 
があります。
この状態ですと、定義ファイルの物理的なパスをJavascript中でXHRのURLとして利用してしまうので、
URIルーティングがあるCodeigniterでは、index.phpが呼ばれてしまい、
正しく動作してくれません。
 

$pathToMySelf = (isset($scriptPathPrefix) ? $scriptPathPrefix : '')

			. $_SERVER['SCRIPT_NAME'] . (isset($scriptPathSufix) ? $scriptPathSufix : '');

if(function_exists('get_instance'))
{
	$ci = get_instance();
	$pathToMySelf = (isset($scriptPathPrefix) ? $scriptPathPrefix : '')
		. '/index.php/' . $ci->uri->uri_string()
		. (isset($scriptPathSufix) ? $scriptPathSufix : '');
}

このように書き換えています。
Codeigniterからの呼び出しでない場合も踏まえて、
コントローラーインスタンスが呼べるかどうかで、振り分けをしています。
 
上記のコードでは、GETパラメーターへの考慮がされていないので、
実務レベルで使うには、そのあたりも考慮した改造が更に必要でしょう。
 


viewファイルの記述は?

viewファイルのへの記述は特に気にするような点はなく、
ここまでで作った定義作成コントローラーをjavascriptとして呼び出して、
bodyにonload="INTERMediator.construct(true);"をつければOKです。
 

<script type="text/javascript" src="http://localhost/index.php/im_require"></script>

  

<body onload="INTERMediator.construct(true);">

 
こんな感じですね。
 


seezoo cmsに入れる?

 
seezoo cmsはCodeigniterベースにできているので、
ここまでで書いたコントローラーを突っ込めばうごいてくれますし、
seezoo cmsには管理者/会員承認機能がそろっているので、
このへんもからめると面白いものができそうです。
 
また、Codeigniter自身のModel(DB)機能を使えば、
Inter-Mediartorではカバーできない複雑な処理も行うこともできますから、
「とても便利系」なライブラリやフレームワークにありがちな、
「あーここまではできないかーorz」という手詰まり感も回避することができます。
 


将来展望

実は、私今年のはじめからseezoo cmsベースで似たようなものを作ろうとしていたのですが、
仕様の練り直しなどで進んでいなかったところがあり、
一気に解決した感じです。
 
CodeigniterにはDB構造を操作するメソッドも揃っているので、
テーブル作成やインデックスの付与などを管理画面からできるようにすれば、
オンライン版FileMakerのようなものができるのでは!?
と思っています。
 
もう少しいじってみよう!
 


P.S.

INTER-Mediatorのコードを覗くと、
プロパティが

var $var = '';

のような、ちょっと古い書き方がされているところがあるようです。
この辺りは改善してもらえるとうれしいなー。

知らんうちにスパム配信サーバ扱いにならないために

オンラインCRMを開発していると、
顧客をセグメントして、メール配信なんていうことは結構行われます。
僕の場合、PHPを使って配信することが多いです。
 
数通のメールならいいですが、何百通・何千通のメールを定期送信していると、
大抵、アカウントがなくなったなどの問題で、エラーメールが返って来ます。
こういったメールアドレスに対して、繰り返しメールを送っていると、
そのうち、送信元のサーバーは「スパムメールを送っている」と判定されかねないので、
エラーが返ったメールアドレスに対しては適切に
次回以降送信しないなどの対応が必要です。
 
多くのメールマガジン送信スタンドはそういった機能をもっていますが、
自分でその機能をつくるにはどうしたらいいでしょうか。
という話です。
 
PHPでqdmail(SMTP送信)を利用して送信した場合を想定して書いていきます。


 
何も設定せずにメールを送信する場合、
エラーメールは大抵の場合、
送信メールサーバー、あるいは受信メールサーバーのどちらかのpostmasterアカウントから
「エラーが有りました」という旨のメールが返信されます。

どのメールアドレスに対してエラーがあったのかなどは、
本文中に書かれていることが多いです。
 
正規表現をつかって、本文中のメールアドレスを抜き出すなどすれば
いいかと思うかもしれませんが、
こちらのとおり(Perlの例ですが)
メールアドレスを正規表現で正しく抜き出すというのは、
非常に骨の折れる話です。
 


送信メールサーバーにPostfixが利用されているサーバーなら、
こういった問題を比較的簡単に処理してくれる機能があります。
VERPという機能です。
こちらが簡単な説明書です。
 


仕組みの概要は
 
not_exists@sample.com(送信先メアド、存在しない)
return@sample.com(エラーリターン先メアド、Return-Pathで指定)
 
という条件でメールを送った場合、

return+not_exists=sample.com@sample.com

にバウンスメール(エラーメール)が送信されます。
return@sample.comに対して
ちょうど「Gmail エイリアス」のような形式で送信をしてくれるのです。
(エラーがあったメールアドレスの「@」は「=」に変換されます)
 
この形式で送信してくれれば、
メールトリガーで何かのスクリプトを起動して
「To」をパースすれば、どのメールアドレスにエラーがあったのか、
簡単に計算出来るという仕組みです。
 
これは便利です。


qdmailでの送信の仕方はこちらを参考にしました。
ありがとうございます。

require_once('qdsmtp.php');

$param = array(
'host'=>'smtp.example.com',
'port'=> 25 ,
'from'=>'<from@example.com> XVERP',
'protocol'=>'SMTP',
);
$smtp = new QdSmtp($param);

SMTP接続の際に設定するFROMメールアドレスが、
Return-Pathになるので、
そのメールアドレスに対して「XVERP」オプションを指定すれば、
基本的には動きます。
(SMTP認証が必要な場合は、オプション値が異なるので、
 くわしくはqdmailの設定を見てください)


 
動かない時の注意点が2つ。
 


【その1】
/etc/postfix/mail.cfに設定を追加する

smtpd_authorized_verp_clients = $mynetworks

を追加しなければ動きません。
実質的には、この設定がVERPでのバウンス処理のスイッチになっているようです。
デフォルト値は「no」になっている環境が多いようです。


【その2】
PHP実行環境(つまり送信元クライアント)とSMTPサーバーが
別PC・サーバーの場合
 
この場合、まず1つに、SMTPは認証が必要になる場合が多く、
最近の場合、SMTP認証を行う場合は、
接続ポートがサブミッションポート「587」でないといけないことがあります。
まずは、そちらを確認します。
 
その上で、
/etc/postfix/mail.cf
にさらに設定を加えなければなりません。
 
通常の場合$mynetworksという変数には
「127.0.0.1」つまりローカルのみが指定されます。
その1の設定を見ると、
 

smtpd_authorized_verp_clients = $mynetworks

 
VERPが許可されるクライアントは「$mynetworks」だけですよ。
という設定なので、
つまり、ローカルからの接続のみが許可されていることになります。
 
$mynetworksに接続元を追加してやらなければいけません。
こちらを書くと長くなってしまうので、説明については
この辺りをご参考に。


最近はCMSなどにメール配信機能がついていたりして、
非常に便利ですが、
知らず知らずのうちにスパム配信サーバーとなっていることのないように、
こういった対応はおこなっておくべきでしょう。

seezoo cms をお名前.comのSDで使う話

どうもseezoo cmsの魔改造野郎イトウキヨノリです。


今日はseezoo cmsをお名前.comの共有ホスティングSDで使った時の話です。

インストールに関しては、特に問題がありません。
DBを作ると「xxxxxxxxxx.cgidb」という謎のホストを指定されますが、
恐る恐るインストールしてみたら、
そこは問題なくインストールできました。
 


が、ハマったのが短縮URLです。
http://domain/index.php/hogehoge/

http://domain/hogehoge/
に短縮する奴ですね。


seezooには予め様々な環境でテストして、
最大公約数的に大丈夫であろうという
mod_rewriteの記述を示してくれます。
これを.htaccessに書き入れてindex.phpと同じ場所にアップすれば、
ほとんどのサーバーでは、
正常に「index.php」を除いたURLで動作してくれます。


が、お名前のSDサーバーではどうやらいくつか問題点があります。

RewriteEngine On
RewriteBase [パス]
RewriteCond $1 !^(index\.php|sitemap.xml|sitemap_ssl.xml|css|js|captcha|uploads|templates|blocks|phpMyAdmin|.+\.gif$|.+\.jpg$|.+\.png$|.+\.js$|.+\.css$|.+\.json$|.+\.ico$|.+\.swf$|.+\.flv$)
RewriteRule ^(.*)$ index.php?__SZREQ__=$1 [QSA,L]

共有ホスティングでPHPがCGIモードで動いている場合は
こんな記述を示してくれます。
CGIモードの場合、PHPのグローバル変数$_SERVER[‘PATH_INFO’]が取得できないことがあり、
その代わりにパスの情報をGETパラメータとしてPHPに渡しています。

また[パス]のところには、
seezooが動いているパスを自動で挿入してくれます。

seezooの場合、ほとんどのサーバーで、
この方法で動きます。


が、お名前.comのSDの場合、このままでは動きません。
まず、「[パス]」の部分、ここは、seezooが適切なパスを取得できないようです。
(サーバーマシンのルートからのフルパスが出力されてしまいます)

どうやら、PHPに渡される環境変数がおかしいようです。
したがって、seezoo側ではどうしようもないですから、
手動で書き換えることになります。

ドキュメントルートでseezooを動かすなら、

RewriteEngine On
RewriteBase /
RewriteCond $1 !^(index\.php|sitemap.xml|sitemap_ssl.xml|css|js|captcha|uploads|templates|blocks|phpMyAdmin|.+\.gif$|.+\.jpg$|.+\.png$|.+\.js$|.+\.css$|.+\.json$|.+\.ico$|.+\.swf$|.+\.flv$)
RewriteRule ^(.*)$ index.php?__SZREQ__=$1 [QSA,L]

このような感じですね。


これでもまだ動かない。なぜ…。
どうもパス解決がseezoo内部でできていない。なぜ…

調べる時間がなかったため、原点に立ち返ることに。
むか~し書いた僕の記事を元に
index.phpの冒頭に

if( isset( $_GET['__SZREQ__'] ) ){
    $_SERVER['PATH_INFO'] = $_GET['__SZREQ__'];
}

と書いたら動いた!

あれー。。。seezooにはこのへんの判定スクリプトも入ってるはずなんだけどなぁ。。。


ちなみに同時的に、seezooの根底で動いているフレームワークである、
Codeigniterをインストールする必要があったのですが、
Codeigniterでも同じ問題が。同じ方法で解決。
どうやらお名前.comのSDはクセモンのようです。

SDでCakeの短縮URLが動かない旨のブログを散見しましたが、
おそらく同じような問題だと思われます。
テストは割愛しますが、Cake使いの方も参考になれば。

PHPをEXEにコンパイル

PHPをWindowsのアプリケーション .exeにコンパイルするっていう話。

5年ほど前PHPがまだ4系全盛だった頃に一回やったことがあったのだが、
今回、再びやらなければならないことが出てきたので、調べた結果をあげておく。


まず、PHPという言語をWindowsで扱う際、
いいことは、基本的には、Windowsだからといって、
よほど複雑なことをしない限りは、
LinuxやBSD系とそれほど変わらない感覚で使える点。
他のインタプリタで言えば、
Perlをよく使うのだが、Perlなどはファイル名に日本語が入る可能性がある場合などは、
別個にモジュールをロードしてくる必要がある、
よく使うよなと思うモジュールがWindows用にコンパイルされたバイナリがない
など骨が折れることもおおいけれど、
PHPならよほど変なことをしなければ、
php.iniをいじるなどでどうにかできる。

ただし、IronRubyとかには負けちゃうけどね…
 
ま、とにかく、なんだかんだ言われながらもよく使う言語であるPHPで
さくっと小さなアプリが作れるのは楽だ。


5年ほど前に、日本でよく紹介されていた、
PHPを.exeにコンパイルするツールは
http://www.bambalam.se/bamcompile/
これ。
当時使ってみたが、まぁ特に問題もなく。
EXEができた記憶がある。
開発が止まっていて、使えるバージョンはPHP4.4.4。
小さなバッチを書くには十分かなと。

でも、せっかくなら、PHP5で書きたいよなーって調べていたら、あった。
しかも日本人が作ってたのが、、、
これだ

1…
2…
3…
http://hirata-create.cocolog-nifty.com/blog/HC-Standalone-B.html

コンパイルツールがGUIで用意されているのが楽。
これを使えば、WindowsGUIアプリも作れる。
使われているPHPのバージョンは5.3.8。
こういったプロジェクトは、放棄される可能性が高いが、
メンテも頻繁に行われいるようで、いいねいいね


PHPをexeにする仕組みは、

  1. PHPをバイトコードにコンパイルする
  2. windowsのexeファイルを作るプロジェクトの中にバイトコードとPHPのコアであるphp.dllを内包する
  3. コンパイル
  4. 実行時、exeファイルのリソースのなかで、PHPのコードをdllに読ませる

という仕組みでできているようだ。
http://www.sukikamo.jp/users/norihiro/programming/20111104.html
▲参考

つまり、ランタイムとコードをまるごとexeの中に入れちゃってるっていう仕組みである。


上記の、ひらたクリエイトさんのツールの場合、
php.dllを独自にカスタマイズしたものを使っているようで、
それに合わせて、PHPのモジュールも独自のものを使わなくてはならないようだ。
PHPの全資産がそのままつかえるわけではないのがちょっとぐぬぬとなる点である。
(他のコンパイルツールは、同バージョンのPHPのエクステンションdllがそのまま使えるものが多い)


exeにコンパイルした場合の注意点としては、
前述のような、リソースのなかにすべてのものを同梱して
インタプリタに解釈させるという仕組みから、
たとえば、テキストファイルを相対パスで指定したりする場合には、
インタプリタから見たパスの場所がずれるため、
通常どおりのパスが指定できない点を注意する。

この解決方法はRES://というURLスキーマを利用する。

$file = '../data/data.txt';
$usage_path  =  'res:///PHP/' . strtoupper(md5($file));

このように書くと、php.dllから見た相対パスが取得できる。

この点を注意すればあとは通常どおりのPHPでWindowsアプリケーションが作れる。


これまで、PHPの他、Perlやなでしこなどを使ってexeファイルを作ってきたが、
速度の面ではPHPが圧倒的に早いようだ。
今後も使ってみようと思う。


追伸。
Perlをexeにする場合は、
http://www.activestate.com/perl-dev-kit
を使うとできる。
なんと、こいつ、PerlをCOM用のDLLを作ることもできるのだが、
仕組みがわかったので、PHPでもDLLつくれるんじゃねぇの?ということに気づいたため、
今度作ってみようと思う。多分誰も得しないが。。。

PHPのodbc関数はデフォルトではLONG*型は取得できない

PHPのODBC関数でドハマりしたのでメモ
表題の通りPHPのodbc関数では、LONG◯◯型の値を全て取得できない。
たとえば、LONG VARCHAR型は VARCHAR型のサイズに縮められて返される。


php.iniまたは関数でLONG*型の取得が可能になる。
他の設定と例に違わず、php.iniのほうが優先される場合もあるので注意。

関数を利用する場合、odbc接続の前に

odbc_binmode(0, 1); 
odbc_longreadlen(0, 0); 

を渡しておけばOK。これで、ダメな場合は、php.iniの設定を変えます。

odbc.defaultlrl = 0
odbc.defaultbunmode = 0

このようにします。

このあたりはちゃんと調整しないと、
レスポンスに影響が出るようです。


【修正】
php.iniを

odbc.defaultlrl = 0
odbc.defaultbunmode = 0

のようにしていると、接続先データソースのタイプによっては、
INT型などの数値型がNULL or 0の数値によるBooleanに変更されてしまうことがあるようです。
出力してみて、おかしいようならば

odbc.defaultlrl = 4096
odbc.defaultbunmode = 2

とします。
defaultlrlはLONG*型を読み込む最大長(バイト)になるので、
データソースに合わせて変更してください。
odbc.defaultbunmodeは2を指定すると、
全ての値をchar型として処理します。
したがって、BLOB型を扱うような場合は、設定に注意をしてください。

楽天レビューを無茶して取得

楽天APIからレビューを取得することができないので、
PHPで楽天のレビューを取得する方法を書いておきます。

具体的にはHTMLをパースして、
必要なデータを引っこ抜いてくるという仕組みです。


正規表現がめんどくさいので、phpqueryを使います。
http://code.google.com/p/phpquery/
phpqueryはjqueryライクな書き方で、HTMLのパースができる便利なライブラリ。
比較的低いバージョンのPHPでも動くところがいい。
動作テスト環境はPHP.5.1.6です。
 


【実戦投入への注意点】

  • 楽天へのアクセスはfile_get_contentsで書いてますが、実戦投入の際は、curl関数などを使ったほうがいいですね
  • 表示させようとする度に、phpqueryで解析するのは重いので、なんだかのキャッシュ機能はつけたほうがいいですね

		require_once( 'phpQuery.php' );
		
		//レビューページ取得
		$url = '楽天のレビューページのURL';
		$code = file_get_contents($url);
		
		//UTF-8に変換したうえで、phpqueryのインスタンスを「EUC-JP」指定で作成
		$code = mb_convert_encoding( $code, 'UTF-8', 'EUC-JP' );
		$doc = phpQuery::newDocumentHTML( $code, 'EUC-JP' );
		
		
		$list = array();
		$i = 0;
		$cnt = $doc['#reviewList .summary']->length();
		while( $i < $cnt )
		{
			$list[$i] = array();
			
			//ポイント
			$list[$i]['point'] = $doc['#reviewList .summary:eq(' . $i . ') .description .title span.eval']->html();
			
			//日付
			$list[$i]['date'] = $doc['#reviewList .summary:eq(' . $i . ') .description .date']->html();
			
			//名前
			$names = explode(
					mb_convert_encoding( 'さん', 'EUC-JP', 'UTF-8'),
					$doc['#reviewList .summary:eq(' . $i . ') dl:eq(0) dt a']->html()
			);
			$list[$i]['name'] = $names[0];
			
			//タイトル
			$list[$i]['title'] = $doc['#reviewList .summary:eq(' . $i . ') .description .reviewtitle .reviewTitle']->html();
			
			//中身
			$list[$i]['text'] = $doc['#reviewList .summary:eq(' . $i . ') .description .text']->html();
			
			$i ++ ;
		}
		
		//ここにポイント日付名前タイトル評価文がリストされる。
		var_dump( $list );

 
ざくっとこんな感じ。
名前のところは余計な情報もくっついてくるので
「さん」のところで分割して名前だけ持ってくるようにする。

phpquery便利。

CodeigniterでFileMakerをごにょごにょする

ライセンス関連でごにゃごにゃもめとるCodeigniter(以下CIと略す)ですけど、
まぁ基本商用においては問題なさそうなので、
仕事では引き続き使っている案件もあります。

なんだかんだ、CIは高速で便利なPHPフレームワークです。
2.0以降CLIからの実行も考慮されていて
http://codeigniter.jp/user_guide_ja/general/cli.html
ローカルアプリケーションを作るのにおいても、結構活躍してくれます。

PHPでFileMakerへODBC接続して、データを取得してこなければならない仕事があるので、
CIでどうにかならんかなと思ってやってみた次第。

結論

$db['default']['hostname'] = 'Driver=FileMaker ODBC;Host=localhost;PRT=2399;database=データベース名;UID=ユーザーID;PWD=パスワード;';
$db['default']['username'] = '';
$db['default']['password'] = '';
$db['default']['database'] = '';
$db['default']['dbdriver'] = 'odbc';
$db['default']['dbprefix'] = '';
$db['default']['pconnect'] = TRUE;
$db['default']['db_debug'] = TRUE;
$db['default']['cache_on'] = FALSE;
$db['default']['cachedir'] = '';
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';
$db['default']['swap_pre'] = '';
$db['default']['autoinit'] = TRUE;
$db['default']['stricton'] = FALSE;

これで接続できます。
で、

上記のCLIからのCIの利用を参考に

php index.php controller_name method_name

これで起動できます。

FileMakerからはpetaexecuteプラグインなどを利用すれば標準出力を取得できるので、なかなか面白いアプリケーションがつくれそうです。

なんども私のブログで出てきましたが、FileMakerで利用できるSQLは、SQL標準に従ってない部分もあります。
したがってSQLを実行する際は、ActiveRecordは使わずにSQL直書きする方が無難でしょう。

Smartyで $obj->method()を実行してみる覚書

smartyで

$obj->method()

を呼べるのかと思って

{$obj->method()}

と書いたら普通に実行できた。


 
たとえばMVCなフレームワークでSmartyを実行しているとき、
コントローラーに

public function test()
{
    return 'テスト';
}

というメソッドを作っておく。
で、Smartyにコントローラーオブジェクトを渡しておいて、
($controllerにその参照が渡っているものとする)

{$controller->test()}

と記述すればコントローラーのメソッド「test」が実行され、
「テスト」と出力される。

返り値がHTMLとして出力されるようだ。

引数も問題なく渡せた。


 
が引数には落とし穴があった。

{$obj->method( 'test', 'test2' )}

などとすると、エラーが起きる。
引数中にかっこがあるとパースエラーが起きるらしい。
可読性は低くなるが、

{$obj->method('test','test2')}

と記述する必要がある。
 
まぁ、そもそもViewにそんなもん書いていいもんかという話だが、
便利なので、覚書。

PHPでレコメンドエンジン

レコメンデーション

ECサイトなどでは、レコメンデーションを実装するのが、普通になってます。
個人的には、サイト回遊率が上がるけど、
コンバージョンのための終着ポイントを明示するのが少し難しくなるので、
商材などにより入れていい場合とそうでない場合があるなと思ってますが、
使いどころは多いので調べてみました。


よくあるのは、ASP提供型のサービスですね。
有名なのはこのへんですかね▼
http://recommend.submit.ne.jp/
 
あとこの会社の社長を知っているのですが、なかなか熱い方で、いいですよ!
http://www.otegaru-recommend.com/


とはいえ、このへんは月額数千円かかります。
売上100万円程度のお店に導入するには、5000円でも結構な額です。
(個人的には売上200万円程度いかないと、総合的には赤字路線だとは思いますが)
 
ということで、オープンソースで自社導入出来る仕組みがないかしらべたところ、
実用レベルで2つありました。

cicindela http://labs.edge.jp/cicindela/
vogoo http://sourceforge.net/projects/vogoo/
 
前者はライブドアが開発したレコメンドエンジンで、
汎用エンジンとしてはかなり強力なエンジンですが、
それだけ導入するには、ハードルは高くなります。

後者は、アプリケーション自体がPHPのライブラリとして動いてくれるものですが、
解析パターンがひとつしかありません。

導入障壁が低いほうがいいので、今回は、後者を利用しました。
「Vogoo」←なんて読むかわかりません(汗


残念なことに開発はすでに終了しているようで、メンテなども行われず、
インストールはMySQL4前提です。でも、普通にMySQL5でも動いています。

調べるとすでに使われている方がいますね。
http://blog.y-110.net/log/eid130.html
http://www.multiburst.net/sometime-php/2009/02/recommendation-engine-vogoo-with-php/
http://labs.unoh.net/2006/04/_vogoo.html
http://www.atyks.org/blog/2011-07-06-1.html
・・・古い記事は、2006年かぁ・・・


 
インストールはインストーラーを走らせて、
vogooのインストールディレクトリをinclude_pathに追加、
あとは、
http://www.atyks.org/blog/2011-07-06-1.html
http://blog.y-110.net/log/eid130.html
この2つの記事の内容を参考にすれば、実装できます。
(レコメンデーションの仕組みをだいたいわかって人ならという前提ですが)

いただけないことにグローバル変数を利用してるのがアレですが…。

あと、サイト内回遊をポイント評価することで、
似た回遊パターンや購入パターンの人を探して、
おすすめするという仕組みでうごいていますが、
デフォルトで0.66ポイント以上のものだけを結果として返すようになっています。
これは、実装の仕方によっては、
まったく結果が得られない可能性もあります。
ポイント評価の方法や、取得評点の閾値は
サイトにあわせて自分で考えたほうが良いと思います。


実は、協調フィルタリングパターンのレコメンデーションは、
5年前にPerlで作ってたのですが、繰り返しPCを変えてるうちに、
元データがどっかにいってしまいました。。。
当時バージョン管理システムを作らずに開発していたせいですね。。。はぁ。。。

PHPカンファレンス関西に行ってきました。

4月2日にPHPカンファレンス関西に行ってきました。
大阪ですよ。大阪。
いつも梅田駅で迷う、小名古屋人の私にとっては、
どきどきの出発でしたが、それほど道のりは遠くなくて良かったです。


なぜ、PHPerではない(と言い張っているだけ)の私がわざわざ大阪に行ったかといいますと、
前の記事に書きましたUst番組『バニトーク』に出てやるぜ!っていうのと、
Twitterで仲良くさせていただいている、
@yat8823jpさん(以下、YATさん)、
@alphabet_hさん(以下、こしあんさん)
に会えるぜ!っていうのでした。


YATさんはECに携わってらっしゃるということで、
Twitterでもマインドを同じくしているので、
開場前に早めにお会いして、色々話をしましたが、
いいですね!適度な熱さと冷静さをもっている方でした。

そして、こしあんさんは、
まっすぐにPHPやらJSやらの言語の真ん中のところを追いかけている方だということは、
Twitterで存じ上げていましたが、
こしあんさんも、また適度な熱さと冷静さをもってらっしゃり、
僕好みの人間性を持っている方でした。

やっぱり会うって大きいと思います!
仲良くさせていただいている某団体(通販の運営者の団体)の代表の方が常々、
「TwitterやFacebookは、あくまでリアル世界のソーシャルの延長」
と仰っている意味が、ものすごく分かった気がします。

YATさん、こしあんさん、今後とも仲良くしましょう。


さて、肝心のPHPカンファレンスの中身は、
「クラウド」をテーマの中心においているせいか、
PHPカンファレンスなのに、
クラウド技術のお話だったり、JSのお話だったりと、
想像していたものと違って面食らってしまいましたが、
内容としては、良いノウハウの宝庫で、それはそれで良かったのかなと思っています。

また、ライトニングトークの枠もあったのですが、
さすが、こちらはdisられてもPHPerを名乗る方々のライトニングトークです。
PHPに対する思いがひしひしと伝わってきて、面白い内容ばかりでした。

ただ、CodeIgniter使いが少なくてしょんぼり…
やっぱ、CakeとSymfonyは強いですね…


本編終了後は、懇親会がありましたが、名古屋で行われる各イベントと異なり、
懇親会の中でも、ライトニングトークがあり、
本編の補足的な内容があったり、
有用なノウハウを伝えるものがあったり、
知らなかった会合やセミナーのお知らせがあったり、
と、ぶっちゃけ本編より充実してるんじゃないかと
錯覚させるような内容で、
お酒のちからもあるのでしょうが、
しゃべって終わりではなく、
みんながみんなどのような立場の人々なのかが分かるような懇親会でした。


名古屋からは@ahomuさんも行って、
はからずも名古屋のCMSの人がそれぞれ行くという布陣で行くことになりましたが、
強豪揃いのPHPerたちの前では、あえなく散ってしまう僕らでした。。。orz


というわけで、大阪人の熱さ、PHPerの熱さを感じることができた良い旅でした。
そして、名古屋、、、まだまだだなぁと感じた旅でした。
今後も何か大阪に関われたらなぁと思います。


あれ?集合写真の真ん中にアウエーの僕が…

Older posts Newer posts