猫も杓子も記事を書く

140文字ではかけないことをかこうと思います。

php備忘録1

仕事で使った+はまったので忘れないように書いておきます。
かなり限られるシチュエーション時のPHP活用法。

入力フォームに改行数の制限をかけたい時

これは比較的簡単でした。
preg_match_allという関数を使います。

PHP: preg_match_all - Manual

正規表現での検索を行いたいので今回はこちら・・・ですよね?

$lines = preg_match_all("/\n|\r\n|\n/", $memo);

このlinesが予め設けた制限を超えていたらfalseにするというわけです。

if($lines >= $limits){
    return false;
}
return true;

一行あたりの文字数を制限したいとき

例えば、200文字入力可能な入力フォームがあったとして、
それを1行あたり50文字の入力に制限したいという時。
かなりのレアケースだと思いますが、
実際にそういう制限を書けなきゃいけなくなったんだからしょうがない。

最初、自分は必死に文字列を配列化して文字数を上限にforを回すとかお馬鹿なことを考えていました。
こんな感じに。

$words = mb_strlen($memo);
$words_array = preg_split("//u", $memo, -1, PREG_SPLIT_NO_EMPTY);
$j = 0;

for ($i=0; $i < $words; $i++) {
    $j++;
    if ($j == $line_limit) {
        break;
    } elseif ($words_array[$i] == "\n"||"\r\n"||"\n") {
        $j = 0;
    }
    if ($i) {
        # code...
    }
}
return false;

・・・馬鹿でしょう?「全体の文字数を見るポインタと改行有無を見るポインタ2ついるな・・・うーん?」とか考えてたんですよ。
笑うところですよここ。(うちにこんなバカ社員いなくてよかった)と安堵するところです。泣いてもいいですか?
こういう場合、文字数ではなくて、文字バイト数で判定するのが定石のようです。
さらに、UTF-8ではマルチバイト文字(特に日本語)を符号化した時のバイト数がまちまちなので、半角1バイト、全角2バイトのSJISに変換してチェックします。変換にはmb_convert_encodingという関数を使います。

PHP: mb_convert_encoding - Manual

半角に対応するため、単純計算で設定した文字数*2が上限になりますね。
では、どうやって文字列の改行コードをチェックするのかといいますと、phpにはexplodeという便利な関数がありまして、

PHP: explode - Manual

この関数で文字列を改行コード毎に区切ってあげます。

$words = explode("/\n|\r\n|\n/", $memo);

あとはこの、区切ったwords配列をforeachでチェックするだけです。すごいぞPHP

$line_limit = 50*2;

foreach ($words as $word) {
      if ( strlen(mb_convert_encoding($word, "sjis")) > $line_limit ){
             return false;
       }
}

return true;

以上!すっきりしました。


ちなみに、もう気づいてしまった方もいらっしゃるかと思いますが、
コレを使ってしまうと、最初に書いた、改行数の制限(preg_match_allのやつ)はいらなくなります。
配列数がそのまま改行数になりますからね。
これはもう、知識の勝利という感じです。

12/6 17:28追記

シンタックスハイライトがうまく機能していないみたいなので一旦外してます。bashの記事の時はうまくいってたんですがね・・・
見づらくて申し訳ない・・・多分僕が悪いんだと思います。

12/7 19:00追記

更に追記。どうやらexplodeはパイプ表記に対応していないのかなんなのか、上のやり方だと区切ってくれません。
なので、先に改行コードを統一する必要があります。
マシンがMacなので、というわけではないですが、今回は\nに統一。

$br = array("\r\n","\r");
$str = str_replace($br, "\n", $value);

$words = explode("\n", $str);

これでいけると思います。責任はもてませんがw