Apache のリライトまとめ

いつも、「これはどうするんだっけ?」「これは何が来るんだっけ?」と忘れてしまうため、備忘録として残します。 (.htaccess に書く場合)
内容が間違っている可能性もありますので、ご参考まで。

.htaccess に書かれたリライトは、深い階層のものが優先的に適用される

上位のパスでリダイレクトをかけようとしても、下位に .htaccess があってリライトの指定がある場合(RewriteEngine on がある場合)はそちらが優先される。

RewriteRule には正規表現とリライト後のパスを書く

RewriteRule <指定されたパスにマッチさせる正規表現> <リライト後のパス>
ということ。

RewriteRule のすぐ後ろには、指定されたパスにマッチさせるための正規表現を書く

例えば http://hoge.test/abc/ へのアクセスで、/ に .htaccess がある場合は、abc/ とのマッチになる。
http://hoge.test/abc/def/ へのアクセスで、/abc に .htaccess がある場合は、def/ とのマッチになる。
頭にスラッシュはつかない。
したがって http://hoge.test/abc/ へのアクセスで / に .htaccess がある場合は、abc や abc/ や . などがマッチする。/abc にはマッチしない。一部でもマッチすれば適用される。

書くものは正規表現なので、 index.html と書いた場合にはこのドットは正規表現の任意の一文字を表すものであって、ドットそれ自体ではない。 つまり index\.html でもマッチする。

なおURLのルート、例えば http://hoge.test/ へのアクセスにマッチさせたい場合、Rewrite / /top/ などと書いてもマッチしない。
この場合はマッチ対象の文字列は空文字列となるので、.* などでなければマッチしない。

RewriteRule が複数ある場合は上にあるものから順に適用される

そういうルールとなっている。

RewriteRule は、RewriteRule に適合しなくなるまで繰り返し評価される

RewriteRule abc.html def.html # (A)
RewriteRule def.html ghi.html # (B)

となっていたときに abc.html へのアクセスが来ると、内部的にはこう動作する。

  1. abc.html が abc.html と一致するか → 一致するので def.html へリライト--- (A)の評価
  2. def.html が def.html と一致するか → 一致するので ghi.html へリライト --- (B)の評価
  3. ghi.html が abc.html と一致するか → 一致しないのでこの RewriteRule は無視 --- (A)の評価
  4. ghi.html が def.html と一致するか → 一致しないのでこの RewriteRule は無視 --- (B)の評価
  5. すべての RewriteRule に一致しなかったので終了 ghi.html がリライト後のパスとなる

直感的には 2 までで終わりそうだが、上記の通り、適合するものがなくなるまで繰り返し適用される。

RewriteRule の [L] フラグは、上記の評価の繰り返しを止めるものではない

RewriteRule abc.html def.html # (A)
RewriteRule def.html ghi.html [L] # (B)
としても、ghi.html が abc.html と def.html にマッチするかは評価される。

RewriteRule abc.html def.html [L] # (A)
RewriteRule def.html ghi.html # (B)
となっている場合は、(A) の評価後いったんはそこで停止するが、評価は繰り返し行われるため、この場合は結局以下のようになる。

  1. (A) の評価 def.html へリライト --- [L]があるので(B)の評価に進まず、また最初から評価が始まる
  2. (A) の評価 マッチせず
  3. (B) の評価 ghi.html へリライト
  4. (A) の評価 マッチせず
  5. (B) の評価 マッチせず
  6. 終了


RewriteRule の [R] フラグがない場合は内部リダイレクトになる

リダイレクトをしたくてリライトを使うケースも多いが、HTTPのリダイレクトを行うには [R] フラグが必要となる。
RewriteRule abc.html def.html
RewriteRule def.html ghi.html
というルールで abc.html にアクセスした場合は、表示されるコンテンツは ghi.html になるが、ブラウザのアドレス上は abc.html のままであるし、ブラウザから ghi.html へのリクエストが出るわけではない。

