オリジナル技術
# handsome # コードの問題 # コード

イケメンタイムマシンが解除されないときのさまざまな問題を解決する

1.1万 語22 分0 閲覧数0 いいね

概要

この記事では、Handsome テーマのタイム マシンの公開失敗に伴うエラー コード 200 と PDO シリアル化例外の理由を分析します。著者は、PHP7.4 をダウングレードし、Typecho コア ファイル Db.php を変更することで問題を解決しました。同時に、作者は、画像のアップロード、絵文字のサポート、コメントの失敗などの一般的な問題に対する公式のトラブルシューティングと修復方法をまとめ、このテーマを使用するユーザーに実践的なガイダンスを提供しました。

typechoに移行した時は自然とイケメンを選びました。このテーマは特に理由もなく購入したので、利用できるすべての機能、特にタイムマシン機能を使用できます。

問題のスクリーンショット

問題の説明

が WeChat 公開アカウントでコンテンツを公開すると、次のエラー

错误码200<pre><code><h1>Serialization of 'PDO' is not allowed</h1></code></pre>
请求失败500 Server Error: Internal Server Error for url: https://tutouzhang.com/

が表示されます

Serialization of 'PDO' is not allowed
自分で公式アカウントを用意して公開することはしなかったため、この2つの公開方法だけを使いましたが、どちらもエラーになりました。WeChat公式アカウントでは2種類のエラーが発生しました。

ここから、これらの問題をどのように解決したかを説明します。

ブラウザでコンテンツを公開すると、次のエラー メッセージが表示されます:

公式 Q

&A;

  • : コメント/タイムマシン関連 www.ihewro.com Time Machine は typecho のコメント機能を再利用しているので、ほとんどの質問が似ています
  • Time Machine が「この公式アカウントが提供するサービスには欠陥があります」という内容の WeChat メッセージを送信
    • 著者のブログが正常に開くか確認してください
  • www.ihewro.com

正常に開ける場合は、パブリックアカウントサービスが正常であることを意味します。開けない場合は、作者に連絡するか、しばらくお待ちください

公認プラットフォームで入力したアドレスがブログのアドレスと全く同じかどうかを確認してください。公式アカウントが最終的に要求するアドレスは、公式アカウントをバインドするときに入力したアドレスではなく、公認プラットフォームで入力したアドレスです。

  • たとえば、www プレフィックス http または https は、ブログのアドレスとまったく同じである必要があります
  • 新しい Web サイトを WeChat にバインドする前に、まずバインドを解除する必要があります。そうしないと、1 つの WeChat ID が複数の Web サイトにバインドされたときに問題が発生します。現時点では、作成者に連絡して >db->fetchRow($this->select()-> を手動でバインド解除する必要があります。
  • タイムマシンが sqlite データベースに新しいラベルを作成すると、ページがスタックします
          $this->db->fetchRow($this->select()->where('coid = ?', $commentId)
              ->limit(1), [$this, 'push']);
    
  • は、typecho コードを変更して一時的に修正する必要があります。
          $item = $this->db->fetchRow($this->select()->where('coid = ?', $commentId)
              ->limit(1));
          $this->push($item);
    

typecho ディレクトリの var/Widget/Feedback.php

  • を開きます 设置——评论——允许使用的HTML标签和属性 $this->db->fetchRow($this->select()->where('coid = ?'
<img src="">
<audio class="" src="" preload>
<video src=""></video>

) の行を検索します。

  • 変更前: usr/uploads 変更後: time コメント領域を比較できず、画像を表示できません。写真/音楽プレーヤー/ビデオプレーヤーを表示できないことについての話
  • Backend sudo chmod -R 777 ./
  • 中に HTML タグ libs/Utils.php を追加します (new Imgcompress タイムマシン/写真のアップロードに失敗した話

typecho ディレクトリの

  • ディレクトリに 设置——评论——在评论中使用Markdown语法(选中) フォルダがあるか確認してください。手動で作成したものがない場合は、フォルダー 777 に 设置——评论——允许使用的HTML标签和属性 権限を与えます。
<blockquote><pre><code><strong><em><h5><h6><a href title><table><thead><tr><th><tbody><td>

Linux 設定フォルダー 777 権限コマンド:

Time Machine は、画像をアップロードするための画像圧縮プロセスを追加します。サーバー環境が gd 拡張子をサポートしていない場合、画像は正常にアップロードされる可能性がありますが、タイム マシンには「アップロードに失敗しました」と表示されます。テーマ ディレクトリ を開いて を検索します。このコード行をコメント化するか削除してください。

コメント領域ではマークダウン構文を使用できません

  • 背景

背景

  • マークダウン構文に対応した HTML タグを追加 地理的位置情報が表示されない話 HTTPSConnectionPool(host= xxxx',port=443):Max retries exceeded with url:/Caused by
    • 地理情報には絵文字が含まれています。タイプ cho は、デフォルトでは絵文字をサポートしません。データベースのフィールド タイプを変更する必要があります: httpstypecho は絵文字のチュートリアルをサポートしています
    • (詳細については、Baidu typecho は絵文字をサポートしており、チュートリアルがあります) タイムマシンを削除する方法 はコメント管理と同じです。 typecho背景の管理で削除できます - コメント
    • コンテンツをブログ タイム マシンに送信できません ZZZ 認証プラットフォームによって入力されたドメイン名にエラー があります。表示されるエラーは通常 http://です。 https:// 認証プラットフォームに入力されたドメイン名は https:// ですが、ブログは ssl
  • をサポートしていません
  • 認定プラットフォーム上のブログ ドメイン名

がサイト アドレスとまったく同じであること (www があるかどうか、プロトコルが http か https

かどうかなど) を確認してください。

は最終的に

  • になります。認証プラットフォームに入力されたドメイン名
  • を確認してください。 WeChat で情報をバインドするために入力されたアドレスが
であっても、認証プラットフォームに入力されるアドレスは

です。結局、リクエストは

  • のアドレスは のままです。 Notice: Undefined function一部のサーバーが ua 判定を行ったため、リクエストを通過できません
  • 一部のサーバーには CC 保護があり、リクエストは禁止されています失敗したコメントの特定のトラブルシューティング方法
  • があります 「コメント要求が失敗しました」または「コメントはブロックされている可能性があり、フィードバック情報がありません」という不特定のエラー。
    • には特定のエラー メッセージがあります
    • 特定のエラー プロンプトは次のタイプに分類されます:
  • 特定の php エラー出力 (特定の関数の呼び出しが存在しないというプロンプトなど)
    • など、通常は特定のプラグインが原因で発生します。コメントに関するプラグイン(コメントメールリマインダーなど)を確認できます
    • CDN「データベース クエリ エラー」 HTML、通常は次の 2 つの状況が考えられます。 CDNコメントに絵文字が含まれていますが、データベースは絵文字をサポートしていません。ここで確認できます css,js,imagetypechoは絵文字チュートリアルをサポートしています
    • typecho データベース フィールドの問題 (通常、モバイル QQ WeChat でコメントするときに問題が発生しますが、コンピューターでは正常です)。具体的な方法については、
    • https://paugram.com/coding/fix-typecho-ua-problem.html
    • を参照してください。
    • 特定の中国語傍受の理由
(「申し訳ありませんが、頻繁に話しすぎます。後でもう一度投稿してください。」など)、またはその他の中国語エラー プロンプトは正常です。
  • typechoのコメント設定で「同一IPからのコメント投稿間隔制限」がオンになっている <meta name="referrer" content="no-referrer" /> はコメントスパム対策プラグインを使用して傍受ルール
  • をトリガーしました

「ページがキャッシュされている場合、最新のコメントは表示できません」

、考えられる状況は次のとおりです。 が使用するプラグインにより、古いバージョンの jquery.js がページに挿入されましたテーマと競合する場合は、F12 キーを押すと、「カラフル マウス」などのエラー メッセージが表示されます。プラグイン設定で jquery をロードしないか、プラグイン を無効にする必要があります。

キャッシュは

ページを静的にキャッシュするため、コメント機能が失敗します ( キャッシュでは、、

、

などの静的リソース ファイルのみをキャッシュすることをお勧めします)。ページが更新されないのに、どうすればコメントが表示されるのでしょうか。 !

请输入图片描述

自分にはあまり効果がないと分かったので、やはり自分で原因を調べるのがよいでしょう。

はサーバー キャッシュ機能を使用します

はデータベース キャッシュ プラグイン

を使用します

はページ コード圧縮プラグイン

を使用します $_SESSION 上記のプロセスのトラブルシューティングを行っても問題が解決しない場合は、デフォルトのテーマに切り替えることができます (切り替える前にハンサムな設定データをバックアップする必要があります。そうしないとクリアされます)。デフォルトのテーマにはこの問題がなく、ハンサムなテーマにはこの問題がある場合は、作成者に連絡して確認してください

「コメント要求が失敗しました」または「コメントはブロックされている可能性があり、フィードバック情報がありません」という具体的なエラー プロンプトはありません

このコード行

をテーマに追加しないでください。 var/Typecho/Db.php

ファイアウォールなどが有効になっている場合、投稿リクエストは傍受されます。通常、コメントに HTML コードが含まれている場合、ファイアウォールによってブロックされます。

<?php

namespace Typecho;

use Typecho\Db\Adapter;
use Typecho\Db\Query;
use Typecho\Db\Exception as DbException;

/**
 * 包含获取数据支持方法的类.
 * 必须定义__TYPECHO_DB_HOST__, __TYPECHO_DB_PORT__, __TYPECHO_DB_NAME__,
 * __TYPECHO_DB_USER__, __TYPECHO_DB_PASS__, __TYPECHO_DB_CHAR__
 *
 * @package Db
 */
class Db
{
    /** 读取数据库 */
    public const READ = 1;

    /** 写入数据库 */
    public const WRITE = 2;

    /** 升序方式 */
    public const SORT_ASC = 'ASC';

    /** 降序方式 */
    public const SORT_DESC = 'DESC';

    /** 表内连接方式 */
    public const INNER_JOIN = 'INNER';

    /** 表外连接方式 */
    public const OUTER_JOIN = 'OUTER';

    /** 表左连接方式 */
    public const LEFT_JOIN = 'LEFT';

    /** 表右连接方式 */
    public const RIGHT_JOIN = 'RIGHT';

    /** 数据库查询操作 */
    public const SELECT = 'SELECT';

    /** 数据库更新操作 */
    public const UPDATE = 'UPDATE';

    /** 数据库插入操作 */
    public const INSERT = 'INSERT';

    /** 数据库删除操作 */
    public const DELETE = 'DELETE';

    /**
     * 数据库适配器
     * @var Adapter
     */
    private $adapter;

    /**
     * 默认配置
     *
     * @var array
     */
    private $config;

    /**
     * 已经连接
     *
     * @access private
     * @var array
     */
    private $connectedPool;

    /**
     * 前缀
     *
     * @access private
     * @var string
     */
    private $prefix;

    /**
     * 适配器名称
     *
     * @access private
     * @var string
     */
    private $adapterName;

    /**
     * 实例化的数据库对象
     * @var Db
     */
    private static $instance;

    /**
     * 数据库类构造函数
     *
     * @param mixed $adapterName 适配器名称
     * @param string $prefix 前缀
     *
     * @throws DbException
     */
    public function __construct($adapterName, string $prefix = 'typecho_')
    {
        /** 获取适配器名称 */
        $adapterName = $adapterName == 'Mysql' ? 'Mysqli' : $adapterName;
        $this->adapterName = $adapterName;

        /** 数据库适配器 */
        $adapterName = '\Typecho\Db\Adapter\\' . str_replace('_', '\\', $adapterName);

        if (!call_user_func([$adapterName, 'isAvailable'])) {
            throw new DbException("Adapter {$adapterName} is not available");
        }

        $this->prefix = $prefix;

        /** 初始化内部变量 */
        $this->connectedPool = [];

        $this->config = [
            self::READ => [],
            self::WRITE => []
        ];

        //实例化适配器对象
        $this->adapter = new $adapterName();
    }

    /**
     * @return Adapter
     */
    public function getAdapter(): Adapter
    {
        return $this->adapter;
    }

    /**
     * 获取适配器名称
     *
     * @access public
     * @return string
     */
    public function getAdapterName(): string
    {
        return $this->adapterName;
    }

    /**
     * 获取表前缀
     *
     * @access public
     * @return string
     */
    public function getPrefix(): string
    {
        return $this->prefix;
    }

    /**
     * @param Config $config
     * @param int $op
     */
    public function addConfig(Config $config, int $op)
    {
        if ($op & self::READ) {
            $this->config[self::READ][] = $config;
        }

        if ($op & self::WRITE) {
            $this->config[self::WRITE][] = $config;
        }
    }

    /**
     * getConfig
     *
     * @param int $op
     *
     * @return Config
     * @throws DbException
     */
    public function getConfig(int $op): Config
    {
        if (empty($this->config[$op])) {
            /** DbException */
            throw new DbException('Missing Database Connection');
        }

        $key = array_rand($this->config[$op]);
        return $this->config[$op][$key];
    }

    /**
     * 重置连接池
     *
     * @return void
     */
    public function flushPool()
    {
        $this->connectedPool = [];
    }

    /**
     * 选择数据库
     *
     * @param int $op
     *
     * @return mixed
     * @throws DbException
     */
    public function selectDb(int $op)
    {
        if (!isset($this->connectedPool[$op])) {
            $selectConnectionConfig = $this->getConfig($op);
            $selectConnectionHandle = $this->adapter->connect($selectConnectionConfig);
            $this->connectedPool[$op] = $selectConnectionHandle;
        }

        return $this->connectedPool[$op];
    }

    /**
     * 获取SQL词法构建器实例化对象
     *
     * @return Query
     */
    public function sql(): Query
    {
        return new Query($this->adapter, $this->prefix);
    }

    /**
     * 为多数据库提供支持
     *
     * @access public
     * @param array $config 数据库实例
     * @param integer $op 数据库操作
     * @return void
     */
    public function addServer(array $config, int $op)
    {
        $this->addConfig(Config::factory($config), $op);
        $this->flushPool();
    }

    /**
     * 获取版本
     *
     * @param int $op
     *
     * @return string
     * @throws DbException
     */
    public function getVersion(int $op = self::READ): string
    {
        return $this->adapter->getVersion($this->selectDb($op));
    }

    /**
     * 设置默认数据库对象
     *
     * @access public
     * @param Db $db 数据库对象
     * @return void
     */
    public static function set(Db $db)
    {
        self::$instance = $db;
    }

    /**
     * 获取数据库实例化对象
     * 用静态变量存储实例化的数据库对象,可以保证数据连接仅进行一次
     *
     * @return Db
     * @throws DbException
     */
    public static function get(): Db
    {
        if (empty(self::$instance)) {
            /** DbException */
            throw new DbException('Missing Database Object');
        }

        return self::$instance;
    }

    /**
     * 选择查询字段
     *
     * @param ...$ags
     *
     * @return Query
     * @throws DbException
     */
    public function select(...$ags): Query
    {
        $this->selectDb(self::READ);

        $args = func_get_args();
        return call_user_func_array([$this->sql(), 'select'], $args ?: ['*']);
    }

    /**
     * 更新记录操作(UPDATE)
     *
     * @param string $table 需要更新记录的表
     *
     * @return Query
     * @throws DbException
     */
    public function update(string $table): Query
    {
        $this->selectDb(self::WRITE);

        return $this->sql()->update($table);
    }

    /**
     * 删除记录操作(DELETE)
     *
     * @param string $table 需要删除记录的表
     *
     * @return Query
     * @throws DbException
     */
    public function delete(string $table): Query
    {
        $this->selectDb(self::WRITE);

        return $this->sql()->delete($table);
    }

    /**
     * 插入记录操作(INSERT)
     *
     * @param string $table 需要插入记录的表
     *
     * @return Query
     * @throws DbException
     */
    public function insert(string $table): Query
    {
        $this->selectDb(self::WRITE);

        return $this->sql()->insert($table);
    }

    /**
     * @param $table
     * @throws DbException
     */
    public function truncate($table)
    {
        $table = preg_replace("/^table\./", $this->prefix, $table);
        $this->adapter->truncate($table, $this->selectDb(self::WRITE));
    }

    /**
     * 执行查询语句
     *
     * @param mixed $query 查询语句或者查询对象
     * @param int $op 数据库读写状态
     * @param string $action 操作动作
     *
     * @return mixed
     * @throws DbException
     */
    public function query($query, int $op = self::READ, string $action = self::SELECT)
    {
        $table = null;

        /** 在适配器中执行查询 */
        if ($query instanceof Query) {
            $action = $query->getAttribute('action');
            $table = $query->getAttribute('table');
            $op = (self::UPDATE == $action || self::DELETE == $action
                || self::INSERT == $action) ? self::WRITE : self::READ;
        } elseif (!is_string($query)) {
            /** 如果query不是对象也不是字符串,那么将其判断为查询资源句柄,直接返回 */
            return $query;
        }

        /** 选择连接池 */
        $handle = $this->selectDb($op);

        /** 提交查询 */
        $resource = $this->adapter->query($query instanceof Query ?
            $query->prepare($query) : $query, $handle, $op, $action, $table);

        if ($action) {
            //根据查询动作返回相应资源
            switch ($action) {
                case self::UPDATE:
                case self::DELETE:
                    return $this->adapter->affectedRows($resource, $handle);
                case self::INSERT:
                    return $this->adapter->lastInsertId($resource, $handle);
                case self::SELECT:
                default:
                    return $resource;
            }
        } else {
            //如果直接执行查询语句则返回资源
            return $resource;
        }
    }

    /**
     * 一次取出所有行
     *
     * @param mixed $query 查询对象
     * @param callable|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
     *
     * @return array
     * @throws DbException
     */
    public function fetchAll($query, ?callable $filter = null): array
    {
        //执行查询
        $resource = $this->query($query);
        $result = $this->adapter->fetchAll($resource);

        return $filter ? array_map($filter, $result) : $result;
    }

    /**
     * 一次取出一行
     *
     * @param mixed $query 查询对象
     * @param callable|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
     * @return array|null
     * @throws DbException
     */
    public function fetchRow($query, ?callable $filter = null): ?array
    {
        $resource = $this->query($query);

        return ($rows = $this->adapter->fetch($resource)) ?
            ($filter ? call_user_func($filter, $rows) : $rows) :
            null;
    }

    /**
     * 一次取出一个对象
     *
     * @param mixed $query 查询对象
     * @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
     * @return object|null
     * @throws DbException
     */
    public function fetchObject($query, ?array $filter = null): ?object
    {
        $resource = $this->query($query);

        return ($rows = $this->adapter->fetchObject($resource)) ?
            ($filter ? call_user_func($filter, $rows) : $rows) :
            null;
    }

    /**
     * 序列化时保存必要的配置信息,不包含连接池
     *
     * @return array
     */
    public function __serialize(): array
    {
        return [
            'adapterName' => $this->adapterName,
            'prefix' => $this->prefix,
            'config' => $this->config
        ];
    }

    /**
     * 反序列化时恢复配置并初始化适配器
     *
     * @param array $data 序列化数据
     * @return void
     */
    public function __unserialize(array $data): void
    {
        $this->adapterName = $data['adapterName'];
        $this->prefix = $data['prefix'];
        $this->config = $data['config'];
        $this->connectedPool = []; // 重置连接池,防止 PDO 被序列化

        // 重新实例化适配器
        $adapterName = '\Typecho\Db\Adapter\\' . str_replace('_', '\\', $this->adapterName);
        if (!class_exists($adapterName)) {
            throw new DbException("Adapter {$adapterName} is not available");
        }
        $this->adapter = new $adapterName();
    }
}

(この場合、テーマ拡張機能の外観設定で ajax コメント スイッチをオフにし、再度コメントすると特定のエラー メッセージが表示されます)

  • 上記の手順を実行しても問題が解決しない場合は、デフォルトのテーマに切り替えることができます(:__serialize() 切り替える前に必ず外観設定インターフェイスのデータをバックアップしてください)。デフォルトのテーマのコメントが正常で、ハンサムなテーマが正常ではない場合は、私に連絡してください。 $connectedPool Comments/Time Machine は、 $adapter を開くときに最新のコメントを表示したいと考えています
  • 記事/タイム マシンを開いてデフォルトで最新のコメントを表示したい場合は、typecho 背景 - コメントを設定し、ページングを有効にし、リスト作成時のデフォルト表示として最初のページ :__unserialize() を表示する必要があります。 (テーマは「新しいコメントを前に表示」するよう強制されています。つまり、最初のページが最新のコメント、最後のページが最も古いコメントになります) $connectedPoolタイムマシン/レビュー ページのページ分割方法 $adaptertypecho バックエンド管理 - 設定 - コメントでページングを有効にする: selectDb()トラブルシューティングの手順

500で報告されたエラーについては説明する必要もありませんが、私のブラウザではアクセスできるのですが、公式アカウントではアクセスできないため、作者の問題ではないかと思いました。その後、問題を解決するためにphp8.0からphp7.4に変更しようとしました。

  • エラー コード :__serialize() 公式アカウント エラー コード 200 は、応答は成功したが、返されたページが間違っていることを示します。そうしたらタイプチョかハンサムが正常な状態に戻ったのではないかと思います。実際には、まだ 500 エラーである可能性があります。 __unserialize() このブラウザ エラーは、PDO オブジェクトをシリアル化しようとすると発生します。 PDO は PHP のデータベース接続クラスであり、シリアル化できません。 Db I 推測: セッション管理 (

  • $_SESSION:

    • __serialize())、キャッシュ メカニズム、オブジェクトの永続性、または状態保存時の PDO を含むクラス。 $adapterName、$prefix この推測のため、トラブルシューティングのためにすべてのプラグインを無効にしましたが、それでも問題が見つからなかったので、typecho に指を向けました。私は彼のバージョン 1.2.1 が変更されたのではないかと真剣に疑っていました。 $config完璧なソリューション $connectedPool が見つかりました $adapter。
    • __unserialize()var/Typecho/Db.php $connectedPool次のコードを貼り付けて上書きします。 $adapter ファイルをバックアップすることを強くお勧めします。
  • 動作原理 をシリアル化する場合:

コメントを読み込み中…
関連記事

関連記事