忍者ブログ

STEP UP BLOG

Home > ブログ > 記事一覧

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

PHPに日付処理における来月の挙動

このバグを直すためにはどうしたらよいかなーと検索をかけて、
出てきた検索結果一覧に既にアクセス済みのリンクがあったら凹みますよね…
あれ? 私昔も同じ間違いしてた??
全然学習してないじゃない…
そんな過去の失敗をまた繰り返すがっかり事案が今日もあったのでここで書かせていただきます。


PHPで来月を取得する必要があったのですが、そのときの処理をわかりやすく書き直したのが以下です。
$ php -r "echo date('m', strtotime('+1 month'));"
05

今日3月31日だよ? 来月4月だよ?
4月31日がないから5月1日になってしまうようです。
同様に1月や5月,8月,10月でも31日だと正しい来月が取得できません。
これは致命的ですよねと思いながらCarbonでも同じ処理を試してみたら、
$dt = new Carbon('next month');
echo $dt->format('m');  // 05

Carbonおまえもか…
PHPどうしようもないなと泣きながら調べて出てきた修正案は、
$dt = date('m', strtotime(date('Y-m-1').' +1 month'));
echo $dt;  // 04

$dt = new Carbon('first day of next month');
echo $dt->format('m');  // 04

$dt = new DateTime('first day of next month');
echo $dt->format('m');  // 04

"first day of"というのが肝要です。
日付処理は難しいですね…
PR

SSLProxyの話

以前このブログで書いた記事を最近参照する機会が度々あり、
自分の記憶力の無さとしっかりと記事に残しておいた先見の明に驚く日々です。
ブログ書いといてよかったーー

というわけで、今回はリバースプロキシのお話。
Apacheで単純にリバースプロキシするだけならProxyPassとProxyPassReserveだけで済みますが、ここにSSLが絡んでくると厄介になります。
SSL証明書のコモンネームなどとプロキシ先のサーバのコモンネームが違っていたりするわけで、そこでエラーとなります。
よって以下のように危なっかしいですがチェックをOffるようにするとエラーが出ずにリバースプロキシが正常に動きます。
セキュリティ的に完璧にするには、リバースプロキシ先のサーバもちゃんとSSL証明書を取得したほうがいいってことなのかな。。

SSLProxyVeryfy none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off

https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslproxyverify

マルチバイト文字対応のwordwrap()

PHPの文字列関数にはかゆいところに手が届く便利な関数が多々あります。
しかし!!
そういう便利な関数(言いようによっては使い道が限定される関数)に限ってマルチバイト文字対応していない。。。
ということで、結局自作しなければならないわけですが、
先日初めて知った関数にwordwrap()という関数がありました。

http://php.net/manual/ja/function.wordwrap.php

指定した文字数で、指定した文字を用いて文字列を分割します。

その通りなのですが、具体例を挙げると、
改行の入っていない長文を100文字ずつに分割して、それぞれに改行文字を追加するというようなことが可能なわけです。
さらに、そもそものPHPがHTMLを出力するための言語として生まれた性質からか、
分割する際に、単語を分割するかどうかも設定できます。
その辺りはマニュアルを参照していただくとわかると思います。

で、こちらのwordwrap()はご想像通り、マルチバイト文字に対応していない。
で、いろんな人が自作mb_wordwrap()を作っていたので、
私も便乗して作ってみました。
しかし、単語を分割するかしないかの判別まで含めると途端に難易度がエベレスト並になるのでそこは含めません。
function mb_wordwrap($string, $width, $break)
{
    $result = [];
    $tmp_str = '';
    $i = 0;
    while (mb_strlen($tmp_str) < mb_strlen($string)) {
        $str = mb_substr($string, $i*$width, $width);
        $result[] = $str;
        $tmp_str .= $str;
        $i++;
    }

    return implode($break, $result);
}

改良余地というか、wordwrap()の仕様漏れがありそうで不安ですが。。。

PHP7のはてな2つ

PHP7がリリースされました。
待望のメジャーバージョンアップです。
時代にそぐわない機能が廃止され、新しい機能がいくつも追加されました。
最大の変化は実行速度が速くなること
そのために内部のデータ構造も大幅に変わりますが、それ自体はコーディングにはあまり関わりないところ。
私がPHP7の新機能で特に気になっているものが以下の二項演算子。
??
はてなが2つの演算子です。
これは左オペランドがnullでないならその値を、nullならば右オペランドの値を返す演算子です。
$x = 'hello';
echo $x ?? 'good bye'; // hello

$y = null;
echo $y ?? 'good bye'; // good bye

echo $z ?? 'good bye'; // good bye

5.6系で実行するとsyntax errorとなりますが、7だと正常に実行されます。
上記の最後の行に注目していただくと、未定義の変数も左オペランドに使えます。
つまり、isset()と同じ挙動なのです。
echo isset($z2) ? $z2 : 'good bye';
echo $z2 ?? 'good bye';

この2つが同じということです。
私にとってこれはかなり便利な新機能です。
こういう新しい演算子によって、自分も面倒だなと思っていた部分を他の人も面倒だなと思っていたことを知れてなんだかホッとしています。

フォーム作りで忘れがちなこと

私が気を付けていてもしてしまいがちな失敗第1位がフォームの複数送信防止の処理です。
ちなみに第2位はティッシュをポケットに入れたまま洗濯しちゃうことです。
フォームの複数送信とは、間違ってsubmitボタンを2回押してしまって2回登録されてしまったりするあれですね。
決済処理なんかだと大変なことになります。
決済などのようなクリティカルな場面では肝に銘じているので大丈夫なのですが、
スピード上げて作っているところではつい楽なほうで実装してしまいがちになってしまいます。
こういうことで過去何度も失敗を。。。
type="submit"をtype="button"にして、
明示的にsubmit()、そして2回クリック出来ないようにすればよいというたったそれだけのことなのに。。。
という失敗の繰り返しに陥らないために、いっそのことhtmlからsubmitというワードを無くしましょう!
とgrepをかけてみたところ、
class名としてそこそこ使われていたので天を仰いだ次第です。
あるディレクトリ以下を監視して、
submitと書かれた箇所を見つけたらアラートを飛ばすような仕組みを作らなければ。。。
道は長い。。。

PAGE TOP