建议themeInit函数改为匿名函数,自定义页面解决方案

Bug,需求以及想法
回复
朱玉磊
帖子: 4
注册时间: 2025年 1月 11日 11:43

建议themeInit函数改为匿名函数,自定义页面解决方案

帖子 朱玉磊 »

建议Widget\Archive.php第751行themeInit函数改为调用:
if (isset($themeInit)) $themeInit();
匿名函数调用最大的好处是可以调用$this对象,如果用之前函数传递的$archive->user,$archive->options对象都访问不了。
另外能不能给个自定义路由接口给functions.php?
比如我想访问 /custom/my 可以自定义自己的页面。
上次由 朱玉磊 在 2025年 1月 11日 14:38,总共编辑 1 次。
Lopwon
帖子: 219
注册时间: 2016年 11月 14日 11:19

Re: 建议themeInit函数改为匿名函数调用

帖子 Lopwon »

代码: 全选

function themeInit($archive) {
	
    // 调用 options
    $options = Helper::options(); // 方式一
    // $options = Typecho_Widget::widget('Widget_Options'); // 方式二
	
    echo 'Blog: ' . $options->title; // 使用 options 输出博客名
	
    // 仿自定义路由
    $requestUri = $archive->request->getRequestUri(); // 完整路径
    $path = '/custom/my/'; // 自定义路径
	
    if (stripos($requestUri, $path) !== false) { // 如果路由中包含自定义路径,则使用 lopwon.php 页面
        $archive->need('lopwon.php'); // 自定义页面,请在 functions.php 相同目录创建 lopwon.php 文件	
        exit;
    }	
	
}
朱玉磊
帖子: 4
注册时间: 2025年 1月 11日 11:43

Re: 建议themeInit函数改为匿名函数调用

帖子 朱玉磊 »

谢谢 @Lopwon 老铁给的解决方案。不过自定义页面这段代码运行不了。
因为在 Typecho\Router.php 第78行 dispatch() 函数,
检查没有这条路由就抛出异常了,根本没给 functions.php 运行的机会。
Lopwon
帖子: 219
注册时间: 2016年 11月 14日 11:19

Re: 建议themeInit函数改为匿名函数调用

帖子 Lopwon »

朱玉磊 写了: 2025年 1月 11日 13:51 谢谢 @Lopwon 老铁给的解决方案。不过自定义页面这段代码运行不了。
因为在 Typecho\Router.php 第78行 dispatch() 函数,
检查没有这条路由就抛出异常了,根本没给 functions.php 运行的机会。
我这里测试运行是正常的 http://snapic.cn/t/grid/index.php/custom/my/
朱玉磊
帖子: 4
注册时间: 2025年 1月 11日 11:43

Re: 建议themeInit函数改为匿名函数调用

帖子 朱玉磊 »

谢谢 @Lopwon 老铁,找到原因了。因为你设置了404.php,我没404页面所以抛出异常。
实际上 http://snapic.cn/t/grid/index.php/custom/my/ 页面输出的http头是404状态。
需要加行 http_response_code 改状态码。

代码: 全选

    if (stripos($requestUri, $path) !== false) { // 如果路由中包含自定义路径,则使用 lopwon.php 页面
        http_response_code (200); 
        $archive->need('lopwon.php'); // 自定义页面,请在 functions.php 相同目录创建 lopwon.php 文件	
        exit;
    }
否则搜索引擎蜘蛛不会抓取,希望官方考虑下我的建议。
Lopwon
帖子: 219
注册时间: 2016年 11月 14日 11:19

Re: 建议themeInit函数改为匿名函数调用

帖子 Lopwon »

朱玉磊 写了: 2025年 1月 11日 14:33 谢谢 @Lopwon 老铁,找到原因了。因为你设置了404.php,我没404页面所以抛出异常。
实际上 http://snapic.cn/t/grid/index.php/custom/my/ 页面输出的http头是404状态。
需要加行 http_response_code 改状态码。

代码: 全选

    if (stripos($requestUri, $path) !== false) { // 如果路由中包含自定义路径,则使用 lopwon.php 页面
        http_response_code (200); 
        $archive->need('lopwon.php'); // 自定义页面,请在 functions.php 相同目录创建 lopwon.php 文件	
        exit;
    }
