現在の位置: ホーム> 最新記事一覧> convert_cyr_string関数を使用してURLパラメーターをエンコードおよび変換するための実用的なヒントは、コードの問題を避けるためにパラメーターを変換します

convert_cyr_string関数を使用してURLパラメーターをエンコードおよび変換するための実用的なヒントは、コードの問題を避けるためにパラメーターを変換します

gitbox 2025-09-17

1。問題のシナリオとアイデアの概要

典型的なプロセスは、ブラウザまたはクライアントURLがパラメーターをエンコードして送信することです(たとえば、 ?name =%e4%f0%e2%e5%f2 )。正しいUTF-8テキストに復元するには、通常、2つのステップが必要です。

  1. URLエンコード( rawurldecode / urldecode )をデコードして、元のバイトシーケンスを取得します。 php.net +1

  2. このバイトシーケンスを正しいシングルバイトエンコード(例:Windows-1251、KOI8-R、CP866など)からUTF-8に変換します。一般的なキリル語のエンコーディングの場合、 convert_cyr_stringは、サーバーPHPバージョンでサポートされている場合に文字セット変換を完了できます。 php.net

注: convert_cyr_stringは、php 7.4以降に非推奨され、php 8.0で削除されます。 MB_CONVERT_ENCODING / ICONVまたはサードパーティのUTF-8ライブラリは、最初に新しい環境で使用する必要があります。互換性と代替ソリューションを以下に示します。 php.net


2。convert_cyr_stringによってサポートされるエンコーディングコード(簡潔)

convert_cyr_string(string $ str、string $ from、string $ to)を使用して、共通の識別は次のとおりです。

  • K - Koi8-r

  • W - Windows-1251

  • I - ISO-8859-5

  • A / D - X-CP866(DOS CP866)

  • M - X-MAC-Cyrillic。 php.net


3。実用的なコードテンプレート( convert_cyr_stringに基づく)

実用的なPHP関数は次のとおりです。URLエンコードされている文字列を受信し、何らかのキリルエンコード文字列(クエリ文字列またはパスセグメントから)を使用し、UTF-8に変換します。:使用する前に、PHPバージョンが引き続きconvert_cyr_string (php≤7.3)をサポートしていることを確認してください。実行中の環境がPHP 8+の場合は、次のセクションにスキップして、代替案を確認してください。

 <span><span><span class="hljs-meta">&lt;?php</span></span><span>
<span class="hljs-comment">/**
 * 意思 URL パラメーター(単一バイトのキリル語のためにエンコードされ、パーセントの記号で逃げる可能性があります)に標準化されています UTF-8 弦。
 *
 * $rawUrlPart: オリジナル URL 一部(例えば $_GET['name'],またはから PATH_INFO/ルートで得られたフラグメント)
 * $sourceCode: ソースコード識別,使用 convert_cyr_string 単一の文字コード('w','k','i','a','d','m')
 *
 * 戻る UTF-8 弦(若无法转换则戻るオリジナル经过 rawurldecode 的弦)
 */</span>
</span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">normalize_cyrillic_url_param</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-keyword">string</span></span></span><span> </span><span><span class="hljs-variable">$rawUrlPart</span></span><span>, </span><span><span class="hljs-keyword">string</span></span><span> </span><span><span class="hljs-variable">$sourceCode</span></span><span> = </span><span><span class="hljs-string">'w'</span></span><span>): </span><span><span class="hljs-title">string</span></span><span> {
    </span><span><span class="hljs-comment">// 先把百分号转义还原のためにオリジナル字节</span></span><span>
    </span><span><span class="hljs-variable">$decoded</span></span><span> = </span><span><span class="hljs-title function_ invoke__">rawurldecode</span></span><span>(</span><span><span class="hljs-variable">$rawUrlPart</span></span><span>); </span><span><span class="hljs-comment">// 予約済みバイト,しないでください + 宇宙に向かいます(に適用されます path segment);から query そして、あります +,利用可能 urldecode()</span></span><span>
    
    </span><span><span class="hljs-comment">// システムがある場合 convert_cyr_string(知らせ:存在する PHP 8+ 削除)</span></span><span>
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">function_exists</span></span><span>(</span><span><span class="hljs-string">'convert_cyr_string'</span></span><span>)) {
        </span><span><span class="hljs-comment">// 最初に単一のバイトをエンコードします(sourceCode)に変換します windows-1251('w'),</span></span><span>
        </span><span><span class="hljs-comment">// それから windows-1251 に頼ります UTF-8(使用 mb_convert_encoding)</span></span><span>
        </span><span><span class="hljs-variable">$asWin1251</span></span><span> = </span><span><span class="hljs-title function_ invoke__">convert_cyr_string</span></span><span>(</span><span><span class="hljs-variable">$decoded</span></span><span>, </span><span><span class="hljs-variable">$sourceCode</span></span><span>, </span><span><span class="hljs-string">'w'</span></span><span>);
        </span><span><span class="hljs-comment">// 意思 windows-1251 二进制字节に頼ります UTF-8 弦</span></span><span>
        </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">function_exists</span></span><span>(</span><span><span class="hljs-string">'mb_convert_encoding'</span></span><span>)) {
            </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-title function_ invoke__">mb_convert_encoding</span></span><span>(</span><span><span class="hljs-variable">$asWin1251</span></span><span>, </span><span><span class="hljs-string">'UTF-8'</span></span><span>, </span><span><span class="hljs-string">'Windows-1251'</span></span><span>);
        } </span><span><span class="hljs-keyword">else</span></span><span> {
            </span><span><span class="hljs-comment">// バックアップとして,試す iconv(のように果利用可能)</span></span><span>
            </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">function_exists</span></span><span>(</span><span><span class="hljs-string">'iconv'</span></span><span>)) {
                </span><span><span class="hljs-variable">$utf8</span></span><span> = @</span><span><span class="hljs-title function_ invoke__">iconv</span></span><span>(</span><span><span class="hljs-string">'CP1251'</span></span><span>, </span><span><span class="hljs-string">'UTF-8//IGNORE'</span></span><span>, </span><span><span class="hljs-variable">$asWin1251</span></span><span>);
                </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$utf8</span></span><span> !== </span><span><span class="hljs-literal">false</span></span><span> ? </span><span><span class="hljs-variable">$utf8</span></span><span> : </span><span><span class="hljs-variable">$asWin1251</span></span><span>;
            }
            </span><span><span class="hljs-comment">// 都不利用可能时,戻るオリジナル解码弦</span></span><span>
            </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$asWin1251</span></span><span>;
        }
    }

    </span><span><span class="hljs-comment">// そうでない場合 convert_cyr_string(のように PHP 8+),直接戻るオリジナル解码弦,発信者に代替案を使用させます</span></span><span>
    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$decoded</span></span><span>;
}
</span></span>

使用例:

 <span><span><span class="hljs-comment">// 仮定 URL のために: /?name=%D0%9C%D0%B8%D1%80</span></span><span>
</span><span><span class="hljs-variable">$raw</span></span><span> = </span><span><span class="hljs-variable">$_GET</span></span><span>[</span><span><span class="hljs-string">'name'</span></span><span>] ?? </span><span><span class="hljs-string">''</span></span><span>;
</span><span><span class="hljs-variable">$name</span></span><span> = </span><span><span class="hljs-title function_ invoke__">normalize_cyrillic_url_param</span></span><span>(</span><span><span class="hljs-variable">$raw</span></span><span>, </span><span><span class="hljs-string">'w'</span></span><span>); </span><span><span class="hljs-comment">// 仮定客户端以 Windows-1251 送信</span></span><span>
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$name</span></span><span>; </span><span><span class="hljs-comment">// 出力は正しいです UTF-8 名前</span></span><span>
</span></span>

エスケープのデコードは、パラメーターソースrawurldecode() (パスセグメントに適しています)またはurldecode()+ +がクエリ文字列のスペースを表す場合)に基づいて選択する必要があります。 2つの違いと推奨使用については、公式ドキュメントを参照してください。 php.net guides.codepath.com


4。PHP8+(または非推奨機能を避けたい) - 推奨される代替

新しいプロジェクトまたはPHP 8+環境の場合、 MB_DETECT_ENCODING + MB_CONVERT_ENCODING / ICONVを使用するか、クライアントがUTF-8を均一に使用できるようにすることをお勧めします(ベストプラクティス)。例:

 <span><span><span class="hljs-meta">&lt;?php</span></span><span>
</span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">normalize_cyrillic_url_param_modern</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-keyword">string</span></span></span><span> </span><span><span class="hljs-variable">$rawUrlPart</span></span><span>, </span><span><span class="hljs-keyword">array</span></span><span> </span><span><span class="hljs-variable">$tryEncodings</span></span><span> = [</span><span><span class="hljs-string">'Windows-1251'</span></span><span>,</span><span><span class="hljs-string">'KOI8-R'</span></span><span>,</span><span><span class="hljs-string">'CP866'</span></span><span>]) : </span><span><span class="hljs-title">string</span></span><span> {
    </span><span><span class="hljs-variable">$decoded</span></span><span> = </span><span><span class="hljs-title function_ invoke__">rawurldecode</span></span><span>(</span><span><span class="hljs-variable">$rawUrlPart</span></span><span>);
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">function_exists</span></span><span>(</span><span><span class="hljs-string">'mb_detect_encoding'</span></span><span>) &amp;&amp; </span><span><span class="hljs-title function_ invoke__">function_exists</span></span><span>(</span><span><span class="hljs-string">'mb_convert_encoding'</span></span><span>)) {
        </span><span><span class="hljs-comment">// 試す检测并转换到 UTF-8</span></span><span>
        </span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$tryEncodings</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$enc</span></span><span>) {
            </span><span><span class="hljs-comment">// 检测字节串是否のために此编码(テストは信頼できない場合があります,故采用試す转换后判断)</span></span><span>
            </span><span><span class="hljs-variable">$maybe</span></span><span> = @</span><span><span class="hljs-title function_ invoke__">mb_convert_encoding</span></span><span>(</span><span><span class="hljs-variable">$decoded</span></span><span>, </span><span><span class="hljs-string">'UTF-8'</span></span><span>, </span><span><span class="hljs-variable">$enc</span></span><span>);
            </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$maybe</span></span><span> !== </span><span><span class="hljs-literal">false</span></span><span>) {
                </span><span><span class="hljs-comment">// 簡単な検証:変換後の元のバイトの長さに似ていますか?(いいえ 100% 信頼性のある,しかし、実用的です)</span></span><span>
                </span><span><span class="hljs-variable">$back</span></span><span> = @</span><span><span class="hljs-title function_ invoke__">mb_convert_encoding</span></span><span>(</span><span><span class="hljs-variable">$maybe</span></span><span>, </span><span><span class="hljs-variable">$enc</span></span><span>, </span><span><span class="hljs-string">'UTF-8'</span></span><span>);
                </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$back</span></span><span> !== </span><span><span class="hljs-literal">false</span></span><span> &amp;&amp; </span><span><span class="hljs-title function_ invoke__">strlen</span></span><span>(</span><span><span class="hljs-variable">$back</span></span><span>) &gt;= </span><span><span class="hljs-title function_ invoke__">strlen</span></span><span>(</span><span><span class="hljs-variable">$decoded</span></span><span>) - </span><span><span class="hljs-number">2</span></span><span>) {
                    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$maybe</span></span><span>;
                }
            }
        }
    }
    </span><span><span class="hljs-comment">// 最后退回オリジナル解码后的弦(おそらくすでに UTF-8)</span></span><span>
    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$decoded</span></span><span>;
}
</span></span>

さらに、成熟したサードパーティライブラリ( Voku/Portable-UTF8など)を使用して、特に高い堅牢性を必要とする生産システムでは、複雑なコーディング/正規化の問題に対処することもできます。 github


5。実用的な提案とキーポイントのリスト

  1. 優先順位:最良の解決策は、すべてのクライアントがUTF-8を均一に使用できるようにすることです(HTML <Meta charset = "utf-8"> 、HTTPヘッダー、APIドキュメントで説明)。これは、基本的に文字化けのコードを避けるためのベストプラクティスです。

  2. 機能選択:URLエンコードを受信するとき、クエリパーツ( ?a = b + c )の場合、 urldecode()は+ +を空間に変えます。パスセグメントの場合、 rawurldecode()が推奨されます。 php.net +1

  3. サーバー側の変換:履歴データまたはサードパーティシステムのみを処理できる場合、バイトシーケンスは上記の変換チェーンを使用してUTF-8に変換されます( RawurldeCodeConvert_Cyr_String (利用可能な場合)またはMB_CONVERT_ENCODING / ICONV )。 php.net +1

  4. 検出とフォールバック:自動検出エンコーディングは100%正確ではありません。重要なシナリオ(検出後の一貫性のチェックなど)に「信頼性」判断を追加し、手動介入の障害を記録したり、特定のルールを追加したりすることをお勧めします。

  5. 非推奨注convert_cyr_stringは、php 7.4で非推奨としてマークされ、php 8.0で削除されています。コードが最新のPHP環境で長い間実行する必要がある場合は、互換性のある代替( MB_CONVERT_ENCODING / ICONV /サードパーティライブラリ)を実装してください。 php.net


