원문기술
# handsome # 코드 문제 # 코드

핸썸 타임머신이 나오지 않을 때 다양한 문제를 해결해보세요

1.1만 단어22 분0 조회수0 좋아요

요약

본 글에서는 핸썸 테마 타임머신 공개 실패에 따른 에러코드 200 및 PDO 직렬화 예외의 원인을 분석합니다. 저자는 PHP7.4를 다운그레이드하고 Typecho 코어 파일 Db.php를 수정하여 문제를 성공적으로 해결했습니다. 동시에 저자는 이미지 업로드, 이모티콘 지원, 댓글 실패 등과 같은 일반적인 문제에 대한 공식적인 문제 해결 및 복구 방법을 요약하여 이 테마를 사용하는 사용자에게 실용적인 지침을 제공합니다.

타입초로 이주하면서 자연스럽게 잘생긴을 선택하게 됐어요. 별다른 이유 없이 이 테마만 구매했기 때문에 제가 사용할 수 있는 모든 기능, 특히 타임머신 기능을 사용할 수 있습니다.

문제 스크린샷

문제 설명

는 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
직접 공식 계정을 만들어 게시하지 않았기 때문에 이 두 가지 게시 방식만 사용했으며 모두 오류가 발생했습니다. WeChat 공식 계정 게시에서는 두 가지 오류가 발생했습니다.

이제 이 문제를 어떻게 해결했는지 설명하겠습니다.

브라우저에서 콘텐츠를 게시할 때 다음 오류 메시지가 나타납니다.

공식 Q

&A;

  • : 댓글/타임머신 관련 www.ihewro.com 타임머신을 typecho의 댓글 기능에서 재사용해서 질문이 대부분 비슷합니다
  • 타임머신은 "이 공식 계정에서 제공하는 서비스에 결함이 있습니다"라는 내용의 WeChat 메시지를 보냅니다.
    • 작성자의 블로그가 정상적으로 열렸는지 확인하세요
  • www.ihewro.com

정상적으로 열릴 수 있다면 공용계정 서비스가 정상이라는 뜻입니다. 열리지 않으면 작성자에게 연락하거나 잠시 기다려 주세요

