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

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

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

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

Q&A

1回答

1541閲覧

phpの関数がマニュアル通りに機能しない

nikuatsu

総合スコア177

PHP

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

0グッド

0クリップ

投稿2022/09/17 00:22

編集2022/09/18 22:35

前提

phpで文字数のカウントに取り組んでいます。

実現したいこと

grapheme_strlenの実行に際して、マニュアル通りの結果を得たいです。

マニュアルはこちらです。

grapheme_strlen
https://www.php.net/manual/ja/function.grapheme-strlen.php

得たい結果はマニュアルの一番最後に載っているこちらです。

echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); //1 - Bingo

発生している問題

該当のソースコードが上記マニュアルと異なる結果を返し、以下7を得ます

該当のソースコード

php

1echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); //7 - なぜ...?

試したこと

試したこと 1(コードの確認)

まずマニュアルのコピペミスを懸念し、改めてコピペしましたが変化なしでした。
これは「質問への追記・修正の依頼」で m.ts10806様 から改めて確認するようご指摘頂き、再三のコピペで確認致しました。

そのコピペの結果は下図です。
イメージ説明

ちなみに3v4lにマニュアルをコピペするとこうなります。
https://3v4l.org/QXCFu

以上みなさんがされても同様だと思いますので、コピペミスは考えにくい思います。

試したこと 2(バージョンの確認)

次にphpバージョンを確認すると 8.0.16 で問題はなさそうでした。

php

1echo phpversion().PHP_EOL; //8.0.16

本当に 8.0.16 なのか?と疑い、「8.0ならエラーになる」という次のリンクのコードを試しました。

PHP 7.3では配列のオフセットの指定に波括弧を利用できましたが、PHP 8.0ではFatal Errorが発生します。
$hoge = [1, 2, 3];
echo $hoge{0};
https://recruit.gmo.jp/engineer/jisedai/blog/php8-version-up-notes/

しかし正しくFatal errorとなりました。

log

1[17-Sep-2022 00:03:57 UTC] PHP Fatal error: Array and string offset access syntax with curly braces is no longer supported in /home/xxxxxxxxxxxx/example.com/public_html/wp-content/themes/test/header.php on line 22
試したこと 3(関数の有無を確認)

grapheme_strlenの有無を確認しましたが以下問題なくtrueでした。

php

1var_dump( function_exists('grapheme_strlen') ); //true
試したこと 4(バージョンの変更)

Xサーバーの管理画面で 8.0.16 を 8.1.6 にアップデートしたものの改善は見られませんでした。
逆に 7.4.28 にダウングレードしても同様でした。

試したこと 5(JavaScriptの停止)

まさか「画面上の17に置換する」というJavaScriptでも動いているのか?と思い、ブラウザでJavaScriptを停止しましたが、さすがにそんなスクリプトはなかったようです。

試したこと 6(コマンドで実行)

Teratermから以下コードをコピペし実行しました。'abc'の方は普通に3ですが、'🏴󠁧󠁢󠁥󠁮󠁧󠁿'の方はペースト時に??????????????になってしまい14となり、どうやらコマンドでは絵文字は使えないようでした。

Teraterm

1php -r "echo grapheme_strlen('abc'),PHP_EOL;" //3 2php -r "echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'),PHP_EOL;" //14
試したこと 7(文字コード確認)
phpの実行で確認

次のコードを実行しましたが、UTF-8で問題ないように思われます。

php

1// デフォルトの判定可能な文字コード 2print_r(mb_detect_order()); 3 4// 文字コード確認 5$utf8s = ['テスト','🏴󠁧󠁢󠁥󠁮󠁧󠁿']; 6foreach( $utf8s as $utf8 ){ 7 echo $utf8 . ':' . mb_detect_encoding($utf8).PHP_EOL; 8} 9 10/* 11Array 12( 13 [0] => ASCII 14 [1] => JIS 15 [2] => UTF-8 16 [3] => EUC-JP 17 [4] => SJIS 18) 19テスト:UTF-8 20🏴󠁧󠁢󠁥󠁮󠁧󠁿:UTF-8 21*/
エディタで確認

尚、下図のようにエディタ(Notepad++)の文字コードも「UTF-8」でしたので、PHPファイル自体の文字コードも問題ないと思われます。
イメージ説明

php.iniで確認

さらにXサーバーの管理画面からphp.iniを見てみましたが、default_charset = UTF-8mbstring.internal_encoding = UTF-8で、これも問題なさそうです。

