Autor Zpráva
Kučik
Profil *
Jsem začátečník v oop. Dělám kalendář, už mám výpis denního a týdenního ale nevím jestli se takhle normálně používá oop. Prostě jestli je to správně podle oběktově orientovanýho myšlení xD.
calendar.php
<?php
class Calendar{
  private $CzechMonth = array(1 => "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec");
  private $CzechDay = Array("Ne", "Po", "Út", "St", "Čt", "Pá", "So");
  private $Day;
  private $Month;
  private $Year;

  function __construct(){
    if(isset($_GET["date"])){
      $Date = Split('-', $_GET["date"]);
      $this->Day = $Date["0"];
      $this->Month = $Date["1"];
      $this->Year = $Date["2"];
    }
    else{
      $this->Day = Date("j");
      $this->Month = Date("n");
      $this->Year = Date("y");
    }
  }

  function Daily($Day, $Month, $Year){
    if($Day == $this->Day and $Month == $this->Month and $Year == $this->Year){
      echo "Dnes - {$this->Day} {$this->CzechMonth[$this->Month]} {$this->Year} (1)";
    }
    else{
      $CountDays = date("t", mktime(0, 0, 0, $this->Month, 1, $this->Year));
      if($Day > $CountDays){
        $Day = $Day-$CountDays;
        $Month = ++$Month;
        if($Month == "13"){
          $Year = ++$Year;
          $Month = "1";
        }
      }
      $WeekDay = date("w", mktime(0, 0, 0, $Month, $Day, $Year));
      echo "{$this->CzechDay[$WeekDay]} - {$Day} {$this->CzechMonth[$Month]} {$Year} (1)";
    }
  }

  function Weekly(){
    $this->Daily($this->Day, $this->Month, $this->Year);
    for($x=1; $x<=6; $x++){
      echo "<br>";
      $this->Daily($this->Day+$x, $this->Month, $this->Year);
    }
  }
}
?>


Takhle to volám:
    $Calendar = new Calendar();
    $Calendar->Weekly(); //vypíše týdenní kalendář

    $Calendar->Daily("11","5","08"); //vypíše jeden den