공식 계정에서 입력한 주소가 공식 계정에서 바인딩할 때 입력한 주소가 아니라 결국 공식 계정에서 요청한 주소가 공인 플랫폼에서 입력한 주소이기 때문에 공식 계정에서 입력한 주소가 블로그 주소와 정확히 일치하는지 확인하세요.

  • 예를 들어 www 접두어인 http 또는 https는 블로그 주소와 정확히 동일해야 합니다.
  • 새 웹사이트를 WeChat에 바인딩하기 전에 먼저 바인딩을 해제해야 합니다. 그렇지 않으면 하나의 WeChat ID가 여러 웹사이트에 바인딩되면 문제가 발생합니다. 현재 >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 백엔드
  • 내부에 HTML 태그 sudo chmod -R 777 ./
  • 추가 libs/Utils.php 타임머신/사진 업로드 이야기 실패 (new Imgcompress typecho 디렉터리의

디렉터리에

  • 폴더가 있는지 확인합니다. 수동으로 생성된 폴더가 없으면 폴더에 777 권한 设置——评论——在评论中使用Markdown语法(选中) 를 부여합니다. 设置——评论——允许使用的HTML标签和属性 Linux 폴더 777 설정 권한 명령:
<blockquote><pre><code><strong><em><h5><h6><a href title><table><thead><tr><th><tbody><td>

Time Machine은 이미지 업로드를 위한 이미지 압축 프로세스를 추가합니다. 귀하의 서버 환경이 gd 확장자를 지원하지 않는 경우, 이미지는 성공적으로 업로드될 수 있지만 타임머신에는 "업로드 실패"라는 메시지가 표시됩니다. 테마 디렉터리

를 열고 를 검색할 수 있습니다. 이 코드 줄에 주석을 달거나 삭제하세요. 주석 영역에서는 마크다운 구문을 사용할 수 없습니다.

배경

  • 배경

마크다운 구문

  • 에 해당하는 html 태그를 추가합니다. 지리적 위치정보에 대한 대화가 표시되지 않습니다 HTTPSConnectionPool(host= xxxx',port=443):Max retries exceeded with url:/Caused by
    • 지리정보에 이모티콘이 포함되어 있습니다. 유형 cho는 기본적으로 이모티콘을 지원하지 않습니다. 데이터베이스의 필드 유형을 수정해야 합니다. httpstypecho는 이모티콘 튜토리얼
    • 를 지원합니다(자세한 내용은 Baidu typecho가 이모티콘을 지원하고 튜토리얼이 있습니다) 타임머신 삭제 방법 는 댓글 관리와 동일합니다. 타입초 배경 관리에서 삭제 가능합니다 - 댓글
    • 블로그 타임머신으로 콘텐츠를 보낼 수 없습니다. ZZZ 인증 플랫폼에서 입력한 도메인 이름에 오류가 있습니다. 표시되는 오류는 일반적으로 http://입니다. https:// 인증 플랫폼에 입력된 도메인 이름은 https://이지만 귀하의 블로그는 ssl
  • 를 지원하지 않습니다.
  • 승인 플랫폼의 블로그 도메인 이름

가 www가 있는지, 프로토콜이 http인지 https인지 등 사이트 주소와 정확히 일치하는지 확인하세요.

는 궁극적으로

입니다. 인증 플랫폼에 입력된 도메인 이름

  • 를 확인하세요. WeChat에서 정보를 결합하기 위해 입력한 주소가
  • 라고 하더라도 인증 플랫폼에 입력된 주소는
입니다. 결국 요청은 여전히

의 주소는

  • 입니다. 일부 서버에서 ua 판단을 내려 요청을 통과할 수 없습니다 Notice: Undefined function일부 서버에는 cc 보호 기능이 있어 요청이 금지됩니다
  • 댓글 실패에 대한 구체적인 문제 해결 방법테마를 최신 버전으로 업그레이드해주세요. 하위버전 테마 댓글 실패 문제는 더 이상 유지되지 않습니다
  • "댓글 요청 실패" 또는 "댓글이 차단될 수 있으며 피드백 정보가 없습니다."라는 메시지를 표시하는 불특정 오류입니다. 에 특정 오류 메시지가 있습니다
    • 특정 오류 프롬프트는 다음 유형으로 구분됩니다.
    • 특정 PHP 오류 출력
  • (예: 특정 함수 호출이 존재하지 않는다는 메시지)등의 경우 일반적으로 특정 플러그인으로 인해 발생합니다. 댓글 관련 플러그인(댓글 이메일 알림 등)을 확인할 수 있습니다.
    • 「데이터베이스 쿼리 오류」
    • CDN, 일반적으로 두 가지 상황이 있습니다. HTML댓글에 이모티콘이 포함되어 있지만 데이터베이스가 이모티콘을 지원하지 않습니다. 여기서 확인할 수 있습니다CDNtypecho는 이모티콘 튜토리얼을 지원합니다 css,js,imagetypecho 데이터베이스 필드 문제 (일반적으로 모바일QQ 위챗에서 댓글을 달 때 문제가 발생하지만 컴퓨터에서는 정상입니다.) 구체적인 방법은
    • https://paugram.com/coding/fix-typecho-ua-problem.html
    • 를 참조하세요.
    • "죄송합니다. 너무 자주 말씀하시네요. 나중에 다시 게시해 주세요."와 같은 특정 중국어 차단 이유
    • 또는 기타 중국어 오류 프롬프트는 정상입니다.
typecho의 댓글 설정에서 "동일 IP의 댓글 게시 간격 제한"이 켜져 있습니다.
  • 는 댓글 스팸 방지 플러그인을 사용하여 차단 규칙 <meta name="referrer" content="no-referrer" />를 실행했습니다.
  • "페이지가 캐시된 경우 최신 댓글을 표시할 수 없습니다."

, 가능한 상황은 다음과 같습니다.

에서 사용하는 플러그인이 이전 버전의 jquery.js를 페이지에 삽입했습니다.테마와 충돌하는 경우 F12를 눌러 "다채로운 마우스"와 같은 오류 메시지를 볼 수 있습니다. 플러그인 설정에서 jquery를 로드하지 않거나 플러그인 를 비활성화해야 합니다. 캐시는

페이지를 정적으로 캐시하여 주석 기능이 실패하도록 합니다(

캐시는 , ,

), 페이지를 정적으로 캐시했기 때문에 페이지가 업데이트되지 않습니다. 귀하의 의견이 어떻게 표시될 수 있습니까? !

는 서버 캐시 기능을 사용합니다

请输入图片描述

저에게는 큰 도움이 되지 않는다는 것을 알았으므로 직접 문제를 점검하는 편이 좋습니다.

는 데이터베이스 캐시 플러그인

를 사용합니다.

는 페이지 코드 압축 플러그인

를 사용합니다.

위 과정을 해결한 후에도 여전히 문제가 있는 경우 기본 테마로 전환할 수 있습니다(전환하기 전에 멋진 설정 데이터를 백업해야 합니다. 그렇지 않으면 삭제됩니다). 기본 테마에는 이 문제가 없고 handsome 테마에는 이 문제가 있는 경우 작성자에게 문의하여 살펴볼 수 있습니다. $_SESSION "댓글 요청 실패" 또는 "댓글이 차단될 수 있으며 피드백 정보가 없습니다"라는 메시지가 나타나는 구체적인 오류 메시지가 없습니다.

이 코드

줄을 테마에 추가하지 마세요!

방화벽 등이 켜져 있으면 게시 요청을 차단합니다. 일반적으로 댓글에 HTML 코드가 포함되어 있으면 방화벽에서 이를 차단합니다. var/Typecho/Db.php

(이 경우 외관 설정 - 테마 강화 기능에서 ajax 댓글 스위치를 끄고 다시 댓글을 달아 구체적인 오류 메시지를 볼 수 있습니다)

<?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();
    }
}

위 프로세스를 따른 후에도 문제가 계속 해결되지 않으면 기본 테마로 전환할 수 있습니다(

  • 로 전환하기 전에 모양 설정 인터페이스에서 데이터를 백업하세요). 기본 테마 댓글은 정상이고 잘생긴 테마는 정상이 아닌 경우 저에게 연락주세요. :__serialize() Comments/Time Machine은 $connectedPool 를 열 때 최신 댓글을 표시하기를 희망합니다. $adapter 기사/타임머신을 열어 기본적으로 최신 댓글을 표시하려면 typecho 배경(댓글)을 설정하고 페이징을 활성화하고 나열 시 첫 번째 페이지
  • 를 기본 표시로 표시해야 합니다. (테마는 강제로 "새로운 댓글을 앞에 표시"합니다. 즉, 첫 페이지가 최신 댓글이고 마지막 페이지가 가장 오래된 댓글입니다.) :__unserialize() 타임머신 페이지 매기기/리뷰 페이지 지정 방법 $connectedPooltypecho 백엔드 관리 - 설정 - 댓글에서 페이징 활성화: $adapter문제 해결 단계 selectDb()500님이 제보한 오류는 굳이 설명할 필요가 없지만, 제 브라우저에서는 접속이 되지만 공식 계정에서는 접속이 되지 않아 작성자의 문제가 아닌가 하는 의심이 들었습니다. 나중에 문제를 해결하기 위해 php8.0에서 php7.4로 변경을 시도했습니다.

오류 코드

  • 공식 계정 오류 코드 200은 응답은 성공했지만 반환된 페이지가 잘못되었음을 나타냅니다. 그렇다면 타입초나 핸섬이 정상상태로 돌아왔을 것이라고 의심해본다. 실제로는 여전히 500 오류일 수 있습니다. :__serialize() 이 브라우저 오류는 PDO 개체를 직렬화하려고 할 때 발생합니다. PDO는 PHP의 데이터베이스 연결 클래스이므로 직렬화할 수 없습니다. __unserialize() I 추측: 세션 관리( Db $_SESSION

  • ), 캐싱 메커니즘, 개체 지속성 또는 상태 저장 시 PDO를 포함하는 클래스. :

    • __serialize()이 추측 때문에 문제 해결을 위해 모든 플러그인을 비활성화시켰으나 여전히 문제가 발견되지 않아 타입초를 손가락질했습니다. 나는 그의 버전 1.2.1이 변경된 것이 아닐까 심각하게 의심했습니다. $adapterName、$prefix 완벽한 솔루션 $config검색 $connectedPool var/Typecho/Db.php $adapter。
    • __unserialize()덮어쓰려면 다음 코드를 붙여넣으세요. $connectedPool파일을 백업하는 것이 좋습니다. $adapter 작동 원리
  • 를 직렬화하는 경우: __serialize()

댓글을 불러오는 중…
관련 글

관련 글