简体   繁体   English

有没有更好的方法来更改PHP中的DOMElement-> tagName属性?

[英]Is there a better way to change a DOMElement->tagName property in php?

I just ran into this building a Textbox control for my MVC framework, where just before finalizing the whole document I call PreRender on everything that inherits from ServerTag (which in turn inherits from DOMElement). 我刚刚在这个构建中遇到了一个用于我的MVC框架的Textbox控件,在完成整个文档之前,我在从ServerTag继承的所有内容上调用PreRender(后者继承自DOMElement)。

The only way i have found to change a DOMElement derived object's tagName is to replace it with a new one with all the attributes synced to the old one. 我发现更改DOMElement派生对象的tagName的唯一方法是将其替换为新属性,并将所有属性同步到旧属性。

This is how that looks in code: 这就是代码中的样子:

protected function PreRenderTextarea( WebPage $sender )
{
    $textarea = $sender->createElement( 'textarea' );
    foreach( $this->attributes as $attribute )
    {
        if ( $attribute->name == 'value' )
        {
            $textarea->nodeValue = $attribute->value;
        }
        else
        {
            $textarea->setAttribute( $attribute->name, $attribute->value );
        }
    }
    $this->parentNode->replaceChild( $textarea, $this );
}

public function OnPreRender( WebPage $sender )
{
    parent::OnPreRender();
    $this->setAttribute( 'value', $this->Value );

    switch( $this->Mode )
    {
        case 'normal' : 
            $this->setAttribute( 'type', 'text' ); 
            break;
        case 'password' : 
            $this->setAttribute( 'type', 'password' ); 
            break;
        case 'multiline' : 
            $this->PreRenderTextarea( $sender ); 
            return; 
            break;
    }
}

Is that really the only way to do it? 这真的是唯一的方法吗? This way has the rather unwanted side effect of nulling all the logic behind the control. 这种方式具有使控制背后的所有逻辑归零的相当不希望的副作用。

Yes, this how you have to do it -- the reason is that you're not just changing the value of a single attribute ( tagName ), you're actually changing the entire element from one type to another. 是的,你必须这样做 - 原因是你不仅要改变单个属性( tagName )的值,而是实际上将整个元素从一种类型更改为另一种类型。 Properties such as tagName (or nodeName ) and nodeType are read-only in the DOM and set when you create the element. 诸如tagName (或nodeName )和nodeType在DOM中是只读的,并在创建元素时设置。

So, creating a new element and moving in place of the old one exactly as you're doing, with DOMNode::replaceChild , is the correct operation. 因此,使用DOMNode::replaceChild创建一个新元素并使用DOMNode::replaceChild完全代替旧元素是正确的操作。

I'm not sure what you mean by "unwanted side effect of nulling all the logic behind the control" -- if you clarify I might be able to give you guidance there. 我不确定你的意思是“废除控制背后所有逻辑的不必要的副作用” - 如果你澄清我可以在那里给你指导。

It sounds like you might not want to have ServerTag inherit from DOMElement and instead you may want to link these two objects through some other pattern, such as composition (ie so a ServerTag "has a" DOMElement instead of "is a" DOMElement) so that you're merely replacing the DOMElement object associated with your ServerTag Textbox object. 听起来你可能不想让ServerTag从DOMElement继承,而你可能想要通过其他一些模式链接这两个对象,比如组合(即所以ServerTag“有一个”DOMElement而不是“是一个”DOMElement)所以您只是替换与ServerTag Textbox对象关联的DOMElement对象。

Or a longer-shot guess is you might be running into issues just copying the attributes (ie textarea has required attributes, like rows and cols , that input does not). 或长镜头的猜测是,你可能会运行到刚刚复制的属性问题(即textarea已要求属性,如rowscols ,该input没有)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM