使用php composer时, 如何优雅修改vendor中第三

2018-10-30  本文已影响0人  PeterQ1998

有些时候在某一个项目中, 使用了一个第三方包, 但是会发现某一些地方不符合项目需求. 或者需要在包代码里注入一段自己的逻辑. 我们可以选择自己维护一个分支, 或者干脆改vendor文件夹, 并它他加入代码管理. 但对于要修改少量代码时, 这样做貌似不太'优雅'

请先查阅函数spl_autoload_register文档

其实composer也是利用这个函数来实现自动加载的.

php代码执行时, 如果遇到代码里依赖了一个类, 而这个类在当前进程中不存在时, php 会按照加载器队列顺序调用通过spl_autoload_register函数注册过的类加载器. 直到某个加载器执行完后, 这个被依赖的类被加载进当前进程空间, 或者所有加载器都执行完这个类仍不存在, 并抛出类不存在的异常.

所以我们也可以利用spl_autoload_register函数, 注册一个加载器, 并使其在队列里位于composer加载器之前. 当php需要加载我们要改动的第三方代码包里的类时, 我们加载自己改好的php文件, 而不是vendor包里的php文件. 这样就达到了覆盖的目的.

煮个栗子:
我写了一个自动抢饿了么最大外卖红包swoole程序. 大概流程就是, 利用hanson/vbot 包监听微信群里发送的红包链接, 并把链接推送到红包队列, 然后有个进程使用小号轮训饿了么接口, 等红包的下一个就是最大时, 用大号去领, 就领到了, 但是有个问题:
vbot 包有个message handler类, 里面有个listen方法. 这个方法里会调用微信网页版的接口. 当收到微信消息时会调用用户的消息处理器, 并且此方法是while(true)循环.所以一旦执行listen方法, 整个进程是会阻塞在这个方法里的, 就算用swoole的异步定时器也无力回天. 但是我又有个需求, 就是异步发送消息: 当某个红包的最大红包来临时, 可以配置不自动抢, 而是把链接转发到一个'内部群', 由群员抢最大红包. 所以我只好修改一下这个类了, 把while(true)循环改成swoole的定时器

左边是修改后的
项目目录结构
项目目录结构
注意到, overwrite文件夹, 就是我用来放覆盖第三方代码php文件的目录
里面的autoload.php文件内容:

<?php

spl_autoload_register(function ($cls) {
    $map = [
        'Hanson\Vbot\Core\MessageHandler' => __DIR__ . '/MessageHandler.php',
        'Hanson\Vbot\Core\Server' => __DIR__  . '/Server.php',
    ];

    if (isset($map[$cls])) {
        echo $cls . ' loaded' . PHP_EOL;
        include $map[$cls];
        return true;
    }
// 注意需要设置prepend参数为true
}, true, true);

项目的composer.json加载了这autoload.php:

{
  "require": {
    "hanson/vbot": "^2.0",
    "symfony/debug": "^4.1"
  },
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    },
    "files": ["src/overwrite/autoload.php"]
  }
}

请自行体会

上一篇下一篇

猜你喜欢

热点阅读