如何在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
相关产品推荐
相关产品推荐