Kučik
Profil *
Teď jsem to poupravil:
  function Daily($Day=null, $Month=null, $Year=null){
    if($Day == $this->Day and $Month == $this->Month and $Year == $this->Year){
      echo "Dnes - {$this->Day} {$this->CzechMonth[$this->Month]} {$this->Year} (1)";
    }
    elseif(!isset($Day)){
      echo "Dnes - {$this->Day} {$this->CzechMonth[$this->Month]} {$this->Year} (1)";
    }


takže když zavolám jenom $Calendar->Daily();
tak to vypíše dnešní den
Timy
Profil
Kučik
Prostě jestli je to správně podle oběktově orientovanýho myšlení xD.
Objektově.

Ten __construct je špatně — takhle je to moc závislé na proměnné $_GET["date"]. Když to třeba budeš chtít použít v jiné aplikaci, tak ta aplikace zase bude muset používat tuhle proměnnou. Vstupní informace dej normálně jako parametr konstruktu.

Dále vypisování pomocí echa přímo ve třídě není dobré. Totéž co předchozí bod — co když budeš potřebovat, aby se to vypsalo nějak jinak? Třeba aby datum bylo tučné nebo něco v tom smyslu. Budeš muset upravit celou třídu. Funkce Daily() by jen měla vracet nějakou proměnnou, kde bude nějak inteligentně uložené datum. Klidně to může být zase další objekt — bude mít tři vlastnosti: day, month, year. A klidně může mít nějakou metodu ToString(), která bude vracet (Ne vypisovat!) běžnou reprezentaci data.

Obecně je lepší, když metoda pouze vrcí nějaký výsledek, vedlejší efekt v podobě vypsání na obrazovku není obvykle vítaný.
Kučik
Profil *
Timy
Díky:), díky moc:)
takže ten __construct
  function __construct($Day=null, $Month=null, $Year=null){
    if(isset($Day)){
      $this->Day = $Day;
      $this->Month = $Month;
      $this->Year = $Year;
    }


to že by to jenom mělo něco vracet chápu ale zase když budu chtít změnit jak to bude vypadat tak budu muset změnit ten jinej celej objekt... mě to teda přijde tak že, jenom přidám pár řádků abych konečnej výpis neměnil v této funkci ale v tomhle objektu..
Kučik
Profil *
Timy
Teď sem si zas uvědomil že když mám ten __construct takhle tak musím dělat podmínku normál v kódu..
    if(isset($_GET["day"])){
      $Calendar = new Calendar($_GET["day"], $_GET["month"], $_GET["year"]);
    }
    else{
      $Calendar = new Calendar();
    }


ale zase nevím .. tohle už vůbec néni oop ne?.. nebo se to takhle může dělat xD?
Alphard
Profil
Tak trochu to souvisí s tím, co už uvedl Timy, ale mně se třeba na 25. řádku nelíbí pevně dané "Dnes". IMHO se může lehce stát, že bude potřeba text změnit. Řešení v podobě metody toString je jedna možnost, další by mohlo být třeba udělat obecnější třídu jako základ a tu potom zdědit a konkrétněji dopracovat. Podobně řádek 4, co když bude někdo chtít změnit názvy dnů? Proč je tam private, popř. není tam metoda umožňujíci změnu?
Kučik
Profil *
Alphard
metoda umožňující změnu?
hmm.. mohl by si mi prosím kus kódu kterej potřebuju změnu přepsat a postnout tak jak to má vypadat.. ?
Alphard
Profil
měl jsem na mysli klasický setter
zjednodušeně, když budu mít proměnnou $rok, tak pro ni mohu udělat setter, který umožní nastavit její hodnotu

function setRok($rok)
{
  // validační pravidla, případně vyhodí výjimku
  $this->rok = $rok;
}


je to dost kódu navíc, jestli to má smysl musíte zvážit sám, byl to jen návrh
Timy
Profil
Kučik
Ten konstrukt v [#4] už je lepší, ale zase není správně zapouzdřený. Co se stane, když udělám tohle?

$Calendar = new Calendar(1);


V konstruktoru bude podmínka „if(isset($Day))“ platná, ale do vlastností Month a Year se uloží null. To asi není správně :-). Další problém se zapouzdřením:

$Calendar = new Calendar("den", "měsíc", "rok");


Co se stane, když tam uložím řetězec? Nebo třeba neexistující měsíc (17)? Správně zapouzdřený objekt by měl být odolný vůči všem špatným vstupům, takže když se pokusím uložit blábol, vyhodí to (asi nejlépe) výjimku. Blábol zkrátka nesmí projít. Obvykle se to řeší nějaký get a set metodami — takže si uděláš další (buď private nebo public — podle toho, jestli chceš umožnit průběžně měnit den nebo jestli má kalendář po vytvoření zůstat neměnný) metodu SetMonth($value), kde zkontroluješ, zda je $value platný formát pro měsíc a teprve pak přiřadíš $this->Month=$value.

to že by to jenom mělo něco vracet chápu ale zase když budu chtít změnit jak to bude vypadat tak budu muset změnit ten jinej celej objekt..
Ee. Představ si, že to bude vracet tenhle objekt:

class Datum
{
	public $Year;
	public $Month;
	public $Day;
	
	public function ToString()
	{
		return $this->Day . ". " . $this->Month . ". " . $this->Year;
	}
}


Takže metoda Daily() vrátí tento objekt — return new Datum(ty tři parametry); — a vypsat si to můžeš jak chceš:

echo $datum->ToString();
echo $datum->Day . "/" . $datum->Month . "/" . $datum->Year;


A můžeš si samozřejmě napsat nějakou obecnou metodu, která bude brát nějaký vzor data: ToString("D. M. Y.");
Alphard
Profil
Kučik:
Ještě bych měl asi dodat, že jestli je to jedna z prvních tříd, kterou jste napsal, tak to není vůbec špatné. Udělejte něco s tou závislostí na $_GET a echem a bude to dobré. Zbytek berte jako doporučení pro další studium. Když to budete upravovat za pár měsíců, uvidíte sám, co jste měl udělat jinak.
koroman
Profil
pozor:
echo do triedy nepatri urcite. aspon do tejto nie. radsej vracaj result.
Kučik
Profil *
Děkuji moc, opravuji to pomalu.. ale přece :)
Pokud by někdo chtěl změnit výstup tak změní jenom třídu Date a v tom jakdyby základu se nemusí hrabat..
<?php
class Date{
  private $CzechMonth = array(1 => "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec");
  private $CzechDay = Array("Ne", "Po", "Út", "St", "Čt", "Pá", "So");

