Ill formatted HTML from a PHP loop

2019-08-04 08:11发布

I am looping through an array and building tables. The HTML is then sent to DOMPDF. However, DOMPDF will not create the PDF if the HTML is ill formatted. I assume that is what is happening in my case. Here is my loop:

<?php foreach($credits as $credit) : ?>
        <?php if($credit['credit_type'] == "short") : ?> 
            <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:0px 0px 15px 0px;"> 
                <tr> 
                    <td><strong><?php echo $credit['category_title']; ?></strong></td> 
                </tr> 
                <tr> 
                    <td><?php echo $credit['credit_heading']; ?></td> 
                </tr> 
            </table> 
        <?php endif; ?> 

        <?php if($credit['credit_type'] == "long") : ?>
            <?php if($credit['category_title'] != $oldvalue) : ?>
                <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:0px 0px 15px 0px;">
                <tbody>
            <?php endif; ?> 
                <tr>
                    <?php if($credit['category_title'] != $oldvalue) : ?>
                          <td width="25%"><strong><?php echo trim($credit['category_title']); ?></strong></td>                 
                          <td width="25%"><strong>Title</strong></td>
                          <td width="25%"><strong>Role</strong></td>
                          <td width="25%"><strong>Director</strong></td>
                    <?php endif; ?>
                </tr>
                <tr>
                    <td width="25%"><?php echo $credit['credit_heading'];?></td>
                    <td width="25%"><?php echo $credit['credit_title']; ?></td>
                    <td width="25%"><?php echo $credit['credit_role']; ?></td>
                    <td width="25%"><?php echo $credit['credit_director']; ?></td>
                </tr>
                <?php if($credit['category_title'] != $oldvalue) : ?>
                    </tbody>
                    </table>
                <?php endif; ?>
                <?php $oldvalue = $credit['category_title']; ?>
        <?php endif; ?> 
    <?php endforeach; ?>

I cannot for the life of me work out which tag I am not closing. If anyone could give some insight, that would be fab!

Specifically, the loop is creating rows that show some headings, and then spit out futher rows whenever the category title changes.

2条回答
疯言疯语
2楼-- · 2019-08-04 08:52

This may be a simple solution but perhaps not the best:

I recommend you to use PHP's Tidy class (eventually you'll have to install it first...)
Here is the link for the Tidy class Manual.

At the first line:

ob_start();

This command buffers everything what is outputed by your follwing script.
The code below should be added at the end of your file, or there where you want to show the output.
It first gets the buffer with ob_get_contents() and than it cleans the code up.
Note that you'll eventually have to change the configuration parameters for your needs, there are really very much.

$raw_output = ob_get_clean();

$config = array('indent' => true, 'output-xhtml' => true, 'wrap' => 0);
$tidy = new Tidy;
$tidy->parseString($raw_output, $config, 'utf8');
$tidy->cleanRepair();

echo $tidy;

This Example Code was modified by the original version of the example on php.net.

Hope that helps you.

查看更多
贪生不怕死
3楼-- · 2019-08-04 09:06

It's a bit difficult to parse without known more about your data. For example, why is a table for "short" credit open and closed with the record, but the table for "long" credit is conditional on the previous record? Is it because you have a flat data structure so related data shows up as a series of consecutive rows? If that's the case things would be easier if the data were a bit more normalized. I.e. you could iterate through each credit record then through the details separately. Any possibility of fixing your data structure?

Analyzing the code you have, your problem appears to be in the logic for the second section of the code. You are setting the value of the variable $oldvalue at the end of the loop. This is after the logic that closes the table. So if you parse two records that have the same category title the second record will output it's table rows completely outside a table (never mind that it will also have a completely empty row). Additionally, if you have a short credit type following a long the table will never be closed.

That being said, working with what you have I'm guessing you may need something like the following:

// build a dummy "previous" record for the first iteration so the conditionals don't break.
<?php $previous_credit = array('credit_type'=>null,'category'=>null); ?>
<?php foreach($credits as $credit) : ?>
    <?php if($credit['credit_type'] == "short" || ($previous_credit['credit_type'] == "long" && $previous_credit['category'] != $credit['category'])) : ?>
              </tbody>
              </table>
    <?php endif; ?> 

    <?php if($credit['credit_type'] == "short") : ?> 
        <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:0px 0px 15px 0px;"> 
            <tr> 
                <td><strong><?php echo $credit['category_title']; ?></strong></td> 
            </tr> 
            <tr> 
                <td><?php echo $credit['credit_heading']; ?></td> 
            </tr> 
        </table> 
    <?php endif; ?> 

    <?php if($credit['credit_type'] == "long") : ?>
        <?php if($credit['category_title'] != $previous_credit['category_title']) : ?>
            <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:0px 0px 15px 0px;">
            <tbody>
            <tr>
                <td width="25%"><strong><?php echo trim($credit['category_title']); ?></strong></td>                 
                <td width="25%"><strong>Title</strong></td>
                <td width="25%"><strong>Role</strong></td>
                <td width="25%"><strong>Director</strong></td>
            </tr>
        <?php endif; ?> 
            <tr>
                <td width="25%"><?php echo $credit['credit_heading'];?></td>
                <td width="25%"><?php echo $credit['credit_title']; ?></td>
                <td width="25%"><?php echo $credit['credit_role']; ?></td>
                <td width="25%"><?php echo $credit['credit_director']; ?></td>
            </tr>
    <?php endif; ?>
    <?php $previous_credit = $credit; ?>
<?php endforeach; ?>

<!-- one last table close for the last record -->
</tbody></table>

(That's some ugly code and I don't have time to keep revising it, so ... community wiki in case anyone else wants to clean it up.)

查看更多
登录 后发表回答