Ben sadece biraz yardıma ihtiyacım var, korkunç bir PHP işlevini yazdı (zinciri elseif -? Anahtarı)

6 Cevap php

Ben ne zaman dayalı bir dizinin değerini belirleyen bir site yapıyorum. Ben bu korkunç (fonksiyonel) senaryosunu yazdı ve ben bunu daha özlü yapılmış olabilir merak ediyorum. Ben bir vaka / switch deyimi ile başladı, ama sorun onunla çalışan birden conditionals almak vardı. Burada kirli senet bulunuyor:

if ($now < november 18th) {
    $array_to_use = $home;
}
elseif (november 18th < $now && $now < november 21st ) {
    $array_to_use = $driving;
}
elseif (november 21st < $now && $now < november 22nd) {
    $array_to_use = $flying;
}
...
...
...
elseif (february 1st < $now) {
    $array_to_use = $arrived;
}
else {
    $array_to_use = $default;
}

Programı aslında daha karmaşık ve içinde 13 elseif ifadeleri vardır. Birisi sadece Coder adlı blok vardı ve bunu yapmak için daha iyi bir yolu var olduğunu teyit misiniz?

EDIT: bunu ben (umarım) ne yapıyorum anlamak kolaydır böylece kaba gerçek kat UNIX zaman değişti

EDIT 2: şu anda kırık Javascript saatini affet, ama bu ben üzerinde çalışıyorum site edin:

Time Table.

Her dizi benim yere göre, ve o zamana dayalı "Onlar şu anda" 15 söz konusudur. Bu bilinen başlangıç ​​/ bitiş zamanları ile küçük bir sorun alanı, bu yüzden esneklik sadece tüm yazılı alma, anahtar değildir. Siz zaman sürekli nasıl görebilir ve dizeleri sadece bir dizi bir anda seçilmesi gerekir.

6 Cevap

İlk olarak, kodlanmış numaralarını almak ve sabitler içine koydu lütfen lütfen lütfen.

$FLIGHT_START_TIME = 1258956001;
$FLIGHT_END_TIME   = 1260511201;

İkincisi, ben Koşullamalar her mini fonksiyonları yapacak:

Yani

function isFlying($time)
{
    return ( $FLIGHT_START_TIME < $time && $time < $FLIGHT_END_TIME );
}

Üçüncü olarak, Koşullamalar sizin bütün set almak ve geçerli durumunu almak için bir işlev içine koymak ve işlev çağrıları değiştirin:

function getStateArrayForTime($time)
{

   if (isDriving($time)
   {
       return $driving;
   }
   if ( isFlying($time) )
   {
        return $flying;
   }
...etc
}

Son senin tek bir işlev çağrısı ile kod bütün inline bölümü değiştirin:

$currentState = getStateArrayForTime($now);

Diğer posterleri de yorumladı var gibi size zaman devlet parametreleri olacak, sadece başlangıç ​​ve bitiş biliyorsanız, bu noktada durumuna dönmek için bir veri tablosu tahrik işlevini kullanabilirsiniz:

böylece ile getStateArrayForTime uygulanmasını değiştirin:

function getStateArrayForTime ($time)
{
// 
$states = array (
    array("startTime" => 1258956001, "endTime" => 1260511201, "state" => $flying),
    array("startTime" => 1260511201, "endTime" => 1260517000, "state" => $driving),
..etc...
);
    foreach($states as $checkStateArray)
    {
        if($checkStateArray['startTime'] < $time && $time < $checkStateArray['endTime'])
        {
            return $checkStateArray['state'];
        }
    }
    return null;
}

"Bu sırada şeyler yapmak neden?" Sonunda, bazı insanlar sorabilir Ben uygulamanın dışında, tüm kredi iddia edemez, ancak Martin Fowler neden temiz kod kadar tek bir seferde bir adım, ve yolun her adımında test, sonra nihayet açıklıyor "Yeniden Düzenleme" adında harika bir kitap vardır tüm süre onlar, işlevsel olarak eşdeğer olduğunu, test fonksiyonları mantıklı değil toptan değiştirin.

Bu overkill olabilir, ama ben bir açık nokta aralıkları her zaman koymak olabilir ki ben böyle bir şey yapardı:

@timeWindows = ({ start -> 0, end -> 1258783201, array -> $home },
                ... ,
                {start -> 1260511201, end -> MAXVAL, array -> $arrived});

ve daha sonra böyle bir döngü

$array_to_use = $default;

foreach (my $window in @timeWindows) {
   if (($now > $window->start) && ($now < $window->end)) {
       $array_to_use = $window->array;
       last;
   }
}

Maalesef bu Perl, ben PHP bilmiyorum, ama ben benzer hayal.

Onları seçmek için bir dizi ve döngü kullanmak için zaman ve dizi koyabilirsiniz.

$Selctions = array(
    1258783201 => $Home,
    1258956001 => $Driving,
    1260511201 => $Flying,
    ...
    1260511201 => $Arriving
);

// MUST SORT so that the checking will not skip
ksort($Selction);
$TimeToUse = -1;
$Now       = ...;
foreach ($Selctions as $Time => $Array) {
    if ($Now < $Time) {
        $TimeToUse = $Time;
        break;
    }
}
$ArrayToUse = ($TimeToUse != -1) ? $Selctions[$TimeToUse] : $Default;

This method can only be used when the times has no gap (one range right after another).

Umarım bu yardımcı olur.

Böyle bir şey yapıyor, bir switch deyimi kullanabilirsiniz:

switch (true)
{
    case $now < 1258783201:
        // your stuff
        break;
    case $now < 1258783201
        // more of your stuff
        break;
    //...
}

Yani en azından biraz daha temiz ...

Böyle bir şey:

$array_to_use = null;
$dispatch = array(1258783201, $home, 1258956001, $driving, ..., $arrived);
for ($i=0; i<count($dispatch); $i+=2) {
    if ($now<$dispatch[$i]) {
        $array_to_use = $dispatch[$i+1];
        break;
    }
}
if ($array_to_use==null) $array_to_use = $dispatch[count($dispatch)-1];

Ayrıca "<" Eğer ihtiyacınız olup olmadığını düşünmek gerekir ya da "<=" durumu.

Sen Komutanlığı Desen öğrenmek isteyebilirsiniz; ayrıca bu durumda yardımcı olabilir.