You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Chillerlan QRCode库的自定义生成器中传递变量给module方法

问题

使用PHP及Chillerlan QRCode库开发二维码生成器时,希望通过传入的$modulShape变量控制二维码模块的形状,但目前无法将该变量传递到自定义SVG输出类的protected function module()方法中,需要实现根据$modulShape的不同值输出对应形状的模块。

以下是现有代码片段:

class QRSvgWithLogoAndCustomShapes extends QRMarkupSVG {
    protected function module(int $x, int $y, int $M_TYPE): string {
        if (
            !$this->matrix->isDark($M_TYPE)
            || $this->matrix->checkType($x, $y, QRMatrix::M_FINDER)
            || $this->matrix->checkType($x, $y, QRMatrix::M_FINDER_DOT)
        ) {
            return '';
        }

        // 这里需要根据$modulShape切换不同形状
        return sprintf('M%1$s %2$s a0.5,0.5 0 1,0 0.001,0', $x, $y);
    }
}

class QrCodeGenerator {
    public function qrgenerate(string $data, $modulShape, bool $includeLogo = false) {
        $options = new SVGWithLogoAndCustomShapesOptions;
        
        if ($includeLogo) {
            $options->svgLogo         = TEMPLATE_PATH.'module/home/github.svg';
            $options->svgLogoScale    = 0.25;
            $options->svgLogoCssClass = 'qr-logo dark';
        } else {
            $options->svgLogo = '';
        }

        $options->version              = -1;
        $options->versionMin           = 1;
        $options->versionMax           = 40;
        $options->outputType           = QROutputInterface::CUSTOM;
        $options->outputInterface      = QRSvgWithLogoAndCustomShapes::class;
        $options->outputBase64         = false;
        $options->eccLevel             = EccLevel::H;

        $options->drawLightModules     = true;
        $options->svgUseFillAttributes = true;

        if ($modulShape == 'circular') {
            $options->drawCircularModules  = true;
            $options->circleRadius         = 0.4;
        }

        $options->connectPaths         = true;
        $options->keepAsSquare         = [
            QRMatrix::M_FINDER_DARK,
            QRMatrix::M_FINDER_DOT,
            QRMatrix::M_ALIGNMENT_DARK,
        ];

        $qrcode = new QRCode($options);
        $qrImage = $qrcode->render($data);

        $matrix = $qrcode->getMatrix($qrcode);
        $version = $matrix->version();

        $qrCodeData = [$data, 'version' => $matrix->version(), $modulShape];
        var_dump($qrImage);
        exit;
        return $qrCodeData;
    }
}
解决方案

Chillerlan QRCode库通过Options类传递所有配置参数,因此可以通过扩展Options类、在自定义输出类中读取配置的方式实现需求,步骤如下:

1. 扩展SVG配置类,新增模块形状属性

在自定义的SVGWithLogoAndCustomShapesOptions类中添加modulShape属性,用于存储传入的形状参数:

class SVGWithLogoAndCustomShapesOptions extends QRMarkupSVGOptions {
    public string $modulShape = 'circular'; // 默认形状设为圆形
}

2. 在自定义SVG输出类中读取配置

自定义的QRSvgWithLogoAndCustomShapes类继承自QRMarkupSVG,该类已持有$options属性,直接在module()方法中读取$this->options->modulShape即可:

class QRSvgWithLogoAndCustomShapes extends QRMarkupSVG {
    protected function module(int $x, int $y, int $M_TYPE): string {
        if (
            !$this->matrix->isDark($M_TYPE)
            || $this->matrix->checkType($x, $y, QRMatrix::M_FINDER)
            || $this->matrix->checkType($x, $y, QRMatrix::M_FINDER_DOT)
        ) {
            return '';
        }

        // 根据modulShape返回对应形状的SVG路径
        return match($this->options->modulShape) {
            'heart' => sprintf('M%1$s %2$s m0.5,0.96 l-0.412,-0.412 a0.3 0.3 0 0 1 0.412,-0.435 a0.3 0.3 0 0 1 0.412,0.435Z', $x, $y),
            'star' => sprintf('M%1$s %2$s l0.2,0.4 l0.45,0.05 l-0.35,0.25 l0.12,0.48 l-0.45,-0.25 l-0.45,0.25 l0.12,-0.48 l-0.35,-0.25 l0.45,-0.05Z', $x, $y),
            // 默认返回圆形
            default => sprintf('M%1$s %2$s a0.5,0.5 0 1,0 0.001,0', $x, $y),
        };
    }
}

3. 在生成方法中传递modulShape参数

在QrCodeGenerator::qrgenerate()方法中,将传入的$modulShape赋值给options的对应属性:

class QrCodeGenerator {
    public function qrgenerate(string $data, $modulShape, bool $includeLogo = false) {
        $options = new SVGWithLogoAndCustomShapesOptions;
        
        // 传递模块形状参数到配置
        $options->modulShape = $modulShape;
        
        if ($includeLogo) {
            $options->svgLogo         = TEMPLATE_PATH.'module/home/github.svg';
            $options->svgLogoScale    = 0.25;
            $options->svgLogoCssClass = 'qr-logo dark';
        } else {
            $options->svgLogo = '';
        }

        // 其余配置保持不变
        $options->version              = -1;
        $options->versionMin           = 1;
        $options->versionMax           = 40;
        $options->outputType           = QROutputInterface::CUSTOM;
        $options->outputInterface      = QRSvgWithLogoAndCustomShapes::class;
        $options->outputBase64         = false;
        $options->eccLevel             = EccLevel::H;

        $options->drawLightModules     = true;
        $options->svgUseFillAttributes = true;

        // 注意:自定义形状优先级高于库自带圆形模块,需关闭避免冲突
        // if ($modulShape == 'circular') {
        //     $options->drawCircularModules  = true;
        //     $options->circleRadius         = 0.4;
        // }

        $options->connectPaths         = true;
        $options->keepAsSquare         = [
            QRMatrix::M_FINDER_DARK,
            QRMatrix::M_FINDER_DOT,
            QRMatrix::M_ALIGNMENT_DARK,
        ];

        $qrcode = new QRCode($options);
        $qrImage = $qrcode->render($data);

        $matrix = $qrcode->getMatrix($qrcode);
        $version = $matrix->version();

        $qrCodeData = [$data, 'version' => $matrix->version(), $modulShape];
        // var_dump($qrImage);
        // exit;
        return $qrCodeData;
    }
}

说明

  • 关闭了原代码中drawCircularModules的配置,因为自定义module()方法优先级更高,避免两种圆形逻辑冲突;
  • 使用PHP的match表达式实现形状判断,代码更简洁,也可以用if-else替代;
  • 确保SVGWithLogoAndCustomShapesOptions继承自正确的基类(QRMarkupSVGOptions),以继承所有SVG相关配置项。

内容的提问来源于stack exchange,提问作者Crunchip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:13:10