否则搜索引擎蜘蛛不会抓取,希望官方考虑下我的建议。
确实,这是通过 404 捕获未定义的路由,从而在路径里匹配自定义的关键词,所以使用了“仿”自定义路由的名称。
Lopwon
帖子: 219
注册时间: 2016年 11月 14日 11:19

Re: 建议themeInit函数改为匿名函数调用

帖子 Lopwon »

朱玉磊 写了: 2025年 1月 11日 14:33 谢谢 @Lopwon 老铁,找到原因了。因为你设置了404.php,我没404页面所以抛出异常。
实际上 http://snapic.cn/t/grid/index.php/custom/my/ 页面输出的http头是404状态。
需要加行 http_response_code 改状态码。

代码: 全选

    if (stripos($requestUri, $path) !== false) { // 如果路由中包含自定义路径,则使用 lopwon.php 页面
        http_response_code (200); 
        $archive->need('lopwon.php'); // 自定义页面,请在 functions.php 相同目录创建 lopwon.php 文件	
        exit;
    }
否则搜索引擎蜘蛛不会抓取,希望官方考虑下我的建议。
我注意到使用 addRoute 在 functions.php 是可以把自定义路由注册到路由表里,而不需要使用插件,只不过需要注册到 Widget_Archive 下操作起来会比较方便,如下(留意注释,以及按需修改):

代码: 全选

function themeInit($archive) {

    $routeName = 'MyRoute'; // 自定义路由名称
    $path = '/custom/my/'; // 自定义路径

    Helper::addRoute($routeName, $path, 'Widget_Archive', 'render'); // 将自定义路由注册到 Widget_Archive
//    Helper::removeRoute($routeName); // 如需移除路由,先解除当前行代码注释,同时注释以上 addRoute 以实现人工手动移除路由,不移除也无影响

    $requestUri = $archive->request->getRequestUri(); // 完整路径

    if (stripos($requestUri, $path) !== false) { // 如果路由中包含自定义路径,则使用 lopwon.php 页面
        $archive->need('lopwon.php'); // 自定义页面,请在 functions.php 相同目录创建 lopwon.php 文件	
        exit;
    }	

}
朱玉磊
帖子: 4
注册时间: 2025年 1月 11日 11:43

Re: 建议themeInit函数改为匿名函数,自定义页面解决方案

帖子 朱玉磊 »

@Lopwon,addRoute 这个方案会导致每次加载主题时都会向数据库写一次路由,
除非首次注册完再注释掉 //Helper::addRoute 代码。

路由接口给 functions.php 是希望自定义功能能在 Widget_Archive 类初始化之前执行,
比如需要查其它数据库或者不查数据库,路由注册到 Widget_Archive 就有点绕弯了。

themeInit我找了几个调用接口,有点多此一举,先凑合用下,还是希望官方改成匿名函数可以直接调用$this->

代码: 全选

function themeInit($archive) {
  if(!$archive->user) $archive->user = \Widget\User::alloc();
  if(!$archive->options) $archive->options = \Widget\Options::alloc();
  if(!$archive->db) $archive->db = \Typecho\Db::get();
}
Lopwon
帖子: 219
注册时间: 2016年 11月 14日 11:19

Re: 建议themeInit函数改为匿名函数,自定义页面解决方案

帖子 Lopwon »

防止重复注册路由,可以加个判断(如下),如果不想注册到 Widget_Archive 可以自定义,但是似乎有些麻烦。

代码: 全选

function themeInit($archive) {

    $routeName = 'MyRoute'; // 路由名称
    $path = '/custom/my/'; // 自定义路径

    $routingTable = Helper::options()->routingTable; // 获取路由表

    if (!array_key_exists($routeName, $routingTable)) { // 如果路由表中不存在自定义的路由名称
        Helper::addRoute($routeName, $path, 'Widget_Archive', 'render'); // 将自定义路由注册到 Widget_Archive
    }

  //  Helper::removeRoute($routeName); // 如需移除路由,先解除当前行代码注释,同时注释以上 addRoute 以实现人工手动移除路由(不移除也无影响),移除路由后,以下代码依然生效,以通过 404 捕获未定义的路由的方式实现仿自定义路由

    $requestUri = $archive->request->getRequestUri(); // 完整路径

    if (stripos($requestUri, $path) !== false) { // 如果路由中包含自定义路径,则使用 lopwon.php 页面
        $archive->need('lopwon.php'); // 自定义页面,请在 functions.php 相同目录创建 lopwon.php 文件
        exit;
    }

}
回复