Search code examples
phpdomdocument

DOMDocument->loadHTML() creating entirely different content from what I pass in


I have a function which takes some variables and returns a DOMDocument with a chunk of html with specific values set based on the passed variables. The function looks like this, I'm sure there are better ways to do this but I don't see why I would be having the issue I am having despite that:

static function getEventContent($eventName, $eventNum){
        $dom = new DOMDocument();
        $dom->loadHTML(
        '<div id="event-' . $eventNum  . '" class="tab-pane' . $eventNum == 0 ? ' active' : '' . '">
                <h2>' . isset($eventName) ? $eventName : 'Event' . '</h2>
                <ol class="nav nav-tabs">
                    <li class="nav-item">
                        <a class="nav-link active" href="#about-' . $eventNum . '" data-toggle="tab">About</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#drawsheet-' . $eventNum . '" data-toggle="tab">Drawsheet</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#players-' . $eventNum . '" data-toggle="tab">Players</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#contact-' . $eventNum . '" data-toggle="tab">Contact</a>
                    </li>
                </ol>
                <div class="tab-content">
                    <div id="about-' . $eventNum . '" class="tab-pane active">
                        <h3>About</h3>
                    </div>
                    <div id="drawsheet-' . $eventNum . '" class="tab-pane">
                        <h3>Drawsheet</h3>
                    </div>
                    <div id="players-' . $eventNum . '" class="tab-pane">
                        <h3>Players</h3>
                    </div>
                    <div id="contact-' . $eventNum . '" class="tab-pane">
                        <h3>Contact</h3>
                    </div>
                </div>
                </div>');
        return $dom;
    }

Somehow by the time I am doing return $dom the entire contents of the DOMDocument have been replaced by a single <p> tag with $eventName as its text. Again, I'm sure theres a better way of generating the content I want (and I'd happily take suggestions) but this makes absolutely no sense. There isn't even a <p> in the content I'm generating. And when I tried commenting out the entire loadHTML() block and replacing it with a simpler loadHTML('<h1>test</h1>') it worked just fine and returned the header tag. For clarity, this works:

static function getEventContent($eventName, $eventNum){
        $dom = new DOMDocument();
        $dom->loadHTML('<h1>test</h1>');
        return $dom->saveHTML();
    }

Solution

  • You've misidentified the problem. You aren't passing in what you think you are. As a rule of thumb, you should break the code down to test where it fails: Store the string you are passing the the method in a variable, echo it to see if the value is what you expect, then pass the variable into the method.

    The problem is caused by the ternary operator you have in the middle of the string.

    Everything from the start of the string up to ? is the condition (black in the image below). This is a true value, so the value you assign is $eventName (green) leaving everything after the : as the value that isn't used (red).

    Screenshot of the code with highlights showing what is described above

    You need parentheses to set the precedence (or to break the string generation up into more manageable chunks).

    <h2>' . (isset($eventName) ? $eventName : 'Event') . '</h2>