2011年10月20日木曜日

正常に表示されてるのに404エラー[Wordpress]

あるサイトの仕上げにHTML Validationチェックをかけていた時のこと。

ちゃんと画面は表示されているのに、Validation ServiceにURLを送信すると404エラーになるページがありました。

どのページも共通してWordpressのヘッダーをrequireしていたので、原因はWordpressしかないと考えました。


require_once 'blog/wp-blog-header.php';

do_something..


こんな感じでwp-blog-header.phpをrequireしていたので、まずはwp-blog-header.phpのソースをチェック。


if ( !isset($wp_did_header) ) {
    $wp_did_header = true;
    require_once( dirname(__FILE__) . '/wp-load.php' );
    wp();
    require_once( ABSPATH . WPINC . '/template-loader.php' );
}


こんなのが書いてあります。

行数が少ないので、一個ずつコメントアウトして動作チェックしてみると、wp() 関数をコメントアウトしたら404エラーが出なくなりました。
そして、template-loader.phpを読まなくても問題ないので、ここで必要なのは wp-load.phpだけということになります。

なので、wp-blog-header.phpのrequireをやめて、wp-load.phpを読み込むように変更しました。


require_once 'blog/wp-load.php';

do_something...


こうすることで404エラーは出なくなり、validationも無事通すことができました。

結局wp()関数が何をしているのかは検証してないけど、Wordpressの機能だけ使えたら問題ないので必要ないでしょう。


これって、画面が正常に表示されているだけに気づきにくい問題です。
もしWordpressを組み込んだサイトを作って、wp-blog-header.phpをrequireしている人がいたら、一度W3CのHTML Validation ServiceにURLを送ってみるとか、Chromeの「要素の検証」で「Network」を開いてチェックしてみるとかしてみた方がいいですね。

ちなみに今回のWordpressのバージョンは3.2系だったと思います。

2011年10月17日月曜日

PHPで0から始まる数値を扱う時の失敗

データベース上でZEROFILLしてあるカラムとか、sprintf('%02d', $number)とかでゼロ埋めしたような数値を扱うことがありました。
この時に0で始まる数値のことを考えずにコードを書くと不具合がでてしまうことがあります。

例えば以下のようなコード

$errors = array (01, 02, 08, 09);
foreach ($errors as $error_code) {
    switch ($error_code) {
        case 01:
            echo 1;
            break;
        case 02:
            echo 2;
            break;
        case 08:
            echo 8;
            break;
        case 09:
            echo 9;
            break;
      }
}

こんなコードを書くと、08の時にcase 08とcase 09を実行し、09の時も同じようにcase 08と09を実行します。

PHPだけじゃなくて他の言語でもそうだと思うけど、0から始まる数値は8進数として扱われます。
上記のコードの場合、0〜7までは動作するけど、8進数では8になると桁が繰り上がるので8以上の値は存在しません。
この時、08の時も09の時も0として扱われているので、 case 08 = case 09 = case 0ということになります。

なので、もし、$errorsの配列に'00'という値があれば、00が回って来た時にもcase 08と case 09を実行していることになります。

ゼロ埋めした数値は時々使うことがあるので、気を付けないといけませんなぁ。

2011年10月15日土曜日

while,for,foreachの中のswitchでcontinueすると・・

foreach文の中でswitchを使った時の失敗。
以下のようなコードを書きました。

foreach ($ary as $key=>$val) {
    switch ($key) {
        case 'aa':
            continue;
            break;

        default:
            break;
    }
    $val =  ......
    .......
}

思惑としては、$keyの値が'aa'だった時だけforeachの次のループに行きたい・・というものでした。
ところが、$keyが'aa'の時でもそのまま次へ行かずにforeach文を実行していました。

そういえばbreakで多重のループを抜ける時は break 2;とかしてたなと思って、continue 2; とすると思った動作になりました。

foreach ($ary as $key=>$val) {
    switch ($key) {
        case 'aa':
            // switchをbreakしてforeachにcontinueする
            continue 2;
            break;

        case 'bb':
            // break 2とするとswitchとforeachを飛ばせる
            break 2;

        default:
            break;
    }
    $val =  ......
    .......
}


C言語か何かで同じような処理を書いた時は、switch内でcontinueしておけば次のループに行けたような記憶があったので、PHPでも大丈夫だと思ってました。

PHPのswitch内でのcontinueはbreakと同じ動作をするような感じですね。
習慣的にswitch文では全部にbreakを付けてるけど、continueが書いてあればbreakは不要かな。

2011年10月13日木曜日

MySQLで時間(TIME)の足し算引き算

時間を保存するカラムを持ったテーブルがあります。
例えば、以下の時間割のテーブルを作ったとしましょう。


-- num 時限
-- subject 教科
-- start_time 開始時刻
CREATE TABLE time_tables (
    id int unsigned PRIMARY KEY auto_increment,
    num smallint unsigned NOT NULL,
    subject varchar(50) NOT NULL,
    start_time time NOT NULL
) CHARACTER SET utf8;


