Home > PHP

PHP Archive

CakePHP1.2をベースにしたオープンソースシステム-NoseRub

この記事の所要時間: 132

CakePHP1.2はまだpre-betaの状態ですが、既にこれをベースとしたオープンソースシステムが公開されています。

それがNoseRubです。

NoseRubはざっと見た感じ「マイクロブログ」に分類されるシステムです。様々なRSSフィードをアグリゲートできるようでTwitterというよりJaikuに近い印象を受けました。NoseRubの内容については上記サイトにこのシステムを利用したサービスが公開されている(ここなど)のでそちらを参考にして下さい。

 

ここで大事なのはこのシステムがCakePHP1.2ベースで作られているという事です。

1.2に関してはpre-betaという事もあり、箇所箇所の情報は見られるのですが、これを実際のシステムに組み込むノウハウがまだ共有されていない状態にあります。その中において実際にサービスとして動作するシステムがオープンソースで公開されているのはとても有り難いことです。

実際にダウンロードして中身を見てみました。ソースはわりと丁寧に書かれていて読みやすいです。やはり根本のフレームワークは理解しているので処理を追いやすいですね。まだ導入部分しか読んでいませんが、細かな実装のヒントが見つかり、これはかなり参考になりそうです。

ちなみに最新版であるNoseRub0.5.1はCakePHP1.2.0.5875 pre-betaベースとなっていました。

これから1.2で実装したい方は是非一度ダウンロードして参考にしてみて下さい。

# ホント、オススメです!

 

ちなみにCakePHPを使ったシステムやサービスなどは以下のサイトに公開されています。

Cake Apps/Sites In The Wild – Cake PHP | Google グループ

PHPSpecマニュアルが登場

  • 2007-11-07 (水)
  • PHP
この記事の所要時間: 045

via: PHPSpec Manual (Work In Progress) – Maugrim The Reaper’s Blog

RSpecのPHP版、PHPSpecのマニュアルが公開されています。

PHPSpec Reference Manual

現在はドラフトでこれから順次更新されていくようです。

RSpec自体試したことはないのですが、興味がある分野なので期待しています。

RSpecって何?な方は、Rubyist Magazineが参考になります。

技術の流れとして、以前はJava->PHPなトレンドでしたが、ここ最近はRuby->PHPとなっていますね(Cakeしかりです)。PHP独自のものが少ないのはやはり実用言語だからでしょうか。

# そんなPHP界で異彩を放つPieceFrameworkは面白い試みだと思います。;-)

PHPでメールの重要度を設定する

  • 2007-11-03 (土)
  • PHP
この記事の所要時間: 137

システムから配信するメールに重要度を付けたいという話しがあったので調べてみました。

重要度を設定しておくと対応しているMUA(OutlookやらBecky!やら)ではメールの横にマークが付加されます。

分かったことは以下のとおり。

  • 重要度はメールヘッダで設定する。
  • 以前はX-PriorityやらX-MsMail-Priorityやらの独自ヘッダで設定し、MUAでは各々独自に処理していた。
  • RFC1327で重要度を表すPriorityヘッダが用意された。

重要度を設定する値はヘッダによって異なります。

ヘッダ 重要度高 重要度やや高 普通 重要度やや低 重要度低
X-Priotiry 1 2 3 4 5
X-MsMail-Priotiry High Normal Low
Priotiry urgent normal non-urgent

 

PHPでテストしてみました。mb_send_mail()でメールヘッダを設定しているだけです。

<?php
$to = 'hoge@example.com';
$subject = 'subject';
$body = 'body';

// ヘッダで重要度高を設定する
$header = 'Priority: urgent';
//$header = 'X-Priority: 1';
//$header = 'X-MsMail-Priority: High';

mb_language('ja');
mb_send_mail($to, $subject, $body, $header);
?>

このコードを実行すると、手元のBecky!では受信したメールに重要度高が設定されているのが確認できました。

どのヘッダを使用するかですが、Becky!では3つの内、どのヘッダを使用しても重要度が設定されていました。RFC1327で定義されているのは「Priority」なので、今後はこれを利用するのが良いでしょう。(対象のMUAが対応していればですが)

