Search code examples
phphtmlfunctionappendchildcreateelement

How to Write a Function that Create and AppendChild HTML Elements in PHP?


Instead of echoing large blocks of HTML code or using the echo <<<HEREDOC, I want to write functions that create HTML elements and append child elements to each other.

The createLoginBar function would create a div that I would attach to other HTML elements into my createLogoutBanner function.

function createLoginBar() {
    $dom = new DOMDocument();
    $login_bar = $dom->createElement('div');
    $login_bar->setAttribute("id", "login_bar");
    $dom->appendChild($login_bar);
    return $dom->saveHTML();
}

function createLogoutBanner() {
    $dom = new DOMDocument();
    $login_bar = createLoginBar();
    $login_flex = createBlankLoginFlex();
    $banner_login_form = createBannerLoginForm();
    $login_message_flex = createLoginMessageFlex();
    $nonmember_signup_flex = createNonSignupFlex();
    $not_a_member_form = createNotAMemberForm();

    $dom->appendChild($login_bar); //This line gives an error
    $login_bar->appendChild($login_flex);
    $login_flex->appendChild($banner_login_form);
    $login_bar->appendChild($login_message_flex);
    $login_bar->appendChild($nonmember_signup_flex);
    $nonmember_signup_flex->appendChild($not_a_member_form);
    return $dom->saveHTML();
}

The $dom->appendChild($login_bar); line in the createLogoutBanner function is giving me Error:

Fatal error: Uncaught TypeError: DOMNode::appendChild(): Argument #1 ($node) must be of type DOMNode, string given in.


Solution

  • As the error states DOMNode::appendChild() expects to be passed a DOMNode.
    Your createLoginBar function is returning a string instead of the node.
    Try the following change:

    function createLoginBar() {
        $dom = new DOMDocument();
        $login_bar = $dom->createElement('div');
        $login_bar->setAttribute("id", "login_bar");
        $dom->appendChild($login_bar);
        return $dom; //->saveHTML();
    }
    

    You will then see the error Fatal error: Uncaught DOMException: Wrong Document Error. This is because you must use the same parent instance of DOMDocument to create the child nodes. Instead of creating a new DOMDocument inside each function, create a top level DOMDocument and pass it to each of the functions to use.

    function createLoginBar(DOMDocument $dom):DOMNode 
    {
        $login_bar = $dom->createElement('div');
        // the following line will cause invalid html if this function is called more than once
        $login_bar->setAttribute("id", "login_bar");
    
        return $login_bar;
    }
    function createBtn(DOMDocument $dom, string $value):DOMNode 
    {
        $btn = $dom->createElement('button', $value);
        $btn->setAttribute("class", "widget");
    
        return $btn;
    }
    
    $dom = new DOMDocument();
    $login_bar = createLoginBar($dom);
    $login_btn = createBtn($dom, 'login');
    
    $login_bar->appendChild($login_btn);
    
    $dom->appendChild($login_bar);
    
    echo $dom->saveHTML();
    

    Result:

    <div id="login_bar"><button class="widget">login</button></div>
    

    Sandbox