ラベル PHP の投稿を表示しています。 すべての投稿を表示
ラベル PHP の投稿を表示しています。 すべての投稿を表示

2014年6月25日水曜日

スクラップブックマーク



はてなブックマークのjavascriptをお気に入りに登録させてしまう仕様をみて


ほーそんなこともできるんですね。


灯台下暗しといいますか、クリック一発で登録の手軽さをこういった形で実現してしまうとはさすがです。


そこで、新発見があったのですから応用して、スクラップブック(本文中の記事だけを取得する)用に


出来ないかと考えてみました。


FireFox用



<a href='javascript:
var h = window.document.getElementById("bkmark");
if(!h){
var f=window.document.createElement("form");
f.method="POST";
f.target="bkmark";
f.action="○○○.php");
f.innerHTML="<input type=\"hidden\" name=\"doc\" id=\"bkmark\"><input type=\"hidden\" name=\"title\" id=\"bkmark_title\"><input type=\"hidden\" name=\"url\" id=\"bkmark_url\">";

var ifr=window.document.createElement("iframe");
ifr.name="bkmark";
ifr.width=0;
ifr.height=0;

window.document.body.appendChild(f);
window.document.body.appendChild(ifr);
h = document.getElementById("bkmark");
}
h.value = escape(window.getSelection().getRangeAt(0)) || "";
window.document.getElementById("bkmark_title").value = escape(document.title);
window.document.getElementById("bkmark_url").value = escape(location.href);
if(h.value){f.submit();}
void(0);
'>スクラップブックマーク(FireFox用)</a>



上記のURLをはてなブックマークと同じように、ブラウザのお気に入りに登録します。


始めは、XMLHttpRequest を使っていたのですが、別ドメインへのアクセスが出来ないことが


すぐにわかり(使う前に気がつけよ。。。)断念しました。


はてなブックマークは、local.href でGETでタイトルとURLを送っていましたが


データを一方的に送信するだけでよいので、iframe枠内に見えないところでPOST送信することにしました。


(一番下に黒いぽちがでてますけど。。。)


スクラップブックで長めの文章を送るとなるとGETではバイト数が足りなくなる場合があるからです。





指定の文章の取得には、window.getSelection().getRangeAt(0) 


でマウスで選択したテキスト部分をPHPプログラムへ送信します。


PHP側は、適当に DBに保存するなり、ファイルに書き出すなりして


後で自分で確認できるように作っておけば良いかと思います。


IEの場合は、window.getSelection().getRangeAt(0) の代わりに


(window.document.selection.createRange())[0]  を使えばできるような気がします。(試してません)


自分のサイト以外でこういったJavascriptを実行させるテクニックは面白いですね。


(FireFoxのアドオンとかは基本的にこれなんですけどね。。。気がつけよ。。。)


Greasemonkeyとかがなぜ流行るのかようやくピント来た気がします(遅)





PHPの日付の加算、減算の備忘録





// 現在日付から○日の取得

echo "1日前" . date("Y/m/d", strtotime("-1 day" ));
echo "1ヶ月前" . date("Y/m/d", strtotime("-1 month"));
echo "1年前" . date("Y/m/d", strtotime("-1 year" ));
echo "1週間前" . date("Y/m/d", strtotime("-1 week" ));


// 指定日付から○日の取得

echo "1日前" . date("Y/m/d", strtotime("2007/12/20 -1 day" ));
echo "1ヶ月前" . date("Y/m/d", strtotime("2007/12/20 -1 month"));
echo "1年前" . date("Y/m/d", strtotime("2007/12/20 -1 year" ));
echo "1週間前" . date("Y/m/d", strtotime("2007/12/20 -1 week" ));


こういうのって、すぐに書き方を忘れてしまうので


書き留めておくと便利かも。





関連リンク:PHPで、先月、翌月などのを扱うときの注意





2010年12月11日土曜日

Web製作でよく使うPHP変数の値有無判定関数





/**
*
* @param mixed $v
* @return boolean
*
**/
function v($v){
if(is_bool($v)){
return $v;
}elseif(is_numeric($v)){ // all numeric (0 and '0') are true.
return true;
}elseif(is_string($v)){
return !empty($v);
}elseif(is_array($v)){
$v = array_filter($v,"v");
return !empty($v);
}elseif(is_object($v)){
return v(get_object_vars($v));
}else{
return !empty($v);
}
}

実際にHTMLに出力するときは 0を値とみなすことのほうが多いと思いますので


0もTRUE扱いにしています。





PHPのStringのゼロに注意






$a = 0;
if(empty($a)){
echo 'TRUE';
}else{
echo 'FALSE';
}


これが、TRUEになることは容易にわかるのですが



$a='0';
if(empty($a)){
echo 'TRUE';
}else{
echo 'FALSE';
}



これも、TRUEになるとは盲点でした。恐るべしPHP





2010年12月1日水曜日

|| をつかって変数を初期化



値の不明な変数を初期化する場合



if($a){
$a = 'hogehoge';
}


もしくは



$a = $a ? $a : 'hogehoge';


これを以下のように書きます。



$a || $a = 'hogehoge';


|| は、if文の条件式にしか普段は使わないのだけれども


編集の初期化処理などに使うと1行で簡潔にかけて意外ときれい。


あまりこういう記述を増やすとPerlみたいに暗号のようなコードになりそうなので


ほどほどにしながら、ワンポイントで使うといいかも。





2010年11月30日火曜日

月、日の桁数をそろえたい時にsubstrの便利な使い方



月とかカレンダーの日をfor文でまとめて出力するときに


以下のように書くことがあるかと思います。




for($i=1;$i<=12;$i++){
echo $i.'月<br>';
}

=================

1月
2月
3月
4月
5月
6月
7月
8月
9月
10月
11月
12月



ただ、これだとレイアウト的に1桁の月と2桁の月でサイズがずれたりすることがあります。


そこで、1桁の月に頭に0をつけて 01月 02月 ... という風に表示したいとします。


IF文で書くと以下のような感じ。ちょっとIF文が仰々しくてあまりうれしくありません。



for($i=1;$i<=12;$i++){
if($i < 10){
echo '0'.$i.'月<br>';
}else{
echo $i.'月<br>';
}
}


これを、substrで書くとこんな感じ



for($i=1;$i<=12;$i++){
echo substr('0'.$i, -2) . '月<br>';
}

=================

01月
02月
03月
04月
05月
06月
07月
08月
09月
10月
11月
12月



全部の月の頭に0をつけて文字列として右から2文字を出力する形です。


別にそれほどエレガントでないかもしれませんが


同じ文字数にそろえたいレイアウトの整形という意味では


非常に的を得た方法ではないかなと思います。





2010年6月23日水曜日

PECLでSQLiteをインストールできないとき



こちらで紹介されているように、途中エラーで止まってしまう場合の対処


http://blog.plastik.jp/archives/44


上記内容の中で、「ソースを直接編集」の部分がどのファイルを編集するべきか


すぐにがわからなかったのでメモ


-> sqlite.c を直接編集



vi sqlite.c

## Line: 56 行目をコメントアウト /* ~ */ で囲う
/* static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; */

## Line: 125, 126 の arg3_force_ref を third_arg_force_ref に変更
PHP_FE(sqlite_open, arg3_force_ref) → PHP_FE(sqlite_open, third_arg_force_ref)
PHP_FE(sqlite_popen, arg3_force_ref) → PHP_FE(sqlite_popen, third_arg_force_ref)



このあと、make && make install でいけました。





2010年6月17日木曜日

fgetcsv で文字化けする場合



fgetcsv の仕様が、PHP4 -> PHP5 で変わったらしくLocale に依存するらしい。


日本語が文字化けする場合は、以下のように明示的にLocaleを変更する



setlocale(LC_ALL,'ja_JP');


fgetcsv 実行前に上記を書けばOK。





2009年11月20日金曜日

PHPでグラデーション画像を作成する



PHP GDは、image関数を使って画像のサイズをリサイズする時によく利用します。


サンプルもググルとたくさんあるので使ってる方も多いかと思います。


いろいろな用途に使われているGDですが、意外とグラデーションをかけた画像を


GDで作成してるサンプルが無いことに気がつきまして書いてみました。





というのも、ものぐさな私はPhotoShopとかでいちいち画像を切り抜くのが非常に大嫌いなもので


ちょっとしたデザインの変更で背景のグラデーション部分を再度切り抜き直したりすることが


発生するとキーーーーっとなってしまいます。





そんなおりプロトタイプのときくらいは、動的に画像を生成してもいいでしょ!


っと、ものぐさな考えを実践すべくだらだらサンプルを探していたのですが


ちょうどいいのが見つからずあきらめて書くことにしました。


まぁ、単純にグラデーションを書ける方向にimageLine で色を変えた線を引く!


ということをやっただけです。かなりあっさりした感じでかけます。


つまり、ことさらサンプルあげるほどでもないというのが実状だったのかも。。。




$sc = 'ffffff'; // 開始色
$ec = '6699aa'; // 終了色

$w = 150; // 画像幅
$h = 50; // 画像高さ

$im = imagecreatetruecolor($w, $h);
$bgc = imagecolorallocate($im, 255, 255, 255);

$al = gradDiv($sc, $ec, $h);
$sc = str2hec($sc);

for($i=0; $i<$h; $i++){
$bgc = imagecolorallocate($im
, $sc['R'] + $al['R'] * $i
, $sc['G'] + $al['G'] * $i
, $sc['B'] + $al['B'] * $i );
imageLine($im, 0, $i, $w, $i, $bgc);
}

header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);

exit;

function gradDiv($sc, $ec, $l){

$S = str2hec($sc);
$E = str2hec($ec);

return array( 'R'=>($E['R'] - $S['R']) / $l
, 'G'=>($E['G'] - $S['G']) / $l
, 'B'=>($E['B'] - $S['B']) / $l);
}

function str2hec($col){
$R = hexdec(substr($col, 0, 2));
$G = hexdec(substr($col, 2, 2));
$B = hexdec(substr($col, 4, 2));

return array('R'=>$R, 'G'=>$G, 'B'=>$B);
}


上記のPHPで以下のようなグラデーションのかかった画像が表示できます。


f:id:bushimichi:20091120013603p:image


ちょっとした変更にもすぐ対応できるので


プロトタイプ用のサイトを作るときなどに重宝します。





2009年11月19日木曜日

OpenIDでmixi id を利用する時には証明書が2つ必要



サンプルにしたがって、mixi OpenIDのサンプルコードを動かしてみた時の備忘録


インストール方法などは以下の参考サイトを参照


参考:http://d.hatena.ne.jp/botchy/20080820/1219255653


mixi 証明書の取得は、以下の2つ必要


https://mixi.jp


https://id.mixi.jp


取得方法は、参考サイトを見てください。


この2つの証明書がmixi OpenIDの曲者です。


これを1つの証明書 both.crtにする必要があります。


どちらかの証明書にもう片方を追記します。(テキストエディッタで編集)


最初はわからなくて別々にcurl_setopt してましたが全くダメでした。








あとは上記の証明書を読み込むようにOpenID Libraryのソースに書き加えます。


Auth/Yadis/ParanoidHTTPFetcher.php 132行目と196行目付近



if ($this->isHTTPS($url)) {
curl_setopt($c, CURLOPT_CAINFO, '/path/to/both.crt');
}


忘れるとまたはまりそうなのでそのための備忘録です。





