なかなか新しいことを覚えるのもしんどい今日この頃ですけどね。
WordPressを勉強しなきゃならない状況になりました。
勉強って、まぁ、自分で自在にプラグインを作れるレベルを指します。
う~ん、これ系、XOOPS以来ですね。
XOOPS、見事に消えちゃいました。
まあ、社内システムでわずかにささやかに動いてますけどね。
とは言え、WordPressも、好きなPHPですからね。しかしコーディング規約を見て、早くもめげそうです。
pdfと組版と画像処理とc++とphpとjavascriptとhtml5とcss3とjQueryとjQueriUIとjQueryMobileとRadStudioとAndroidSDK/NDKとWordPressとWelcartを統合するエンジニア的視点。。廃止→as3とflashとflex 追加→柔道
2015年2月21日土曜日
WordPressのプラグインをつくらなきゃいけない件
2014年6月26日木曜日
画像を縮小する(平均化)する件。
アルファチャンネルにアルファチャンネルを重ねる件とも似通った話ですが、画像を縮小化する場合の処理を考えてみます。
簡単に考えるために、2ピクセルを1ピクセルにすることを考えます。
もちろん、□と■を平均化すれば、中間のグレイになるだろうことはだれでも予想がつきます。
では、R1G1B1A1とR2G2B2A2を平均するにはどうすればよいか。
正しい方法ではないですが、特殊解から一般解を導くとたいてい合っている!
という方法があります。
そうすると、
0x00FFFFFF と 0xFFFFFFFF を混合すれば、、
0x80FFFFFF と なりそうなことは容易に想像できます。
※または、0x7FFFFFFF
ということは、、アルファの値は単純に平均をとるだけでいいような気がするので、
いいということにしましょう。
問題は、RGB部分のFFFFFFというところです。
これだけみると間違った方法をとってしまいそうなので、
別の特殊解を考えて見ます。そう、
0x00FF0000 と 0xFFFFFFFF を混合しても、、
0x80FFFFFF と、同じ結果となります。
当然と言えば当然で、アルファが0であれば、RGBが何であっても
表示上は何も無いので同じわけです。
さぁ、ここで、これらを黒地に置いた場合を考えると、
0x00FF0000 → 0xFF000000
0xFFFFFFFF → 0xFFFFFFFF
そうすると、前回と同じように、V1、α1、V2、α2とすると、
V1=100、α1=0
V2=100、α2=1.0
結果→α3=0.5、V3=100
とすると、どうやら、(V1α1+V2α2)/2 が、黒地に置いたときの実際の値と思われるので、
V3=((V1α1+V2α2)/2)/α3
=((0*100)/2)/0.5=50/0.5=100 という感じと予測できます。
V1=100、α1=0.5とすれば、
V3=(150/2)/0.75=75/0.75=100 となり、V3=100、α3=0.75となるので、
これでもあってるっぽいですね。
で、結論としては、
●αは単純に平均化するのみ
●RGBはそれぞれの要素に関して、αをかけたR´G´B´を足し合わせて平均化し、
平均化されたαで割り返す
となります。
簡単に考えるために、2ピクセルを1ピクセルにすることを考えます。
もちろん、□と■を平均化すれば、中間のグレイになるだろうことはだれでも予想がつきます。
では、R1G1B1A1とR2G2B2A2を平均するにはどうすればよいか。
正しい方法ではないですが、特殊解から一般解を導くとたいてい合っている!
という方法があります。
そうすると、
0x00FFFFFF と 0xFFFFFFFF を混合すれば、、
0x80FFFFFF と なりそうなことは容易に想像できます。
※または、0x7FFFFFFF
ということは、、アルファの値は単純に平均をとるだけでいいような気がするので、
いいということにしましょう。
問題は、RGB部分のFFFFFFというところです。
これだけみると間違った方法をとってしまいそうなので、
別の特殊解を考えて見ます。そう、
0x00FF0000 と 0xFFFFFFFF を混合しても、、
0x80FFFFFF と、同じ結果となります。
当然と言えば当然で、アルファが0であれば、RGBが何であっても
表示上は何も無いので同じわけです。
さぁ、ここで、これらを黒地に置いた場合を考えると、
0x00FF0000 → 0xFF000000
0xFFFFFFFF → 0xFFFFFFFF
そうすると、前回と同じように、V1、α1、V2、α2とすると、
V1=100、α1=0
V2=100、α2=1.0
結果→α3=0.5、V3=100
とすると、どうやら、(V1α1+V2α2)/2 が、黒地に置いたときの実際の値と思われるので、
V3=((V1α1+V2α2)/2)/α3
=((0*100)/2)/0.5=50/0.5=100 という感じと予測できます。
V1=100、α1=0.5とすれば、
V3=(150/2)/0.75=75/0.75=100 となり、V3=100、α3=0.75となるので、
これでもあってるっぽいですね。
で、結論としては、
●αは単純に平均化するのみ
●RGBはそれぞれの要素に関して、αをかけたR´G´B´を足し合わせて平均化し、
平均化されたαで割り返す
となります。
2014年6月25日水曜日
アルファチャンネルにアルファチャンネルにを重ねる件(3)
で、前回、こんなことを書いたわけです。
そうです。白(0xff)の上に画像を置いた揚句、
= V1 * alp1 + V2 * alp2 - V1 * alp1 * alp2(式1)
--------------------------------------------------
●元ピクセル
値V1、α:alp1
●のせる方のピクセル
値V2、α:alp2
としたとき合成したピクセルの値(B)は、
A = (0xff * (1-alp1) + V1 * alp1) * (1-alp2) + V2 * alp2
alp3 = alp2 + alp1*(1-alp2)
B = (A - 0xff*(1-alp3))/alp3
--------------------------------------------------
しかし、ハタと気づくわけです。
または感じるわけです。
何かが美しくないと。(o^^o)
そうです。白(0xff)の上に画像を置いた揚句、
あとからその部分を取り除くような考え方をしているわけです。
じゃぁ、黒の上に置いたらどうなるか。
そうすると、0xFFの部分が0になるわけなので、
A = (V1 * alp1) * (1-alp2) + V2 * alp2
alp3 = alp1 + alp2 - alp1*alp2(式2)
B = A /alp3
2014年6月24日火曜日
アルファチャンネルにアルファチャンネルにを重ねる件(2)
で、色が違うときの話です。
まず、サンプル。

では、重なり部分のR成分の計算。
0xff * 0.5 + 0xff * 0.5 = 0xff
0x80*0.3 + 0xff * 0.7 = 0xD9
では、重なり部分は、
(0xff * 0.5 + 0xff * 0.5) * (1-0.3) + 0x80 * 0.3=0xD9
うんうん。ここまではあってますね。
では、前回と同じように合成後のアルファを考えると、
0.3 + 0.5 * (1-0.3)→0.65となる。
0.5 + 0.3 * (1-0.5)→0.65.もちろん同じ。
0xff * 0.35 + A * 0.65 = 0xD9
よって、
0xD9-0xff*(1-0.65)→0xC5
これをRGB要素全てに適用すればできる。。ハズ。
また重なってない部分を考えると、
0.3 + 0 * (1-0.3) →0.3
0xff*0.7 + A * 0.3 = 0xD9
A=0xff、アルファ:0.3
うん。できてるな。(o^^o)
ということで、
●元ピクセル
値V1、α:alp1
●のせる方のピクセル
値V2、α:alp2
A = (0xff * (1-alp1) + V1 * alp1) * (1-alp2) + V2 * alp2
alp3 = alp2 + alp1*(1-alp2)
B = (A - 0xff*(1-alp3))/alp3
となります。
地道に展開したらもしかして簡単になるのでしょうか。。。
やってみますわー。
っといましたが、かここであることに気付くわけです。
で、それは次回で(o^^o)
まず、サンプル。

では、重なり部分のR成分の計算。
0xff * 0.5 + 0xff * 0.5 = 0xff
0x80*0.3 + 0xff * 0.7 = 0xD9
では、重なり部分は、
(0xff * 0.5 + 0xff * 0.5) * (1-0.3) + 0x80 * 0.3=0xD9
うんうん。ここまではあってますね。
では、前回と同じように合成後のアルファを考えると、
0.3 + 0.5 * (1-0.3)→0.65となる。
0.5 + 0.3 * (1-0.5)→0.65.もちろん同じ。
0xff * 0.35 + A * 0.65 = 0xD9
よって、
0xD9-0xff*(1-0.65)→0xC5
これをRGB要素全てに適用すればできる。。ハズ。
また重なってない部分を考えると、
0.3 + 0 * (1-0.3) →0.3
0xff*0.7 + A * 0.3 = 0xD9
A=0xff、アルファ:0.3
うん。できてるな。(o^^o)
ということで、
●元ピクセル
値V1、α:alp1
●のせる方のピクセル
値V2、α:alp2
としたとき合成したピクセルの値(B)は、
A = (0xff * (1-alp1) + V1 * alp1) * (1-alp2) + V2 * alp2
alp3 = alp2 + alp1*(1-alp2)
B = (A - 0xff*(1-alp3))/alp3
となります。
地道に展開したらもしかして簡単になるのでしょうか。。。
やってみますわー。
っといましたが、かここであることに気付くわけです。
で、それは次回で(o^^o)
アルファチャンネルにアルファチャンネルを重ねる件。
アルファチャンネル付き画像に、
アルファチャンネル付き画像を乗せたときの結果が、
PHP画像合成のバグもこの範疇に入ると思われます。
ということで、計算しやすくするため、以下の画像を考えます。
これは、イラレで矩形を透過属性付きで作成したもので、
黒白はα=1、
右の赤の矩形はα=80%
左と中央の赤の矩形はα=40%
■白の上に赤40%→#FF9999。
R要素→ FF*60%+FF*40% → 0xff
GB要素→ FF*60%+00*40% → 153 → 0x99
よって、FF9999
■黒の上に赤40%→#660000。
R要素→ 00*60%+FF*40% → 0x66
GB要素→ 00*60%+00*40% → 0x00
よって、660000
■白の上に赤40%、さらに赤40%→#FF5C5C
さてここの考え方が、全てのポイントである。
GB要素→ FF*A%+00*40% → 92 → 0x5C
よって、Aは36%である。
ということは、明らかに、60%*60%である。
ようするに、アルファ:40%の画像の上に、アルファ30%の画像を載せたときの
アルファは、
30% + 40% * (100-30)% → 30+28 → 58% となる。
逆にすると、
40% + 30% * (100-40)% → 40+18 → 58% となり、やっぱり同じである。
シンプルな話なんですけどね。。。。。。(o^^o)
ただし、サンプルは同じ色のアルファだけ変えたサンプルなので、
色が違うときは、、、次回で。(-_-;)
アルファチャンネル付き画像を乗せたときの結果が、
思わしくない状況に遭遇することがあります。
では、何が正しいのかをちゃんと考えてみます。PHP画像合成のバグもこの範疇に入ると思われます。
ということで、計算しやすくするため、以下の画像を考えます。
これは、イラレで矩形を透過属性付きで作成したもので、
黒白はα=1、
右の赤の矩形はα=80%
左と中央の赤の矩形はα=40%
としました。
そして画面キャプチャをとって、ピクセルの値を調べた値を#テキスト表示しています。
■白の上に赤40%→#FF9999。
R要素→ FF*60%+FF*40% → 0xff
GB要素→ FF*60%+00*40% → 153 → 0x99
よって、FF9999
■黒の上に赤40%→#660000。
R要素→ 00*60%+FF*40% → 0x66
GB要素→ 00*60%+00*40% → 0x00
よって、660000
■白の上に赤40%、さらに赤40%→#FF5C5C
さてここの考え方が、全てのポイントである。
GB要素→ FF*A%+00*40% → 92 → 0x5C
よって、Aは36%である。
ということは、明らかに、60%*60%である。
ようするに、アルファ:40%の画像の上に、アルファ30%の画像を載せたときの
アルファは、
30% + 40% * (100-30)% → 30+28 → 58% となる。
逆にすると、
40% + 30% * (100-40)% → 40+18 → 58% となり、やっぱり同じである。
ただし、サンプルは同じ色のアルファだけ変えたサンプルなので、
色が違うときは、、、次回で。(-_-;)
2014年6月16日月曜日
PHPの画像合成のバグ
PHPで画像の合成なのですが、、
もちろん、
imagesavealphaと
imageAlphaBlendingを設定して、
imagecopyしたものを、
imagepng したわけですが、
こんな結果です。
●1

●2

●3
全て、中央の画像に右の画像を合成したものが左の画像なので、
本来は全て同じハズです。
違いは、中央の画像のα=0のピクセルのRGBの値が3つとも違い、
上から、0x000000(黒) 0xff0000(赤) 0xffffff(白)です。
要するにBLENDするときに、α=0の部分ももってきてしまって、
BLENDした挙句、αの値の平均でもとっているのでしょうかね。
どっちにしても、ダメっすねー。
まぁきちんと解明してみますです。(o^^o)
とりあえず、こういうバグがあるということでした。
追記
本来はこうあるべきというの作成。
上段がイラレで作成、
下段が自前のプログラムで作成。
残念ながら、僅かな誤差がありましたが(3Fと40とか^^;)、
基本的にはあっています。
imagesavealphaと
imageAlphaBlendingを設定して、
imagecopyしたものを、
imagepng したわけですが、
こんな結果です。
●1

●2

●3
全て、中央の画像に右の画像を合成したものが左の画像なので、
本来は全て同じハズです。
違いは、中央の画像のα=0のピクセルのRGBの値が3つとも違い、
上から、0x000000(黒) 0xff0000(赤) 0xffffff(白)です。
要するにBLENDするときに、α=0の部分ももってきてしまって、
BLENDした挙句、αの値の平均でもとっているのでしょうかね。
どっちにしても、ダメっすねー。
まぁきちんと解明してみますです。(o^^o)
とりあえず、こういうバグがあるということでした。
追記
本来はこうあるべきというの作成。
上段がイラレで作成、
下段が自前のプログラムで作成。
残念ながら、僅かな誤差がありましたが(3Fと40とか^^;)、
基本的にはあっています。
2013年4月2日火曜日
PHPでサロゲートペアをJSONで扱うときのバグ。(2)
とりあえず、こういう風に修正。
【PEARのJSON.php】
【PEARのJSON.php】
function bin2hexU16($utf16){
$ret = sprintf('\u%04s', bin2hex($utf16));
$n = strlen($ret);
if($n != 10) return $ret;
return substr($ret,0,6) . '\u' . substr($ret,6);
}
//旧
//$ascii .= sprintf('\u%04s', bin2hex($utf16));
//新
$ascii .= sprintf('%s', $this->bin2hexU16($utf16));
PHPでサロゲートペアをJSONで扱うときのバグ。
どうにもこうにもダメなのである。
何がって、PHPでサロゲートペアをJSONで扱う時のバグである。
以下、サンプルコード。
●json_encodeの場合
{"doc":{"info":{"t":"\ud800\udc0b"}}}
え?d800ってなんだ!?d840じゃないのか!!
●Services_JSONのencodeの場合
{"doc":{"info":{"t":"\ud840dc0b"}}}
え?d840dc0bって8桁じゃないか!?
ってことで、どっちにしてもダメです。
でも、PEARのJSONの方は、明らかに、
sprintf('\u%04s', bin2hex($utf16));
っていう行が発見できるので、8ケタの時は、\uを入れるように、ここを修正すればなんとかなる。
んーー。。やっぱこんなことやる人は、そうそういないってことだよなぁーー。
何がって、PHPでサロゲートペアをJSONで扱う時のバグである。
以下、サンプルコード。
require_once "JSON.php";
$json["doc"]["info"]["t"] = "𠀋";//0x2000Bが1文字
$jsonstr = json_encode($json);
file_put_contents("c:/tmp/2000C.txt",$jsonstr);
$jjj = new Services_JSON;
$jsonstr = $jjj->encode($json);
file_put_contents("c:/tmp/2000C-PEAR.txt",$jsonstr);
で結果なのだが、、●json_encodeの場合
{"doc":{"info":{"t":"\ud800\udc0b"}}}
え?d800ってなんだ!?d840じゃないのか!!
●Services_JSONのencodeの場合
{"doc":{"info":{"t":"\ud840dc0b"}}}
え?d840dc0bって8桁じゃないか!?
ってことで、どっちにしてもダメです。
でも、PEARのJSONの方は、明らかに、
sprintf('\u%04s', bin2hex($utf16));
っていう行が発見できるので、8ケタの時は、\uを入れるように、ここを修正すればなんとかなる。
んーー。。やっぱこんなことやる人は、そうそういないってことだよなぁーー。
2013年3月21日木曜日
C++でJSONを扱う件。
C++でJSONを扱う件です。
もちろん、
double pw = doc.info.pw;
のような形でアクセスできればCODINGもラクですが、
structやらclassやらを専用に準備してなきゃできないわけで、
動的には無理なわけです。
ということで、いろんなパーサとかを見てまわったのですが、
なかなかイイ感じのものがない。
『どうする?』 →つくりましょう!
STEP1
STEP1は、当然ながら、object型みたいなものを定義するところから始まります。
クラスでも構造体でもかまいませんが(C++において、classとSTRUCTはほとんど同じ)、
DOM的に、親、子、兄、弟を参照するポインタをもつobjectを定義すればいいのです。
さらに、このOBJECTを生成するようなコンテナもあったほうが、あとあと便利なので、そこからつくります。
即ち、
こうしておけば、Cのデストラクタで、createされたobjectをキレイに破棄できますよね。
。。つづく。。
★
もちろん、
double pw = doc.info.pw;
のような形でアクセスできればCODINGもラクですが、
structやらclassやらを専用に準備してなきゃできないわけで、
動的には無理なわけです。
ということで、いろんなパーサとかを見てまわったのですが、
なかなかイイ感じのものがない。
『どうする?』 →つくりましょう!
『だれがやる?』 →私でしょう!
『いつやるか?』 →今でしょう!
ということで、つくりました。
といっても、上記のようにはできるわけもなく、ここはPHP方式でやります。
即ち、
double pw = doc.info.pw;
ではなく、
double pw = D["doc"]["info"]["pw"];
って形です。
STEP1
STEP1は、当然ながら、object型みたいなものを定義するところから始まります。
クラスでも構造体でもかまいませんが(C++において、classとSTRUCTはほとんど同じ)、
DOM的に、親、子、兄、弟を参照するポインタをもつobjectを定義すればいいのです。
さらに、このOBJECTを生成するようなコンテナもあったほうが、あとあと便利なので、そこからつくります。
即ち、
objectContainer C; objson& o = *C.createObjectJson(); o["doc"]["info"]["pw"] = 297.0;みたいな使い方です。
こうしておけば、Cのデストラクタで、createされたobjectをキレイに破棄できますよね。
。。つづく。。
★
2013年3月12日火曜日
スマフォWEBアプリで写真をタイル表示させる件。(2)
ということで、タイル状に配置する件ですが、タテ長の場合、ヨコ長の場合に、
おおまかに言えば、【必ず入るように配置】の場合と、【部分的に正方形で表示】の場合が考えられます。まぁやりかたとしては大してかわりませんが、
【必ず入るように配置】は、以下ですね。
そして、部分画像と割り切って、正方形としてしまうのが、以下です。
スマフォのアプリなんかはこっちです。
もちろん、部分画像にした方が、切れてしまう部分はあるものの、
解像度としては高くなり有利ではあります。
でも、それは、写真の一覧だからであって、何かしらの選択の場合に、やはり全体をみて欲しいときもあります。その場合は前者になりますね。
どっちにしてもPHPでの実装は非常に簡単で、まず前者の場合。
【画像をLOAD】→【タテとヨコを測る】→【タテヨコ大きい方の数値で正方形の画像を生成】
→【LOADした画像を中央に配置】→【作成した画像をそのまま出力】
で完成。
後者の場合も、
【画像をLOAD】→【タテとヨコを測る】→【タテヨコ小さい方の数値で正方形の画像を生成】
→【LOADした画像を中央に配置】→【作成した画像をそのまま出力】
ということで、正方形にする時の辺の長さをどこをとるかだけの差です。
もちろんその場合に、サムネイル用の場合を考えれば、
あえて、縮小した大きさの正方形で作成するというのも、用途によってはアリですね。
ということで、PHPを。
エラー処理とかしてませんので(-_-;)
// $fn:ファイルパス
$localimage = imagecreatefrompng($fn); // PNGの時
// $localimage = imagecreatefromjpeg($fn); // JPEGの時
//------------------
$ww = imagesx ( $localimage );
$hh = imagesy ( $localimage );
//------------------
if($ww > $hh){
$hh2 = $ww;
$ww2 = $ww;
}else{
$ww2 = $hh;
$hh2 = $hh;
}
//------------------
$image = imagecreatetruecolor($ww2, $hh2);
$bgColor = imagecolorallocate($image, 0x0, 0x0, 0x0);
imagefill($image, 0, 0, $bgColor); // 背景を塗ってから
// imagecolortransparent($image,$bgColor); // 透明にしたいとき
$bb = imagecopy($image, $localimage,
(int)(($ww2 - $ww)/2), (int)(($hh2 - $hh)/2), // COPY先
0, 0, // COPY元
$ww, $hh);
if(is_resource ( $localimage )) imagedestroy($localimage);
header('Content-type: image/jpeg');
imagejpeg($img);
2013年3月8日金曜日
スマフォWEBアプリで写真をタイル表示させる件。
スマフォのアプリの写真をviewするやつなんか見ると、
当然のように、一覧表示があります。
一覧はだいたいタイル状になっていて、その中に画像が縮小されて表示されてる。
まぁ、あたりまえのコトのように実装されてますよね。

いや、でも、しかし、、、←今でしょう!とかじゃなくて、、、
これを、WEBアプリでやろうとすると、、いやぁー。。大変です。
そもそも、とある矩形にピッタリに入るように、タテまたはヨコを縮小表示させるなんて、
CSS的には、いくら探しても無いわけで。
じゃぁどうする!作りましょう!PHP側で。
ってコトで、2通り考えます。
ひとつは、jpegで表示。
ひとつは、pngで表示。
jpegだと透過できないので、bgcolorとあわせる必要がある。
pngだと容量が大きくなる。

まぁ、使い分けを考えて両方できるようにしましょう。
つづく。
当然のように、一覧表示があります。
一覧はだいたいタイル状になっていて、その中に画像が縮小されて表示されてる。
まぁ、あたりまえのコトのように実装されてますよね。

いや、でも、しかし、、、←今でしょう!とかじゃなくて、、、
これを、WEBアプリでやろうとすると、、いやぁー。。大変です。
そもそも、とある矩形にピッタリに入るように、タテまたはヨコを縮小表示させるなんて、
CSS的には、いくら探しても無いわけで。
じゃぁどうする!作りましょう!PHP側で。
ってコトで、2通り考えます。
ひとつは、jpegで表示。
ひとつは、pngで表示。
jpegだと透過できないので、bgcolorとあわせる必要がある。
pngだと容量が大きくなる。

つづく。
2013年3月6日水曜日
An active access token must be used to query information about the current user.な件。
FaceBook連携のWEBアプリを作ってるときの話なのですが。。
An active access token must be used to query information about the current user.
というエラー。
出ました。ご他聞にもれず。
で、いろいろ情報収集。
まぁここらへんからたどれば、解決しそうな感じはしたのです。
http://fb.dev-plus.jp/forum/topic.php?id=67
でも、いっこうに改善されず。
ところが、ひょんなことから、localhost連携だと成功。
WEBサーバだと失敗。
んーーーー。よくある。それだ!
ってことで、WEBサーバ、リバースプロキシしてるんですよね。
だから、PHP、で$_SERVER['HTTP_HOST']がサーバ名になってまうわけです。
で、GREP。
その結果、以下のコードを発見。
protected function getHttpHost() {
if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
return $_SERVER['HTTP_X_FORWARDED_HOST'];
}
return $_SERVER['HTTP_HOST'];
}
コンストラクタにたは、 if (isset($config['trustForwarded']) && $config['trustForwarded']) {
$this->trustForwarded = true;
}
そっか。ってことで、無事に、コンストラクタを以下にすることにより、解決。$facebook = new Facebook(array( 'appId' => $appId, 'secret' => $secret, 'trustForwarded' => true, 'cookie' => true ));
2013年3月1日金曜日
で結局、JSONPathのラッパークラスを書く。。(2)
●使い方サンプル
まぁ問題は、JSONPathのpathの文字列に慣れてないことくらい^^;^^;
まぁ問題は、JSONPathのpathの文字列に慣れてないことくらい^^;^^;
$p = new gJPath;
$jstr = file_get_contents(******************);
$json = json_decode($jstr,true);
$p->setJson($json);
// $p->json = json_decode($jstr,true); //まぁこれでも同じですが。。
$xpath = "$..name";
$v = $p->getValueOne($xpath); // 所得
$xpath = "$..layers.[*].name";
$v = $p->getValueOne($xpath); // 所得
$xpath = "$..imgurl";
$v = $p->getValueOne($xpath); // 所得
$xpath = "$..layers.[*].name"; // 配列として所得
$v = $p->getValue($xpath);
foreach($v as $one) echo "【{$one}】";//表示させてみたりとか
$xpath = "$..layers.[*].name";
$v = $p->getPathOne($xpath);
$xpath = "$..layers.[*].items[?(@['name']=='札文字')]";
$v = $p->getValueOne($xpath); // 所得
$v = $p->getValue($xpath); // 配列として所得
$xpath = "$..name";
$p->setValue($xpath,"new 'Name' DA\\YO!");//一括更新
$xpath = "$..items[?(@['name']=='札文字')]";
$patstr = $p->getPathOne($xpath);
$patstr .= "['mtext']";
$v = $p->getValueDirect($patstr); // patstrから値を所得
$p->setValueDirect($patstr,"でへへへ!");// patstrから値を設定
$v = $p->getValueDirect($patstr); // patstrから値を所得(当然かわっている)
●クラス require_once "./jsonpath-0.8.1.php";
//---------------------------------------
class gJPath{
public $json; // object
//-------------------------
/* 初期値 */
//-------------------------
function __construct(){
$this->json = null;
}
//-------------------------
// objectをセットする
//-------------------------
public function setJson(&$v){
$this->json = &$v; // ここで&を忘れちゃダメよ。
}
//-------------------------
function __destruct(){
// とりあえず特にやることなし。
}
//-------------------------
// マッチしたものを返す。
// falseでなければ、Arrayを返す
//-------------------------
public function getValue($pat){
$match = jsonPath($this->json, $pat);
return $match;
}
//-------------------------
// マッチしたものを返す。
// falseか値かどっちかを返す。
// $patが必ず1コか0コが確定している場合とかに使う。
//-------------------------
public function getValueOne($pat){
$match = $this->getValue($pat);
if($match == false) return false;
return $match[0];
}
//-------------------------
// マッチしたPATHを返す。
// falseでなければ、Arrayを返す
//-------------------------
public function getPath($pat){
$match = jsonPath($this->json, $pat, array("resultType" => "PATH"));
return $match;
}
//-------------------------
//
//-------------------------
public function getPathOne($pat){
$match = $this->getPath($pat);
if($match == false) return false;
return $match[0];
}
//-------------------------
// マッチするものに全て値を設定する。
//-------------------------
public function setValue($pat,$value){
$match = $this->getPath($pat);
if($match != false){
foreach($match as $u){
$this->setValueDirect($u,$value);
}
}
}
//-------------------------
// 【$['abc'][0]】のような文字列と値を引数にしてセットする。
// arrayとかをvalueにするなよ!
// $pathはパターンじゃないから注意!
//-------------------------
public function setValueDirect($path,$value){
$evalstr = "\x24this->json" . substr($path,1);
$valuestr = "";
if(is_string($value)){
$value = preg_replace("/\x5c\x5c/", "\x5c\x5c\x5c\x5c",$value); // 【\】 を 【\\】 にする
$value = preg_replace("/\x27/", "\x5c\x27",$value); // 【'】 を 【\'】 にする
$valuestr = "'{$value}'";
}else{
$valuestr = "{$value}";
}
@eval("{$evalstr}={$valuestr};");
}
//-------------------------
// $pathはパターンじゃないから注意!
//-------------------------
public function getValueDirect($path){
$evalstr = "\x24this->json" . substr($path,1);
@eval("\x24v={$evalstr};");
return $v;
}
//-------------------------
JSONPathのサイトの説明の間違い。
いやいや。。。。。
ライブラリの説明サンプルが、しっかり間違っていたのか、
それとも、仕様が変わったのにサンプルを修正していなかったのか、、
こぉーゆーことがあるとちょっとめげますが。。。。
http://goessner.net/articles/JsonPath
ということで、正誤表。
priceが10以下をselectするJSONPathですが。。。(-_-;)
誤: $..book[?(@.price<10)]
正: $..book[?(@['price']<10)]
です。
2013年2月28日木曜日
で結局、JSONPathのラッパークラスを書く。。
で結局、JSONPathのラッパークラスを書いてみた。
当然、どー使いたいかを書いてからコーディング。
★使い方のイメージ
できたけど、、これからテスト&デバッグ。
当然、どー使いたいかを書いてからコーディング。
★使い方のイメージ
$p = new gJPath;
$p->setJson($json);
$patstr = $p->getPathOne("$..author2"); // patString所得
$value = $p->getValueDirect($patstr); // 所得
$p->setValueDirect($patstr,$newValue); // 設定
こんな感じで。できたけど、、これからテスト&デバッグ。
今さらながらJSONPath。(PHP)
なぜ今さらながらJSONPathかっていうと、どうにもいい感じにつかえるやつがなかったのです。
http://goessner.net/articles/JsonPath/
LastUpdateが2007年だけど^^;^^;
で、テストコードを書いてみると、ちょっとイイ感じです。
何がイイかって、resultTypeに"PATH"なるものが設定できるところで、この先頭の$を削除してObjectの変数名をつっこみ、
"黒魔術"のevalで、参照したり設定したり。
※javascriptの方も同様にできました。
●テストコード
http://goessner.net/articles/JsonPath/
LastUpdateが2007年だけど^^;^^;
で、テストコードを書いてみると、ちょっとイイ感じです。
何がイイかって、resultTypeに"PATH"なるものが設定できるところで、この先頭の$を削除してObjectの変数名をつっこみ、
"黒魔術"のevalで、参照したり設定したり。
※javascriptの方も同様にできました。
●テストコード
require_once "pear/Var_Dump.php";
require_once "./jsonpath-0.8.1.php";
$jstr = file_get_contents('samplejson.txt');
$json = json_decode($jstr,true);
$match1 = jsonPath($json, "$..author");
$match2 = jsonPath($json, "$..author", array("resultType" => "PATH"));
$res1 = Var_Dump::display($match1,true);
$res2 = Var_Dump::display($match2,true);
header( "Content-Type:text/html; charset=utf-8");
$idxstr = $match2[1];
$idxstr = "\x24json" . substr($idxstr,1);
eval("\x24aa=" . $idxstr . ";");
echo "-> {$aa}
";
$idxstr .= "='A123456789';";
@eval($idxstr); // 失敗してもtry-catchで拾えません^^;
$res3 = Var_Dump::display($json,true);
echo "-> " . $idxstr . "
";
echo $res1;
echo $res2;
echo $res3;
exit;
/*
samplejson.txtの中身。
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
*/
?>
●表示結果-> Evelyn Waugh
-> $json['store']['book'][1]['author']='A123456789';
array(4) {
0 => string(10) Nigel Rees
1 => string(12) Evelyn Waugh
2 => string(15) Herman Melville
3 => string(16) J. R. R. Tolkien
}
array(4) {
0 => string(31) $['store']['book'][0]['author']
1 => string(31) $['store']['book'][1]['author']
2 => string(31) $['store']['book'][2]['author']
3 => string(31) $['store']['book'][3]['author']
}
array(1) {
store => array(2) {
book => array(4) {
0 => array(4) {
category => string(9) reference
author => string(10) Nigel Rees
title => string(22) Sayings of the Century
price => float 8.95
}
1 => array(4) {
category => string(7) fiction
author => string(10) A123456789
...略...
2013年2月27日水曜日
PHPでJSONデータを扱うとき。
PHPでJSONを扱うときの話ですが、
まぁこんなデータを扱う時の話ですが、、、
*["items > name == {$tareget}"]
セレクタみたいなやつで一発でかけるならいいんですが、、、まぁそういうクラスを書いてもいいんだけど、、、それほどでもなかったので、なめてみるコードを書いてみました
こんな感じで。
まぁこんなデータを扱う時の話ですが、、、
//-------------------------------------------
{
"doc":{
"pages":{
"layers":[
{
"items":[
{
"name":"abcdefgh",
。。。。データいろいろ。。。。
"items":[
{
。。理論上無限階層下。。データいろいろ。。。。
うん。*["items > name == {$tareget}"]
セレクタみたいなやつで一発でかけるならいいんですが、、、まぁそういうクラスを書いてもいいんだけど、、、それほどでもなかったので、なめてみるコードを書いてみました
こんな感じで。
//-------------------------------------------
// objectのTREEを下っていって、*['name']=$nameのとき*[$tag]=$valueをセットする件。
//-------------------------------------------
public static function searchAndSet(&$json,$name,$tag,$value){
$ar = array_keys($json);
$n = count($ar);
for($w=0;$w<$n;$w++){
$br = @array_keys( $json[ $ar[$w] ] );
if(count($br) > 0){
$ret = xxxxxxxx::searchAndSet($json[$ar[$w]],$name,$tag,$value);
if($ret != null) return $ret;
}
if($json[ $ar[$w] ]['name'] == $name){
$json[ $ar[$w] ][$tag] = $value;
return $value;
}
}
return null;
}
追記) あ、NAMEが一意なのが前提なコードです。
2012年5月29日火曜日
javascriptでJSONをPOSTしてみてPHPで受け取る。
前回のつづきで、javascriptでObjectを生成し、
それをJSON化し、それをPHPでPOSTで受け取るテストをしてみます。
テストとしては、どうやって文字列処理をすればいいのかってことですね。
また、javascriptからPOSTする方法も含めてテストしてみます。
ってことで、こんなコードでテスト
まぁJSONできてるから、JSONをdecodeできる文字列に変更する必要があるわけです。
まず、これはPHPの設定になるわけですが、文字のエンコードを調べます。
echo mb_detect_encoding($param);
ってやってみると、、
UTF-8
となりました。これが「UTF-8以外でいいことなんて、とりあえず何もありませんから、PHPは全てUTF-8前提で考えます。
ってことで、var_dumpでこういう結果↓をえるためには、
そうやったからって言って、速度が速くなるわけでもないので(実験しました)、見やすいように3行にしました。
関数としてはたいしたことない関数。
しかしここで、PHPでencodeすると、こんな文字列になります。
それをJSON化し、それをPHPでPOSTで受け取るテストをしてみます。
テストとしては、どうやって文字列処理をすればいいのかってことですね。
また、javascriptからPOSTする方法も含めてテストしてみます。
ってことで、こんなコードでテスト
php
$a = Var_Dump::display($_POST,true); echo $a;で、結果は、、
------------------POST------------------
array(1) {
param => string(77) {\"dat1\":\"【\'】【\\\"】【\\\\】【/】【\\r】【\\n】【\\t】\"}
}
ってことは、、、
{"dat1":【'】【\"】【\\】【/】【\r】【\n】【\t】}
が
{\"dat1\":\"【\'】【\\\"】【\\\\】【/】【\\r】【\\n】【\\t】\"}
になってるってことです。
じゃぁこれをどうやって取り込むかってことですね。まぁJSONできてるから、JSONをdecodeできる文字列に変更する必要があるわけです。
まず、これはPHPの設定になるわけですが、文字のエンコードを調べます。
echo mb_detect_encoding($param);
ってやってみると、、
UTF-8
となりました。これが「UTF-8以外でいいことなんて、とりあえず何もありませんから、PHPは全てUTF-8前提で考えます。
ってことで、var_dumpでこういう結果↓をえるためには、
array(1) {
dat1 => string(52) ◆【'】【"】【\】【/】【
】【
】【 】
}
PHP側で、こういう↓文字列処理をすればいいことになります。$param = $_POST['param'];
$param = preg_replace("/\x5c\x5c\x22/", "\x22",$param); //【\"】 を 【"】 にする
$param = preg_replace("/\x5c\x5c\x27/", "\x27",$param); //【\'】 を 【'】 にする
$param = preg_replace("/\x5c\x5c\x5c\x5c/", "\x5c\x5c",$param); //【\\】 を 【\】 にする
もちろん、preg_replaceなので配列にして渡してもいいんですが、、、そうやったからって言って、速度が速くなるわけでもないので(実験しました)、見やすいように3行にしました。
関数としてはたいしたことない関数。
function objectFromJsJson($v){
$vv = preg_replace("/\x5c\x5c\x22/", "\x22",$v); // 【\"】 を 【"】 にする
$vv = preg_replace("/\x5c\x5c\x27/", "\x27",$vv); // 【\'】 を 【'】 にする
$vv = preg_replace("/\x5c\x5c\x5c\x5c/", "\x5c\x5c",$vv); // 【\\】 を 【\】 にする
$json = json_decode($vv,true);
return $json;
}
しかしここで、PHPでencodeすると、こんな文字列になります。
//【コード】
$str = json_encode($json);
echo $str;
//【結果】
{"dat1":"\u25c6\u3042\u3010'\u3011\u3010\"\u3011\u3010\\\u3011\u3010\/\u3011\u3010\r\u3011\u3010\n\u3011\u3010\t\u3011"}
日本語が\u表記になります。まぁ、文字のエンコードの問題があるので、この方が扱いやすいといわれればその通りかもしれません。
ラベル:
html,
javascript,
json,
PHP
2011年2月2日水曜日
PHPでsmartyするとき。
PHPでsmartyするときなんですけどー、、
せっかく、テンプレート化するんだから、うまく分離してつくりたいものです。
ここでいううまく分離というのは、
テンプレートだけをブラウザで表示させても、それらしく見えるように作れれば、
それが一番いいのでは?
という考えです。
まぁちょっと考えればわかることなんですが、とりあえず、あんまり見たことはない。
たぶん、大方の人は、可変部分をテンプレートにいれないからです。
うぅーん、正確な言い方じゃなかった。
テンプレートをhtmlで表示させるときは有効だけど、smartyで使うときは無効になるような
デリミタ設定をしてやればいいのです。
それがこれ。
よって、$maintableをおきかえれば、それでOKってことになりますね。
まぁ逆に、htmlができあがった時点で、可変部分については、デリミタで囲んで、置き換える変数を加えてやれば、それでOK。
昔は、DreamWeaverが8の時代には、拡張子がtplなやつを使えるように、
いろいろ設定したりアイコン作ったりしたけど、、最近はテンプレートの拡張子をhtmlしちゃうとといういい加減さです。^^;^^;
せっかく、テンプレート化するんだから、うまく分離してつくりたいものです。
ここでいううまく分離というのは、
テンプレートだけをブラウザで表示させても、それらしく見えるように作れれば、
それが一番いいのでは?
という考えです。
まぁちょっと考えればわかることなんですが、とりあえず、あんまり見たことはない。
たぶん、大方の人は、可変部分をテンプレートにいれないからです。
うぅーん、正確な言い方じゃなかった。
テンプレートをhtmlで表示させるときは有効だけど、smartyで使うときは無効になるような
デリミタ設定をしてやればいいのです。
それがこれ。
$sm = new Smarty;
$sm->left_delimiter = "<!--{";
$sm->right_delimiter = "}-->";
そうすると、<!--{$maintable}-->
<!--{* -->
<table>
<tr><td>1</td><td>2</td></tr>
<tr><td>A</td><td>B</td></tr>
</table>
<!-- *}-->
みたいに書けば、html表示したときはtableが表示され、smarty経由だと、tableが表示されなくなる。よって、$maintableをおきかえれば、それでOKってことになりますね。
まぁ逆に、htmlができあがった時点で、可変部分については、デリミタで囲んで、置き換える変数を加えてやれば、それでOK。
昔は、DreamWeaverが8の時代には、拡張子がtplなやつを使えるように、
いろいろ設定したりアイコン作ったりしたけど、、最近はテンプレートの拡張子をhtmlしちゃうとといういい加減さです。^^;^^;
2011年1月22日土曜日
PHP@x64@Windows7でfsockopenが必ずエラーとなる。
PHPのWindowsの64ビット版。
公式にはまだないようですが、なんとなくdownloadして使ってみてるんですが、、、、、
とりあえず、、
fsockopen は必ずエラーになることがわかりました。
しょうがないので、こんな感じで、ベタな関数を使ってクラスをかきました。
ローレベルの関数は問題なく実行できたので、とりあえずはこれは使ってみます。。。。
そういえば、、readfile関数も微妙に怪しい。。。。。^^;^^;
公式にはまだないようですが、なんとなくdownloadして使ってみてるんですが、、、、、
とりあえず、、
fsockopen は必ずエラーになることがわかりました。
しょうがないので、こんな感じで、ベタな関数を使ってクラスをかきました。
ローレベルの関数は問題なく実行できたので、とりあえずはこれは使ってみます。。。。
そういえば、、readfile関数も微妙に怪しい。。。。。^^;^^;
class alexsock{
private $portn;
private $address;
private $sock;
private $counter;
//-------------------------
/* 初期値 */
//-------------------------
function __construct(){
$this->address = 'localhost';
$this->portn = 20002;
$this->counter = 10;
}
//-------------------------
function __destruct(){
// とりあえず特にやることなし。
}
//-------------------------
function setAddress($v){
$this->address = $v;
}
//-------------------------
function setPort($v){
$this->portn = $v;
}
//-------------------------
function create(){
$this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($this->sock === false) return false;
return true;
}
//-------------------------
function connect(){
$result = socket_connect($this->sock, $this->address, $this->portn);
if($result === false) return false;
return true;
}
//-------------------------
function setNonblock(){
socket_set_nonblock($this->sock);
}
//-------------------------
function setBlock(){
socket_set_block($this->sock);
}
//-------------------------
function setWaitTime($milisec){
$this->counter = $milisec / 100;
if($this->counter < 1) $this->counter = 1;
}
//-------------------------
function close(){
socket_close ($this->sock);
}
//-------------------------
function write($msg){
$writelen = socket_write($this->sock, $msg, mb_strlen($msg));
return $writelen;
}
//-------------------------
function read($slen){
$readlen = socket_read($this->sock, $slen);
return $readlen;
}
//-------------------------
function readEx($slen){
for($w=0;$w<$this->counter;$w++){
if($readstr == false){
$readstr = socket_read($this->sock,$slen);
if($readstr != false) return $readstr;
usleep(100000); // マイクロ秒単位
}
}
return false;
}
//-------------------------
// ありがちな準備
//-------------------------
function alexPrepare($add="127.0.0.1",$portn=20002,$milisec=10000){
$this->setAddress($add);
$this->setPort($portn);
$this->setWaitTime($milisec);
$b = $this->create();
if(!$b) return false;
$b = $this->connect();
if(!$b) return false;
$this->setNonblock();
return true;
}
//-------------------------
}
登録:
投稿 (Atom)





