Typecho复选框无法选中问题(Handsome主题)

Typecho复选框无法选中问题(Handsome主题)

Bug描述

image-20240417155203781

在博客handsome外观设置后台中,选中复选框后保存设置;然后刷新,此时复选框并不是选中状态,而且观察前台,正确选中复选框的操作并没有生效;

寻找Bug的思路

核心是看那一步出错了,当我们打开后台外观设置,然后选中复选框,之后保存设置,这期间到底发生了什么,一步步排查错误;

选中复选框之后,html标签会发生变化,复选框会被打上选中的标志;之后点击保存设置,浏览器会向服务器Post一个打包好的表单,表单中是各种设置的参数信息;服务器收到表单之后,会处理表单,处理好之后将数据保存在数据库的表中;前台中收到网页访问请求,在运行网站时从数据库的表中找到各种设置的参数,然后生成访问的网页;

所以我们可以从以下几个方向进行排查:

  1. 前端界面变化是否正确:在选中复选框后,确保HTML标签发生了相应变化,复选框被正确打上了选中的标志,同时前端代码中checked被设置为true。可以使用浏览器的开发者工具检查复选框的状态变化。
  2. 表单提交是否成功:在保存设置时,确保浏览器向服务器成功发送了POST请求,并且请求中包含了正确的设置内容。可以在浏览器的开发者工具中查看网络请求,确认POST请求是否包含了期待的数据。
  3. 服务器端数据处理是否正确:在服务器端处理表单数据时,确保数据被正确接收并保存到了数据库中。可以在服务器端的处理代码中添加日志或调试信息,以确保数据处理的逻辑正确执行。
  4. 前台页面加载逻辑是否正确:在前台页面加载时,确保从数据库中正确读取了设置参数,并且这些参数被正确应用到了生成的网页中。您可以检查前端代码,确认设置参数被正确地应用到了页面上。

排查Bug

前端界面变化是否正确

打开网页开发者工具(按下F12,如果进入debug模式则关闭debug模式后刷新页面)

image-20240417160815460

找到复选框的html代码,看其checked参数:

image-20240417161148673

可以看到checked参数为false,为未被选中;选中复选框;

image-20240417161525167

选中之后,checked参数为true,说明前端界面变化正常;


表单是否正确提交

在选中几个复选框后,按下保存设置,然后看开发者设置中的网络,找到Post的内容;

image-20240417161956867

找到使用POST方法的项目,发现返回码是302,代表重定向,而我们在保存设置之后会重定向到外观设置页面中,符合我们的预期;之后找到POST的具体表单信息:

image-20240417162222142

可以看出我们选择的复选框的id确实被添加到了表单中(复选框对应的id可以在html看到,也可以到外观设置页面源代码中找到)

也就是当我们选中复选框后,浏览器确实把复选框被选中这一信息加入到表单中post到了服务器;


服务器端数据处理是否正确

服务器收到post的表单之后,首先进行数据处理,然后将处理过的数据保存在对应的数据库中;我们先排查数据库中是否保存了复选框选中的相关信息;

查找数据库
# 启动mysql
mysql -u root -p

# 进去mysql之后,查找所有数据库
SHOW DATABASES;

# 找到typecho使用的数据库,启动;
USE typecho_blog;

# 列出所有表;
SHOW TABLES;

# 我们发现有一张名为typecho_options的表,查看;
SELECT * FROM typecho_options;

找到indexsetup相关的项:

image-20240417164205576

(如果没有处理之前,数据库中indexsetup为null,即说明数据库没有被写入;而其他非复选框项可以看到数据库中已经写入了,所以只有复选框没有被写入数据库中)

查看服务器接受的表单已经处理后的表单数据

找到文件\typecho\var\Widget\Themes\Edit.php,打开找到处理POST的表单的相关项;

    /**
     * 配置外观
     *
     * @param string $theme 外观名
     * @throws \Typecho\Db\Exception
     */
    public function config(string $theme)
    {
        // 已经载入了外观函数
        $form = Config::alloc()->config();

        /** 验证表单 */
        if (!Config::isExists() || $form->validate()) {
            $this->response->goBack();
        }
        
		/** 处理表单数据到数据库中 */
        $settings = $form->getAllRequest();
        if (!$this->configHandle($settings, false)) {
            if ($this->options->__get('theme:' . $theme)) {
                $this->update(
                    ['value' => serialize($settings)],
                    $this->db->sql()->where('name = ?', 'theme:' . $theme)
                );
            } else {
                $this->insert([
                    'name'  => 'theme:' . $theme,
                    'value' => serialize($settings),
                    'user'  => 0
                ]);
            }
        }

        /** 设置高亮 */
        Notice::alloc()->highlight('theme-' . $theme);

        /** 提示信息 */
        Notice::alloc()->set(_t("外观设置已经保存"), 'success');

        /** 转向原页 */
        $this->response->redirect(Common::url('options-theme.php', $this->options->adminUrl));
    }

我们可以从上面代码中看出首先程序验证表单数据form的合法性,然后将form中信息通过getAllRequest()函数提取到settings中,之后将settings中信息分类并使用serialize()序列化处理为字符串之后保存在数据库中;

加入输出调试信息的代码,即输出formsettings中的数据;

$settings = $form->getAllRequest();之后加入以下代码:

// 假设您已经有了$form对象,并调用了getAllRequest()方法获取了$settings数组
$formDump = print_r($form, true); // true参数使print_r返回信息而不是打印
$settingsDump = print_r($settings, true);

// 合并$form和$settings的内容
$combinedContent = "Form Object:\n" . $formDump . "\nSettings Array:\n" . $settingsDump;
// 保存内容到当前目录的bug.txt文件中,如果文件不存在会自动创建
// 指定绝对路径
$absolutePath = '/home/lighthouse/project/blog/typecho/var/Widget/Themes/bug.txt';
// 保存内容到指定目录的bug.txt文件中,如果文件不存在会自动创建
file_put_contents($absolutePath, $combinedContent);

然后在博客后台外观设置中勾选复选框之后,点击保存设置;查看/home/lighthouse/project/blog/typecho/var/Widget/Themes/bug.txt文件,其中settings的内容如下:

Settings Array:
Array
(
    [indexsetup] => 
    [thumbStyle] => 0
    [thumbArrangeStyle] => water_fall
    [themetype] => 2
    [themetypeEdit] => 
    [BGtype] => 2

    .........
    
    
    [expert] => {
"first_screen_animate":true
}
    [asideSetting] => 
    [sidebarSetting] => 
)

可以看到indexsetup中的内容为空,也就是表单处理结束后复选框选中这一信息丢失了;(其余外观设置信息没有丢失!)

至于表单form转换为settings中为什么只有复选框信息丢失,笔者能力有限,没有找到;

但是可以确定settings已经错误了,导致数据库中没有复选框选中的相关信息;所以如果可以修改settings,至少可以保证之后数据库中数据正确,这样访问博客时从数据库中取数据就正确,外观设置也就可以如我们所愿。


修复Bug

在之前输出调试信息的地方手动设置settings的复选框相关项;

$settings = $form->getAllRequest();

// 假设您已经获取了settings数组,之后为新添加代码;
// $settings['featuresetup'] = 
$settings['indexsetup'] = array( // 手动设置复选框被选中的项目的id到indexsetup中;
    'notShowRightSideThumb',
    'BigAvatar'
);
$settings['featuresetup'] = array( // 另一个复选框项目,也手动制定;
    'isPjax',
    'emailToQQ',
    'hightlightcode',
    'isPageAnimate',
    "openCategory",
    'FixedImageSize',
    'tocThree',
    'smoothscroll',
    'mathJax'
);

复选框中项目的id可以在\typecho\usr\themes\handsome\functions_mine.php中找到:

image-20240417170504613

image-20240417170542330

修改之后,点击外观设置,保存设置,然后打开博客前台,看设置是否生效(已生效)

同时,外观设置的前台中,我们手动设置的复选框项也已经被选中;(说明前台页面加载逻辑有效)

image-20240417170822860

分别去bug.txt中查看settings的输出信息以及在数据库中查看indexsetup项:

Settings Array:
Array
(
    [indexsetup] => Array
        (
            [0] => notShowRightSideThumb
            [1] => BigAvatar
        )

    [thumbStyle] => 0
    [thumbArrangeStyle] => water_fall
    .....
)

bug.txt中的settings信息中,indexsetup已经非null;

image-20240417171129088

数据库中信息也已经非null;


总结

虽然没有彻底解决复选框丢失的Bug,但是通过在代码中直接设定复选框对应项目有效,使得页面外观至少设置成功了;

在后台外观设置中复选框依旧没有用,如果想要选择复选框中内容,需要手动到代码中修改添加复选框的id到数组中;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OutlierLi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值