質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

4回答

1742閲覧

PHPで文字コードをチェックする関数

gsuisk

総合スコア72

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2017/08/29 08:00

ある本を参考にして、与えられた文字列の文字コードが有効なものかをboolで返す関数を作りました。そこで3点質問があります。

PHP

1function check(array $data){ 2 $result = true; 3 4 foreach ($data as $key => $value) { 5 if(is_array($value)){ 6 $value = implode("", $value); 7 } 8 if(!mb_check_encoding($value)){ 9 $result = false; 10 break; 11 } 12 } 13 return $result; 14}

(1)引数が配列型であるのは、文字列を一つずつチェックするためだと思いますが、一度に一つの文字列をチェックする方法はないのでしょうか?

(2)関数内にあるmb_check_encodingですが、マニュアルを見ると指定するエンコーディング(ここではutf-8)が第二引数で必要なようですが、何も指定せずに動作するのはなぜでしょうか?

(3)utf-8でない文字列を代入した$jisで、以下のように実行しているのですが、check()の引数に[$jis]と[]がついている理由を教えてください。配列にキャストしているのでしょうか?

PHP

1$word = "こんにちは"; 2$jis = mb_convert_encoding($word, 'Shift-JIS'); 3 4if(check([$jis])){ 5 echo "TRUE"; 6}else{ 7 echo "FALSE"; 8}

つまり上記は

PHP

1$word = "こんにちは"; 2$jis = mb_convert_encoding($word, 'Shift-JIS'); 3$jis = str_split($jis); 4 5if(check($jis)){ 6 echo "TRUE"; 7}else{ 8 echo "FALSE"; 9}

に同じでしょうか?

質問が多くてすみません。一つでもお答えしていただけると幸いです。

どうかよろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

(1)引数が配列型であるのは、文字列を一つずつチェックするためだと思いますが、一度に一つの文字列をチェックする方法はないのでしょうか?

check複数の文字列について一気にチェックを掛ける関数です。そもそも1個であれば、このようなヘルパー関数を使わずとも、直接mb_check_encodingを呼ぶか(3)のように、「1個だけの配列」にすれば片付きます。

(2)関数内にあるmb_check_encodingですが、マニュアルを見ると指定するエンコーディング(ここではutf-8)が第二引数で必要なようですが、何も指定せずに動作するのはなぜでしょうか?

エンコードを指定しない場合、mb_internal_encoding()の設定を参照することになりますが、そのやり方はおすすめできません。UTF-8を明記した方がいいです。

(3)utf-8でない文字列を代入した$jisで、以下のように実行しているのですが

これは(1)で触れたように、配列しか受け付けない関数なので、1個でも配列にして代入している、というだけです。なお、日本語などマルチバイトのコードをstr_splitにかけると、バイト単位で処理する都合上文字の途中でぶった切られる危険性がありますので、やってはいけません。

投稿2017/08/29 08:09

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gsuisk

2017/08/29 09:41

ご回答ありがとうございます! (1)については、例えば "abc" という文字列を配列にキャストしてcheck()に渡すと、check関数では Array ( [0] => abc )と複数の文字列を1つの配列インデックス[0]に格納するという意味ですね。 ( [0]=>a [1]=>b...となるのではなく) 文字列を一文字ずつ取り出しているのだと勘違いしていました。 (2)に関しては、マニュアルの string $encoding = mb_internal_encoding() とは引数がないときの初期値を意味していたのですね。念のためmb_check_encoding($value, "utf-8")としておきます。 (3)について、mbがついていないオプションはマルチバイトに対応していない可能性が高いのですね。使うときはマニュアルを見てみます。
guest

0

ベストアンサー

(1)引数が配列型であるのは、文字列を一つずつチェックするためだと思いますが、一度に一つの文字列をチェックする方法はないのでしょうか?

書いてある通り、「一度に一つの」文字列をチェックするなら、引数の型をstringにして、foreachを削除すれば良いでしょう。

php

1function check(string $value){ 2 $result = true; 3 4 if(!mb_check_encoding($value)){ 5 $result = false; 6 break; 7 } 8 return $result; 9}

また、mb_check_encoding自体がbooleanを返すので、下記のようにすることもできます。
(もはや何のために関数でラップしているのか意味不明ですが)

php

1function check(string $value){ 2 return mb_check_encoding($value); 3}

