Создание всего вывода файла PHP пройти через “файл фильтра” прежде чем быть отображенным

Я думал, что дам этому выстрел с помощью классов и полиморфизма. У меня было предыдущее повторение, которое использовало разделение на подклассы, которое закончило тем, что имело слишком много служебное. Я переключился на более гибкого делегата / объектная модель общественной собственности, которая значительно лучше. Мой код очень немного более точен, мне жаль, что я не мог придумать лучший способ генерировать "несколько месяцев назад", который не казался слишком сверхспроектированным.

я думаю, что все еще придерживался бы Jeff, если тогда каскад, потому что это - меньше кода и это более просто (определенно легче гарантировать, что это будет работать как ожидалось).

Для ниже кода PrintRelativeTime. GetRelativeTimeMessage (Несколько TimeSpan назад) возвраты относительное сообщение времени (например, "вчера").

public class RelativeTimeRange : IComparable
{
    public TimeSpan UpperBound { get; set; }

    public delegate string RelativeTimeTextDelegate(TimeSpan timeDelta);

    public RelativeTimeTextDelegate MessageCreator { get; set; }

    public int CompareTo(object obj)
    {
        if (!(obj is RelativeTimeRange))
        {
            return 1;
        }
        // note that this sorts in reverse order to the way you'd expect, 
        // this saves having to reverse a list later
        return (obj as RelativeTimeRange).UpperBound.CompareTo(UpperBound);
    }
}

public class PrintRelativeTime
{
    private static List<RelativeTimeRange> timeRanges;

    static PrintRelativeTime()
    {
        timeRanges = new List<RelativeTimeRange>{
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromSeconds(1),
                MessageCreator = (delta) => 
                { return "one second ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromSeconds(60),
                MessageCreator = (delta) => 
                { return delta.Seconds + " seconds ago"; }

            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromMinutes(2),
                MessageCreator = (delta) => 
                { return "one minute ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromMinutes(60),
                MessageCreator = (delta) => 
                { return delta.Minutes + " minutes ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromHours(2),
                MessageCreator = (delta) => 
                { return "one hour ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromHours(24),
                MessageCreator = (delta) => 
                { return delta.Hours + " hours ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.FromDays(2),
                MessageCreator = (delta) => 
                { return "yesterday"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-1)),
                MessageCreator = (delta) => 
                { return delta.Days + " days ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-2)),
                MessageCreator = (delta) => 
                { return "one month ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-1)),
                MessageCreator = (delta) => 
                { return (int)Math.Floor(delta.TotalDays / 30) + " months ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-2)),
                MessageCreator = (delta) => 
                { return "one year ago"; }
            }, 
            new RelativeTimeRange
            {
                UpperBound = TimeSpan.MaxValue,
                MessageCreator = (delta) => 
                { return (int)Math.Floor(delta.TotalDays / 365.24D) + " years ago"; }
            }
        };

        timeRanges.Sort();
    }

    public static string GetRelativeTimeMessage(TimeSpan ago)
    {
        RelativeTimeRange postRelativeDateRange = timeRanges[0];

        foreach (var timeRange in timeRanges)
        {
            if (ago.CompareTo(timeRange.UpperBound) <= 0)
            {
                postRelativeDateRange = timeRange;
            }
        }

        return postRelativeDateRange.MessageCreator(ago);
    }
}
5
задан Gaurav Sharma 22 July 2009 в 10:36
поделиться

5 ответов

Ознакомьтесь с ob_start , который позволяет передать обработчик обратного вызова для пост-обработки вывода вашего скрипта.

Например, PHP включает встроенный обратный вызов ob_gzhandler для использования при сжатии вывода:

<?php

ob_start("ob_gzhandler");

?>
<html>
<body>
<p>This should be a compressed page.</p>
</html>
<body>

Вот более полный пример, иллюстрирующий, как вы можете привести в порядок свой HTML с помощью tidy extension :

function tidyhtml($input)
{
    $config = array(
           'indent'         => true,
           'output-xhtml'   => true,
           'wrap'           => 200);

    $tidy = new tidy;
    $tidy->parseString($input, $config, 'utf8');
    $tidy->cleanRepair();

    // Output
    return $tidy;
}

ob_start("tidyhtml");

//now output your ugly HTML

Если вы хотите, чтобы все ваши PHP-скрипты использовали тот же фильтр, не включая его напрямую, ознакомьтесь с директивой конфигурации auto_prepend_file .

14
ответ дан 18 December 2019 в 09:09
поделиться

Вы можете использовать буферизацию вывода и указать обратный вызов при вызове ob_start ()

<?php
function filterOutput($str) {
    return strtoupper($str);
}

ob_start('filterOutput');
?>

<html>
    some stuff
    <?php echo 'hello'; ?>
</html>
3
ответ дан 18 December 2019 в 09:09
поделиться

Вы можете использовать буферизацию вывода PHP функции для этого

Вы можете предоставить метод обратного вызова, который вызывается при сбросе буфера, например:

<?php

function callback($buffer) {   
    // replace all the apples with oranges  
    return (str_replace("apples", "oranges", $buffer)); 
}

ob_start("callback");
?>
<html>
<body>
    <p>It's like comparing apples to oranges.</p>
</body>
</html>

<?php
ob_end_flush();
?>

В этом случае вывод буферизируется, а не отправляется из сценария и непосредственно перед сбросом вашего метода обратного вызова называется.

1
ответ дан 18 December 2019 в 09:09
поделиться

Посмотрите, как используется Smarty . Это система шаблонов для PHP, которую рекомендуется использовать, и к которой вы можете подключить глобальные фильтры вывода.

0
ответ дан 18 December 2019 в 09:09
поделиться

править: ответ Пола лучше. Итак, это будет

ob_start("my_filter_function");

Мой первоначальный ответ был:

Этого можно достичь с помощью буферизации вывода .

Например:

ob_start();
// Generate all output
echo "all my output comes here."
// Done, filtering now
$contents = ob_get_contents();
ob_end_clean();
echo my_filter_function($contents);
0
ответ дан 18 December 2019 в 09:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: