[php]トークン分解でphp_strip_whitespace()関数を実装する

Written by uechoco 12月 29

1つ前の[php]php_strip_whitespace()でソースコードの容量を削減の続き。前の記事では

ちなみにphp_strip_whitespace()関数は、PHP5.0.0から実装され、PHP5.0.1から正しく動くようになった関数です。それより前のバージョンでこの関数を使いたい場合はPEAR::PHP_Compatを利用するのが一番早い方法です。

と書きました。

PEAR::PHP_Compatではどうやってこの関数を再現しているかというと、PHP_Compat内のphp_strip_whitespace()関数のCVSレポジトリを見るとわかります。が、下に貼り付けました。

PHP:
  1. <?php
  2. // $Id: php_strip_whitespace.php,v 1.13 2007/04/17 10:09:56 arpad Exp $
  3.  
  4.  
  5. /**
  6.  * Replace T_DOC_COMMENT in PHP 4
  7.  */
  8. if (!defined('T_ML_COMMENT')) {
  9.    define('T_ML_COMMENT', T_COMMENT);
  10. } else {
  11.    define('T_DOC_COMMENT', T_ML_COMMENT);
  12. }
  13.  
  14.  
  15. /**
  16.  * Replace php_strip_whitespace()
  17.  *
  18.  * @category    PHP
  19.  * @package     PHP_Compat
  20.  * @license     LGPL - http://www.gnu.org/licenses/lgpl.html
  21.  * @copyright   2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad @php.net>
  22.  * @link        http://php.net/function.php_strip_whitespace
  23.  * @author      Aidan Lister <aidan @php.net>
  24.  * @version     $Revision: 1.13 $
  25.  * @since       PHP 5
  26.  * @require     PHP 4.0.0 (user_error) + Tokenizer extension
  27.  */
  28. function php_compat_php_strip_whitespace($file)
  29. {
  30.     // Sanity check
  31.     if (!is_scalar($file)) {
  32.         user_error('php_strip_whitespace() expects parameter 1 to be string, ' .
  33.             gettype($file) . ' given', E_USER_WARNING);
  34.         return;
  35.     }
  36.  
  37.     // Load file / tokens
  38.     $source = implode('', file($file));
  39.     $tokens = token_get_all($source);
  40.  
  41.     // Init
  42.     $source = '';
  43.     $was_ws = false;
  44.  
  45.     // Process
  46.     foreach ($tokens as $token) {
  47.         if (is_string($token)) {
  48.             // Single character tokens
  49.             $source .= $token;
  50.         } else {
  51.             list($id, $text) = $token;
  52.            
  53.             switch ($id) {
  54.                 // Skip all comments
  55.                 case T_COMMENT:
  56.                 case T_ML_COMMENT:
  57.                 case T_DOC_COMMENT:
  58.                     break;
  59.  
  60.                 // Remove whitespace
  61.                 case T_WHITESPACE:
  62.                     // We don't want more than one whitespace in a row replaced
  63.                     if ($was_ws !== true) {
  64.                         $source .= ' ';
  65.                     }
  66.                     $was_ws = true;
  67.                     break;
  68.  
  69.                 default:
  70.                     $was_ws = false;
  71.                     $source .= $text;
  72.                     break;
  73.             }
  74.         }
  75.     }
  76.     return $source;
  77. }
  78.  
  79. // Define
  80. if (!function_exists('php_strip_whitespace')) {
  81.     function php_strip_whitespace($file)
  82.     {
  83.         return php_compat_php_strip_whitespace($file);
  84.     }
  85. }

どうやらtoken_get_all()関数を用いて与えられたソースコードをトークン分解した後、コメントトークン以外を文字列連結した結果を返すというもののようです。