ちなみにBecky!自身で重要度を設定すると「X-Priority」と「X-MsMail-Priority」がヘッダに付加されていました。

今回は管理者向けメールなので受信するMUAが限定できました。様々なMUAに対応する際どのヘッダが対応しているかを調査する必要があるでしょう。

私自身はメールに重要度を設定しないので有用かどうかはあまりピンと来ませんが。:-p

CakePHP 公開する時はデバッグ情報を出さない

この記事の所要時間: 351

CakePHPで作ったシステムを公開する時は、フレームワークが出力するデバッグ情報に気をつけましょう。

1. SQLログ

DEBUG定数の値を2以上に設定すると実行されたSQL文がログとして画面に表示されます。通常本稼働する際はDEBUGを0にしてこの出力は抑制するのですが、たまに本稼働でもSQL文がログが出力されているサイトがあります。

ちなみにSQLログに含まれるキーワードをGoogleで検索すると出力したままのサイトが見つかったりします。

“queries took” “Took (ms)” – Google 検索

対策

[app/config/core.php]にあるDEBUGを0にしておきます。公開サイトでSQL文を確認したい場合はCakePHP SQLをログに記録する方法などを使ってログファイルに出力するのが良いでしょう。

[app/config/core.php]

//	define('DEBUG', 2);
	define('DEBUG', 0);

2. PageControllerへのルーティング

デフォルトのURLルーティングでは[/]と[/pages/*]なURLはPageControllerのdisplayアクションにルーティングされるようになっています。displayアクションでは[/pages/]以降で指定された値をビューテンプレートとして出力します。([/]は/pages/homeとして処理されます)

[/]なURLは大抵アクセスを想定しているのでルーティングを変更すると思うのですが、[/pages/*]なURLは変更を忘れがちです。そのままだと[/pages/home]なURLを指定すると、フレームワークに含まれるhome.thtmlが出力されてしまいます。

http://example.com/pages/home

対策

[app/config/routes.php]にあるPageControllerへのルーティングを削除します。

[app/config/routes.php]

// [/]のURLルーティングを変更
//	$Route->connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
	$Route->connect('/', array('controller' => 'top', 'action' => 'index'));
(snip)
// [/pages/*]のURLルーティングを変更
//	$Route->connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));

3. 存在しないコントローラ、アクション

これもDEBUG定数の値によって出力されます。DEBUGの値が1以上の場合、存在しないコントローラやアクションがURLで指定されるとエラーメッセージが表示されてしまいます。

例えばそこで[/a/a]のように存在しないであろうコントローラやアクションを指定すると「Missing Controller」や「Missing Method」が表示されます。

対策

1.と同様にDEBUGの値を0にします。

対策-さらに

フレームワークは[/foo(/bar)?]なURLであればコントローラとアクション(/barがなければ/indexが存在するとみなす)を探そうとします。ですのでリバースプロキシなどで外部からCakePHPシステムへアクセスされるURLを限定してしまうのもアリです。

こうしておけば予期せぬURLからのアクセスを防ぐことができるので、URLルーティングにおける想定外の動作を防ぐことができます。(この手法は結構好きなので良く使用します。;-))

便利機能には注意を

CakePHPに限らず各種フレームワークには開発に有用なデバッグ情報出力などの機能が用意されています。これらの情報は開発には役立ちますが、一般に公開すると攻撃者へヒントを与えることにもなりますし、何より見た目が宜しくありません。

特にURLルーティングに関しては今時のフレームワークでは実装されている機能だと思います。外部に公開するシステムでは、あらかじめ想定外のURLが指定された場合、どのような動作をするかを確認しておきましょう。

CakePHPガイドブック登場

この記事の所要時間: 032

先日ご案内したCakePHP本がいよいよ登場します。タイトルは「CakePHPガイドブック」です。

ベタな名前ですが、あえて奇をてらわず、定番となる本になって欲しい!という執筆陣の思いが詰まっています。またカバーもシンプルなデザインになっているのでオフィスに置いて頂いても違和感無いかと思います。

10月末頃には書店に並ぶそうです。見かけたら一度手に取って頂ければ嬉しいです。

# 私自身も初めての書籍なのでとても楽しみです。;-)

出版元のマイコミさんのサイト [MYCOM BOOKS – CakePHPガイドブック]

PHPソースからドキュメントを生成するツール

この記事の所要時間: 524

PHPソースからドキュメントを生成する主要な3ツールを試してみました。どのツールもそれほど深くは調べていないのでインストール+アルファ程度の設定変更で試しています。

環境はCentOS4.4+PHP5.2.3です。

phpDocumentor

PHPでできたツールです。pearコマンドでインストールできることもあって、PHPのドキュメントジェネレータとして人気があります。

  • インストール

pearコマンドでインストールできます。

$ pear install --alldeps phpdocumentor
  • ドキュメント生成

phpdocコマンドで生成します。とりあえずドキュメントを生成するだけなら設定ファイルの変更は不要です。

./src 以下のPHPファイルを対象に ./doc 以下にドキュメントを生成
$ phpdoc -t ./doc -d ./src 

[参考サイト]

Doxygen

C++でできたツールです。DoxygenはC/C++、Javaをはじめ様々な言語についてドキュメントを生成することができます。どちらかと言うと、C/C++、Java、Pythonがメインのツールですが、PHPでも十分なドキュメントを生成することができます。

  • インストール

CentOS4用はRPMがあるのでyumコマンドでインストールできます。

$ sudo yum install Doxygen

ただRPMは1.3.9ですので、最新版(1.5.3)がよければソースからインストールします。

$ tar zxvf doxygen-1.5.3.src.tar.gz
$ cd doxygen-1.5.3
$ ./configure
$ make
$ sudo make install
  • ドキュメント生成

まず設定ファイルを生成します。-gで生成する設定ファイルのファイル名を指定します。ファイル名を指定しなければDoxyfileという設定ファイルがカレントディレクトリに生成されます。

$ doxygen -g [config]

次に設定ファイルを編集します。下記は最低限変更した方が良いと思う項目です。

$ vi Doxyfile
# ドキュメント出力ディレクトリ(省略すればカレントディレクトリに出力)
# => doc ディレクトリに出力
#OUTPUT_DIRECTORY =
OUTPUT_DIRECTORY = doc

# ソースディレクトリ(省略すればカレントディレクトリ)
# => src ディレクトリ以下のファイルを解析
#INPUT =
INPUT = src

# 再帰的にソースディレクトリを解析する
# => 再帰する(YESにしないとINPUTで指定したディレクトリのみ解析する)
#RECURSIVE = NO
RECURSIVE = YES

# ソースコードページを生成する
# => ソースコードページを生成
#SOURCE_BROWSER = NO
SOURCE_BROWSER = YES

# ソースコードページにてコメントを削除する
# => ソースコードページにコメント出力
#STRIP_CODE_COMMENTS = YES
STRIP_CODE_COMMENTS = NO

ドキュメント生成コマンドを実行するとドキュメントが生成されます。

$ doxygen Doxyfile

[参考サイト]

PHPXRef

Perlでできたツールです。phpDocumentorやDoxygenとは少し毛色が異なり、クラス図などは表示されません。上記2ツールはクラス構造などをドキュメント化しますが、PHPXRefはソースコード自体をドキュメント化するのを目的としています。

  • インストール

PHPXref – The PHP Cross Referencing Documentation Utilityから最新版ソース(0.7)をダウンロードして展開するだけでokです。

$ tar zxvf phpxref-0.7.tar.gz
$ cd phpxref-0.7
  • ドキュメント生成

設定ファイルを編集します。展開したディレクトリ内にあるphpxref.cfgが設定ファイルになります。

$ vi phpxref.cfg
# ソースディレクトリ(省略すればカレントディレクトリ)
SOURCE=src

# ドキュメント出力ディレクトリ(省略すればカレントディレクトリに出力)
OUTPUT=doc

ドキュメント生成コマンドを実行するとドキュメントが生成されます。

$ ./phpxref.pl

[参考サイト]

出力サンプル

CakePHP1.1.17.5612のソースを各ツールで出力してみました。

クラス構造を確認するならDoxygenが、ファイル構造を確認するならPHPXRefが良さそうです。ただDoxygenにはクセがあるようで、PEARパッケージのようにファイル名とクラス名が異なる場合は上手く生成ができませんでした。(良い方法があればどなたかヘルプを・・・;-))

モバイル向けGoogle AdSenseをPHPで使う

この記事の所要時間: 436

Google AdSenseにモバイル版が登場しました。

通常のAdSenseではJavaScriptを使って広告を表示するのですが、携帯ではJavaScriptが使えないので、PHPやPerlなどサーバ側で実行する言語で記述します。AdSenceサイトではPHP/Perl/JSP/ASPのコードが用意されており、モバイル向けAdSense設定を行うとそれぞれのコードが表示されます。

PHP用コードを確認したところ、コードの流れは単純で、AdSense IDや広告フォーマット、HTTPリクエスト(HTTP_USER_AGENT等)などを専用変数に設定して、最後にリモートにあるPHPコードをrequire()しているだけです。

コードを見て気になる点があったのでメモしておきます。

$_SERVERにキーが無いことを想定していない

$_SERVER[‘HTTPS’]や$_SERVER[‘HTTP_REFERER’]など値が存在しない可能性があるものをそのまま参照しています。これらの値が存在しない場合は「Notice: Undefined index」が発生します。

[対応策]

isset()やempty()で連想配列にキーが存在するかどうかを確認します。単純に回避するなら[@]をつけてエラーメッセージの出力を抑制する方法もあります。

require()でリモートスクリプトをインクルード

PHP5.2.3でコードを実行したところ、以下のメッセージが表示されました。

Warning: require() [function.require]: URL file-access is disabled in the server configuration in /home/www/xxxx/ad.php on line 17

これはallow_url_includeディレクティブがoffになっているために発生します。allow_url_includeはPHP5.2.0からは追加されたもので、これがoffになっているとリモートにあるスクリプトをinclude()やrequire()でインクルードすることができません。

allow_url_includeはデフォルトはoffとなっているので、そのままだとこのコードは動作しません。

対応策としては3通りの方法があります。

[対応策1] allow_url_includeをonにする

allow_url_includeをonにすればこのコードは動作します。しかしこのディレクティブはセキュリティリスク(RFI等)を回避するためにoffにされているものなので、できればこの方法は取らない方が良いです。

またallow_url_includeはphp.iniやhttpd.confでのみ設定が可能なので、共用サーバなどでは設定が変更できないかもしれません。

[対応策2] file_get_contents()でリモートスクリプトを読む

file_get_contents()でリモートスクリプトを読み込む方法です。file_get_contents()は単にファイルを読み込んでその内容を返すだけなので、allow_url_includeの影響は受けません。

あとは読み込んだスクリプトをeval()で実行しようと思いました。が、eval()でエラーが発生しました。「<&php」「&>」が引っかかっているようです。対応しても良いのですが、これはこのまま放置。

[対応策3] リモートスクリプトをローカルに置く

require()で読み込んでいるスクリプトをローカルに置いてしまいます。そしてrequire()でローカルのファイルをインクルードするようにします。こうすればallow_url_includeの設定に関わらずスクリプトを実行できます。

ちなみにリモートスクリプトは以下のようになっています。

<?php

/**
 * Copyright (C) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     @license http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

$google_dt = time();

function google_append_url(&$url, $param, $value) {
  $url .= "&" . $param . "=" . urlencode($value);
}

function google_append_globals(&$url, $param) {
  google_append_url($url, $param, $GLOBALS&#91;"google"&#93;&#91;$param&#93;);
}

function google_append_color(&$url, $param) {
  global $google_dt;

  $color_array = split(",", $GLOBALS&#91;"google"&#93;&#91;$param&#93;);
  google_append_url($url, $param,
                    $color_array&#91;$google_dt % sizeof($color_array)&#93;);
}

function google_get_ad_url() {
  $google_ad_url = "http://pagead2.googlesyndication.com/pagead/ads?";
  $google_scheme = ($GLOBALS&#91;"google"&#93;&#91;"https"&#93; == "on")
      ? "https://" : "http://";
  foreach ($GLOBALS&#91;"google"&#93; as $param => $value) {
    if ($param == "client") {
      google_append_url($google_ad_url, $param,
                        "ca-mb-" . $GLOBALS["google"][$param]);
    } else if (strpos($param, "color_") === 0) {
      google_append_color($google_ad_url, $param);
    } else if ((strpos($param, "host") === 0)
               || (strpos($param, "url") === 0)) {
      google_append_url($google_ad_url, $param,
                        $google_scheme . $GLOBALS["google"][$param]);
    } else {
      google_append_globals($google_ad_url, $param);
    }
  }
  google_append_url($google_ad_url, "dt", 
          round(1000 * array_sum(explode(" ", microtime()))));

  return $google_ad_url;
}

$google_ad_handle = fopen(google_get_ad_url(), "r");
if ($google_ad_handle) {
  while (!feof($google_ad_handle)) {
    echo fread($google_ad_handle, 8192);
  }
  fclose($google_ad_handle);
}

?>

[おまけ] require()よりinclude()

require()は読込に失敗した場合、Fatal errorが発生してスクリプトの実行が止まってしまいます。一方include()は読込ができなくてもWarningが出るのみです。広告は最悪表示されなくとも問題無いので、include()(もしくは@include())を使った方がより良いでしょう。

allow_url_fopenをonにしておく

最後に大事なこと。どのような対策を取るにせよallow_url_fopenはonである必要があります。これはリモートスクリプト自体がfopen()でリモートファイルを読みに行っているためです。またallow_url_includeをonにしたところでallow_url_fopenがoffだとリモートファイルのインクルードは動作しません。

allow_url_fopenはデフォルトではonになっているので問題無いかと思いますが、上手く動作しない場合はご確認を。

まとめ

モバイル向けGoogle AdSenseのPHPでの使用法について見てきました。各言語用にコードが用意されているのは素晴らしいことなのですが、つまづきそうな点が幾つかあるので注意が必要です。

あとデザインですが、シングル広告でもかなり画面幅を取ります。もう少し控えめなパターンがあると嬉しいです。

デザイナー向けPHPチュートリアルビデオ

  • 2007-09-27 (木)
  • PHP
この記事の所要時間: 034

KILLER PHP – FOR WEB DESIGNERS

PHP VIDEO TUTORIALS FOR WEB DESIGNERS

20以上のPHPチュートリアルビデオが公開されています。サイトではデザイナー向けと謳っているだけに基本的な内容から解説されているようです。

チュートリアルの内容は全て英語になるのですが、インストール方法やソースコードの説明などは映像もあるので何となく理解できます。個人的には解説されている内容自体は知っているので英語の勉強になって良いです。;-)

これからPHPを触れる方には参考になるのではないでしょうか。

楽天API PEAR::Services_Rakuten-0.2.1リリース

  • 2007-09-19 (水)
  • PHP
この記事の所要時間: 116

楽天ウェブサービスをPHPで利用するPEARライブラリ「PEAR::Services_Rakuten-0.2.1」をリリースしました。

本リリースでは以下の内容を修正しています。(nekolifeさん、ご指摘ありがとうございました。)

  • 商品検索等でgenreIdに0を指定すると「keyword or genreId have not been set.」が表示される

インストール・アンインストール

インストール方法は以下です。

$ pear install --alldeps /blog/download/Services_Rakuten-0.2.1.tgz

インストール時に「Failed to download pear/XML_Serializer within preferred state “stable”」といったエラーが発生した場合は以下のコマンドでXML_Serializerをインストール後、Services_Rakutenをインストールして下さい。

$ pear install --alldeps XML_Serializer-beta

アンインストール方法は以下です。

$ pear uninstall __uri/Services_Rakuten

使用方法はこちらをご参考下さい。

PHP 5.2.4 の新機能

  • 2007-09-06 (木)
  • PHP
この記事の所要時間: 453

PHP5.2.4がリリースされています。

基本バグフィックス&セキュリティアップデートのようなので大きな変更はありませんが、ChangeLogから興味を引いた変更点をメモしておきます。

–enable-versioningの廃止

追加機能では無いですが。

PHP3/PHP4を同時にApacheモジュールとして実行できるオプションでしたが、今回廃止されました。まあ昨今ではさすがに使っている人はいないでしょうけど、PHP3->PHP4の移行期には必須とも言えるオプションだったので、感慨深いものがあります。

PHPエラーをstderrに出力可能に

CGI/CLI版では、display_errors=stderrに設定することにより、PHPエラーをstderr(標準エラー)に出力することができるようになりました。なおデフォルトではこれまでどおりstdoutに出力されます。

stderrにPHPエラーを出力

$ php -d 'display_errors=stderr' -r 'a' > stdout 2> stderr
$ cat stdout
$ cat stderr
PHP Parse error:  syntax error, unexpected $end in Command line code on line 1
Parse error: syntax error, unexpected $end in Command line code on line 1

PHPエラーでHTTP 500を返す

PHP5.2.4ではPHPエラーでHTTP 500を返す参照

前項のPHPエラーをstderrに出力するのと同じノリですね。

PCRE_VERSION定数を追加

正規表現ライブラリであるPCREのバージョンを表す定数が追加されています。

$ php -r 'echo PCRE_VERSION . PHP_EOL;'
7.2 2007-06-19

あとGDでもバージョンを表す定数が追加されています。(GD_MAJOR_VERSION, GD_MINOR_VERSION GD_RELEASE_VERSION, GD_EXTRA_VERSION, GD_VERSION_STRING)

php_ini_loaded_file()追加

現在読み込んでいるphp.iniファイルの絶対パスを返す関数です。

CLIで何か挙動がおかしいなあと思ったら、読み込んでいるphp.iniを確認するのも良いかもしれません。

$ php -r 'var_dump(php_ini_loaded_file());'
string(29) "/home/hoge/php524/lib/php.ini"
$ php -c . -r 'var_dump(php_ini_loaded_file());'
string(18) "/home/home/php.ini"

ReflectionExtensionクラスにinfo()を追加

extensionをリフレクションするReflectionExtensionクラスにinfo()が追加されました。

$ php -r '$obj = new ReflectionExtension("mbstring"); $obj->info();'

mbstring

Multibyte Support => enabled
Multibyte string engine => libmbfl
Multibyte (japanese) regex support => enabled
Multibyte regex (oniguruma) version => 4.4.4
Multibyte regex (oniguruma) backtrack check => On

mbstring extension makes use of "streamable kanji code filter and converter", which is distributed under the GNU Lesser General Public License version 2.1.

Directive => Local Value => Master Value
mbstring.language => neutral => neutral
mbstring.detect_order => no value => no value
mbstring.http_input => pass => pass
mbstring.http_output => pass => pass
mbstring.internal_encoding => ISO-8859-1 => no value
mbstring.substitute_character => no value => no value
mbstring.func_overload => 0 => 0
mbstring.encoding_translation => Off => Off
mbstring.strict_detection => Off => Off

ReflectionClass::getDefaultProperties()でstaticクラス変数が取得可能に

ReflectionClass::getDefaultProperties()でstaticクラス変数が取得できるようになっています。

<?php
class Foo
{
    public static $fooStatic = 'foo';
    protected $foo = 'foo';
}

$class = new ReflectionClass('Foo');

print_r($class->getDefaultProperties());
$ /home/hoge/php523/bin/php ref.php 
Array
(
    [foo] => foo
)

$ /home/hoge/php524/bin/php ref.php 
Array
(
    [fooStatic] => foo
    [foo] => foo
)

ホーム > PHP

検索
フィード
メタ情報

Return to page top