PHP多版本兼容问题:获取select下option的value与textContent时报错求助
嗨,我看你遇到了PHP不同版本下处理DOM元素的兼容性问题,这个报错其实很好解决,我来给你捋一捋~
错误原因分析
你收到的Call to undefined method DOMText::getAttribute()错误,本质是因为你用childNodes获取<select>的子节点时,拿到的不只是<option>元素,还包含了空白文本节点(比如标签之间的换行、空格)。这些空白节点属于DOMText类型,它们并没有getAttribute()方法,在某些PHP版本(比如你提到的7.0.33、7.4.33)中,DOM扩展会保留这些空白节点,遍历到它们时就会触发报错;而之前能正常运行的版本,大概率是因为对应的libxml库(PHP DOM依赖的底层库)默认忽略了空白节点,所以没碰到这个问题。
另外还要提一句:你之前代码里用array_push($imageextentionM[$n->getAttribute('value')] = $n->textContent);的写法其实是语法错误,array_push的正确用法是array_push(数组, 元素),你直接给数组赋值键值对的话,不需要用array_push,直接写$imageextentionM[$value] = $text就可以了,之前的版本没报错可能是巧合。
解决方案
这里给你两种可靠的解决方式,都能兼容所有你提到的PHP版本:
方案1:过滤节点类型,只处理元素节点
遍历childNodes时,先判断节点是否为元素节点(也就是<option>),跳过文本节点:
$selectElement = $doc->getElementById('imageextention'); $imageextentionM = array(); if ($selectElement && $selectElement->nodeName === "select") { $serials = $selectElement->childNodes; foreach ($serials as $n) { // 只处理元素节点,跳过文本、注释等非元素节点 if ($n->nodeType === XML_ELEMENT_NODE) { $value = $n->getAttribute('value'); $text = $n->textContent; $imageextentionM[$value] = $text; } } } // 处理fontcolor的逻辑同理 $selectElement2 = $doc->getElementById('fontcolor'); $fontcolorM = array(); $activecolortxtM = ""; if ($selectElement2 && $selectElement2->nodeName === "select") { $serials2 = $selectElement2->childNodes; foreach ($serials2 as $n) { if ($n->nodeType === XML_ELEMENT_NODE) { $value = $n->getAttribute('value'); $text = $n->textContent; $fontcolorM[$value] = $text; } } }
方案2:直接在目标select下获取option元素(更推荐)
这种方式更简洁,也能避免拿到页面其他地方的<option>——你之前用$doc->getElementsByTagName('option')会获取全页面的option,现在改成先定位到目标<select>,再在它的范围内调用getElementsByTagName:
// 处理imageextention $selectElement = $doc->getElementById('imageextention'); $imageextentionM = array(); if ($selectElement && $selectElement->nodeName === "select") { $options = $selectElement->getElementsByTagName('option'); foreach ($options as $option) { $value = $option->getAttribute('value'); $text = $option->textContent; $imageextentionM[$value] = $text; } } // 处理fontcolor $selectElement2 = $doc->getElementById('fontcolor'); $fontcolorM = array(); $activecolortxtM = ""; if ($selectElement2 && $selectElement2->nodeName === "select") { $options2 = $selectElement2->getElementsByTagName('option'); foreach ($options2 as $option) { $value = $option->getAttribute('value'); $text = $option->textContent; $fontcolorM[$value] = $text; } }
总结
两种方案都能解决你的版本兼容问题,其中方案2更直观可靠,也能避免误取其他元素的风险。修改后你的代码应该能在所有提到的PHP版本中正常运行啦~
备注:内容来源于stack exchange,提问作者justsev