試したこと 8(他の Grapheme 関数)

Grapheme 関数が他にいくつかございましたので、以下を実行してみました。おそらく本来は同じ値になるはずですが、こちらもおかしかったです。

php

1echo bin2hex('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); 2//f09f8fb4f3a081a7f3a081a2f3a081a5f3a081aef3a081a7f3a081bf 3echo bin2hex(grapheme_substr('🏴󠁧󠁢󠁥󠁮󠁧󠁿',0,1)); 4//f09f8fb4
試したこと 9(index.phpで実行)

WordPressを介さずpublic_html直下のindex.phpで実行しました。これもマニュアルをコピペした5行のみを記載しましたが、変化は見られませんでした。

イメージ説明

補足情報(FW/ツールのバージョンなど)

尚、ご参考になるかわかりませんが、Xサーバーを利用しWordPress上で実行しブラウザで結果を確認しています。

原因、解決策、他に試すべき事柄などについて思い当たることがございましたら、ご回答宜しくお願い致します。

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

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

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

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

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

m.ts10806

2022/09/17 00:35 編集

7を返すのは2つ目のmb_strlen()です。 本当に最後の1行だけを実行していますか? grapheme_strlen()は本当に有効化されているのでしょうか?(デフォルトでは入らないはず) つまり、そもそも Uncaught Error: Call to undefined function grapheme_strlen() が発生してたりしませんか? エラー表示ONにして確認してみてください。
nikuatsu

2022/09/17 00:45

> 本当に最後の1行だけを実行していますか? はい。もう一度マニュアルをコピペし以下実行しました。(コメントアウトはマニュアルのまま。) echo strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); //28 - oh no echo mb_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); // - closer, but no echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); //1 - Bingo その結果は以下で、やはり7です。 2877 > grapheme_strlen()は本当に有効化されているのでしょうか? 次のコードを実行しました。 var_dump( function_exists('grapheme_strlen') ); 結果は次のようになりました。 bool(true) > Uncaught Error: Call to undefined function grapheme_strlen() 発生していませんでした。
m.ts10806

2022/09/17 00:54

上記記載しておいてください。
nikuatsu

2022/09/17 01:50 編集

記載しておきました。ありがとうございます。 ちなみに一番怪しいコピペミスを疑い改めてコピペしましたがダメでした。こんなことあるでしょうか。 もうXサーバーがphpを改ざんして提供している以外に考えられません…
otn

2022/09/17 10:35

'🏴󠁧󠁢󠁥󠁮󠁧󠁿'などはTeratermでは入力できないと思いますが、ファイルは具体的にどうやって作って、具体的にどうやってサーバーにコピーしていますか?
nikuatsu

2022/09/17 11:46

Teratermでは仰る通り入力できません。質問にも記載しておりますように、「試したこと 6」のコードをコピーし、Teratermにペーストするとハテナマークに変換されますので、その状態で実行しました。なので14となります。ファイルというのはなんのファイルですか?Teratermではファイルは呼んでおりません。echoの実行のみです。
m.ts10806

2022/09/17 11:58

>もうXサーバーがphpを改ざんして提供している以外に考えられません… それは明確に「ない」と言い切れます。 迷惑行為をしているなら即アカウント自体を無効にしますし、 そうでないなら1ユーザのテストプログラム程度にわざわざ手を入れることはないです。 監視必要なくらいなら実行させません。 一応以下では1が出ました。 https://3v4l.org/QXCFu ただ見ての通り、スペースが結構あります。 そこをカウントされてるとかはないでしょうか? また、そのスクリプトファイルの文字コードはUTF-8になっていますか? 確認してください。
otn

2022/09/17 13:02

> ハテナマークに変換されますので、その状態で実行しました。 ??? echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); というプログラムを次項したのでは無いのですか??? そのプログラムファイルは(Teratermから入力したのでは無いだろうから)具体的にどうやって作って、具体的にどうやってサーバーにコピーしていますか? という質問なのですが???
nikuatsu

2022/09/17 13:48

otn様 うーん、何がそちらの理解の妨げになっているかわかりません。以下は繰り返しになってしまいますが、正確な表現を心がけてみます。なんとか頑張って読解してください。 まず「試したこと 6」に記載してあるコードをTeratermにペーストすると、「試したこと 6」に記載してあるようにハテナマークの連続になります。これは「試したこと 6」に記載してあるようにTeratermから実行しました。すべて記載してある通りです。 試しに php -r "echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'),PHP_EOL;" をTeratermにペーストしてみてください。ハテナマークの連続になります。 「>Teratermから入力したのでは無い」ということはありません。「試したこと6」に記載してあるようにTeratermにペーストして実行しています。
nikuatsu

