我能覆盖PHP内置函数echo()吗?

15

我最近查看了我的源代码,它非常混乱。

我的 PHP 源代码:

echo '<h1>Rar<h1>';
echo '<span>Rar</span>';
echo '<p>Rar</p>';

当我查看渲染页面的浏览器源代码时:

<h1>Rar</h1><span>Rar</span><p>Rar</p>

有没有办法让我覆盖echo,以便每个输出都以换行符结尾,类似于

function echo($string)
{
 echo $string . "\r\n";
}

2
而当你不想换行时呢?那么你会怎么做? - grapefrukt
“当你不想要换行符时怎么办?”--- 使用 print 语句? - PurplePilot
5
在我看来,HTML是供浏览器阅读的,而不是人类。只要你的源代码可读性良好,就不用担心HTML输出。干净的HTML输出是锦上添花,但在任何稍微复杂一点的应用中,如果没有适当的模板或像Tidy这样的工具,很难实现。 - deceze
1
deceze 是正确的,HTML 是为浏览器而设计的。如果您想查看 HTML,我建议使用 Firebug。Firebug 可以为您提供完整的折叠和展开视图,甚至在 JavaScript 修改时更新 HTML。非常方便。 - Niels Bom
你为什么要编辑和维护由PHP脚本生成的HTML文件呢? - Niels Bom
显示剩余4条评论
6个回答

10

echo并不是一个函数,而是一种语言声明。它不能被重新定义。如果你想要美化你的输出标记,可以看看Tidy


可以使用IDE的搜索/替换方法,将所有的echo语句替换为echo PHP_EOL,。这会在任何输出之前追加操作系统特定的换行符。请注意,在PHP_EOL后面加上逗号非常重要。

你可以像这样使用echo输出多个值:

echo 'one', $foo, PHP_EOL,
     'two', $bar, PHP_EOL;

因此,每行都不需要写echo

然而,我同意任何建议使用更专业的方法来分离内容和布局,例如使用模板视图或HereDoc。

此外,精美的标记几乎没有什么好处。如果您使用类似Firebug的工具检查HTML,则无论标记实际上有多混乱,您都将获得正确格式化的标记。此外,在访问量大的站点上,您经常会发现标记被压缩,这与您所试图做的正好相反,因为所有这些换行符和制表符都会增加页面的大小,从而导致页面加载速度变慢和流量成本增加。


3

您有多种输出HTML的可能性。

您可以使用heredoc语法:

$html = <<<EOF
<h1>Rar<h1>
<span>Rar</span>
<p>Rar</p>
EOF
echo $hml;

或者(在我看来更好的方式)将HTML与PHP分离。例如,将所有PHP逻辑放在文件顶部,然后在PHP块之后放置HTML:
<?php
   // all your PHP goes here
   $foo = 'bar'
?>
<!-- HTML comes here -->
<html>
  <body>
    <div>Hello <?php echo $foo; ?> </div>
  </body>
</html>

可以像上面展示的那样打印变量。但是这些变量不包含HTML。

当你必须根据条件输出HTML时,可以使用控制语句的替代语法

<?php if($some_condition): ?>
    <h1>Rar<h1>
    <span>Rar</span>
    <p>Rar</p>
<?php endif ?>

这样做也更容易调试您的HTML,因为它不仅仅是一个PHP字符串。


2

您可以设置和输出缓冲区,然后通过htmltidy运行缓冲区。为此,tidy扩展甚至有特定的函数。只需在开始输出HTML之前调用此函数:

ob_start('ob_tidyhandler');

1

虽然这个解决方案没有覆盖echo,但你可以通过添加一个换行符来获得类似于echo的效果。添加:

function e() {
    return o::singleton();
}

class o {
    private static $instance;

    public static function singleton()
    {
        if (!isset(self::$instance)) {
            $className = __CLASS__;
            self::$instance = new $className;
        }
        return self::$instance;
    }

    public function __set($prop, $txt) {
        echo $txt . PHP_EOL;
    }
}

将它返回到你的文件中,然后你就可以使用:

e()->o = "Line which ends in newline";

instead of echo.


0

您可以通过使用__toString()魔术方法来间接重载echo(),示例如下:

<?php
class CleanOutput
{
    public $content;

    public function __construct($c) {
        $this->content= $c;
    }

    public function __toString() {
        return $this->content . '\r\n';
    }
}

$text= new CleanOutput('Hello world!');
echo $text;
?>

以上代码将输出带有换行和回车的 "Hello world!"。当然,还有更多封装的方法,但这超出了我的回答范围。 编辑:
正如所指出的那样,上述解决方案速度较慢/笨拙。以下是一种使用输出缓冲的更优雅的解决方案:
<?
function clean_up($foo) {
   return $foo . '\r\n';
}
ob_start('clean_up');
ob_implicit_flush(true);
echo "Hello world!";
?>

这样做更快,更干净(虽然从技术上讲它并没有“覆盖”echo)。


4
绝对正确且巧妙的解决方案。问题是,原帖作者现在需要将他正在“echo”的每个文本块都用“new CleanOutput()”来包装,这忽略了问题的重点。;-) - deceze
2
这非常低效;它需要超过10倍于echo/print等效的时间。另外,'\r\n'将不能按预期工作,必须用双引号括起来。 - Johannes Gorset
非常正确(在两种情况下)。 OP 问是否可以覆盖echo。 我展示了它可以:P - David Titarenco
2
从技术上讲,这并不覆盖 echo。每当对象在字符串上下文中使用时,将使用 __toString。这是 echo,但也包括 print(string)'foo' . $object - Gordon
不错的观点,Gordon。我加入了另一个更优雅的解决方案。 - David Titarenco
1
这个第二种解决方案非常棒!谢谢你! - OMA

0
另一个解决方案是使用适当的模板引擎将代码与布局分离。

@Gordon,我同意。PHP可以用作模板引擎。但并不总是这样使用。在这些情况下,拥有模板会使生活更简单吗?@Natrium,不完全是这样。我喜欢Google webapp和Django(两个Python框架)的做法,PHP也可以使用Smarty或类似的框架来实现相同的效果。 - Sri
1
@Srirangan 使用模板是可以的,但在PHP之上添加另一个引擎会使您的应用程序变得臃肿无用,这是我个人的看法。 - Gordon
@Gordon 一般来说我同意你的观点,但是最近我尝试了一下 HAML,发现模板引擎可以将代码行数减少50%,同时提高可读性和有效性保证。 :) - deceze
@deceze 那性能呢?也有提升吗?此外,在计算中是否考虑了框架本身的 LOC?如果您想要保证有效输出,可以使用 DOM 进行模板化或通过 Tidy 透明地运行输出。 - Gordon
@Gordon 我不明白为什么框架的LOC计数很重要,如果它可以节省我大量的打字。编译后的模板文件也可以轻松缓存;在生产环境中可以无限期地使用。 - deceze
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接