17

背景: WordPress サイトのデータベースの*.sqlバックアップをダウンロードし、古いデータベース テーブル プレフィックスのすべてのインスタンスを新しいものに置き換えました (たとえば、デフォルトwp_から のようなものにasdfghjkl_)。

WordPress がデータベースでシリアライズされた PHP 文字列を使用していることを知りました。私がしたことは、シリアライズされた文字列の長さの整合性を台無しにしてしまいます。

問題は、これを知る直前にバックアップ ファイルを削除し (私の Web サイトはまだ正常に機能していたため)、その後、いくつかのプラグインをインストールしたことです。したがって、元に戻す方法はありません。したがって、次の 2 つのことを知りたいと思います。

  1. 可能であれば、どうすればこれを修正できますか?

  2. これにより、どのような問題が発生する可能性がありますか?

(この記事では、たとえば WordPress ブログの設定とウィジェットが失われる可能性があると述べています。しかし、私のブログのすべての設定はそのままであるため、これは私には起こらなかったようです。内部が壊れるか、または将来どのような問題が発生するか. したがって、この質問.)

4

6 に答える 6

19

このページにアクセスしてください: http://unserialize.onlinephpfunctions.com/

そのページには、次のサンプルのシリアル化された文字列が表示されます: a:1:{s:4:"Test";s:17:"unserialize here!";}. それの一部を取る-- s:4:"Test";。これは、「文字列」、4 文字、そして実際の文字列を意味します。あなたがしたことで、数字の文字数が文字列と同期しなくなったと確信しています。上記のサイトのツールをいじってみると、たとえば「Test」を「Tes」に変更するとエラーになることがわかります。

あなたがする必要があるのは、新しい文字列と一致するようにそれらの文字数を取得することです。他のエンコーディングを破損していない場合 (コロンなどを削除した場合)、問題は解決するはずです。

于 2013-02-28T15:34:36.377 に答える
11

ドメインを localhost から実際の URL に変更しようとした後、同じ問題に遭遇しました。いくつか検索した後、Wordpressのドキュメントで答えを見つけました:

https://codex.wordpress.org/Moving_WordPress

そこに書かれていることを引用します。

このシリアル化の問題を回避するには、次の 3 つのオプションがあります。

  • > ダッシュボードにアクセスできる場合は、Better Search Replace または Velvet Blues Update URLs プラグインを使用してください。
  • ホスティング プロバイダー (またはあなた) が WP-CLI をインストールしている場合は、WP-CLI の検索置換を使用します。
  • データベースで検索と置換クエリを手動で実行します。注: wp_posts テーブルでのみ検索と置換を実行してください。

シリアライゼーションを壊さずにデータベース内のものを置き換えることができるWP-CLIを使用することになりました: http://wp-cli.org/commands/search-replace/

于 2015-09-22T18:56:26.260 に答える
3

私はこれが古い質問であることを知っていますが、決してしないよりは遅いほうがいいと思います。最近、シリアル化されたデータに対して検索/置換が実行されたデータベースを継承した後、この問題に遭遇しました。何時間も調査した結果、これは文字列の数がずれているためであることがわかりました。残念ながら、大量のエスケープと改行を含む非常に多くのデータがあり、場合によっては数え方がわからず、データが多すぎて自動化が必要でした。

その過程で、私はこの質問に出くわし、Benubird の投稿が私を正しい道に導いてくれました。彼のコード例は、多数の特殊文字と HTML を含み、ネストが非常に深いレベルの複雑なデータの本番環境では機能せず、特定のエスケープ文字とエンコーディングを適切に処理しませんでした。そのため、私はそれを少し変更し、追加のバグに数え切れないほどの時間を費やして、私のバージョンがシリアル化されたデータを「修正」できるようにしました。

// do some DB query here
while($res = db_fetch($qry)){
    $str = $res->data;
    $sCount=1; // don't try to count manually, which can be inaccurate; let serialize do its thing
    $newstring = unserialize($str);
    if(!$newstring) {
        preg_match_all('/s:([0-9]+):"(.*?)"(?=;)/su',$str,$m);
#           preg_match_all("/s:([0-9]+):(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")(?=;)/u",$str,$m); // alternate: almost works but leave quotes in $m[2] output
#           print_r($m); exit;
        foreach($m[1] as $k => $len) {
            /*** Possibly specific to my case: Spyropress Builder in WordPress ***/
            $m_clean = str_replace('\"','"',$m[2][$k]); // convert escaped double quotes so that HTML will render properly
            // if newline is present, it will output directly in the HTML
            // nl2br won't work here (must find literally; not with double quotes!)
            $m_clean = str_replace('\n', '<br />', $m_clean); 
            $m_clean = nl2br($m_clean);  // but we DO need to convert actual newlines also
            /*********************************************************************/
            if($sCount){
                $m_new = $m[0][$k].';'; // we must account for the missing semi-colon not captured in regex!
                // NOTE: If we don't flush the buffers, things like <img src="http://whatever" can be replaced with <img src="//whatever" and break the serialize count!!!                  
                ob_end_flush(); // not sure why this is necessary but cost me 5 hours!!
                $m_ser = serialize($m_clean);
                if($m_new != $m_ser) {
                    print "Replacing: $m_new\n";
                    print "With: $m_ser\n";
                    $str = str_replace($m_new, $m_ser, $str);
                }
            }
            else{
                $m_len = (strlen($m[2][$k]) - substr_count($m[2][$k],'\n'));
                if($len != $m_len) {
                    $newstr='s:'.$m_len.':"'.$m[2][$k].'"';
                    echo "Replacing: {$m[0][$k]}\n";
                    echo "With: $newstr\n\n";
                    $str = str_replace($m_new, $newstr, $str);
                }
            }
        }
        print_r($str); // this is your FIXED serialized data!! Yay!
    }
}

私の変更に関するちょっとマニアックな説明:

  • Benubird のコードをベースとして数えようとすると、大規模なデータセットに対して不正確すぎることがわかりました。
  • 私の場合、try は成功しますが、空の文字列を返すだけなので、try/catch を避けました。そのため、代わりに空のデータをチェックします。
  • 私は多数の正規表現を試しましたが、すべてのケースを正確に処理できるのは Benubird の mod だけでした。具体的には、「;」をチェックする部分を変更する必要がありました。「幅:100%; 高さ:25px;」のような CSS で一致するためです。そして出力を壊しました。そのため、「;」の場合にのみ一致するように前向き先読みを使用しました。二重引用符のセットの外にありました。
  • 私のケースには改行、HTML、およびエスケープされた二重引用符がたくさんあったため、それをクリーンアップするためにブロックを追加する必要がありました。
  • データが正規表現によって誤って置き換えられ、シリアライズでも誤ってカウントされるという奇妙な状況がいくつかありました。これに役立つサイトは何も見つかりませんでしたが、最終的にはキャッシングなどに関連している可能性があると考え、出力バッファー (ob_end_flush()) をフラッシュしようとしましたが、うまくいきました。

これが誰かの役に立てば幸いです...調査と奇妙な問題への対処を含めて、ほぼ20時間かかりました! :)

于 2016-04-03T03:19:33.410 に答える
1

個人的には、PHP で作業したり、DB 資格情報を公開ファイルに配置したりするのは好きではありません。ローカルで実行できるシリアル化を修正するための ruby​​ スクリプトを作成しました。

https://github.com/wsizoo/wordpress-fix-serialization

コンテキスト編集: 最初に正規表現を介してシリアル化を識別し、次に含まれるデータ文字列のバイト サイズを再計算することで、シリアル化の修正に取り組みました。

$content_to_fix.gsub!(/s:([0-9]+):\"((.|\n)*?)\";/) {"s:#{$2.bytesize}:\"#{$2}\";"}

次に、エスケープされた SQL 更新クエリを使用して、指定されたデータを更新します。

escaped_fix_content = client.escape($fixed_content)

query = client.query("UPDATE #{$table} SET #{$column} = '#{escaped_fix_content}' WHERE #{$column_identifier} LIKE '#{$column_identifier_value}'")
于 2016-10-13T23:14:43.950 に答える
1

文字列の長さが正しくないためにエラーが発生した場合 (私がよく見たもの)、このスクリプトを修正して修正できるはずです。

foreach($strings as $key => $str)
{
    try {
        unserialize($str);
    } catch(exception $e) {
        preg_match_all('#s:([0-9]+):"([^;]+)"#',$str,$m);
        foreach($m[1] as $k => $len) {
            if($len != strlen($m[2][$k])) {
                $newstr='s:'.strlen($m[2][$k]).':"'.$m[2][$k].'"';
                echo "len mismatch: {$m[0][$k]}\n";
                echo "should be:    $newstr\n\n";
                $strings[$key] = str_replace($m[0][$k], $newstr, $str);
            }
        }
    }
}
于 2016-01-04T09:30:13.823 に答える