Anzeigen von Kursen in einem HTML-Kalender

  • Ich kämpfe seit einiger Zeit mit der Lesbarkeit meines Codes. Nachdem ich versucht habe, so viel Einblick wie möglich zu erhalten (für meine Standards). Auf meiner Ebene glaube ich, ich verstehe und benutze es in Ordnung für meine Ebene.

    Aber ich habe immer noch große Brocken gemischter HTML / CSS in der Präsentation. Oft habe ich ein mittelmäßiges komplexes mehrdimensionales Array als Rückgabewert, und auf der tatsächlichen Präsentationsseite durchlaufe ich es, mache aber trotzdem eine Menge Sachen damit.

    Also Ich beschäftige mich jetzt mit Template-Engines wie Smarty, aber ich kann mich nicht damit auseinandersetzen, wie ich in Beispielen wie dem folgenden Code etwas tatsächlichen Code damit speichern würde, bei dem ich in der Präsentation iteriere und mit dem Array arbeite:

     $courseinfo = new courseinfo($_SESSION['course_short']);
    $row = $courseinfo->get_all(); 
    $default = $courseinfo->get_default();
    $prices = $courseinfo->get_prices();
    $month_min_show = 5;
    
    //color settings for prices
    $colorlow = '#6F6'; 
    $colormid = '#09F'; 
    $colorhigh = '#F90'; 
    $colorspecial = '#F0F';
    $colorfull = 'rgba(255,0,0,0.3)';
    
    
    /* CONTENT CALENDAR
    -----------------
    -----------------
    */
    
    echo '<div id="calendar">';
    $count['month'] = 0;
    foreach($row as $month)
    {
        $lastcourse = end($month['course']);
        $laststart = $lastcourse['date'];
        $enddate = new DateTime($laststart);
        $enddate->modify('+ '.($lastcourse['length']-1).' days');
        $iterate = new DateTime('01-'.date('m',strtotime($laststart)).'-'.$month['year']);
        if (!isset($stored['year']) || isset($stored['year']) && $stored['year'] != $month['year'])
        {
    
            if($count['month'] > $month_min_show) { break;}     // don't show next year if $month_min_show months already displayed
            if(isset($stored['year'])) { echo '<br /><br /><br /><div style="margin-top:-10px"></div>';}
            echo '<span class="year" style="float:left;">'.$month['year'].'</span>';
            echo '<div style="float:right;margin-top:-20px;padding-right:5px;">';
            echo '<div style="float:left;font-size:12px;font-weight:bold;">PRICES '.$month['year'].'</div>';
    
            echo '<div class="pricelegend" style="background-color:'.$colorfull.'">fully booked</div>';
            if (in_array('low',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colorlow.'">'.$default['price_low'].' &euro;</div>'; }
            if (in_array('mid',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colormid.'">'.$default['price_mid'].' &euro;</div>'; }
            if (in_array('high',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colorhigh.'">'.$default['price_high'].' &euro;</div>'; }
            if (in_array('custom',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colorspecial.'">Special Offer</div>';}
    
    
            echo '</div><div style="clear:both;"></div><hr width="800px;" align="left"/>';
        }
    
    
        echo '<div class="m_start">'.mb_strtoupper($month['monthname'],'UTF-8').'<br />';
            echo '<span class="yearsmall">'.$month['year'].'</span>';
        echo '</div>';
        echo '<div class="courses">';
        echo '<div style="float:left;width:10px;">&nbsp;</div>';
        while($iterate<=$enddate)
        {
            $dayname = strftime('%a',$iterate->format('U'));
            if ($dayname == "So" OR $dayname == "Sa") { $daycolor = "#999"; } else { $daycolor = "#FFF";}
    
            echo '<div class="dayname" id="'.$iterate->format('dmY').'" style="color:'.$daycolor.'">'.$dayname.'</div>';
    
            $iterate->modify('+ 1 days');
        }
            echo '<br />';
    
        $lineswitch = 0;
        foreach($month['course'] as $course) 
        { 
            $date = $course['date'];
            $date = new DateTime("$date");
            $coursewidth = $course['length']*20-2;
            if($course['class'] == 'low') { $pricecolor = $colorlow; }
            elseif($course['class'] == 'mid') { $pricecolor = $colormid; }
            elseif($course['class'] == 'high') { $pricecolor = $colorhigh; }
            else {$pricecolor = $colorspecial;}
            if($course['user'] >= $course['usermax']) { $pricecolor = $colorfull;  }
            if(isset($_SESSION['course_id']) && $_SESSION['course_id'] == $course['id']) { $bordercolor = 'border-color:#FFF';} else {$bordercolor = '';}
    
            if($course['user'] < $course['usermax']) { echo '<a class="clink" id="'.$course['id'].'" href="'.$_SESSION['book_url'].'?course='.$course['id'].'" target="_self">'; }
            echo '<div class="course" style="background-color:'.$pricecolor.';'.$bordercolor.';width:'.$coursewidth.'px;margin-top:'.$lineswitch*17 .'px;margin-left:'.(10+($date->format('d')-1)*20).'px">';
    
            if($course['user'] < $course['usermax'])
            {
                echo '<span class="coursestart">&nbsp;'.$date->format('d').'</span>';
    
    
                if($course['length'] > 1) 
                {
                    echo '-';
                    $date->modify('+ '.($course['length']-1).' days');
                    echo '<span class="courseend">'.$date->format('d').'&nbsp;</span>';
                }
            }
            else { echo '<span style="color:#000;">x</span>'; }
    
            echo '</div>';
            if($course['user'] < $course['usermax']) {echo '</a>';}
            unset($date);
            if ($lineswitch == 0) { $lineswitch = 1;} else {$lineswitch = 0;}
        }
        echo '</div>';
    
        echo '<div class="m_end"></div>';
        echo '<div style="clear:both;"></div><br />';
        $stored['year'] = $month['year'];
        $count['month']++;
    
    }       
    echo '</div>';
     

    Hier ein Beispiel des Arrays, das ich durchläuft:

     Array ( [04.2012] => 
        Array ( [monthname] => April [year] => 2012 [course] => 
            Array ( 
               [0] => Array ( [id] => 106 [date] => 2012-04-02 14:00:00 [length] => 3 [class] => mid [price] => 110 [user] => 0 [usermax] => 20 [day] => 02 [week] => 14 [dayname] => Mo [hours] => 3 ) 
               [1] => Array ( [id] => 107 [date] => 2012-04-03 10:00:00 [length] => 3 [class] => mid [price] => 110 [user] => 0 [usermax] => 20 [day] => 03 [week] => 14 [dayname] => Di [hours] => 3 ) 
               [2] => Array ( [id] => 108 [date] => 2012-04-05 14:00:00 [length] => 3 [class] => mid [price] => 110 [user] => 0 [usermax] => 20 [day] => 05 [week] => 14 [dayname] => Do [hours] => 3 )   
              ) 
           ) 
     

    Dies ist ziemlich viel Code, wie Sie sehen können. Nur so können Sie eine Vorstellung davon bekommen, wie ich noch arbeiten muss viel mit dem Array.

    • Wie könnte ich das in kleinere Stücke aufteilen oder es lesbarer und einfacher machen, damit zu arbeiten?

    Hoffe, ich könnte klarstellen, was ich hier will ... und sicher, wenn Sie etwas anderes finden, das in diesem Code völlig dumm ist, geben Sie mir ein Wort!

    Ich würde nicht wissen, wie eine Vorlagen-Engine helfen würde, da es immer noch viele if s und dynamische Änderungen gibt.

    Sidenote: Ich arbeite alleine und werde es immer tun, also ist die Trennung nur für mich.

    25 January 2018
    200_successAsik
3 answers
  • Vielen Dank für das perfekte Beispiel der realen Präsentationslogik.
    Die meisten Leute, die primitive Vorlagenlösungen einsetzen, haben einfach keine Ahnung von einer solchen komplexe Fälle Existenz.

    Drei Regeln, um es richtig zu machen:

    1. Verwenden Sie PHP als Template Engine.
    2. Kein HTML-Tag oder keine Textkonstante mit PHP-Echo ausgeben, sondern nur reines HTML verwenden.
    3. Verschieben Sie ALLE Datenvorbereitungen in den Geschäftslogikteil.

    Formatieren Sie ALLE Ihre Daten in der Geschäftslogik.
    Übergeben Sie nur Skalare an die Vorlage. Keine datetime-Objekte!
    Keine komplexe Logik - verwenden Sie nur die grundlegende PHP-Syntax in der Vorlage.

    Informieren Sie sich also zweimal über Ihre Daten:

    • das erste Mal, um alle Datenvorbereitungen und Formatierungen durchzuführen.
    • und das nächste Mal, um die eigentliche Ausgabe in der Vorlage auszuführen.

    So wird PHP-Code so

     $count['month'] = 0;
    foreach($row as $i => $month)
    {
        $month['lastcourse'] = end($month['course']);
        $month['laststart']  = $month['lastcourse']['date'];
        $month['enddate']    = new DateTime($month['laststart']);
        $month['enddate']->modify('+ '.($month['lastcourse']['length']-1).' days');
        $month['iterate']    = new DateTime('01-'.date('m',strtotime($month['laststart'])).'-'.$month['year']);
        $month['showyear']   = (!isset($stored['year']) || isset($stored['year']) && $stored['year'] != $month['year']);
        $month['monthname']  = mb_strtoupper($month['monthname'],'UTF-8');
        $row[$i]             = $month;
    }   
     

    Während die Vorlage so sauber ist wie diese

     <div id="calendar">
    <? foreach($row as $month): ?>
      <? if ($month['showyear']): ?>
        <? if ($stored['year']): ?>
            <br /><br /><br /><div style="margin-top:-10px"></div>
        <? endif ?>
            <span class="year" style="float:left;"><?=$month['year']?></span>
            <div style="float:right;margin-top:-20px;padding-right:5px;">
            <div style="float:left;font-size:12px;font-weight:bold;">PRICES <?=$month['year']?></div>
            <div class="pricelegend" style="background-color:<?=$colorfull?>">fully booked</div>
            some code removed
            </div><div style="clear:both;"></div><hr width="800px;" align="left"/>
      <? endif ?>
            <div class="m_start"><?=$month['monthname']?><br />
            <span class="yearsmall"><?=$month['year']?></span>
            </div>
        <div class="courses">
        <div style="float:left;width:10px;">&nbsp;</div>
    <? endforeach ?>
    </div>
     

    Ich werde nicht Ihren gesamten Code neu formatieren, sondern einfach geben Sie eine Idee

    28 November 2011
    Your Common Sense
  • Mit diesem Batch arbeiten:

     //color settings for prices
    $colorlow = '#6F6'; 
    $colormid = '#09F'; 
    $colorhigh = '#F90'; 
    $colorspecial = '#F0F';
    $colorfull = 'rgba(255,0,0,0.3)';
    
    // ...
    // ...
    // ...
    
    if (in_array('low',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colorlow.'">'.$default['price_low'].' &euro;</div>'; }
    if (in_array('mid',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colormid.'">'.$default['price_mid'].' &euro;</div>'; }
    if (in_array('high',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colorhigh.'">'.$default['price_high'].' &euro;</div>'; }
    if (in_array('custom',$prices[$month['year']])) { echo '<div class="pricelegend" style="background-color:'.$colorspecial.'">Special Offer</div>';}
     

    Eine Möglichkeit wäre, etwas zu verwenden wie folgt:

     # place your colors into an array instead
    $colors = array();
    $colors['low'] = '#6F6'; 
    $colors['mid'] = '#09F'; 
    $colors['high'] = '#F90'; 
    $colors['special'] = '#F0F';
    $colors['full'] = rgba(255,0,0,0.3);
    
    # price legend array, since your code appears to be checking each one
    $priceLegend = array();
    $priceLegend[] = 'low';
    $priceLegend[] = 'mid';
    $priceLegend[] = 'high';
    $priceLegend[] = 'custom';
    
    // ...
    // ...
    // ...
     

    Dann auf der HTML-Ausgabeseite:

     <div class="pricelegend" style="background-color:<?php echo $colors['full']; ?>">fully booked</div>
    <?php
        foreach($priceLegend as $key => $value) {
        if (in_array($value,$prices_array[$months_array['year']])) {
            $priceBackclr = $colors_array[$value];
            $priceDisplay = $defaults_array['price_'.$value];
            $priceDisplay .= ($priceDisplay != 'Special Offer') ? ' &euro' : '';
            ?>
            <div class="pricelegend" style="background-color:<?php echo $priceBackclr; ?>"><?php echo $priceDisplay; ?></div>';
            <?php
        }
    }
    ?>
    </div><div style="clear:both;"></div><hr width="800px;" align="left"/>
     

    Es sieht nach viel mehr Code aus, aber Änderungen vorzunehmen sollte nicht so schwer sein. Nehmen Sie hier eine Änderung vor, dann werden die anderen folgen. Ich meine, für den (beispielsweise) div-Stil der Preislegende oder etwas.

    Jedenfalls ist es nur einer von vielen Möglichkeiten dies zu tun .. Und Sie können dies auf andere Abschnitte des Codes anwenden ... Es gibt bessere Methoden da draußen; Ich hoffe, dass hier mehr veröffentlicht wird.

    [EDIT] Zusätzliche Option / Code, die als Ergebnis des laufenden Kommentartauschs [EDIT]

     # function does the in_array for you
    function findInArrayAndReturnAsArray($valueToFind, $arrayToFindIn, $outputType) {
        # use $outputType so that if you would like, 
        # you can reuse this function to do other stuff like find 
        # another value in another array
    
        $outputArray = array();
    
        if ($outputType = 'price') {
            if (in_array($valueToFind, $arrayToFindIn)) {
    
                $outputArray[] = $colors_array[$valueToFind];
                $temp = $defaults_array['price_'.$valueToFind];
                $temp .= ($priceDisplay != 'Special Offer') ? ' &euro' : '';
                $outputArray[] = temp;
            }
        } 
    
        return $outputArray;
    
    }
     

    Dann in Ihrer Vorlage Wenn Sie es anzeigen müssen, verwenden Sie es folgendermaßen:

     # go through each item in the price legend array and grab the results and then echo them with the html
    foreach($priceLegend as $key => $value) {
        $priceLegendDisplay = findInArrayAndReturnAsString($value , $prices_array[$months_array['year']], 'price');
        echo = '<div class="pricelegend" style="background-color:'.$priceLegendDisplay[0].'">'.$priceLegendDisplay[1].'</div>';
    }
     

    Die Funktion can Hilfe DRY Deinen Code aus. Es kann flexibel genug sein, um andere Aktionen aufzunehmen, die auf den von Ihnen festgelegten $outputType Werten basieren und deren Code Sie verwenden. Stellen Sie sich diese Funktion irgendwo vor, und Ihre Ausgabeseite ruft sie einfach auf. Wenn Sie können, erstellen Sie eine eigene Klasse, die Funktionen wie diese enthält, die die Ausgabe von Daten behandeln. Es mag wie ein controller und view aus dem MVC-Entwurfsmuster aussehen, aber mit der Feinabstimmung können Sie es in ein reines view verwandeln. Ich denke also, was ich sage, ist .. Ein Designmuster, einen objektorientierten Ansatz zu verwenden und im Hinterkopf zu bleiben, um dem Prinzip Don't Repeat Yourself treu zu bleiben.

    30 November 2011
    Nonym
  • Sie könnten auch eine Vorlagen-Engine wie Twig oder Smarty .

    Sie bieten eine vollständige Trennung von Anzeige und Logik.

    25 January 2018
    Sam OnelaDave