2009年11月1日日曜日

PHPで、先月、翌月などを扱うときの注意



※ かなり初歩的な話ですのでご了承ください





PHPで、先月、翌月の月を取得するような場合、以下のようなプログラムを書いてしまいませんか?




echo '先月 => '. date('m', strtotime('-1 month')) .'<br>';
echo '今月 => '. date('m') .'<br>';
echo '翌月 => '. date('m', strtotime('+1 month')) .'<br>';


------ 結果 ------

前月 => 10
今月 => 11
翌月 => 12


(今日を11月01日とした場合です)



上記の結果は期待した結果で現状11月01日の場合は問題ありません。





ところが、10月31日の場合を例にとって見ます。




echo '前月 => '. date('m', strtotime('2009-10-31 -1 month')) .'<br>';
echo '今月 => '. date('m', strtotime('2009-10-31') ) .'<br>';
echo '翌月 => '. date('m', strtotime('2009-10-31 +1 month')) .'<br>';


------ 結果 ------
先月 => 10
今月 => 10
翌月 => 12



大変なことに、先月が10になってしまいました。


もっと、過去にもどって見てみると







for($i=1;$i<=12;$i++){
echo $i. 'ヶ月前 => '. date('m', strtotime('2009-10-31 -'.$i.' month')) .'<br>';
}

------ 結果 ------
1ヶ月前 => 10
2ヶ月前 => 08
3ヶ月前 => 07
4ヶ月前 => 07
5ヶ月前 => 05
6ヶ月前 => 05
7ヶ月前 => 03
8ヶ月前 => 03
9ヶ月前 => 01
10ヶ月前 => 12
11ヶ月前 => 12
12ヶ月前 => 10



もう、ありえないことになってしまいますね。


よく見ると31日のある日とない日で計算が狂ってしまうという内容です。


2月にいたっては、29~31日もアウトですね。





これはおそらく10月31日の1ヶ月前は9月31日となり


9月31日とは9月30日の次の日だから10月1日のことになるってことでしょう。


そのため、10月31日の1ヶ月前の月は10月って事になります。





strtotime の -1 month とは、日付はそのままで月だけ1減らすという意味で


決して先月にシフトするという意味ではない。


関数を作った側の理屈はなんとなくあっている気がするのですが


使ってる側にしてみると間違いやすいポイントかなと思います。





従いまして、先月、翌月とかを正確に取得するには現在の日を考慮いれて


今月の1日から起算して1ヶ月前とかになるようにします。




echo '先月 => '. date('m', strtotime(date('Y-m-1').' -1 month')) .'<br>';
echo '今月 => '. date('m') .'<br>';
echo '翌月 => '. date('m', strtotime(date('Y-m-1').' +1 month')) .'<br>';

------ 結果 ------

前月 => 10
今月 => 11
翌月 => 12







for($i=1;$i<=12;$i++){
echo $i. 'ヶ月前 => '. date('m', strtotime(date('Y-m-1').' -'.$i.' month')) .'<br>';
}

------ 結果 ------

1ヶ月前 => 10
2ヶ月前 => 09
3ヶ月前 => 08
4ヶ月前 => 07
5ヶ月前 => 06
6ヶ月前 => 05
7ヶ月前 => 04
8ヶ月前 => 03
9ヶ月前 => 02
10ヶ月前 => 01
11ヶ月前 => 12
12ヶ月前 => 11






ぶっちゃけ、昨日上記のバグを発見したからこのエントリーなんですけどね(汗)


かなり初歩的なバグが混入していて情けない思いをしました。未熟者です。


こんなのは常識だよーって言われそうですが、知らない人がいましたら後学のために参考になれば幸いです。





2009年8月6日木曜日

PHPからRsyncを実行する時にはまったこと



PHPの exec , system 関数を使って、直接コマンドを実行することができます。


これをうまく使えば、PHP単体では実現しにくいことを


他のアプリと連携して実行することができます。


そんなわけで、ためしにWebのインターフェイスからボタンを押すと


サーバ上のファイルのバックアップをとるように、PHPからRsyncを実行させようとした時の話です。


下準備として、実行するRsyncを手打ちでまず実行できるか確認します。



# サーバ上の /xxx/xxxx/ のファイルをローカルの /xxx/xxxx/ に同期させると考えます。

rsync -auv -e ssh xxxx@example.com:/xxx/xxxx/ /xxx/xxxx/



※ssh を利用するためパスワードを入力せずに接続できるよう公開認証キーの設定をしておく


(この設定は、ネットでもたくさん情報ありますのでそちらをご覧ください)








上記の手打ちの rsync コマンドは難なく実行できたので


PHPから同様のコマンドを実行するようにして見ます。






system('rsync -auv -e ssh xxxx@example.com:/xxx/xxxx/ /xxx/xxxx/')








自信たっぷりに実行してみたのですが


ものの見事に、うまく動作できずはまってしまいました。





ポイントは2点、パーミッションとパスです。





まず、パーミッションに関しては、PHPからrsyncを実行するので当然ユーザはhttpdの実行者(apache)になります。


先ほどsshをパスワードなしで接続できる設定をしたのは、apache ではなく他のユーザアカウントでした。


apacheでパスワードなしの設定をしても良いのですがその場合にrsyncでファイルを同期したときの所有者が


apache になってしまい都合が悪いです。





ユーザアカウント hogehoge とかで実行したいですね。


そこで、PHPをApacheのモジュールではなく、CGI経由で実行するようにします。


phpには、mod_suphp というCGI経由で実行するためのモジュールがあるのでインストールします。


(mod_suphpのインストール方法は割愛します)


インストールができたら、phpinfo() などで Server APIを確認します。CGI/FastCGI と出ていたら設定OKです。


suphpの設定が多少難易度が高いかもしれません。





次に、rsync の実行する際のパスです。


PHPのexec ,system 関数は、どうもそのままだと絶対パスで表記する必要があるらしく


上記のコマンドは、以下のようにする必要があります。sshのほうも絶対パスです。


(何か環境変数的なパラメータを初期化すればいけるのかもしれませんが。。。)



system('/usr/bin/rsync -auv -e /usr/bin/ssh xxxx@example.com:/xxx/xxxx/ /xxx/xxxx/')








このことがわからず四苦八苦したため、かなり時間のロスをしまいました。


知っていればどうってことないのですが、知らない場合はひたすらレスポンスが真っ白で何も値が返ってこない地獄を見ます。


(もう少し、エラー的なメッセージを表示させてくれたら助かるのに。。。)





たまにしかこういうプログラムは書かないから、


何度も同じ穴にはまりそう。


一応、備忘録として書き留めておくけど


書いたこと忘れたら意味ないよなぁ。。。。





2009年2月13日金曜日

バックエンドサーバでも、リモートIPアドレスを取得する



気がつけば、2ヶ月近く日記を書いてなかった。。。。




$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'] ;



mod_proxy とかを使って、バックエンドでPHPを実行しているときとかに


クライアントの接続元IPアドレスを取得する際に利用。


知ってると、どうってことないけど、わからないときは結構調べたりするようなことかな。





2008年8月21日木曜日

携帯サイトで利用するJPG



携帯サイトで、JPG画像を利用して表示できない場合は、Content-Type を確認してみるとよい。



○ Content-Type: image/jpeg

× Content-Type: image/jpg


サーバ出力で画像を生成している場合などで、 image/jpg とするようなことは結構ある気がします。。。


私の場合は、PEAR::Image_Graph を使ったときに、Content-Type:image/jpg に出くわしました。





Image/Canvas/GD/JPG.php に、header 出力部分があるので利用の際は確認したほうがいいです。





2008年8月19日火曜日

PHPの最適化 12 PHP Optimization tips



(元ネタ http://www.ilia.ws/files/zend_performance.pdf)




  1. staticが使えるなら、staticを使う。速度は4倍になる。

  2. __get, __set, __autoload は避ける。

  3. require_once() はコストがかかる。

  4. include や require では絶対パスで指定する。

  5. スクリプトの開始時間は $_SERVER[’REQUEST_TIME’] で得る。

  6. 正規表現は、文字列関数で代用できないか探る。(文字を見つけるだけならstrposなどでもよい)

  7. str_replace は preg_replace より早いが、strtr は str_replace の4倍早い。

  8. 文字列/配列両方を受け入れる柔軟さを持つ関数は避ける。変わりに個別の関数を用意する。

  9. @によるエラー制御は遅い

  10. $row[’id’] は $row[id] より7倍早い

  11. エラーメッセージはコストがかかる

  12. for ($x=0; $x < count($array); $x) の count() のようにループの度に呼ばれる関数はさけ、変数に格納する。


ねた的には、古いですがふとしたときに思い出すと良いかも。


自社のフレームワークに、こういうエッセンスを入れていくのが重要なのかな。


個人的には、require_once は使いまくりなので、どうにかコスト削減に努めたいです。(便利だからねぇ)


弊社のプログラミングの基本的な方針



便利なコード >>>>(優先順位)>>>> パフォーマンスがでるコード(コスト小)


基本的に便利なほうを優先する傾向にあります。


ここで言う便利とは、使いやすく、理解しやすく、人間的に優しいもの。という意味です。


省略したり、コードを短くしたり、難解なテクニックを使うのは、プログラマーの質によって


ムラが出るため、チームで仕事をしたりしているといろいろ弊害が出てきます。


(みんながスーパープログラマーなら問題ないけどね。。。)


この辺はシステムの要件にもよります。


普通の公道を走るのに、F1のマシンは必要ないですね。


ただし、燃費が良いほうが好まれるのは、公道でも、F1でも同じです。


このあたりの必要なパフォーマンス要件をしっかりと事前に考えて取り組むのが重要かと。


また、必ずしもトレードオフとか限らないので


「人間にもマシンにとっても優しい方法」を考えるのはなかなか楽しいものです。


得てして、人間に優しいコードは、パフォーマンス的にも良い場合が少なくありません。


そういう気質は、すぐに目の前の仕事から脱線してあらぬ方向へ行ってしまいますが、


プログラマーには、必要な「遊びごころ」だと思ってます。





2008年3月3日月曜日

月末の日付を取得する



3月末の日付を取得したい場合




date("Y/m/d", strtotime("2008/4/1 -1 day"));

date("Y/m/d", mktime(0,0,0,4,0,2008));



どちらも、次月 2008年4月1日の1日前と考えれば取得できますね。





2007年6月14日木曜日

Drawライブラリー Javascript

Open-jACOB Draw2D



フローチャート図などVisioやPowerPointで書くような図がかけます。





ブラウザ上にそのままフリーハンドでかけます。

Thinkature - Real-time collaboration for the web







wz_jsgraphics.js 図形が非常にきれいにかけます。

DHTML: Draw Line, Ellipse, Oval, Circle, Polyline, Polygon, Triangle with JavaScript





Prototypeベースのグラフィックスフレームワーク

SVG/VML/Canvas の方式で描画することが出来ますのでIEでもOKです。

Prototype Graphic Framework













Powered by ScribeFire.

Javascript Game

Javascript でマリオ

http://overdrawn.net/mario/#



かなり良くできてます。すげーが、マリオがどこに?クリボーをクリックするとへこみます。

?ブロックをクリックするときのこがでてくるけど、とることができない。。。どうやるんだ?



ブロック崩し

これが、Javascriptでできてるとは信じられません。

DHTML Arkanoid V1.2B | Level 1









Powered by ScribeFire.