  public function ReturnDate($Day, $Month, $Year)
  {
    $WeekDay = date("w", mktime(0, 0, 0, $Month, $Day, $Year));
    return "{$this->CzechDay[$WeekDay]} - {$Day} {$this->CzechMonth[$Month]} {$Year} (1)";
  }

  public function ReturnDateToday($Day, $Month, $Year)
  {
    return "Dnes - {$Day} {$this->CzechMonth[$Month]} {$Year} (1)";
  }
}
?>


<?php
class Calendar extends Date{
  private $Day;
  private $Month;
  private $Year;
  
  function __construct($Day=null, $Month=null, $Year=null){
    if(isset($Day) and isset($Month) and isset($Year)){
      if(checkdate($Month, $Day, $Year)){
        $this->Day = $Day;
        $this->Month = $Month;
        $this->Year = $Year;
      }
      else{
        die("Neexistující datum");
      }
    }
    else{
      $this->Day = Date("j");
      $this->Month = Date("n");
      $this->Year = Date("y");
    }
  }
  
  function Daily($Day=null, $Month=null, $Year=null){
    if($Day == $this->Day and $Month == $this->Month and $Year == $this->Year){
      echo parent::ReturnDateToday($Day, $Month, $Year);
    }
    elseif(!isset($Day)){
      echo parent::ReturnDateToday($Day, $Month, $Year);
    }
    else{
      $CountDays = date("t", mktime(0, 0, 0, $this->Month, 1, $this->Year));
      if($Day > $CountDays){
        $Day = $Day-$CountDays;
        $Month = ++$Month;
        if($Month == "13"){
          $Year = ++$Year;
          $Month = "1";
        }
      }
      echo parent::ReturnDate($Day, $Month, $Year);
    }
  }

  function Weekly(){
    $this->Daily($this->Day, $this->Month, $this->Year);
    for($x=1; $x<=6; $x++){
      echo "<br>";
      $this->Daily($this->Day+$x, $this->Month, $this->Year);
    }
  }
}
?>


volám to pořád stejně:
    if(isset($_GET["day"])){
      $Calendar = new Calendar($_GET["day"], $_GET["month"], $_GET["year"]);
    }
    else{
      $Calendar = new Calendar();
    }
    $Calendar->Weekly();
Kučik
Profil *
Alphard
jj je to můj úprvně první nějakej pokus s oop:) díky:)
Kučik
Profil *
vylpšená kontrola data
  function __construct($Day=null, $Month=null, $Year=null){
    if(isset($Day) and isset($Month) and isset($Year)){
      if(is_numeric($Day) and is_numeric($Month) and is_numeric($Year)){
        if(checkdate($Month, $Day, $Year)){
          $this->Day = $Day;
          $this->Month = $Month;
          $this->Year = $Year;
        }
        else{
          die("Neexistující datum");
        }
      }
      else{
        die("Datum néni číslo");
      }
    }
    else{
      $this->Day = Date("j");
      $this->Month = Date("n");
      $this->Year = Date("y");
    }
  }
Mastodont
Profil
Namísto is_numeric použij ctype_digit, jinak projde třeba "12.4" jako den.

A volat die() uvnitř třídy není dobré. Používej výjimky.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: