Avatar billede -zonic- Nybegynder
15. september 2009 - 10:02 Der er 21 kommentarer og
2 løsninger

objektorienteret PHP Kalender - problemer med aftale objekter i et array?

hejsa,


jeg har prøvet at udvikle en kalender, som vi kender den fra diverse reklamerende virksomheder der sender deres papkalendere ud til folk med posten... dette er mit første forsøg på at lave noget med objektorienteret php, da jeg ville lege lidt med det...

se kalenderen her:

http://www.pixel8.dk/pages/skb/

jeg har nu det problem at jeg skal have aftaler i min kalender...

Dette må jo så være aftale objekter...?

jeg kan ikke rigtigt greje hvordan jeg skal lave en liste af aftaler som så kan findes frem ved at der søges på den dato man er på, så jeg savner lidt hjælp til hvordan jeg griber det an...

I får lige min kalender kode her.:

require_once($_SERVER['DOCUMENT_ROOT']. "/pages/skb/classes/appointment.php");

class Calendar extends Appointment {
    var $months;
    var $month;
    var $year;
    function Calendar() {
    }
    function dayConvert($day) {
        if($day == "7") { $day = "Sø"; }
        if($day == "1") { $day = "Ma"; }
        if($day == "2") { $day = "Ti"; }
        if($day == "3") { $day = "On"; }
        if($day == "4") { $day = "To"; }
        if($day == "5") { $day = "Fr"; }
        if($day == "6") { $day = "Lø"; }
        return $day;
    }
   
    function getStart() {
        return $this->month;
    }
   
    function daysOfMonth() {
        $mo = $this->month;
        $ye = $this->year;
        return cal_days_in_month( CAL_GREGORIAN, $mo, $ye );
    }
   
    function thisDay() {
        $mo = $this->month;
        $t = mktime(0, 0, 0, $mo,  $this->day,  $this->year);
        return $this->dayConvert(date("N",$t));
    }
    function isWeekend() {
        $t = mktime(0, 0, 0, $this->month,  $this->day,  $this->year);
        $r = date("N",$t);
        if($r == 6) {
            return 'sa';
        } elseif($r == 7) {
            return 'su';
        }
    }
   
    function thisMonth() {
        $mo = $this->month;
        $ye = $this->year;
        $t = mktime(0, 0, 0, $mo, date("d"), $ye);
        return date("F",$t);
    }
   
    function thisYear() {
        $mo = $this->month;
        $ye = $this->year;
        $t = mktime(0, 0, 0, $mo,  date("d"),  $ye);
        return date("Y",$t);
    }   

    function showCalendar() {
        for($co= 0; $co < $this->months ; $co++) {
            if($this->month >12) { $this->month = 1; $this->year++; }
            echo "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"float:left;\" class=\"calendar\">\n";
            echo "<tr>\n";
            echo "<td class=\"month\" colspan=\"3\">".$this->thisMonth()." ". $this->thisYear()."</td>\n</tr>\n";
            $this->day = 1;
            for ($y= 1; $y <= $this->daysOfMonth(); $y++) {
                echo "<tr>\n";
                echo "<td class=\"day1".$this->isWeekend()."\" align=\"left\">".$this->thisDay()."</td>\n";
                echo "<td class=\"day".$this->isWeekend()."\" align=\"right\">".$y."</td>\n";
                echo "<td class=\"event".$this->isWeekend()."\" align=\"left\"></td>\n";
                echo "</tr>\n";
                $this->day++;
            }
            for($z= $this->daysOfMonth(); $z < 31; $z++) {
                echo "<tr>\n<td colspan=\"3\" class=\"none\">&nbsp;</td>\n</tr>\n";
            }
            echo "</table>\n";
            $this->month++;
        }
    }
}



når den opretter en td, skal den så søge efter om der er nogle aftaler på den dato..
Jeg regner med at køre det fra en mysql når jeg er færdig, men skal jeg så bare helt droppe at bruge aftale objekter og så bare lave en funktion der søger på dato og udskriver aftale på td'en... så er det vel ikke rigtigt oop længere? og så skal der også ske et mysql kald for hver dag jeg har i min kalender, istedet for at gøre det hele af én gang?

eller skal jeg lade db'en køre alle aftaler igennem af én gang, gemme objekterne i et array og så på én eller anden måde søge i dette array af objekter og udskrive aftalen til en given dato..? og i så fald - hvordan griber jeg det an?




min kalender bliver nu oprettet således.:

$ap0 = new Appointment(date("j-n-Y"),"test");
$ap1 = new Appointment("13-1-2009","Stephan");
$ar1 = new ArrayList();
$ar1->add($ap0);
//se bort fra ovenstående :-)