6。クイック比較の例(両端が互換性)

シナリオA:レガシークライアントはKOI8-Rでパラメーター(クエリ)を送信し、サーバーはUTF-8を取得したいと考えています。

 <span><span><span class="hljs-variable">$raw</span></span><span> = </span><span><span class="hljs-variable">$_GET</span></span><span>[</span><span><span class="hljs-string">'q'</span></span><span>];                </span><span><span class="hljs-comment">// オリジナル %xx 弦</span></span><span>
</span><span><span class="hljs-variable">$bytes</span></span><span> = </span><span><span class="hljs-title function_ invoke__">rawurldecode</span></span><span>(</span><span><span class="hljs-variable">$raw</span></span><span>);      </span><span><span class="hljs-comment">// バイナリバイトを取得します</span></span><span>
</span><span><span class="hljs-comment">// 若利用可能 convert_cyr_string:</span></span><span>
</span><span><span class="hljs-variable">$win</span></span><span> = </span><span><span class="hljs-title function_ invoke__">convert_cyr_string</span></span><span>(</span><span><span class="hljs-variable">$bytes</span></span><span>, </span><span><span class="hljs-string">'k'</span></span><span>, </span><span><span class="hljs-string">'w'</span></span><span>); </span><span><span class="hljs-comment">// koi8-r -&gt; windows-1251</span></span><span>
</span><span><span class="hljs-variable">$utf8</span></span><span> = </span><span><span class="hljs-title function_ invoke__">mb_convert_encoding</span></span><span>(</span><span><span class="hljs-variable">$win</span></span><span>, </span><span><span class="hljs-string">'UTF-8'</span></span><span>, </span><span><span class="hljs-string">'Windows-1251'</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$utf8</span></span><span>;
</span></span>

シナリオB:PHP 8+環境、最新の方法を使用して自動変換を試してください。

 <span><span><span class="hljs-variable">$raw</span></span><span> = </span><span><span class="hljs-variable">$_GET</span></span><span>[</span><span><span class="hljs-string">'q'</span></span><span>];
</span><span><span class="hljs-variable">$bytes</span></span><span> = </span><span><span class="hljs-title function_ invoke__">rawurldecode</span></span><span>(</span><span><span class="hljs-variable">$raw</span></span><span>);
</span><span><span class="hljs-variable">$utf8</span></span><span> = </span><span><span class="hljs-title function_ invoke__">normalize_cyrillic_url_param_modern</span></span><span>(</span><span><span class="hljs-variable">$raw</span></span><span>, [</span><span><span class="hljs-string">'Windows-1251'</span></span><span>,</span><span><span class="hljs-string">'KOI8-R'</span></span><span>,</span><span><span class="hljs-string">'CP866'</span></span><span>]);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$utf8</span></span><span>;
</span></span>

7。結論(キーポイントのレビュー)

  • convert_cyr_stringは、かつてキリル語のシングルバイトエンコーディング間の交換を処理する便利な関数であり、サポートされているコードにはk、w、i、a、d、mが含まれます。ただし、この関数はPHP 7.4で非推奨され、PHP 8.0で削除されます。新しいプロジェクトは、代わりにMB_CONVERT_ENCODING / ICONVまたはサードパーティライブラリを使用することをお勧めします。 php.net

  • Carlebled URLパラメーターの問題に直面して、キーは次のとおりです。最初にパーセンテージサイン( rawurldecode / urldecode )を正しくデコードし、実際のソースエンコーディングに基づいてバイトシーケンスをUTF-8に変換します。パスとクエリのデコード関数を選択するときは、2つの間のハンドリングスペース( + )の違いに注意してください。 php.net +1

  • 最も安全な長期戦略は、UTF-8を統一された方法で使用し、インターフェイスドキュメントとクライアントの実装のコーディング仕様に明確に同意することです。履歴またはサードパーティのデータが必要な場合、上記の変換チェーンが採用され、堅牢性を確保するために検出およびフォールバックメカニズムが追加されます。 github php.net

  • 関連タグ:

    URL