リダイレクトしたいだけなら Redirect ディレクティブの使用を検討する

単にページが移動したなどの場合は、リライトを使うまでもなく Redirect ディレクティブで十分なケースもある。




正規表現のおさらい (4)

正規表現のおさらいシリーズ
その1:http://developer.venture-net.co.jp/entry/2018/06/22/174206
その2:http://developer.venture-net.co.jp/entry/2018/06/29/192116
その3:http://developer.venture-net.co.jp/entry/2018/07/06/185719

今回は第4弾です。

後方参照

正規表現は複雑な文字列パターンを探す場合に有用ですが、文字列パターンを置換する場合にも非常に強力に機能します。

丸括弧でくくったものはグループ化されるということは以前におさらいした通りです。このグループ化された部分は、後から参照することができます。

後からというのはいつなのかということになりますが、これは正規表現を実際に利用する環境・プログラミング言語・ソフトウェアによりますが、置換後の指定をするところになります。

例えば JavaScript では、/ (スラッシュ)で囲んだものは正規表現オブジェクトになります。
/[abc]/ とすれば、a か b か c の1文字、ということになります。
そして、文字列の置換を行う場合は文字列オブジェクトの replace メソッドを使用します。

'abcdef'.replace('a', 'b'); とすれば、文字列 abcdef について、a を b に置換する、ということになり、この置換前の文字列には、正規表現を指定することができます。

'abcdef'.replace(/a/, 'b'); とすることもできるというわけです。

つまりこの replace メソッドの2番目の引数が置換後の指定をするところであり、上記ではそれに 'b’ を指定したということになります。


本題です。

ある9桁の数字を、3桁ごとに区切ってハイフンを入れたいとします。例えばこうです。

123456789 → 123-456-789

このような置換を行う場合、まず正規表現はどうなるでしょうか。数字が9桁なので、/[0-9]{9}/ と書くことができます。 しかしここでは3桁ごとにグループ化したいので、

/([0-9]{3})([0-9]{3})([0-9]{3})/ のように書いてみます。これも、「0から9までのどれかが3つきて、その後に0から9までのどれかが3つきて、その後に0から9までのどれかが3つくる」という正規表現なので、9桁の数字にマッチします。

この丸括弧で囲ったグループ化した部分は、置換後の指定で使うことができます。この機能を 後方参照 と呼びます。
JavaScript では、後方参照は $ と数字であらわします。例えば $1 や $2 のようになります。$1 は1つ目のグループ、$2 は2つ目のグループということになります。

まとめると、9桁の数字を3桁ごとに区切ってハイフンを入れるには、以下のようになります。

正規表現:/([0-9]{3})([0-9]{3})([0-9]{3})/
置換後の文字列:$1-$2-$3

JavaScript で書くことこうなります。

var s  = '123456789'.replace(/([0-9]{3})([0-9]{3})([0-9]{3})/, '$1-$2-$3');






正規表現のおさらい (3)

前々回前回正規表現についておさらいしてきました。
今回は最長マッチと最短マッチについておさらいします。

最長マッチ

繰り返しを表現するものとして、?、*、+ がありました。* や + は0/1回以上 の繰り返しにマッチするわけですが、それでは a+ という正規表現は、文字列 "aaaab" のどこにマッチするのでしょうか。
これは aaaa にマッチします。デフォルトでは、可能な限り長くマッチするように動作します。このことを指して、最長マッチ とか 最長一致 と言ったりします。

最短マッチ

最長マッチの逆で、マッチ可能の部分で最も短いところにマッチする指定を 最短マッチ といい、* や + の後ろに ? をつけることで最短マッチになります。
a+? という正規表現は、文字列 "aaaab" の最初の a にマッチします。



上記の通り * や + はデフォルトでは最長マッチなのですが、それでは少し困る場合があります。例えばHTMLコードでaタグを探したいとします。

aタグは、 <a href="/">HOME</a> のように 開始タグ、テキスト、終了タグ からなり、開始タグにはいくつかの name="value" 形式の属性を指定することができます。

単純に考えると、これを抜き出すための正規表現はこのようになります。

<a .+</a>

つまり、
・<a が来て
・そのあとに空白が1つ来て
・そのあとに任意の文字が1つ以上来て
・最後に </a> という終了タグが来る
ということになります。
属性やリンクテキストがどのような文字で構成されるかはわかりませんから、.+ を使ってどのような文字にもマッチさせる試みは正しいように思われます。

しかしこれには落とし穴があります。

<a href="/">HOME</a> <a href="/access">ACCESS</a> <a href="/contact">CONTACT</a> とaタグが3つ並んでいる文字列の場合はどこにマッチするでしょうか。
この場合は、頭の <a から最後の </a> までの全体にマッチしてしまいます。 普通はこのようにマッチさせたいことはなく、それぞれのaタグにマッチさせたいはずです。

なぜこのようになるのかといえば、.+ が </a> にもマッチしてしまうからです。.+ は任意の文字が1回以上ですから、</a> にマッチするのは誤りではありません。 そしてデフォルトでは最長マッチのため、可能な限り長く -- 一番最後の </a> の手前までマッチしてしまうというわけです。

ここで最小マッチが活きます。 <a .+?</a> という正規表現であれば、マッチ可能な最小の長さでマッチするため、狙い通りの <a href="/">HOME</a> にマッチすることになります。




正規表現のおさらい (2)

前回の記事正規表現のごくごく基本をおさらいしましたので、今回もう少し進んでおさらいしてみたいと思います。

任意の一文字にマッチする - . (ピリオド)

| (縦棒) を使うことで、どれかにマッチするという正規表現を記述できました。
ha((ve)|s|d) と書けば、have、has、had のいずれにもマッチさせることができます。
もし、そのバリエーションがもっとたくさんあって、 どれ と限定することができない場合は、任意の一文字にマッチする . (ピリオド/ドット) というメタ文字を使います。

これを使って ha. と書いた場合は、hai hae ham hap などなど、ha のあとにどんな文字が来てもマッチします。
また h.s と書いた場合には、has his hes hvs など、h と s の間にどんな文字が来てもマッチすることになります。

もちろん . は続けて書くこともできます。 h.. と書けば、h のあとにどんな二文字が来てもマッチするということになります。

どれか1つにマッチする - [] (角かっこ)

. を使うとすべての文字にマッチしますが、すべてではないものの全部にマッチさせたいわけではない場合には、[] (角かっこ) を使うことができます。 h[aiev]s と書いた場合には、has his hes hvs にマッチし、haas hos hs などにはマッチしません。[] の中のどれか一文字にマッチします。
これだけなら h(a|i|e|v)s と書くこともできますが、[
] の特徴は文字の範囲指定ができることと、それを含まないという表現ができることです。

[] では文字の範囲をハイフンを用いて指定することができ、例えば h[a-d]s と書いた場合は、has hbs hcs hds にマッチします。つまり [a-d] は a b c d のどれかということになります。

そして、[] の中で先頭に ^ をつけた場合、例えば h[^a]s と書いた場合は、「hの次にa以外の文字が来てsが来た場合」をあらわします。
ですから h[^a]s の場合は、his hos hes などにマッチし、has にはマッチしません。 h[^a-d]s と書いたなら、his hos hes などにマッチし、has hbs hcs hds にはマッチしないということになります。

これを使えば、「アルファベット一文字」は [a-zA-Z] とあらわすことができます。数字一文字は、[0-9] とあらわすことができます。

決まった繰り返し回数 - {} (大かっこ)

繰り返しを指定するものとしては、? が0か1回、+ が1回以上、* が0回というのは前回おさらいした通りです。
{} を使うと、決まった回数の繰り返しを指定することができます。 例えば a{3} などと書きます。{3} であれば、{3} の直前が3回連続してあらわれた場合を意味します。したがって a{3} であれば aaa にマッチします。 a+ の場合、a や aa にもマッチしますが、a{3} では a や aa はマッチしません。

さらに、{1,3} などの書き方をすることができ、この場合は「1回以上3回以下」のように回数の範囲を表現することができます。
a{1,3} であれば、a aa aaa にマッチします。aaaa にはマッチしない - と勘違いしてしまいそうになりますが、a{1,3} だけであれば、aaaa の場合は最初の三文字の aaa 部分にマッチします。
xa{1,3}x であれば、xax や xaax にマッチしますが、xaaaax にはマッチしません。



正規表現のおさらい

テキスト処理をするのには欠かせない 正規表現 についておさらいしたいと思います。

コードを書く方であれば基本技術といって差し支えないほど、正規表現は強力なツールです。
ですが、コードを書かない方にとっても、正規表現は間違いなく強力なツールになります。 ぜひ簡単なところから使用してみていただきたいと思います。

そもそも正規表現とは:

正規表現(せいきひょうげん、英: regular expression)とは、文字列の集合を一つの文字列で表現する方法の一つである。 https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE より

ということで、文字列のパターンをあらわすものです。
これを駆使することによって、テキストの検索が非常に便利になることがあります。
例えば、あるテキストの中から "walk in" と "walkin" を抽出したいとします。普通に検索するならば、"walk in" と "walkin" で2回検索すればよいことです。
しかし、"walk-in" も検索したくなったらどうなるでしょうか。あるいは "walking" は抽出したくないとしたらどうなるでしょうか。 単なるテキスト検索では、複数回検索する必要があったり、抽出結果をフィルタしたりする必要が出てきます。

こんなときは、正規表現の出番です。
"walkin" も "walk-in" も "walk in" もすべて1つのかたちであらわすことができるるが、正規表現です。

正規表現は、任意の文字(列)と、特別な意味を与えるメタ文字から構成されます。
メタ文字以外は、普通のテキスト検索と同じようにヒットします。"walkin" は walkin という文字列にマッチします。(正規表現では、その表現が当てはまってヒットすることをマッチするという言い方をします)

正規表現ではメタ文字を使って、主に「繰り返す回数」「AまたはB」の組み合わせで記述します。

繰り返す回数

0回か1回

0回か1回を表すのは ? (はてなマーク) です。その ? の直前にあるものが、0回または1回あらわれることを意味します。
ですから、"walk ?in" という正規表現は、? の直前にある空白が0回または1回あらわれるときにマッチするので、"walkin" にも "walk in" にもマッチします。

0回以上

0回以上をあらわすのは * (アスタリスク) です。その直前にあるものが0回以上あらわれることを意味します。
"walk   in" という文字列に対して、"walk ?in" はマッチしません。"walk ?in" では、あらわれる空白は1回までです。 一方 "walk *in" という正規表現では、"walk   in" にもマッチします。

1回以上

1回以上をあらわすのは + (プラス記号) です。その直前にあるものが1回以上あらわれることを意味します。
"walk +in" なら、"walk in" にも "walk   in" にもヒットしますが、"walkin" にはヒットしません。

AまたはB

"walk in" にも "walk-in" にもマッチさせたい場合は、| (縦棒) を使います。 " |-" とすれば、空白かハイフンかどちらかにマッチする となります。 なお、 | がどれとどれの選択なのかを指示するために、丸括弧を使って | で選択する部分をくくります。
"( |-)"
丸括弧もメタ文字であり、丸括弧でくくったものをグループ化する意味があります。

ここまでのメタ文字を使って、冒頭の "walkin" "walk in" "walk-in" にマッチする正規表現は、以下のように記述することができます。
"walk( |-)?in"
まず walk が来て、そのあと空白かハイフンが0回または1回あらわれ、そのあと in が来る ということになります。

なお上記では "walking" の "walkin" 部分にもマッチしてしまいますが、正規表現の技巧を駆使すれば "walking" にはマッチしない正規表現を記述することもできます。



いまひとつな例でしたが、これまで正規表現を使ったことがない方も、簡単な正規表現から使い始めてみることをおすすめします。
きっとテキスト操作の効率化に寄与するはずです。



PHP でグラフ画像を作成する

Web アプリケーションなら、JavaScript でも高品質なグラフを描画することができますし、画像として保存することができるものもあります。
ただ今回、

  • サーバサイドでレポートを生成する
  • レポートは PDF ファイル
  • レポートにグラフを埋め込む

という要件があり、サーバサイドでグラフ画像を生成することになりました。
グラフを生成するためのライブラリはいくつかあるようですが、今回は pChart を使用しました。 公式はこちら↓

www.pchart.net

最初にライブラリを入手します。こちら からダウンロードします。 この記事を書いている時点では 2.1.4 が最新でしたので、これを落としてきます。 中身はこのようになっています。
pChart2.1.4
├─cache
├─class
├─data
├─examples
├─fonts
└─palettes


コードを書きます。この3ファイルを取り込みます。

require_once 'pChart2.1.4/class/pData.class.php';
require_once 'pChart2.1.4/class/pDraw.class.php';
require_once 'pChart2.1.4/class/pImage.class.php';


主に使用するクラスは pData と pImage になります。(が pDraw も require が必要です)
「pData の内容を pImage を使って出力する」というイメージです。
グラフのデータを pData で設定します。

$data = new pData();
$data->addPoints([1, 2, 3, 4], 'data1');
$data->addPoints([5, 6, 7, 8], 'data2');


pData を生成して addPoints でデータを設定します。そのデータが何なのか、名前も一緒に指定します。気温の変化であれば、
addPoints([20.1, 22.3, 21.8, 23.4], 'temperature'); などのようになるでしょう。 今回欲しかったのは積み上げ棒グラフなので、複数回 addPoints しています。


ラベルの設定も addPoints で行います。

$data->addPoints(['A', 'B', 'C', 'D'], 'labels');
$data->setAbscissa('labels');


ラベル用のデータにつけた名前を、setAbscissa に指定します。
データの設定はこれで終わりです。次に pImage です。

$image = new pImage(800, 400, $data);
$image->setGraphArea(50, 30, 700, 360);
$image->setFontProperties(['FontName'=>'pChart2.1.4/fonts/calibri.ttf', 'FontSize'=>15]);


pImage のコンストラクタに、画像のサイズと pData を渡します。さらに、その画像中のどこがグラフの領域になるかを setGraphArea で指定します。
この例なら、左から50px上から30pxの点と、左から700px上から360pxの点で表される領域です。
そして setFontProperties で使用するフォントファイルを指定します。この例ではライブラリに付属のものを指定していますが、日本語を使用したい場合は IPA フォントなどのパスを指定します。 OTF も使用できます。

グラフを描画します。

$image->drawScale(['Mode'=>SCALE_MODE_ADDALL]);
$image->drawStackedBarChart();
$image->autoOutput('graph.png');


drawScale には様々なオプションを指定することができ、目盛りを制御することができます。
drawStackedBarChart で積み上げ棒グラフの描画を行います。グラフの種類によってコールするメソッドを切り替えます。
autoOutput に出力先ファイルパスを渡し、画像ファイルとして出力します。これでグラフ画像が得られます。

コードの全体と出力された画像は以下になります。

<?php
require_once 'pChart2.1.4/class/pData.class.php';
require_once 'pChart2.1.4/class/pDraw.class.php';
require_once 'pChart2.1.4/class/pImage.class.php';

$data = new pData();
$data->addPoints([1, 2, 3, 4], 'data1');
$data->addPoints([5, 6, 7, 8], 'data2');
$data->addPoints(['A', 'B', 'C', 'D'], 'labels');
$data->setAbscissa('labels');

$image = new pImage(800, 400, $data);
$image->setGraphArea(50, 30, 700, 360);
$image->setFontProperties(['FontName'=>'pChart2.1.4/fonts/calibri.ttf', 'FontSize'=>15]);
$image->drawScale(['Mode'=>SCALE_MODE_ADDALL]);
$image->drawStackedBarChart();
$image->autoOutput('graph.png');

f:id:venturenet:20180615145133p:plain



最後に、pChart には 1.X 系と 2. X系が存在し、この両者に互換性はありません。 ネット上で pChart について調べ物をするときには、そのページがどちらのバージョンのことを書いているのか、気をつけてみるようにした方がよいかと思います。


docforce2でSalesforceのオブジェクト設計書を自動生成する

データベーススキーマを設計する場合は、ER図を書いたり何らかの設計書を書くというのが普通かと思いますが、Salesforce では簡単にオブジェクトの構造を構築することができるため、良し悪しは別にして設計書の類は作成せずに開発を進めることも多いかと思います。
しかし後から設計書を要求されたり、あるいはオブジェクト構造を確認するのにドキュメントの方がやはりわかりやすいということで設計書が欲しくなることがあります。
こんなときは、DRY原則に従って Salesforce 上のオブジェクトからドキュメントを自動生成できると便利です。 今回はそのツールの1つ、docforce2 の使い方を備忘録として残しておきます。

Javaランタイムのインストール

Java のランタイムがインストールされていない場合は、まずここからダウンロードしてインストールします。

MavensMate のインストール

MavensMate(現在は開発終了) で出力されるデータが必要になるため、ここからダウンロードしてインストールします。
MavensMate-app-v0.0.10-win-x64-setup.zipでよいでしょう。

MavensMate でデータ出力

MavensMate を起動します。
最初にワークスペースディレクトリを指定します。メニューから Settings を開き、データを置くディレクトリを Workspaces で指定します。ここでは D:\temp\mm とします。

f:id:venturenet:20180608113557p:plain f:id:venturenet:20180608113609p:plain

次に、プロジェクトを作成します。 メニューから New Project を選択して New Project のタブを開き、ワークスペース、プロジェクト名、Salesforce のユーザ名、パスワード、本番/サンドボックス/開発環境のどれであるかを指定します。
これらの情報を入力したら、Project Metadata のタブを開きます。ここで、

  • ApprovalProcess
  • CustomObject
  • Workflow

の3つを選択しますが、それぞれのツリーを開いて少し待っているとその要素が表示されるので、その中から必要なものを選択します。 ただしここでは全部選択するのが無難かもしれません。 選択したら Create Project ボタンをクリックしプロジェクトを作成します。

f:id:venturenet:20180608114331p:plain f:id:venturenet:20180608114341p:plain

プロジェクトが作成されると、ワークスペースとして指定したディレクトリにデータが出力されます。

docforce2 のインストール

GitHub - nyasba/docforce2: salesforce document generator から git で引っ張るか zip をダウンロードします。 ここでは zip でダウンロードして、D:\temp\docforce2-master に設置したものとします。

docforce2 の設定と実行

基本的には ここ に書かれている通りです。 出力対象のオブジェクトを設定するために、zip で展開したディレクトリの直下にある docforce.yml を開きます。
inputBaseDir には、先程出力したデータのパスを指定します。D:\temp\mm\<プロジェクト名>\src になります。
outputDir には出力先ディレクトリを指定します。

inputBaseDir : "D:/temp/mm/Test/src"
outputDir : "output"
resources :
    - resource :
          object : "objects/Account.object"
          approvalProcesses : 
          workflow : "workflows/Account.workflow"
          author: "test"


  • 承認プロセスがなくても approvalProcesses のキーだけは指定する
  • ワークフローがなくても、workflow のキーと値は指定する
  • インデントがずれないように注意する (ずれるとエラーになります)

という点に気をつけましょう。

設定ができたら、コマンドラインで実行します。

D:\temp\docforce2-master>gradlew run


環境、設定に誤りがなければ、これでオブジェクトごとに Excel ファイルで設計書が出力されます。