phpってトークン分解が関数でできるんですね。トークン分解と聞いてふと思い出したのがPHPソースからフローチャートを生成する | Shin x blogというブログの記事。がんばればphpだけでフローチャートを出力するプログラムが作れるのでは!?と妄想してしまいました。フローチャートに限らず、ソースコードを図示するという処理には少し興味があるので、token_get_all()関数は自分の中ではかなりツボな発見でした。php_strip_whitespace()関数が役に立った瞬間でした。

[php]php_strip_whitespace()でソースコードの容量を削減

Written by uechoco 12月 29

 また謎の関数を見つけてしまいました。php_strip_whitespace()関数です。ソースコードの文字列を与えるとコメントと空白文字を取り除いてくれるという関数ですが、使いどころがあまりない気がします。マニュアルには

PHP のソースコード filename
からコメントと
空白文字を取り除いたものを返します。これは、スクリプトの中で
実際のコードの量がどれくらいなのかを知るのに役立つでしょう。
これは コマンドライン
から php -w を実行するのと同じです。

PHP: php_strip_whitespace - Manual

とありますが、実際のコード量が知りたくなったりするもんでしょうか?1バイト当たり1円でソースコードを販売するとか?

?

 ちなみにphp_strip_whitespace()関数は、PHP5.0.0から実装され、PHP5.0.1から正しく動くようになった関数です。それより前のバージョンでこの関数を使いたい場合はPEAR::PHP_Compatを利用するのが一番早い方法です。

?

 がんばって使用例を考えてみたのですが

  • DirectoryIterator+php_strip_whitespace()でソースコード容量一括削減!
  • phpソースコードの難読化ツールの第一歩

くらいしか思いつきませんでした。余分な字句解析を行わなくなるので、実行速度が気持ち的に速くなりそうな気もしますが、
Optimizer/Cacher(ZendOptimizer/eAccelerator/APC/xcacheなど)を入れれば無駄な努力になりそう
です。

 じゃぁ何で記事にしたの?と言われたら次の記事を書くための前振りだったり。

?

[php]トークン分解でphp_strip_whitespace()関数を実装する
http://labs.uechoco.com/blog/2007/12/phpphp_strip_whitespace_tokenizer.html

[php]PEAR日本語マニュアルPDF版を作ってみた

Written by uechoco 12月 28

 m-takagiさんのPiece Network 1 資料公開 (2)という記事の中で、PHP日本語マニュアルのPDF版を公開していました。20MB以上の大きなファイルですが、オフラインでphpをやるときに持っておくと便利かなっと思ってDLしました。

?

 PHP日本語マニュアルをやったんなら、PEAR日本語マニュアルのPDF版も作ってくれればいいのに・・・と他人事のように思ったわけですが、いきなり「PEAR日本語マニュアルPDF版作ってください!!」ってメールを送るのはいかがなものかと。そこでふと思い出したのは、ネット上にはいろんなサイトでPEARのマニュアルの複製がされてるよなーっと。実際調べてみたら、PEAR :: Manual :: ドキュメントの作成というページでマニュアルの作成方法が載っていました。このとおりにやればできるのか!?っと実践してみたわけです。

 途中VirtualBoxやらVMwareやらに苦しめられて、結局はLinux機をセットアップした話は省略。

?

 一応以下のページを参考にしました。同じようなことをやってみたい方は参照してみてください。

 私が行った手順としては、

  1. cvsやらautoconfやらjadeやらjadetexやらpsgmlやらsgml-commonやらをyumでインストール
  2. 適当なディレクトリにcvs.php.netからphpdoc/とpeardoc/をチェックアウト
  3. peardocディレクトリにて以下のコマンド peardoc# autoconf peardoc# ./configure --with-lang=ja --with-dsssl=../phpdoc/docbook/docbook-dsssl/ peardoc# make bightml
  4. たぶんこれでマニュアルが1つのHTMLになっているpear_manual_ja.htmlファイルが出力される
  5. Windowsに持っていってFirefoxでPDFに印刷
  6. Adobe Acrobatの使えるPCに持っていってPDFに出力