2022/09/17 14:08

m.ts10806様 さすがにないですよね… 「スペースがカウントされている」の件は意味が理解できませんでした。 文字コードの件は「試したこと 7」として追加させて頂きまして、問題ないように思われます。 アドバイスありがとうございます
otn

2022/09/17 15:38

そもそも、echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); は一度も実行しておらず、 echo grapheme_strlen('??????????????'); しか実行していないと言うことですか? 質問を読んで、そこに書いてある通り、 「echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); を実行したら 7が表示された」 ということかと思ったのですが、それは嘘? 「echo grapheme_strlen('??????????????');を実行して14が表示された」 といことなら、そりゃそうですとしか言い様がないです。
otn

2022/09/17 15:48 編集

他のコメントも含め、読み返すと、やはり echo grapheme_strlen('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); を実行したと思えるのですが、 これで3度目の質問ですが、そのプログラムが書かれたファイルはどうやって作ってどうやってサーバー上に置いたのですか?Windows上で作ったのではと推測しています。 (この文章でどこか意味のわからないところはありますか?)
otn

2022/09/17 16:21

echo bin2hex('🏴󠁧󠁢󠁥󠁮󠁧󠁿'); で、 f09f8fb4f3a081a7f3a081a2f3a081a5f3a081aef3a081a7f3a081bf が表示されますか? echo bin2hex(grapheme_substr('🏴󠁧󠁢󠁥󠁮󠁧󠁿',0,1)); ではどうですか?
m.ts10806

2022/09/17 21:02 編集

Windowsメモ帳でPHPマニュアルのコード貼り付けて見た感じだとすごーく「7」って出そうな感じですね。 https://ddjkaamml8q8x.cloudfront.net/questions/2022-09-18/47737c84-5061-40c6-98c2-203916178e2a.png テキストエディタだと https://ddjkaamml8q8x.cloudfront.net/questions/2022-09-18/28786235-dbfa-4679-b880-ba22e58c224b.png まぁコピペしようっても、HTMLとしては結構細かく分けられてるので、コピペ先の環境によって解析結果が変わるようには思いますが。 https://ddjkaamml8q8x.cloudfront.net/questions/2022-09-18/35ea5f4c-7f9b-4083-bd80-f48a3a092280.png >「スペースがカウントされている」の件は意味が理解できませんでした。 私が提示した3v4lを見てもらえれば分かりますが、コードエディタ部分に絵文字以降にスペースが沢山出ています。 そこも貼り付けられてしまう環境にてファイルを作って実行されたのではという懸念です。 追記された「WordPress上で」というのはotnさんの依頼には応えられていません。 このテストプログラムをどいうファイル名で作成し、どこに置き、どのように実行(アクセス)しているのかです。 WordPressの機能の中のPHPファイルに書いているのですか? てっきりPHPマニュアルの5行だけをコピペしたtest.phpのようなものを準備してブラウザもしくはphpコマンドでそのphpファイルにアクセスしたのかと思っていたのですが。 あと文字コードについてはPHPファイル自体の文字コードも関係します。 確認されたのはプログラム内の文字コード(宣言)だと思います。
nikuatsu

2022/09/17 21:02

otn様 まず bin2hex の件は「試したこと 8」に追加させて頂きました。 そして「試したこと 6」のみ実行はTeratermで、これがハテナマークに変換され14となると記載しています。7になるのは「該当のソースコード」でこれがハテナマークに変換されることはありません。そして「該当のソースコード」と「試したこと1、2、3、4、5、7、8」はXサーバーでWordPressのheader.phpに記述して実行しています。filezillaでアップロート致しました。
m.ts10806

2022/09/17 21:03

コメントに長々追記してるので、そちらも確認を。 WordPress度外視で実行しないと有効性は証明できないと思います。
nikuatsu

2022/09/17 21:44 編集

m.ts10806様 > そこも貼り付けられてしまう環境にてファイルを作って実行されたのではという懸念です。 スペースの件理解が追いつきました。多方面からのアドバイス誠にありがとうございます。 私のエディタは Notepad++ で、ペーストすると次の画像のようになり、見た感じスペースはありません。 https://imgur.com/a/icPMhQB > てっきりPHPマニュアルの5行だけをコピペしたtest.phpのようなものを準備してブラウザもしくはphpコマンドでそのphpファイルにアクセスしたのかと思っていたのですが。 すべて仰る通りです。 header.phpは5行のみです。 パスは「試したこと2」の記載と同様で次のパスです。 /home/xxxxxxxxxxxx/example.com/public_html/wp-content/themes/test/header.php (一般的にXサーバーでWordPressを使う人のほとんどは「簡単インストール」という機能を介してこのディレクトリにheader.phpが入ります。) そして「該当のソースコード」と「試したこと1、2、3、4、5、7、8」は、ブラウザでアクセスして結果を確認しています。 > あと文字コードについてはPHPファイル自体の文字コードも関係します。 > 確認されたのはプログラム内の文字コード(宣言)だと思います。 これは「PHPファイル自体の文字コード 確認」と検索しましたが方法がわからずでした。 > WordPress度外視で実行しないと有効性は証明できないと思います。 まったく仰る通りでした。「試したこと 9」に追加させて頂きましたが、public_html直下のindex.phpでも変化は見られませんでした。
m.ts10806

2022/09/17 21:28

>header.phpは5行のみです。 WordPressに取り込まれてる機能に入ってる時点で純粋なPHPからは離れると思います。 public_html配下に適当なPHPファイルを別途新規で作ってアップロードして実行してください。
nikuatsu

2022/09/17 21:42

m.ts10806様 > WordPress度外視で実行しないと有効性は証明できないと思います。 > public_html配下に適当なPHPファイルを別途新規で作ってアップロードして実行してください。 仰る通りでした。こちらは「試したこと 9」に追加させて頂きました。 > 使ってるエディタにおける文字コードの確認の仕方を調べないと意味がないです。 ありがとうございます。「試したこと 7」に加筆させて頂きました。
m.ts10806

2022/09/17 22:08

次。 ①2877が出ている画面キャプチャを提示してください。 ②先に私が提示した実行結果 https://3v4l.org/QXCFu のコードをコピペして実行してみてください。 ③ご自身で https://3v4l.org/ にてPHPマニュアルからコピペして実行した結果を教えてください。
nikuatsu

2022/09/17 23:09 編集

m.ts10806様 > ①2877が出ている画面キャプチャを提示してください。 こちら https://imgur.com/a/0T41c1u です。 > ②先に私が提示した実行結果 https://3v4l.org/QXCFu のコードをコピペして実行してみてください。 そのコードをコピーしてエディタにペーストすると、その見た目表示されているようなスペースはなくなり、2つ前の返信の https://imgur.com/a/icPMhQB と同じようにペーストされます。 そしてペーストしたものをfilezillaでアップロードしてブラウザから見てみると➀と完全に同じでした。 (以上の➀と➁は、WordPressを介さずpublic_html直下のindex.phpで実行致しました。) > ③ご自身で https://3v4l.org/ にてPHPマニュアルからコピペして実行した結果を教えてください。 ご提示の https://3v4l.org/QXCFu と完全に同じです。スペースが見た目にあり、実行すると2871となります。こちら https://3v4l.org/QXCFu です。
m.ts10806

2022/09/17 22:52 編集

質問本文に追記を 画像も他サービスではなくteratailの画像添付機能で。
otn

2022/09/18 05:55

サーバー上のファイルの中身が期待通りになっていない可能性もあると思って作成方法・転送方法などを聞いたのですが、(RloginなどちゃんとUnicodeを扱える端末でログインしてサーバー上でvi等で作成という方法もあるので) bin2hexで調べた方が確実だなと質問を切り替えました。ファイルの中の文字は大丈夫そうなので、やはり実行環境のほうですね。php.iniの範囲だと関係するのは intl.default_locale くらいしか無さそうですが、おそらくそこでは無いと思います。 この数行のファイルを直接実行していないとは思ってもいなかったのですが、直接実行しても同じということなので、これ以上はちょっとわからず、他の方にお任せします。
nikuatsu

2022/09/18 11:39

otn様 ありがとうございます。bin2hexで調べるというのはまったく発想になかったので助かりました。
guest

回答1

0

質問の意図を把握できていない回答だったので取り下げます。

以下、取り下げた回答なので参考にしないでください。

発生する原因は分かりませんが、PHPマニュアルの表示仕様に余計な情報が付与されるのが原因のようですね。(多分、HTMLエスケープするとそうなるんだと思います)
結果としては、PHPマニュアルと同じコードを書けていない状態になっています。

PHPマニュアルのものをそのままコピーして、他のウェブフォームなどに張り付けると(質問中のURLそのままです)
イメージ説明
という感じで、🏴󠁧󠁢󠁥󠁮󠁧󠁿とシングルクォートの間に空白?のようなものが含まれた形でペーストされ、それがカウントされています。

一方で;
一旦適当なエディタに張り付けてから、ダブルクリックではなく前方からshift+→で選択して
🏴󠁧󠁢󠁥󠁮󠁧󠁿のみをコピーしてその他の箇所を自分で書いた場合はマニュアルと同じカウントになります。
イメージ説明

エディタにコピーした際には見た目は正しくコピーされているように見えるのですが、後方からカーソルを動かしていくと、見えない6文字が存在するような挙動をします。
推測するに、手元の環境で試された時も1文そのままや、前後のシングルクォート込み、ダブルクリックで領域選択等の方法でコピーされていたのではないでしょうか。
その場合、(エディタ上では)見えない6文字をカウントしてしまうんだと思われます。

投稿2022/09/18 11:10

編集2022/09/18 15:51
tanat

総合スコア18727

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

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

nikuatsu

2022/09/18 13:43 編集

ありがとうございます。ところで「>余計な情報」というのは、「>🏴󠁧󠁢󠁥󠁮󠁧󠁿とシングルクォートの間に空白?のようなもの」や「>見えない6文字」のことでしょうか? でしたらこれらは余計ではなく、「>HTMLエスケープするとそうなる」ものでもありません。 「黒い旗の絵文字」と「黒い旗の絵文字とスペースなどを繋げて表現する旗の絵文字」を区別する部分なので、コピペの際にあるのが正常です。 そしてその部分を含めて1文字とカウントしてくれるのがgrapheme_strlenで、今回はそれが機能しないという質問になります。
tanat

2022/09/18 15:48

すみません、質問の意図を理解できていない回答でしたね。 手元の環境だと > そしてその部分を含めて1文字とカウントしてくれるのがgrapheme_strlenで、今回はそれが機能しないという質問になります。 についてそのままコピペで正常に機能していましたので、回答は取り下げます。 状況としては、「その部分」がソースコードになる前に誤って変換されている様に思われるので、以下の様なケースを確認/試されると何か進展があるかもしれません - ソースコードのアップロード時にFTPのテキストモードでアップしているなど、変換処理が挟まる可能性はありませんか? - 例えば、ソースコードをzipでアップロードしてサーバ上でunzipして `php ファイル名`で実行するとどうなりますか?
tanat

2022/09/18 16:01

あとは、、サーバのウィルスチェック機能の有無の確認などでしょうか。 また、ファイル自体の正しさを検証するため、一度ローカル環境でファイルが意図通り動作することを確認されることをお勧めします。
nikuatsu

2022/09/19 03:17 編集

> すみません、質問の意図を理解できていない回答でしたね。 いえ、質問内容を見直す良い機会になりました。どうぞお気になさらずです。 > 以下の様なケースを確認/試されると何か進展があるかもしれません 次の処理で確認しましたが、変化なしでした。 PC で index.php を圧縮 → filezilla でアップロード → TeraTerm で unzip → ブラウザでサイト読み込み > あとは、、サーバのウィルスチェック機能の有無の確認などでしょうか。 これはメールにはチェックが入るようですが、filezilla を介したアップロードの際にチェックはないようです。
nikuatsu

2022/09/19 02:38 編集

> また、ファイル自体の正しさを検証するため、一度ローカル環境でファイルが意図通り動作することを確認されることをお勧めします。 これはバイト数だけ見れば問題なさそうです。つまり 🏴󠁧󠁢󠁥󠁮󠁧󠁿 だけ保存したファイルが28バイトでしたので正常だと思われます。
tanat

2022/09/19 11:03

仮に変換されていたとしたら、バイト数だけでは判断できないので、ファイルのMD5‥で比較するとかをオススメします
nikuatsu

2022/09/20 04:01

なるほど、MD5というのがピンときていないのですが、「試したこと 8」のbin2hexではいかがでしょうか。
tanat

2022/09/26 00:27 編集

md5文字列のハッシュ計算方法の一種で、一般的にファイルのMD5といった場合はファイル全体のハッシュ値を指します。 https://webkaru.net/linux/md5sum-command/ ファイルのサイズが同じでも中身が違う場合は別の値になります
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問