開始時刻10分前の情報が欲しい時、start_timeから10分を引けばいいんですけど、普通に引き算してもダメです。
TIMEDIFF関数を使って引き算することができます。


SELECT TIMEDIFF(start_time, '00:10:00') as before10min
  FROM time_tables;


逆に10分後の情報が欲しい時は、ADDTIME関数を使います。


SELECT ADDTIME(start_time, '00:10:00') as after10min
  FROM time_tables;


例えば時間を監視する処理が走っていて、ある時間の何分前になったら集計を行うとか、そんな時に使えそうですね。

2011年10月11日火曜日

スマホは欲しいけどホントに必要かよく考えてみる

正直iPhoneには今のところ興味がありません。
どちらかと言うとiPadの方が興味ありますね。

スマートフォンを持つならandroidかblackberryを選択すると思います。

いつでもどこでもネットができて、便利なアプリケーションが使えるというのがスマートフォンの良いところなのかな?
電車とかバスとか、移動中の暇つぶしとしては最適だと思うけど、本当に必要かというと疑問です。

通常の携帯でもパケットをフルに使ってた人にしてみれば差がないかもしれないけど、あまりパケットを使っていなかった人にしてみると、毎月5,000円くらいの通信費が上乗せされてくることになります。
年間で約60,000円、これを払ってまで得たい機能がスマホにあるのか・・それをまず考えないといけません。

2年契約が基本だと思うので、2年間で約120,000円の出費増が確定するわけです。
これなら普通の携帯で我慢して出費を他のものに回した方が良いような気もします。

スマホ持ってるけど、アプリとかネットするのは家の中がメイン・・という人なら、携帯は普通の携帯を持って、androidなりiPadなりのタブレット端末を一台持って無線LAN環境で使うのが一番良いんじゃないかな。
もっと通信費を安くしてほしいですね。

2011年10月10日月曜日

jQueryでconfirmした後のfadeOutが動かない時

例えば、ショップカート等で「削除」ボタンでカートから商品を消すような処理があります。
まず本当に削除していいか確認メッセージを出しますよね?

ということで、まずはjavascriptで

if (!confirm('削除OK?')) {
    return false;
}

みたいなのを書きました。

その後、ajaxで削除処理をして、画面上から選んだ商品をfadeOutするという処理をしたかったわけです。


$(this).fadeOut('slow', function() {
    $(this).remove();
});


これをやるとfadeOutのアニメーションをスキップして、パッと消えてしまうんです。
でも、fadeOutのコールバック関数内でfadeOutをやると、その部分はアニメーションしました。


$(this).fadeOut('slow', function() {
    $(this).remove();
    $('#something').fadeOut('slow');
});


何かfadeOutの前にワンクッション置けばいいのかと思って、fadeOutの前にdelay(0)を入れてみると正常に動作するようになりました。
大まかな流れは以下のような感じです。


if (!confirm('削除OK?')) {
    return false;
}
$.ajax({
    type:'get',
    url:'./del/',
    data:'item=xxx',
    success:function(data) {
        // delay(0)をfadeOutの間に入れる
        $('del_elm').delay(0).fadeOut('slow', function() {
            $(this).remove();
        });
    }
});


Chromeでしか確認してないけど、これで大丈夫なんじゃないかな?
もっとスマートな方法があれば教えて下さい。

2011年10月7日金曜日

smartyテンプレートで配列の文字列に変数を指定する

PHPはフレームワークがすっかり定着していますが、smartyもまだまだ捨てたもんじゃありません。
元々テンプレート的に使えるPHPなので、smartyは本末転倒だとか言われてますけどね・・。
でもフレームワークは規約に縛られてやりにくい場合もあったので、自分なりに作れるsmartyは使いやすいです。
smartyを使う場合は、一貫して「自分規約」を貫かないと面倒なことになるのかな。

さて前置きはこの程度で本題...

smartyのテンプレート内で配列を使った際に、連想配列のハッシュキーを

{$array.$hash1_$hash2}

みたいな感じでアンダースコアで2つの変数を繋げたい場合がありました。

そのまま書いてみるとエラーで画面が表示されません。

そこで色々やってみた結果、繋げたいハッシュキーをassignでcatするという方法にたどり着きました。

{assign var='hash' value=$hash1|cat:'_':$hash2}
{$array.$hash}

こうするとちゃんとハッシュキーとして認識されました。

cat関数はsmartyテンプレート内で文字列を繋げる時に使う関数で、 何個も繋げる時は $var1|cat:$var2:var3:var4 という感じでいけるようです。

今回は(_)アンダースコアと$hash2を$hash1に繋げただけなので、 $hash1|cat:'_':$hash2 となっています。

面倒といえば面倒だけど、やってしまえばそれまでです。