$cal = new Calendar();
$cal->months = 6;
$cal->month = date("m");
$cal->year = 2009;
$cal->showCalendar();

håber nogle kan hjælpe mig da jeg er helt ny i oop...

på forhånd tak!
Avatar billede repox Seniormester
15. september 2009 - 10:32 #1
Du kunne jo starte med at fortælle hvad formålet er med den - i mine øjne - besynderlige løsning? For mig virker det som om du blot har valgt at bruge OOP fordi du kan - ikke fordi det løser noget smart.

OOP er en genial måde at organisere og strukturere sin kode på; men udover at du har en kalender i din klasse, hvad har du så opnået? Er det smarte i Appointment klassen?

Anyways, du bestemmer selv hvordan du vil lave din aftaler.
Personligt ville jeg anvende arrays til at hente aftaler.
F.eks:

$array["2009-09-09"][0]["start"] = "11:00";
$array["2009-09-09"][0]["slut"] = "12:30";
$array["2009-09-09"][0]["navn"] = "Møde med Karsten";

$array["2009-09-14"][0]["start"] = "8:00";
$array["2009-09-14"][0]["slut"] = "11:00";
$array["2009-09-14"][0]["navn"] = "Bestyrelsesmøde";

$array["2009-09-14"][1]["start"] = "12:30";
$array["2009-09-14"][1]["slut"] = "13:30";
$array["2009-09-14"][1]["navn"] = "Tandlæge";


Da du ikke ser ud til at være helt ubekendt med PHP antager jeg at du nemt kan regne ud hvordan ovenstående skal bruges.

Så er det jo nemt når du 'laver en td' kontrollerer datoen op mod arrayet.
Hvordan du laver arrayet afhænger jo af hvordan du henter dine aftaler.
Avatar billede -zonic- Nybegynder
15. september 2009 - 10:39 #2
hejsa..

jeg tænkte nok at min løsning ikke var særlig oop "valid" ;-) da en kalender vel skulle bygges op af flere klasser, med en kalender der indeholder nogle dage, som indeholder nogle aftaler?  men det jeg synes jeg har opnået her er, at jeg har mere struktur og så har jeg nærmest ingen kode blandet ind i min html som jeg ellers ville have blandet sammen...

men mit problem er netop som du beskriver... jeg er ret godt bekendt med php, men jeg har aldrig haft success med at bruge arrays til noget som helst brugbart, og ville derfor ikke vide hvordan jeg skulle få noget ud af de arrays som du beskriver...

Min appointment klasse er sådan set ikke videre smart, den kan bare oprette nogle aftaler med de properties du selv skriver...  men så er det jo et objekt og der kan jeg SLET ikke få noget udskrevet fra...


Kan du vise mig hvordan jeg ville få noget ud af det..?


Ps. hvordan laver du din kode i den fine blå kasse? :-)
Avatar billede -zonic- Nybegynder
15. september 2009 - 10:45 #3
og i øvrigt så har jeg haft et spørgsmål kørende herinde netop for at finde ud af hvad oop kunne gøre for mig her: http://www.eksperten.dk/spm/884922 - så måske jeg ikke helt har forstået formålet?

Formålet med kalenderen er at lave en kalender der kan holde en note på de givne dage... det er sådan set alt... og så skal jeg bare have 6 forskellige kalendere - da det er til noget holdsport, hvor hvert hold skal have sådan en kalender.... skulle jeg have grebet det hele helt anderledes an?
Avatar billede repox Seniormester
15. september 2009 - 11:28 #4
Der ville være mere formål i at blot lade dine klasser håndtere kalenderdataene end også at skrive HTML ud.

Formålet med OOP er netop at lave noget der er så vedligeholdelsesfrit som overhovedet muligt. Genbrug, refaktorering og struktur er nøgleordene.

Den hellige gral inden for al programmering er at adskille logik fra præsentation.

PHP er et klytsprog hvor det er mere besværligt at opnå end med mange andre sprog. Men man kan selv gøre meget for det.

Din klasse outputter HTML for dig, hvilket betyder at hvis jeg ville bruge en mere pæn og ren måde at lave kalenderen på, skal jeg konsekvent ind og tilrette din klasse. Du har også forudbestemt CSS klasser på elementerne i HTML'en, som også skal rettes til så det passer - endda med dynamiske klassenavne. Det er ikke særlig fleksibelt.

Jeg ville hellere bruge noget ala:


