如何简化PHP数组键的isset判断,实现DRY代码优化?
嘿,这个重复代码的问题确实头疼,尤其是还要处理几十个商品的时候!我来帮你一步步优化,彻底实现DRY原则,同时理清isset判断的必要性。
1. 简化数量选中判断:替换重复的isset/empty检查
原来逐个索引写isset($_POST["item3lQty"][X]) && !empty(...)完全没必要,而且扩展性极差。咱们可以写一个通用函数来检查某个商品的数量数组是否有有效输入:
function hasSelectedQuantities(string $qtyKey): bool { // 先确保POST里有这个数组,避免Undefined Index错误 if (!isset($_POST[$qtyKey]) || !is_array($_POST[$qtyKey])) { return false; } // 过滤掉空字符串、0(如果你的需求是0也算未选中的话),只保留有效数量 $validQuantities = array_filter($_POST[$qtyKey], function($qty) { $trimmedQty = trim($qty); return $trimmedQty !== '' && (int)$trimmedQty > 0; }); // 如果有至少一个有效数量,就返回true return count($validQuantities) > 0; }
现在,原来的一大串判断可以简化成一行:
if (hasSelectedQuantities("item3lQty")) { // 处理商品逻辑 }
2. 通用化商品处理函数:告别N个ItemX函数
既然所有商品的处理逻辑都是一模一样的(只是字段前缀不同:3l、4l...),咱们可以把逻辑封装成一个通用函数,通过前缀参数来动态获取POST字段:
function processItem(string $prefix) { $qtyKey = "item{$prefix}Qty"; // 先检查是否有选中的数量,没有就直接返回 if (!hasSelectedQuantities($qtyKey)) { return; } // 动态获取商品的相关字段 $itemQty = $_POST[$qtyKey]; $itemCode = $_POST["itm{$prefix}"]; $itemDesc = $_POST["des{$prefix}"]; $itemColor = $_POST["clr{$prefix}"]; // FPDF绘制逻辑(完全复用,不用重复写) $this->SetFont('Arial', '', 10); $this->SetFillColor(242); $this->SetLineWidth(1); $this->SetX(33); $this->Cell(97, 20, $itemCode, 'LRB', 0, 'L'); $this->Cell(300, 20, $itemDesc, 'LRB', 0, 'L'); $this->Cell(95, 20, $itemColor, 'LRB', 0, 'L'); // 循环输出所有数量单元格,不用写6次Cell! foreach ($itemQty as $qty) { $displayQty = trim($qty) !== '' ? $qty : ''; $this->Cell(28, 20, $displayQty, 'LRB', 0, 'C'); } // 最后两个固定单元格 $this->Cell(28, 20, '', 'LRB', 0, 'C'); // 计算总和时把空值转成0,避免错误 $total = array_sum(array_map(fn($q) => (int)$q, $itemQty)); $this->Cell(38, 20, $total, 'LRB', 1, 'C'); }
现在处理几十个商品只需要调用这个函数就行:
// 处理商品3l processItem('3l'); // 处理商品4l processItem('4l'); // ... 其他商品直接加一行就行
3. 表单部分也可以DRY:用循环生成所有商品
你的表单现在也是重复写N次fieldset,咱们可以把所有商品的信息存在一个数组里,然后循环生成表单:
// 把所有商品的信息整理成数组(可以从数据库读取,或者手动定义) $items = [ [ 'prefix' => '3l', 'itm' => $itm3l, 'des' => $des3l, 'clr' => $clr3l, 'img_full' => $img3l_full_lnk, 'img_thumb' => $img3l_82px_lnk, 'price' => $price3l, 'price_xx' => $price3l_xx ], [ 'prefix' => '4l', 'itm' => $itm4l, 'des' => $des4l, // ... 其他商品的信息 ], // ... 所有商品都放在这里 ];
然后循环生成表单:
foreach ($items as $item) { ?> <fieldset class="item-fieldset" form="itemsForm"> <legend><?php echo $item['itm']; ?></legend> <div class="item_image_container"> <a href="<?php echo $item['img_full']; ?>" target="_blank"> <img class="item_image" src="<?php echo $item['img_thumb']; ?>"/> </a> <span class="click_full_image">Click for full size</span> </div><!-- ITEM_IMAGE div CLOSE --> <table class="inputs" border="1" cellspacing="1"> <tbody> <tr class="gridaddrows"> <td colspan="8" class="radius"> <div class="itemdesc"><?php echo $item['des']; ?></div> </td> </tr> <tr class="gridrows"> <td class="gridtitle">XS</td> <td class="gridtitle">SM</td> <td class="gridtitle">MD</td> <td class="gridtitle">LG</td> <td class="gridtitle"></td> <td class="gridtitle"></td> <td class="gridtitle">Total Pcs</td> </tr> <tr> <input type="hidden" name="itm<?php echo $item['prefix']; ?>" value='<?php echo $item['itm']; ?>'> <input type="hidden" name="des<?php echo $item['prefix']; ?>" value='<?php echo $item['des']; ?>'> <input type="hidden" name="clr<?php echo $item['prefix']; ?>" value='<?php echo $item['clr']; ?>'> <!-- 生成4个可见的数量输入框 --> <?php for ($i = 0; $i < 4; $i++) : ?> <td> <input type="number" class="item<?php echo $item['prefix']; ?>" min="0" max="288" name="item<?php echo $item['prefix']; ?>Qty[]" placeholder="Qty" autocomplete="off"> <br> <span class="price"><?php echo $item['price']; ?></span> </td> <?php endfor; ?> <!-- 生成2个隐藏的数量输入框 --> <td> <input type="number" class="item<?php echo $item['prefix']; ?>" min="0" max="288" name="item<?php echo $item['prefix']; ?>Qty[]" placeholder="Qty" autocomplete="off" style="visibility: hidden"> <br> <span class="price" style="visibility: hidden"><?php echo $item['price']; ?></span> </td> <td> <input type="number" class="item<?php echo $item['prefix']; ?>" min="0" max="288" name="item<?php echo $item['prefix']; ?>Qty[]" placeholder="Qty" autocomplete="off" style="visibility: hidden"> <br> <span class="price" style="visibility: hidden"><?php echo $item['price_xx']; ?></span> </td> <td><input type="number" class="item<?php echo $item['prefix']; ?>total" value="" readonly/></td> </tr> </tbody> </table> </fieldset> <?php }
这样表单部分也不用重复写几十次,后续新增商品只需要在$items数组里加一条记录就行。
关于isset判断的必要性
你原来的逐个索引isset($_POST["item3lQty"][X])完全没必要!因为HTML里的name="item3lQty[]"会让浏览器把所有输入框的值包装成一个数组提交,哪怕所有输入都是空,$_POST["item3lQty"]也会是一个包含6个元素的数组(元素可能是空字符串)。
不过必须保留对整个数组的isset检查,也就是isset($_POST[$qtyKey]) && is_array($_POST[$qtyKey]),这是为了避免用户手动构造请求时没有提交这个数组,导致Undefined Index错误。
至于单个索引的isset,完全可以去掉,因为数组已经存在,我们只需要处理每个元素的值即可,空值直接显示空字符串就好,不会影响FPDF的绘制。
内容的提问来源于stack exchange,提问作者Bigfootbud