?

 pearのマニュアルは結構細かいところでハマったりして大変でした。このPEAR日本語マニュアルを作る前にm-takagiさんの記事のとおりにPHP日本語マニュアルのbightmlの作成も行ったのですが、こちらはPhD(PHP based DocBook renderer)がさくさくとやってくれたので簡単でした。PEARのマニュアルって作るの大変ですね。

 びっくりしたのが、FirefoxやAdobe Acrobatで開こうとすると、なかなか開いてくれないことです。Firefoxは印刷中の使用メモリが750MBを越えました。[名前をつけて保存]ダイアログがなかなかでなくてプロセスが停止したのかと思って、タスクを切ろうか残そうか迷いましたが、なんとか保存先も指定できて、無事にPDF化できました。

?

 作ったPDFは2つ。1つはFirefoxで印刷したゴシック体のもの。もう1つはAcrobatで印刷したハイパーリンクが有効になっているけど明朝体のもの。お好きなほうをDLしてください。■(12/28 21:00)Acrobatでちゃんとしたフォントを適用したものを出力しました。

 作った後で気づいたのですが、Acrobat版の印刷の向きを間違えたくさいです。あとはエンドユーザーマニュアルを作っていないPEARのパッケージが多いなぁっと。PEARってマニュアル見るよりソース見るか、サンプル見たほうが早いんですよね。じゃぁ、何のために作ったんだろう?

■追記:書いた直後

 そうそう、もう1つ後から気づいたのは、PEARの日本語chmファイルは更新されていないけど、bightmlファイルは頻繁に更新されているんですよ。どうして気づかなかったんでしょう?こんなに苦労せずとも、いきなりPDF化できたようでした。まぁ、いい経験になったかな。

[php][linux]yumでphpのpearを入れる

Written by uechoco 12月 27

 久しぶりにFedora 7 on VirtualBoxを使ってます。phpが入ってなかったので

yum install php

で適当にphpをインストールしてもらいました。pearのライブラリも欲しかったのでpearコマンドを打ってみたらないって言われました。探しても見つかりません。どうやら別途インストールするみたいでした。

yum install php-pear

で入ってくれました。pearコマンドも使えるようになりました。

 うーん。やっぱLinuxまったくできないなぁ(汗

[php][書籍]紹介:PEAR―PHPライブラリ

Written by uechoco 12月 26

またphpの本が出ましたね。『PEAR PHPライブラリ』です。著者は最近フレームワークの本をいくつも出している佐久嶋 ひろみさんです。価格は?\3,360、現時点ではAmazonの商品画像がでていませんが、既にいくつかの本屋には置いてあります。私はヨドバシカメラのパソコン書籍コーナーにて発見しました。

この時期にPEARの本が出るのは意外な気がしますね。内容としては、

PART1:PEARの概要・インストール方法・チャネルサーバーへのアクセスの仕方・PEARコマンドの使い方などのPEAR自体の説明

PART2:PEARの定番ライブラリの概要とその使い方の説明。取り扱っている主なライブラリとしては、DB、MDB2、HTML_QuickForm、Mail、Cache_Lite、Log、Config、HTTP_Request、Auth、Text_CAPTCHA、Pager、Services_Amazon、HTML_AJAXなどです。ここにあげたもの以外にも載っています。

PART3:サード・パーティのパッケージとして、Pearifiedチャネルサーバのライブラリもいくつか紹介されています。Pearified::Javascript_Prototype、JavaScript_Scriptaculous、Pearified::Editors_FCKeditor、Pearified::Smartyです。PHPUnitやPhing、Propelなどが載っています。そのほかにはSymfonyもPEARコマンドからインストールできるので、symfonyの説明なんかも載っています。

PART4:チャネルサーバーを構築する方法と、パッケージの作成やその管理方法などの紹介です。

PEARで良く使うような有名どころのライブラリはだいたい紹介されていると思います。また、一般的にはPEARライブラリという認識ではないのですが、prototype.jsやscript.aculo.us、SmartyなどをPEARコマンドから入るからといって紹介してしまう強引さがちょっと好きです。同じ理屈でSymfonyの説明までしてくれるのはお徳ですね。PHPUnitやPhing、Propelの説明があるのもいいですね、symfonyを本気で学ぶのであれば、他のsymfony本を見たほうがいいですが、概要だけでも知っておきたいという場合は、この本の内容だけでも十分かもしれません。

面白いなと思ったのが、チャネルサーバーの構築方法が載っていることです。こういう形で書籍化されると、「PEARのライブラリに登録するほどの自信はないけれど、でも多くの人に使ってもらいたい!」っていう人が、自分たちのライブラリをチャネルサーバーを立てて発信しやすくなりますね。

2007/12/26:たまたま本屋で見かけたので、手にとって見たらびっくりでした。内容違げーじゃねーかwこの記事はcbook24.comのこの本の目次を参考に書いたのですが、Part3はSymfony以外全部違いますね。正確な情報がネットにないような気がしたので、買ってきました。目次載せます。

  1. PEARのしくみとインストール
    1. PEARとは
      1. PEARパッケージとパッケージマネージャ
      2. http://pear.php.net/サイト
      3. チャネル
    2. PEARパッケージマネージャのインストール
      1. PEARのディレクトリ構造
      2. Windowsでのインストール
      3. http://pear.php.net/go-pearによるインストール
      4. PEARのローカルコピーの作成
      5. include_pathディレクティブの設定
    3. パッケージのインストール
      1. パッケージの基本的なインストール方法
      2. 依存性の自動的解決
      3. パッケージのバージョンアップ
      4. パッケージのダウンロード
      5. ダウンロードファイルのインストール
      6. URLによるインストール
      7. PEARパッケージ情報の取得
    4. チャネル
      1. チャネルの登録
      2. 登録済みチャネル一覧表示
      3. チャネル情報
      4. チャネルで配布されるパッケージリスト
      5. パッケージのインストール
      6. インストールされたパッケージの一覧表示
      7. チャネル情報の更新
      8. 性的なURIによるパッケージ
    5. Web-based PEAR Frontend
      1. Web-based PEAR Package Managerのインストール
      2. パッケージのインストール
      3. チャネルサーバーのパッケージのインストール
  2. PEARパッケージ
    1. ログ記録 (PEAR::Log)
      1. PEAR::Logとは
      2. ログ記録の基本的な使い方
      3. インスタンス生成
      4. ログレベル
      5. ログの出力
      6. 出力先の指定
    2. ダンプ (PEAR::Var_Dump)
      1. PEAR::Var_Dumpとは
      2. Var_Dumpパッケージとvar_dump()関数
      3. display_mode
      4. Table用オプション
      5. Text用オプション
    3. 設定ファイル (PEAR::Config)
      1. PEAR::Configとは
      2. 設定値取得の基本手続き
      3. 設定ファイルの形式
      4. 設定ファイルの作成
      5. さまざまな設定ファイル
    4. キャッシュ (PEAR::Cache_Lite)
      1. PEAR::Cache_Liteとは
      2. キャッシュの基本手順
      3. ページのキャッシュ
      4. 関数のキャッシュ
    5. HTTPリクエスト (PEAR::HTP_Request)
      1. PEAR::HTTP_Requestとは
      2. リクエストの基本手順
      3. リクエストパラメータの送信
      4. リクエストヘッダ
      5. クッキーの送信
      6. Basic認証
      7. ファイルのアップロード
    6. ファイルダウンロード (PEAR::HTTP_Download)
      1. PEAR::HTTP_Downloadとは
      2. ダウンロードの基本手順
      3. set系メソッドを使ったダウンロード
      4. スタティックメソッドを使ったダウンロード
      5. 動的に生成したデータのダウンロード
      6. 複数ファイルをまとめて圧縮してダウンロード
    7. メール (PEAR::Mail、PEAR::Mail_Mime)
      1. PEAR::Mailとは
      2. メール送信の基本手順
      3. PEAR::Mail_Mimeとは
      4. マルチパートメールの送信
    8. フォーム出力 (PEAR::HTML_QuickForm)
      1. PEAR::HTML_QuickFormとは
      2. HTML_QuickFormの要素
      3. フォームデータの検証
      4. PEAR::HTML_QuickForm2
      5. fieldsetによる要素のグループ化
      6. HTML_QuicForm2の要素とパラメータの設定
      7. データの一括指定
    9. データベース (PEAR::MDB2)
      1. PEAR::MDB2とは
      2. データベース接続の基本手順
      3. DSN
      4. 結果の取得
      5. クォート処理
      6. プリペアドステートメント
      7. トランザクション
      8. データベースの管理
    10. ユーザー認証 (PEAR::Auth、PEAR::Auth_HTTP)
      1. PEAR::Authとは
      2. 認証情報の管理
      3. HTTP認証
    11. 認証用コード画像生成 (PEAR::Text_CAPTCHA)
      1. PEAR::Text_CAPTCHAとは
      2. Text_CAPTCHAによる画像の生成
    12. メニュー生成 (PEAR::HTML_Menu)
      1. PEAR::HTML_Menuとは「
      2. メニュー表示の基本手順
      3. メニューデータのデータ構造
      4. HTML_Menuの出力モード
    13. ページング (PEAR::Pager)
      1. PEAR::Pagerとは
      2. Pagerの基本的な使い方
      3. Pagerの動作モード
      4. アイテムの表示
      5. 表示件数の変更
    14. Tag Cloud (PEAR::HTML_TagCloud)
      1. PEAR::HTML_TagCloudとは
      2. HTML_TagCloudの基本的な使い方
      3. タグの一括追加
      4. フォントカラーのカスタマイズ
    15. RSS解析 (PEAR::XML_RSS)
      1. RSSとは
      2. XML_RSSによるRSSのパース
    16. Webサービス (PEAR::Services_Amazon)
      1. PEAR::Services_Amazonとは
      2. Services_Amazonによる処理の流れ
      3. ヘルプ情報の取得
    17. Ajax (PEAR::HTML_AJAX)
      1. PEAR::HTML_AJAXとは
      2. リモートファイルの取得
      3. リモートクラスのメソッドの実行
      4. Proxyクラス
  3. サード・パーティのパッケージ
    1. テストツール (PHPUnit)
      1. PHPUnitとは
      2. PHPUnitの基本的な使い方
      3. テスト結果と実行制御
      4. 例外のテスト
      5. スケルトンの自動生成
      6. @assertアノテーション
    2. ビルドツール (Phing)
      1. Phingとは
      2. Phingの基本的な使いかた
      3. build.xmlの書式
      4. Phingによるテストの自動化
      5. Phingによるパッケージの作成
    3. O/Rマッピング (Propel)
      1. Propelとは
      2. データベース走査モデルの自動生成
      3. Propelクラスを使用したデータベース操作
      4. バリデーション
    4. フレームワーク (Symfony)
      1. Symfonyとは
      2. アプリケーションの作成
      3. Symfonyの設定
      4. Symfonyのヘルパー
      5. フォームの検証
      6. データベースへのアクセス
  4. チャネルサーバの構築
    1. パッケージとチャネルサーバのしくみ
      1. package.xml
      2. tarballの作成
      3. channel.xml
    2. チャネルサーバの構築
      1. Chiara_PEAR_Serverによるチャネルサーバの構築
      2. PEAR_PackageProjectorを使ったパッケージの作成
      3. パッケージのリリースと管理
      4. 依存関係のあるパッケージ
    3. コーディング規約
      1. 書式などの指針
      2. 命名規則
      3. phpDocumentorによるドキュメントの作成

書籍実物より目次部を引用

佐久嶋 ひろみさんの著書