如何重构这个条件以避免重复?

时间:2009-06-10 10:31:01

标签: php dry

这是可以按日期过滤的事件页面的一部分(使用预定义的日期范围或日期选择器)。

我想避免为每个条件重复整个foreach ($days as $day_number)...等循环。

我想整个循环可以移动到一个函数,但我不确定如何实现它。

<?php

// open the db connection
$db = new wpdb('user', 'pass', 'db', 'server');


// $today = date('Y-m-d');
$today = '2009-06-21';
$tomorrow  = date( 'Y-m-d', mktime(0, 0, 0, date('m'), date('d')+1, date('Y')) );
$seven_days_ahead = date( 'Y-m-d', mktime(0, 0, 0, date('m'), date('d')+6, date('Y')) );
$thirty_days_ahead = date( 'Y-m-d', mktime(0, 0, 0, date('m'), date('d')+29, date('Y')) );


echo '<div class="column first">';


if ( ! empty($_REQUEST['date_range']) )    
{
    // user has chosen a date/range, show matching events 


    $date_range = mysql_real_escape_string($_REQUEST['date_range']);


    switch( $date_range )
    {
        case 'all':

            // code here

            break;

        case 'next_7_days':

            // code here

            break;

        case 'next_30_days':

            // code here

            break;

        default:

            // code here

    }


}
else
{
    // no date selected, show todays events

    $days = convert_date_to_day_number( $today );

    foreach ( $days as $day_number )
    {
        $where = sprintf( 'WHERE e.day_id = %s', $day_number );

        $events = get_events( $where );

        if ($events)
        {
            echo '<table class="results">';

            render_day( $day_number );

            foreach ($events as $event)
            {
                render_event($event);
            }  

            echo '</table>';
        }
        else
        {
            echo 'No events';                            
        }
    }

}

echo '</div> <!--/column-->';





function convert_date_to_day_number($date)
{
    global $db;

    $sql = "SELECT day_number FROM days WHERE day_date = '$date'";

    $day_numbers = $db->get_results($sql);

    foreach ($day_numbers as $key => $value)
    {
        $day_number[] = $value->day_number;
    }

    return $day_number;
}


function get_events($where)
{
    global $db;

    $sql = "SELECT
                 e.id,
                 TIME_FORMAT(e.start_time, '%H:%i' ) AS start_time,
                 e.x_prod_desc AS title,
                 -- e.title_en AS title,
                 p.name_en AS place,
                 et.name_en AS type,
                 w.week_number,
                 d.day_date AS start_date
             FROM event AS e
             LEFT JOIN place AS p ON p.id = e.place_id
             LEFT JOIN event_type AS et ON et.id = e.event_type_id
             LEFT JOIN days AS d ON d.id = e.day_id
             LEFT JOIN week AS w ON w.id = d.week_id ";   

    $sql .= $where;

    $events = $db->get_results($sql);

    return $events;          
}

function render_event($event)
{
    $request_uri = $_SERVER['REQUEST_URI'];

    $output = <<<EOD

    <tr class="week-$event->week_number">
        <td class="topic"></td>
        <td class="time">$event->start_time</td>
        <td class="summary">
         <a href="$request_uri&amp;event_id=$event->id">$event->title</a>   
        </td>
        <td class="type">$event->type</td>
        <td class="location">
           <span class="addr">$event->place</span>
        </td>
    </tr>

EOD;

    echo $output;
}


function render_day( $day_number )
{
    global $db;

    $sql = "SELECT
                d.day_number,
                DATE_FORMAT( d.day_date, '%W %e %M %Y' ) AS date,
                DATE_FORMAT( d.day_date, '%b' ) AS month,
                DATE_FORMAT( d.day_date, '%e' ) AS day
            FROM days AS d
            WHERE day_number = " . $day_number;

    $day = $db->get_results($sql);

    $day = $day[0];

    $output = <<<EOD

    <tr class="day">
        <th colspan="5">
            <em class="date">
                <abbr class="dtstart" title="20090605T1806Z">
                    <span title="$day->date">
                        <span class="month">$day->month</span>
                        <span class="day">$day->day</span>
                </span>
                </abbr>
            </em>
            $day->date
            <span class="event-day">Day $day->day_number</span>
        </th>
    </tr>

EOD;

    echo $output;
}
?>

4 个答案:

答案 0 :(得分:3)

首先,您可能希望将strtotime用于相对日期:

$today = '2009-06-21';
$tomorrow  = date( 'Y-m-d', strtotime('+1 day') );
$seven_days_ahead = date( 'Y-m-d', strtotime('+7 days') );
$thirty_days_ahead = date( 'Y-m-d', strtotime('+30 day') );
    // or +1 month (=> calendar month)

其次,您可以使用begin&amp; amp设置两个变量。结束日期,然后:

$date = $start_date; // 'Y-m-d' format
while( $date <= $end_date ) {
    //code here or fill up a table with your days
    // using $date
    $date = date( 'Y-m-d', strtotime( '+1day', strtotime($date) ) );
}

每当使用PHP中的日期时,您应该检查strtotime

答案 1 :(得分:2)

我不会每天查询一次数据库,而是创建一个WHERE语句,获取所需日期范围内的所有事件,然后将其发送到循环遍历结果集中每一行的渲染函数如果当天与之前一天不同,请在致电render_day()之前致电render_event()

switch (/* input from user */) {
    // Build a date range here.
    // Resulting statement would be something like:
    // WHERE event_date >= '2009-06-10' AND event_date < '2009-06-17'
}

$events = get_events($filter);
$prev_date = null;
foreach ($events as $event) {
    if ($event->date != $prev_date) render_day($event->date);
    render_event($event);
    $prev_date = $event->date;
}

答案 2 :(得分:0)

哇!我看过了!

首先使用模板引擎(如smarty)或任何其他方式来分割代码和HTML。从函数内部回显HTML是一个坏主意。

我不确定,但我认为在数据库中使用unix-timestamp可以简化数据结构。关于php代码也一样。请仔细阅读php手册中的date/time functions,我想,你会发现很多有趣的东西......

实际上,正如我从代码中看到的那样,使用时间戳和模板会将代码缩减到某些行以获取数据并将其分配给模板引擎。 PHP的“date()”函数已经可以选择返回周数,一周或一年中的日期等...

这是虚拟的问题,你的代码可能是什么样的:

$begin = mktime(...);
$end = mktime(...);
$query = "
    SELECT a,b,c 
    FROM events 
    WHERE ctime >= $begin AND ctime <= $end AND ...
";
$events = array();
while ($fetch = fetch_here(...))
{
    $event = new MyEvent();
    $event->loadDBFetch($fetch);
    array_push($events, $event);
}
$tplEngine->assign('events', $events);

当然,这不是一个随时可用的解决方案,但在我看来,您的代码可能与此类似。

答案 3 :(得分:0)

function generateEventsTable($dateStr)
{
    $days = convert_date_to_day_number( $today );
    foreach ( $days as $day_number )
    {
        $where = sprintf( 'WHERE e.day_id = %s', $day_number );
        $events = get_events( $where );
        if ($events)
        {
            echo '<table class="results">';
            render_day( $day_number );
            foreach ($events as $event)
            {
                render_event($event);
            }  
            echo '</table>';
        }
        else
        {
            echo 'No events';                            
        }
    }
}

这样称呼:

generateEventsTable($today);