NexusPHP 建站优化 (3) 升级NPHP到PHP 7

Rhilip 2020-02-07 PM 7876℃ 7条

因为NexusPHP较早就停止维护,所以官方源码基本只能停留在PHP5.3-5.6版本使用,无法使用PHP7,然而随着PHP5.x(甚至PHP7.0)已经完全停止维护,势必有必要将NPHP推进到PHP7.x。然而主要阻碍这种推进的原因是因为:

  1. Mysql库在PHP7中不存在,必须更换到 Mysqli库。
  2. Memcache库在PHP7出现兼容性问题,需要调整连接代码,或更换到 Memcached库 或者 Redis库。
  3. Github或其他开源代码库中没有PHP7版本的NexusPHP。

基于以上原因,本文给出相关方法实现:

  • 使用psr-4相关方法,加载/classes目录中库文件。
  • 替换Cache组件的后端为Redis。
  • 使用单例模式的Mysqli wrapper组件替换原Mysql库相关方法,将Mysql连接改成只有第一次执行query或相关方法时才连接,避免NPHP遭受CC攻击时,大量连接请求直接拖垮Mysql导致服务不可用;并提供stmt方法支持,可以通过更换写法的形式组件将NPHP的real_query实现改成stmt实现,防止SQL注入。
  • 移除PHP 7中不存在的相关方法,例如 get_magic_quotes_gpc 等。

以下讲解和代码patch均基于本人fork的官方源码 Rhilip/NexusPHP(v1.5.beta5.20120707),不提供除本文外的任何形式的说明以及免费讲解

具体请见:Rhilip/NexusPHP#2

image-20200207133455442.png

请注意:

  1. 可以使用该库 MySQL wrapper for MySQLi ,快速提供mysqli库在mysql方法名下的支持,但因为其过于简单,且无法使用到stmt特性,故本文不做额外说明。
  2. 部分小细节,比如 $arr[id] ,PHP 4 style constructors 等未在此步骤中体现。你应该参照PHP官方升级教程 Migrating from PHP 5.6.x to PHP 7.0.x 或使用 PHPStan 等静态工具进行进一步的检查。

详细步骤说明

  1. composer.json中注册namespace,之后使用composer dumpautoload 刷新依赖,假定此处的命名空间为NexusPHP。(@744d83d

    "autoload": {
      "psr-4": {
        "NexusPHP\\": "classes/"
      }
    }
  2. 修改原classes/目录下的组件,并优化使用这些组件的相关PHP脚本。(@684ed5a)(注意,我们这里会全局使用类似\NexusPHP\Components\Cache 的形式调用这些组件,而不是用use声明。因为这样可以最快速的进行全局替换)
  3. 将Cache组件的后端改为Redis,并使用魔法方法__call()封装的形式提供Redis原生方法支持。(@1605687)
  4. 构造Database组件,并提供原有mysql相关方法。(@4da4f84)
  5. 使用全局替换的形式对原mysql_方法进行替换(@35dc3ea),替换规则如下(注意替换顺序从下到上不要错误):

    # 以下启用Match模式
    mysql_query(      ->  \NexusPHP\Components\Database::query(
    mysql_real_escape_string(  ->  \NexusPHP\Components\Database::real_escape_string(
    mysql_error()     ->  \NexusPHP\Components\Database::error()
    mysql_affected_rows()  -> \NexusPHP\Components\Database::affected_rows()
    mysql_errno()     ->  \NexusPHP\Components\Database::errno()
    mysql_insert_id() ->  \NexusPHP\Components\Database::insert_id()
    mysql_fetch_array(  ->  mysqli_fetch_array(
    mysql_fetch_assoc(  ->  mysqli_fetch_assoc(
    mysql_fetch_row(    ->  mysqli_fetch_row(
    mysql_num_rows(     ->  mysqli_num_rows(
    mysql_connect(      ->  mysqli_connect(
    mysql_free_result(  ->  mysqli_free_result( 
    
    sqlesc(           ->  \NexusPHP\Components\Database::escape(
    sql_query(        ->  \NexusPHP\Components\Database::query(
    get_row_count(    ->  \NexusPHP\Components\Database::count(
    get_row_sum(      ->  \NexusPHP\Components\Database::sum(
    get_single_value( ->  \NexusPHP\Components\Database::single(
    
    # 以下启用Match,Regex模式
    array_map\(['"]sqlesc['"], ?(array\(.+?\)|\$.+?)?\)  -> \\NexusPHP\\Components\\Database::escape($1)

image-20200207120139459.png

并修改dbconn(),仅保留其中userlogin相关部分,移除散落的 dbconn_announce(), sql_query(), sqlesc(), get_row_count(),get_row_sum(), get_single_value() 方法定义。注意,除dbconn_announce() 方法之外,其他函数及变量的定义可能在之前的全局替换中被修改了,请定位到其原先位置然后删除。

然后同样使用全局搜索,检查是否还有遗漏mysql_方法未清理完成,剩下的应该只有lang以及settings里面的一些变量定义,这些可以不管。

image-20200207125837729.png

  1. 移除在inculde/core.php中定义的全局数组 $query_name,并使用\NexusPHP\Components\Database::getQueryHistory() 方法进行替换。到这里,我们的NPHP基本已经可以在PHP7+Redis环境中运行了。(@118fcad)
  2. 打开include/core.php中的debug方法,并移除一些PHP7中已经不兼容的一些方法,比如get_magic_quotes_gpc()。除此以外,NPHP还有类似 $arr[id]的一些不规范写法,在打开debug之后你可以看到notice的提示,你需要进行相关修正。(@17ba5c4)

    error_reporting(E_ALL);
    ini_set('display_errors', 1);
  3. 使用stmt方法进行优化,防止SQL注入(此处仅作示例) (@f9ddf9a)

    function write_log($text, $security = "normal")
    {
        \NexusPHP\Components\Database::query("INSERT INTO sitelog (added, txt, security_level) VALUES(NOW(), ?, ?)", [$text, $security]) or sqlerr(__FILE__, __LINE__);
    }
标签: nexusphp, mysqli, php7, redis

非特殊说明,本博所有文章均为博主原创。

评论啦~



已有 7 条评论


  1. Archer
    Archer

    hi,

    Interesting project, but don't you think that the number of dependency (RidPT) risks discouraging a lot of people?

    While other scripts do the job with less prerequisites and therefore easily installable, perhaps not as optimized but which works relatively well.

    回复 2020-03-30 00:14
    1. Rhilip
      Rhilip 博主

      I don't think so. Though you see a lot of pre-requests, The only extra needed is the Swoole Extenstion for PHP. And other pre-request software like Redis or Memcached, MySQL is needed for every Private Tracker Software.

      回复 2020-04-23 10:49
  2. happytao
    happytao

    functions.php中的format_comment和format_url模式中使用了php7已废弃的正则匹配模式PREG_REPLACE_EVAL,可参考https://www.php.net/manual/zh/reference.pcre.pattern.modifiers.php。应该将/正则/e这种替换成不包含e模式的。否则就无法展示编辑的内容了,例如首页的最新消息(学习中,刚看到这里

    回复 2020-05-01 12:35
    1. Rhilip
      Rhilip 博主

      是的,这一块没有在文章中体现,应该做补充。此外,替换的Database组件在实际应用过程中,也发现了一些问题,由于个人和站点原因,相关commit并没有体现在公开repo中。

      回复 2020-05-03 17:46
  3. 888
    888

    tjupt 就是用的php7

    回复 2020-05-20 14:03
  4. Star
    Star

    R酱,有研究怎样升级到php8吗?期待教程!

    回复 2021-02-02 17:50
    1. Rhilip
      Rhilip 博主

      PHP8并没有实质性更新,能升级到PHP7的基本可以无痛升级到PHP8

      回复 2021-02-04 19:21