<div id="Calender">
<?php

  include("calender.obj.php");
  $cal = new Calendar();
  $cal->setMonths = 6;
  $cal->setCurrentMonth(date("m"));
  $cal->setYear = 2009;

  $days[0] = "Sø";
  $days[1] = "Ma";
  $days[2] = "Ti";
  $days[3] = "On";
  $days[4] = "To";
  $days[5] = "Fr";
  $days[6] = "Lø";

  $months = $cal->getMonths();
  foreach($months as $month):

    $days = $cal->getDaysForMonth($month["monthNo"]);
?>
  <div class="month">

    <?php
      for($i = 1; $i <= $days; $i++):
        $dayAttributes = $cal->getDayAttributes($month["monthNo"], $i);
        $abbDay = $days[$dayAttributes["dayOfWeek"]];
        $className="day";
        if($dayAttributes["isWeekend"])
          $className = "weekend";
    ?>
      <div class="<?php echo $className; ?>"><?php echo $abbDay; ?></div>
    <?php endfor; ?>
  </div>
<?php endforeach; ?>
</div>


På den måde har jeg brugt en klasses funktioner til at gøre oprettelsen af en kalender nemmere for mig, hvor jeg selv bestemmer det visuelle output. Klassen har så bare hjulpet mig med at afgøre en masse ting.

Arrays er geniale - de kan bruges til hvad som helst. I mit eksempel kunne jeg bruge det førnævnte arrays således:


...
?>
  <div class="<?php echo $className; ?>"><?php echo $abbDay; ?>
    <?php
      $tmp = $cal->getYear()."-".$month["monthNo"]."-".$i;
      if(isset($array[$tmp])):
        foreach($array[$tmp] as $events):
    ?>
    <strong><?php echo $events["navn"]; ?></strong><br />
    <?php
        endforeach;
      endif;
    ?>
  </div>
<?php
...


De fine blå kasser laver jeg BB-code-tag'ene [ div] og [ /div]

Efter at have læst lidt i den tråd du referer til, kan jeg godt se hvorfor du er lidt forvirret - og så alligevel ikke. Du fik mange gode og fine svar fra nogle meget dygtige mennesker, men du misser essensen i det, på grund af de mange tilbagemeldinger.

Du efterlyser selv et praktisk eksempel, så nu skal jeg give dig et.

Forestil dig du har et website med (for at holde tallet nede) 20 sider.
Hver af de tyve sider har nogle funktionaliter, som hver især kontakter MySQL databasen for henholdsvis oprette brugere, tælle downloads, hente statistik og så videre.

Hver af dine tyve sider indeholder således noget ala:

<?php

    include("dbconnect.php"); // virker til at være en meget populær løsning i disse dage
    $sql = "SELECT * FROM users WHERE userId = '".$_SESSION["userId"]."' LIMIT 1";
    $result = mysql_query($sql);
    ...

?>


Nogle af dine sider har endda mange flere forespørgsler, men idéen er den samme. Lad os gange det op med tyve og antage at der er ca 3 mysql forespørgsler i gennemsnit for hver fil du har = 60 mysql forespørgsler.

Nu sker det usandsynlige, så; PHP opdateres til en udgave hvor MySQL extensionen har udfaset funktionen mysql_query(). Horribelt! Den rædsel! Dine 20 sider, med hver især 3 mysql forespørgsler i gennemsnit skal nu rendes igennem så du kan rette din mysql_query() til mysqli_query() så du endnu engang er med... Men det kan være omstændigt - og hvad hvis du glemmer en? Så opdages det måske først for sent og hvilken betydning kan det have medført? Puha, jeg ser mange timers rettelser... :/

Men, men, men - løsningen kunne have været simpel.
Se her:

<?php

  include("mysql.obj.php");
  $db = new MySQL(); //klassens __construct() henter brugernavn og kodeord fra en config fil
  $sql = "SELECT * FROM users WHERE userId = '".$_SESSION["userId"]."' LIMIT 1";
  $result = $db->queryItem($sql);
 

  ...
?>


Nu kunne jeg faktisk bare nøjes med at rette mysql_query() til mysqli_query() et eneste sted (nemlig i min MySQL klasse) og så virkede alting som det skulle, lige med det samme - alle steder!

Det er hvad man vil kalde et abstraktionslag - men det er heldigvis kun en lille del af OOP. Men stadig et praktisk eksempel.
Avatar billede -zonic- Nybegynder
15. september 2009 - 17:10 #5
tak for dit svar :-) jeg tror det giver mere mening nu.. jeg har fået udskrevet aftalerne som du foreslog nu, men har lige endnu et spm... hvis nu jeg knalder 100 aftaler ind i mit array og gerne vil sortere det på tid, hvordan får du så det ind i din foreach løkke? eller vil du bare sortere dem når du smider dem i arrayet fra db'en med en sql sætning med order by?  - vil egentlig også bare gerne vide om det er muligt at sortere arrayet :-)
Avatar billede -zonic- Nybegynder
15. september 2009 - 17:20 #6
i øvrigt.. hvis jeg nu gerne ville slippe for at oprette dem som arrays men gerne ville kunne lave aftaler som objekter, vil det så stadig være muligt at udskrive dem som arrays? for det synes jeg slet ikke jeg kunne få til at virke...?


jeg forestiller mig...


$app = new Appointment($start,$slut,$navn);
$arr = new ArrayList();

$arr->add($app);

og så udskrive den fra det array.. men kan overhovedet ikke lige greje hvordan den skal skæres... har i øvrigt hentet en klasse "ArrayList", men synes ikke det hjalp meget...

skal det gribes helt anderledes an?


<?
/**
* ArrayList class
*
* @version 0.2
* @author Tim Anlauf <schranzistorradio@gmx.de>
**/
class ArrayList {
    /**
    * Array, representing the arrayList
    **/
    var $arrayList;
    /**
    * Pointer variable. used to detect the last element of the list in hasNext() method.
    **/
    var $pointer=0;
        /**
    * Constructor
    * Constructs a new list. The Parameter $arr is optional. If set an ArrayList
    * with the elements in array is created. Otherwise a empty list is constructed.
    * @param arr - one dimensional array (optional)

    **/

        function ArrayList($arr="") {

            if (is_array($arr) == true)

            $this->arrayList = $arr;

        else

            $this->arrayList = array();

    }

    /**
    * Inserts the specified element at the specified position in this list.
    * @param index integer - position in list
    * @param $obj
    **/
    function addToPos($index, $obj) {       

        if ($this->isInteger($index))

            $this->arrayList[$index] = $obj;

        else

            die("ERROR in ArrayList.addToPos <br> Integer value required");

    }
   
    function findNote($obj,$se) {
        $this->find = array_search($se,$obj);
        return $this->find;
    }

    /**
    * Appends the specified element to the end of this list.
    * @param
    **/

    function add($obj) {

        array_push($this->arrayList, $obj);

    }

    /**
    * Appends all of the elements in the specified Array to the end of this list
    * @param arr - one dimensional array
    **/

    function addAll($arr) {

        $this->arrayList = array_merge($this->arrayList, $arr);

    }

    /**
    * Removes all of the elements from this list.
    **/   

    function clear() {

        $this->arrayList = array();

    }

    /**
    * Returns true if this list contains the specified element.
    * @param obj
    * @return boolean
    **/

    function contains($obj) {

        return in_array($obj, $this->arrayList);

    }

    /**
      *  Returns the element at the specified position in this list.
    * @param index
    **/

    function get($index) {

        if ($this->isInteger($index))

            return $this->arrayList[$index];

        else

            die("ERROR in ArrayList.get <br> Integer value required");

    }

    /**
    * Searches for the first occurence of the given argument. If the element isn¥t found, -1 is returned
    * @param obj
    * @return integer
    **/

    function indexOf($obj) {

        while (list ($key, $val) = each ($this->arrayList))

                if ($obj == $val) return $key;

        return -1;   

    }

    /**
    * Tests if this list has no elements.
    * @return boolean
    **/

    function isEmpty() {

        if (count($this->arrayList) == 0) return true;

            else return false;   

    }

    /**
    * Returns the index of the last occurrence of the specified object in this list.
    * @param obj
    * return integer
    **/

    function lastIndexOf($obj) {

        return array_search($obj, $this->arrayList);

    }

    /**
    * removes the element at the specified position in this list.
    * @param index
    **/

    function remove($index) {

        if ($this->isInteger($index)) {

            $newArrayList = array();

           

            for ($i=0; $i < $this->size(); $i++)

                if ($index != $i) $newArrayList[] = $this->get($i);

                   

            $this->arrayList = $newArrayList;

        }

        else {

            die("ERROR in ArrayList.remove <br> Integer value required");

        }

    }   

    /**
    * Removes from this List all of the elements whose index is between fromIndex, inclusive and toIndex, exclusive.
    **/

    function removeRange($fromIndex, $toIndex) {

        if ($this->isInteger($fromIndex) && $this->isInteger($toIndex)) {

            $newArrayList = array();

           

            for ($i=0; $i < $this->size(); $i++)

                if ($i < $fromIndex || $i > $toIndex ) $newArrayList[] = $this->get($i);

                   

            $this->arrayList = $newArrayList;       

        }

        else

            die("ERROR in ArrayList.removeRange <br> Integer value required");

    }



    /**
    * Returns the number of elements in this list.
    * return integer
    **/

    function size() {

        return count($this->arrayList);

    }

    /**
    * Sorts the list in alphabetical order. Keys are not kept in position.
    **/

    function sort() {

        sort($this->arrayList);

    }

    /**
    * Returns an array containing all of the elements in this list in the correct order.
    * @return array
    **/

    function toArray() {

        return $this->arrayList;

    }
   
    function toString($obj) {
        return $obj->note;
    }

    /* Iterator Methods */

    /**
    * Returns true if the list has more elements. Advice : excecute reset method before
    * using this method
    * @return boolean
    **/

    function hasNext() {

        $this->pointer++;

       

        if ($this->pointer == $this->size()) return false;   

            else return true;       

    }

    /**
    * Set the pointer of the list to the first element
    **/

    function reset() {

        reset($this->arrayList);

        $this->pointer=0;

    }

    /**
    * Set the pointer of the next element of the list
    * @return current element
    **/

    function next() {

        $cur = current($this->arrayList);

        next($this->arrayList);

        return $cur;

    }

    /* private Methods */

    /**
    * Returns true if the parameter holds an integer value
    * @return boolean
    **/

    function isInteger($toCheck) {

        return eregi("^-?[0-9]+$", $toCheck);

    }

}

?>

Avatar billede arne_v Ekspert
16. september 2009 - 01:16 #7
Lidt blandede kommentarer:

1)  Jeg tror at din kode kunne kortes meget ned hvis du brugte PHP's DateTime klasse (kræver dog en nyere PHP version)

2)  Der mangler ligesom nogle private/public angiver for at opnå envcapsulation.

3)  Det er meget meget sjældent at multi dimensionale arrays er god OOP. Normalt skal man have et en dimensionalt array af en klasse.

4)  Den ArrayList klasse ser meget Java/C# agtig ud - jeg er ikke overbevist om at det er den bedste måde at gøre det på i PHP.

5)  Din objekt model er gal. En Calendar arver ikke fra Appointment. En Calendar indeholder 0-mange Appointment's.
Avatar billede -zonic- Nybegynder
16. september 2009 - 10:50 #8
tak for dine kommentarer...  :-)

1) jeg har php 5.2, så kan jeg vel godt bruge den klasse? ligger den automatisk i php? jeg synes det jeg lige kan finde på nettet ligner alm functions som ikke har noget med oop at gøre? - kan jeg i øvrigt bruge den klasse du snakker om sammen med mine funktioner?

2) ja, jeg må indrømme, jeg har slet ikke brugt private / public endnu - jeg prøver lige at komme en smule ind under huden på det hele først og arbejde lidt med det..

3) kan det så lade sig gøre med objekter som jeg prøvede på at få til at virke? hvis jeg, hvordan :-)

4) Ja, der stod også at det var en klasse tilsvarende java.util.ArrayList  - og det eneste oop erfaring jeg har er et java introduktionsfag, men der synes jeg ikke det var et problem at udskrive fra objekter i en arraylist.. men jeg husker det dog ikke helt..

5) ja, jeg ved godt den er gal... bruger dog heller ikke appointment classen... men huskede det egentlig som om man skulle binde klasserne sammen, men det skal de vel egentlig ikke... når en kalender indeholder aftaler skal den vel egentlig ikke associeres med klassen?


æv hvor er jeg faktisk ikke særlig god til det her :-(
Avatar billede repox Seniormester
16. september 2009 - 11:37 #9
#8

Jeg tilslutter mig arne_v's kommentarer - overordnet set gaber du over for meget.

2) private, public og protected er en grundlæggende struktur i PHP OOP. Istedet for at skrive forældet kode, kan du lige så godt vænne dig til at skrive den kode der bliver brugt idag - du risikerer bare at altid være bagud i forhold til teknologien med den indstilling.

3) Hvis du nu starter med at forklare, hvorfor du konsekvent vil bruge objekter til at lave dine 'aftaler' med, ville det måske være interessant for os at forsøge at løse opgaven på den måde; for mig virker det som om du forsøger at gøre tingene unødvendigt komplicerede - særligt når du begynder at hente klasser og objekter som andre har lavet, for at opnå dit mål. Det er en dårlig måde at lære/udvikle sig på.

Du bliver nød til at starte lidt mere 'blødt' ud med din udvikling inden for OOP. Lav nogle små objekter som kan løse trivielle opgaver for dig - lav et abstraktionslag til din database - lav en klasse som kan generere et RSS feed for dig.. Mulighederne er mange - men essensen er altid den samme - keep it simple.
Avatar billede -zonic- Nybegynder
16. september 2009 - 12:55 #10
okay.. tilbage til min grund idé med at lave min kalender med oop...

jeg havde en forventning om at det var nemmere at overskue min html når først min kalender klasse var kodet... dvs, jeg troede at formålet var at alt foregik inde bagved, mens man i html'en blot skulle bruge klassen, såsom.:



$app = new App($dato,$note);
// så mine aftaler også bare var én linje der skulle skrives og at de så kunne hives ud med funktioner :-)

$cal = new Date();
$cal->months = 5;
$cal->showCalendar();



så havde jeg en forventning om at kunne genbruge denne kalender på alle de sider jeg havde lyst til blot med nye aftaler og måske andre månedviews....


det var så ikke helt korrekt antaget, kan jeg forstå, da man åbenbart ikke skal blande html ind i sine klasser ? :-)

nu ser min kode så ud således .:


$cal = new Date();
$cal->months = 5;
$cal->startMonth = date("m");
$cal->width = 160 * $cal->months;
//$cal->showCalendar();
$array["2009-09-07"][0]["start"] = "16:00";
$array["2009-09-07"][0]["navn"] = "Preben";

$array["2009-09-07"][1]["start"] = "18:00";
$array["2009-09-07"][1]["navn"] = "Else";

$array["2009-09-07"][2]["start"] = "20:00";
$array["2009-09-07"][2]["navn"] = "Hans";

$array["2009-09-14"][0]["start"] = "16:00";
$array["2009-09-14"][0]["navn"] = "Rasmus L";

$array["2009-09-21"][1]["start"] = "16:00";
$array["2009-09-21"][1]["navn"] = "Louise";

$array["2009-09-28"][0]["start"] = "16:00";
$array["2009-09-28"][0]["navn"] = "Marie";

$array["2009-10-05"][0]["start"] = "16:00";
$array["2009-10-05"][0]["navn"] = "Kim";

$array["2009-10-12"][1]["start"] = "16:00";
$array["2009-10-12"][1]["navn"] = "Jack";

// calendar

echo "<table class=\"caltable\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"".$cal->width."\">\n<tr>\n";

        for($co= 0; $co < $cal->months ; $co++) {
            if($cal->month >12) { $cal->month = 1; $cal->year++; }
            echo "<td valign=\"top\">\n";
            echo "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"float:left;\" class=\"calendar\">\n";
            echo "<tr>\n";
            echo "<td class=\"month\" colspan=\"3\" valign=\"middle\">".$cal->getMonth()." ". $cal->getYear()."</td>\n</tr>\n";
            $cal->day = 1;
            for ($y= 1; $y <= $cal->daysOfMonth(); $y++) {
                echo "<tr".$cal->isTodayColor().">\n";
                echo "<td class=\"day1\"".$cal->isWeekend()." align=\"left\" valign=\"middle\">".$cal->getDay()."</td>\n";
                echo "<td class=\"day\"".$cal->isWeekend()." align=\"right\" valign=\"middle\">".$y."</td>\n";
                echo "<td class=\"event\"".$cal->isSunday()." align=\"left\" valign=\"middle\">";
                $tmp = $cal->getDate();
                if(isset($array[$tmp])) {
                    foreach($array[$tmp] as $events) {
                          echo "<strong>".$events["start"]. " - ".$events["navn"]."</strong><br />\n";
                    }
                }
                echo "</td>\n";
                echo "</tr>\n";
                $cal->day++;
            }
            for($z= $cal->daysOfMonth(); $z < 31; $z++) {
                echo "<tr>\n<td colspan=\"3\" class=\"none\">&nbsp;</td>\n</tr>\n";
            }
            echo "</table>\n</td>\n";
            $cal->month++;
        }


jeg ved godt at jeg stadig har blandet lidt html ind i min klasse ved f.eks. isWeekend() som returnerer en farve til min td... er det også dumt? bør jeg istedet lave.:


function isWeekend() {
        $t = mktime(0, 0, 0, $this->month,  $this->day,  $this->year);
        $r = date("N",$t);
        if($r >= 6) {
            return true;
        } else {
            return false;
        }
    }



og så bruge if($cal->isWeekend) { echo "style=\"background-color:#ccc;\""; }

for mig virker min html pludselig uoverskuelig igen, og synes jeg har meget kode i den alligevel, som jeg troede var formålet at pakke væk... og så vidste man også altid hvor det skulle rettes hvis noget gik galt - nemlig i showCalendar() - men det er helt forkert forstået? :-)

i det mindste er mit visuelle resultat efterhånden tilfredsstillende, synes jeg.. :-)
http://www.pixel8.dk/pages/skb/

men hvad siger I til mine refleksioner ?  ( er i øvrigt MEGET taknemlig over at I gider komme med konstruktiv kritik - jeg føler at jeg får meget ud af det! ) :-)
Avatar billede repox Seniormester
16. september 2009 - 13:27 #11
Som udgangspunkt er der ikke noget i vejen med din tankegang, det er blot en forkert retning du er kommet i.

Personligt synes jeg ikke din kode er overskuelig, når du har alt det HTML i din klasse - ydermere, så er det ikke ønskeligt for mig at din klasse skal bestemme hvordan min HTML skal se ud.

Idét jeg (og de fleste andre) ikke bruger tabeller i min HTML mere vil jeg være nødsaget til at modificere din Calender klasse for at tilpasse det til mit eksisterende design. Og som jeg allerede har nævnt en gang, så bruger du utrolig meget tid på at bestemme hvordan tingene skal se ud. Du burde spørge dig selv om din kalender skal kunne implementeres i dit design eller om dit design skal tilpasses til din kalender. Svaret burde være åbenlyst.

Din kalender er desværre også et utroligt besværligt udgangspunkt for at lære dig om OOP. Det ville her være mere relevant at udvikle klasser en kalender kunne have behov for.
Du går meget op i dine aftaler i en kalender. En klasse der kan oprette, slette og andre former for adminstrering af aftaler ville være et godt supplement til en kalender.
Det kunne måske endda være interessant at have et objekt der kan administrere fødselsdage, hvis det også skal på kalenderen. Eller hvis kalender skal have mulighed for have nogle 'ikoner' der indikerer forskellige typer begivenheder.

Nu er du allerede kommer op på tre klasser der kan bruges til din kalender. Så ville det måske være naturligt at vælge et overordnet objekt der håndterer de tre objekter og deres funktioner i relation til din kalender.

Men kalenderen skal stadig laves i HTML.

Der er pr. definition ikke noget i vejen med at blande HTML ind i klasse - spørgsmålet er hvordan det kommer til anvendelse.

F.eks. har jeg en funktion i mit database abstraktionslag (som jeg nævnte tidligere) der ser således ud:

        private function _handleError( $input )
        {
            $this->dberror = $input;
            if($this->show_errors)
                echo $this->dberror;

            return false;
        }


Anvendelsen finder sted når mit objekt støder på fejl.
F.eks:

<?php

  $db = new Mysql();
  $sql = "SELECT * table LIMIT 10";
  $db->query($sql);

?>


Ovenstående vil fejle, men lige nu gør mit objekt det lydløst.

Havde jeg derimod gjort således:

<?php

  $db = new Mysql();
  $db->showErrors();
  $sql = "SELECT * table LIMIT 10";
  $db->query($sql);

?>


ville jeg få en html linie der er skrevet således:
[i]<p><strong>MySQLi query failed:</strong> mysql fejl<br />Query: sql forespørgslen</p>[i]

Jeg har valgt dette fordi jeg oftest vil have vist fejlene i mit HTML lag, så derfor vil jeg også have det til at se pænt og letlæseligt ud når fejl endelig opstår.

Jeg tror også din HTML ser uoverskuelig ud fordi du bruger meget energi i at pakke det ind i echo()'s og skal escape alt muligt og huske linieskift og så'n noget...
Avatar billede -zonic- Nybegynder
16. september 2009 - 14:47 #12
jeg tror ikke helt jeg forstår din funktion.. hvad gør det at din handle_error starter med en _ ?

og så forstår jeg ikke helt hvad det er den gør?  og jeg kan heller ikke se hvordan din handle_error virker?
Avatar billede repox Seniormester
16. september 2009 - 15:35 #13
Det er bare en navngivning? Ingen grund til at blive forvirret over det. Den gør ingenting.
Det er bare den måde jeg navngiver private funktioner.
Jeg kunne også have valgt p istedet for _... Eller s...

Men ellers min _handleError() funktion aktiveres når jeg har lavet fejl.

Se denne kodestump:

<?php

  $db = new Mysql();
  $sql = "SELECT * table LIMIT 10";
  $result = $db->result2array();

?>

Idet jeg instancierer mit objekt kalder jeg min klasses __construct(). Den vil så kontakte nogle forskellige funktioner. Den første funktion vil forsøge at skabe forbindelse til databasen. Hvis det ikke kan lade sig gøre sender den fejlen videre til _handleError():
[div]

[div]
            $this->mysqli = new mysqli($host, $user, $pass, $database);
            if($this->mysqli->connect_errno)
                return $this->_handleError("Connection could not be established - mysqli returned: ".$this->mysqli->connect_errno);



På samme måde når jeg kører min $db->query() kontrollerer jeg om mysqli returnerer fejl på min mysql query:

        private function _select( $statement )
        {
           
           
            if(isset($this->stmt))
                $this->num_rows = $this->stmt->num_rows;
            else
            {
           
                if($this->result = $this->mysqli->query($statement))
                    $this->num_rows = $this->result->num_rows;
                else
                    return $this->_handleError("MySQL query failed: ".$this->mysqli->error." - Query: ".$statement);
            }

            return true;
        }
Avatar billede arne_v Ekspert
16. september 2009 - 15:56 #14
re 1)

DateTime er i 5.2 (men der er dog mindst 2 nye relevante metoder i 5.3).

re 3)

Et array med N objekter med M attributter er bedre end M arrays hver med N elemementer af simpel type.

re 5)

Arv skal bruges naar det giver mening. Klassen Hund kan arve fra klassen Dyr.

Composition/aggregation skal bruges naar det giver mening. Klassen garderobeskab indeholder instanser af klasen Toej.
Avatar billede -zonic- Nybegynder
16. september 2009 - 16:14 #15
det giver mere mening.. men jeg tror det der forvirrer mig er, at jeg ikke ved hvad der er dine egne funktioner og hvad der er direkte fra php...

fra dit forrige indlæg...


hvad indeholder denne :

$db->showErrors(); <- funktionen showErrors()

og så længere oppe inde i .:



  private function _handleError( $input )
        {
            $this->dberror = $input;
            if($this->show_errors) <--- show_errors ? hvor er den variabel sat?
                echo $this->dberror;

            return false;
        }


din kode i nederste eksempel bruger bare din _handleError til at udskrive hvilket giver god mening, udover hvad denne er for en: $this->mysqli->error


men jeg tror jeg har fat i meningen, går bare ud fra at det er fordi kodestumperne er taget ud af kontekst? :-)


i øvrigt mht din table kritik...

Da jeg lærte kodeskik i sin tid, tror faktisk også det var én herindefra (måske OleBole) der lærte mig det, der sagde han: brug elementer til det de er tiltænkt.. en div til design, en tabel til en tabel... jeg bruger også divs til alt hvad jeg laver i design, det kan så diskuteres om man synes en kalender er en tabel eller ej... det vil jeg jo så mene at den er :D


glemte i øvrigt
Avatar billede -zonic- Nybegynder
16. september 2009 - 16:17 #16
hmm.. glem den sidste linje :-)
Avatar billede repox Seniormester
16. september 2009 - 16:29 #17
Min showErrors():

        public function showErrors()
        {
            $this->show_errors = true;
        }


Alt hvad den gør er at sætte den private klassevariabel show_errors til true.

Min handleError():

        private function _handleError( $input )
        {
            // læg $input i en public klasevariabel
            $this->dberror = $input;
           
            // kontroller om show_errors er true
            if($this->show_errors)
                echo $this->dberror; // udskriv hvis true


            // returner false til at kontrollere på
            return false;
        }


$this->mysqli->error tilgår blot en tilgængelig variabel fra MySQLi extensionen som jeg har instancieret tidligere. Som du selv siger - taget ud sammenhæng...

Min tabelkritik er blot en personlig holdning.
For mig er tabelstrukturen til at præsentere data med.
En kalender, som du tegner op her er ikke data (i mine øjne) men 'bare' en kalender.

Hvad du mener tabeller skal bruges til er for så vidt ikke interessant for argumentationen; faktum er at jeg, fordi jeg ikke vil bruge din tabel, skal rette din klasse til uanset om du mener at en kalender er tabeldata eller ej.

Hvad du ellers bruger tabeller til er mig bedøvende ligeglad; det er jo ikke min kode du vedligeholder ;)
Avatar billede -zonic- Nybegynder
17. september 2009 - 10:37 #18
det kan der være noget om :-)


jeg siger mange tak for de gode svar og diskussion.... smid et svar :-)
Avatar billede repox Seniormester
17. september 2009 - 10:44 #19
Jeg deler gerne med arne_v - han kom med nogle gode kommentarer som ikke kunne være tråden foruden. :)
Avatar billede arne_v Ekspert
18. september 2009 - 03:44 #20
Tjo.

Men du lavede trods alt det meste af arbejdet.

Måske vil en 80-20 fordeling afspejle indsatsen og bidragene.
Avatar billede dkfire Nybegynder
18. september 2009 - 16:09 #21
repox: kunne man se hvordan du din database klasse ser ud eller er den for stor til det ?
Avatar billede arne_v Ekspert
18. september 2009 - 20:29 #22
Med hensyn til arv, saa skal du bruge "is a" og "has a" som kriterier for ja/nej.
Avatar billede repox Seniormester
18. september 2009 - 21:54 #23
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester