为什么我的 HTML 在使用 Smarty 渲染时格式如此糟糕?

Why is my HTML so poorly formatted when rendered with Smarty?

为什么我的 HTML 查看源代码时格式如此糟糕?

合作对象:

  1. WAMPSERVER (64 BITS & PHP 5.5) 2.5

  2. Slim Framework v2

  3. RedBeanPHP 4.2

  4. Smarty 3.1.21


index.php:

<?php

// load required files
require 'class/Slim/Slim.php';
require 'class/RedBean/rb.php';

// register slim auto-loader
\Slim\Slim::registerAutoloader();

// set up database connection
R::setup('mysql:host=localhost;dbname=slimcms','root','');
R::freeze(true);


// initialize app
$app = new \Slim\Slim(array(
    'mode' => 'development'
    ,'debug' => true
    ,'view' => new \Slim\Views\Smarty()
    ,'templates.path' => './templates'
));


$view = $app->view();

$view->parserDirectory = dirname(__FILE__) . '/class/Smarty/';
$view->parserCompileDirectory = dirname(__FILE__) . '/compiled';
$view->parserCacheDirectory = dirname(__FILE__) . '/cache';



// handle GET request for index
$app->get('/', function() use ($app){
    $books = R::findAll('book');
//print_r($books);
    $app->render('home.tpl',array('books'=>$books));

});


$app->run();

templates/home.tpl:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Home</title>
</head>
<body>    
    <div id="content">
        {foreach name=aussen item=book from=$books}
            {foreach key=key item=value from=$book}
                {if $key == 'id' }
                    <a href="{$key}/{$value}">{$key}</a>
                {else}{$key}{/if}
            {/foreach}
            <hr />
        {/foreach}
    </div>    
</body>
</html>

当我通过 chrome 查看 源代码时:

    <!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Home</title>
</head>
<body>
    <div id="content">
                                                        <a href="id/1">id</a>
                                            rating                            price                            title                        <hr />
                                                        <a href="id/2">id</a>
                                            rating                            price                            title                        <hr />
            </div>
</body>
</html>

我会预期:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <title>Home</title>
</head>
<body>
    <div id="content">
        <a href="id/1">id</a> rating price title
        <hr>
        <a href="id/2">id</a> rating price title
        <hr>
    </div>
</body>
</html>

目前我找到的解决方案。

=> ~1.1 Dindent

=> ~0.11 tidy,

在 php.ini 中启用扩展=php_tidy.dll

index.php: ~1.1 使用这个:

<?php

// load required files
require 'class/Slim/Slim.php';
require 'class/RedBean/rb.php';
require 'class/Dindent/Indenter.php';                      //<= added

// register slim auto-loader
\Slim\Slim::registerAutoloader();

// set up database connection
R::setup('mysql:host=localhost;dbname=slimcms','root','');
R::freeze(true);


// initialize app
$app = new \Slim\Slim(array(
    'mode' => 'development'
    ,'debug' => true
    ,'view' => new \Slim\Views\Smarty()
    ,'templates.path' => './templates'
));


$view = $app->view();


$view->parserDirectory = dirname(__FILE__) . '/class/Smarty/';
$view->parserCompileDirectory = dirname(__FILE__) . '/compiled';
$view->parserCacheDirectory = dirname(__FILE__) . '/cache';



// handle GET request for index
$app->get('/', function() use ($app){
    $books = R::findAll('book');
//print_r($books);

    //$app->render('home.tpl',array('books'=>$books));
    $indenter = new \Gajus\Dindent\Indenter();             // <= start added
    ob_start();                                            //
    echo $app->render('home.tpl',array('books'=>$books));  //
    $content = ob_get_contents();                          //
    ob_end_clean();                                        //
    echo $indenter->indent($content);                      // <= end added


});


$app->run();

~0.11 使用这个:

ob_start();
    $app->render('home.tpl',array('books'=>$books));
    $buffer = ob_get_clean();
    $tidy = new tidy();
    $clean = $tidy->repairString($buffer,
        array(
            'indent' => true
            ,'indent-attributes' => true
    ));
    echo $clean;

预期输出:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Home</title>
    </head>
    <body>
        <div id="content">
            <a href="id/1">id</a> rating price title 
            <hr />
            <a href="id/2">id</a> rating price title 
            <hr />
        </div>
    </body>
</html>

既然问的是"why is the code not pretty?"不是"how do I make it pretty?",我就简单回答一下:

Smarty(和 PHP)正好通过您放入模板的空格;它不知道您正在创建的 HTML 结构。唯一会被剥离的是 Smarty 标签本身。

例如,如果你这样写:

  [ 
  {if $foo}
        foo
  {else}
        bar
  {/if}
  ]

所有这些空格都将成为输出的一部分,这将是:

  [

        foo

  ]

或:

  [

        bar

  ]

因此,如果您不希望输出中出现空格,请不要将其包含在输入中。

一个技巧是将其注释掉:

  [{* 
  *}{if $foo}{*
        *}foo{*
  *}{else}{*
        *}bar{*
  *}{/if}{*
  *}]

这将导致:

  [foo]

或:

  [bar]

这是对问题 "why" 部分的回答。关于未说出口的 "how to fix" 部分,您最好尝试找出如何生产更小的 HTML,而不是更漂亮的

编译时,Smarty 用 PHP 代码块替换 {} 包含的片段,包含在 <?php?>.

以下 Smarty 模板片段:

<div id="content">
    {foreach name=aussen item=book from=$books}
        {foreach key=key item=value from=$book}
            {if $key == 'id' }
                <a href="{$key}/{$value}">{$key}</a>
            {else}{$key}{/if}
        {/foreach}
        <hr />
    {/foreach}
</div>

变成类似:

<div id="content">
    <?php foreach ($books as $book): ?>
        <?php foreach ($book as $key => $value) : ?>
            <?php if ($key == 'id'): ?>
                <a href="<?php echo $key; ?>/<?php echo $value; ?>">{$key}</a>
            <?php else ?><?php echo $key; ?><?php endif; ?>
        <?php endforeach; ?>
        <hr />
    <?php endforeach; ?>
</div>

请注意,上面的 PHP 代码不是 Smarty 生成的。由于 Smarty 存储分配给模板的变量的方式、处理内置函数属性的方式、变量修饰符以及它提供的其他功能,Smarty 生成的代码更加复杂。
但出于本次讨论的目的,这个过于简化的代码版本就足够了。这里重要的是 Smarty 不会更改 { ... } 块之外的任何内容。

Smarty 不会破坏 template/HTML 代码的格式。 PHP 就是这样做的。

PHP 解释代码块(包含在 <?php?> 中)并将它们替换为它们生成的输出(如果有)。但如果换行符紧跟在 PHP 结束标记 ?>.

之后,它也会删除换行符

The closing tag for the block will include the immediately trailing newline if one is present.

(来源:http://php.net/manual/en/language.basic-syntax.instruction-separation.php

但是,SmartyPHP 都没有删除用于 Smarty 标签缩进的空格(因为它们不在标签内)。他们进入了决赛 HTML,由于删除了换行符,他们破坏了格式。