「一度に複数の」の書き間違いでしたら、可変長引数を使ってcheck($str1, $str2, $str3...)のように呼び出すこともできます。
PHPのバージョンによって書き方が違うので、詳しくは公式ドキュメントをご覧ください。
http://php.net/manual/ja/functions.arguments.php

(2)関数内にあるmb_check_encodingですが、マニュアルを見ると指定するエンコーディング(ここではutf-8)が第二引数で必要なようですが、何も指定せずに動作するのはなぜでしょうか?

内部文字エンコーディングを使っています。内部文字エンコーディングは下記の方法で調べることができます。

php

1echo mb_internal_encoding();

(3)utf-8でない文字列を代入した$jisで、以下のように実行しているのですが、check()の引数に[$jis]と[]がついている理由を教えてください。配列にキャストしているのでしょうか?

配列にキャストしています。
str_split($jis)は全角文字に対応していませんので、下記のような恐ろしいことになります。

php

1var_export(str_split('こんにちは')); 2 3array ( 4 0 => '?', 5 1 => '?', 6 2 => '?', 7 3 => '?', 8 4 => '?', 9 5 => '?', 10 6 => '?', 11 7 => '?', 12 8 => '?', 13 9 => '?', 14 10 => '?', 15 11 => '?', 16 12 => '?', 17 13 => '?', 18 14 => '?', 19)

投稿2017/08/29 08:25

tsuemura

総合スコア663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gsuisk

2017/08/29 09:48

ご回答ありがとうございます。 おっしゃる通り、 function check(string $value){ return mb_check_encoding($value); } このほうが簡単だと思うのですが、なぜ私のコード(本に書いてあった)はややこしく書いてあるのでしょうか? 文字コードをチェックする対象は基本「文字列」ですよね?わざわざ配列にキャストしてからcheck()に渡さないといけないし面倒な気がします。配列でも文字列でも一つの関数でチェックできるようにしているだけでしょうか?
tsuemura

2017/08/29 09:55

> 配列でも文字列でも一つの関数でチェックできるようにしているだけでしょうか? その通りです。一つの文字列をチェックするだけなら、単にmb_check_encoding($string)で出来ます(新たに関数を作る必要はありません)。
gsuisk

2017/08/31 16:44

ありがとうございました。
guest

0

とりあえず(2)に関して。
PHP: mb_check_encoding - Manual
第2引数を省略すると、代わりにmb_internal_encoding()の結果を使うので問題なし。

(3)に関して。
check()関数の引数が配列を前提としているので、
$jis単体では渡せないから配列をその場で作るために
if(check(array($jis))){って書くか、
if(check([$jis])){って書くことになった、
ということではないかと。
配列の初期化(の文法)に関しては
PHP: 配列 - Manual
を参照。

(1)に関して。
引数が配列かどうかを関数の冒頭で判断して、
配列のときの動作と文字列単体のときの動作を組むようにすれば良いですね。
例えばis_array()を使えば配列かどうかの判定が出来ます。
でもまぁ、中身としてはmb_check_encoding()での判定を
foreach()で回しているだけで、
その場面での必要な設計をしただけで実践では使わないんじゃないかなと察します。

投稿2017/08/29 08:19

編集2017/08/29 08:25
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

(1)引数が配列型であるのは、文字列を一つずつチェックするためだと思いますが、一度に一つの文字列をチェックする方法はないのでしょうか?

文字列を1文字ずつの配列にしたものを受け取る、と勘違いされてませんか?

文字列の配列を受け取りそれを1つずつチェックする、1つでも不正な物があったら打ち切り、という実装になってます。Webアプリケーションなどで、渡された複数のパラメータを一度にチェックするためのコードでしょう。

(2)関数内にあるmb_check_encodingですが、マニュアルを見ると指定するエンコーディング(ここではutf-8)が第二引数で必要なようですが、何も指定せずに動作するのはなぜでしょうか?

マニュアルを見ると第二引数を省略した場合はmb_internal_encoding()が渡されることになっています。

http://php.net/manual/ja/function.mb-check-encoding.php

(3)utf-8でない文字列を代入した$jisで、以下のように実行しているのですが、check()の引数に[$jis]と[]がついている理由を教えてください。配列にキャストしているのでしょうか?

上に書いたとおり、複数の文字列を配列として受け取りチェックするコードですので、1つの文字列をチェックするにも配列として渡す必要があります。1要素の配列として渡しているコードで、1文字ずつに分解される訳ではありません。

投稿2017/08/29 08:13

suzukis

総合スコア1449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問