[PHP] meerdere objecten in een object

Pagina: 1
Acties:
  • 129 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Goedemiddag,

ik ben met iets bezig dat veel weg heeft van een factuursysteem dus ik houd dat meer even als voorbeeld aan.

Bij dat factuursysteem maak ik een onderscheid in factuurregel, subtotaalregel en totaalregel.
De factuurregels komen uit de database, de rest is afleidbaar.
Dit komt m.i. in het kort neer op onderstaande

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php

class factuurregel {
 var $prijs;
 var $aantal;
 var $regelprijs

 functiongetDataByID() {
  // data opvragen uit database
 }
 
 function berekenPrijs() {
   // prijs berekenen
 }
}

class subtotaalregel {

 var $subtotaalregelprijs;

 function berekenSubtotaal() {
  // optellen van de regelprijzen

 }

}

class totaalregel {

 var $totaalregelprijs;

 function berekenTotaal() {
  // optellen van de subtotalen

 }
}

?>


Een subtotaalregel is dus afhankelijk van 1 of meer factuurregels.
Moet ik die factuurregels zien als objecten of juist in een array stoppen binnen class subtotaalregel?
Een multidimensionale array is dan vervolgens basis voor de subtotaalregel.
Hier krijg ik wel het een en ander mee gemaakt.

Maar een object lijkt me netter en overzichtelijker maar wat ik niet kan vinden is het volgende:


PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

$totaal = new totaalregel;

$subtotaal_1 = new subtotaalregel;
$regel_1 = new factuurregel;
$regel_2 = new factuurregel;

$subtotaal_2 = new subtotaalregel;
$regel_3 = new factuurregel;
$regel_4 = new factuurregel;

?>


Hoe moet ik binnen het object Subtotaal werken met meerdere Factuurregels?
Hoe weet ik nu dat $regel_1 onderdeel is van $subtotaal_1?
En is het slim om binnen de Subtotaal alle berekende regelprijzen op te tellen, of kan ik beter bij Factuurregel een functie maken die de berekende regelprijs toevoegt aan Subtotaal?

Ik hoop dat het een beetje duidelijk is wat ik bedoel.

[ Voor 6% gewijzigd door Verwijderd op 10-07-2007 18:38 ]


Acties:
  • 0 Henk 'm!

  • Borizz
  • Registratie: Maart 2005
  • Laatst online: 24-08 20:35
Waarom voeg je niet een variabele 'subtotaal' toe aan de class factuurregel? Het is immers gewoon een eigenschap van die factuurregel, ook een functie getSubtotaal() zou niet misstaan in die class..

Dat maakt het volgens mij alweer een stuk simpeler.

De class totaalregel, zou ik hernoemen naar Factuur, en die bevat dan een aantal factuurregels (bijv een array van factuurregel objecten).

If I can't fix it, it ain't broken.


Acties:
  • 0 Henk 'm!

  • Depress
  • Registratie: Mei 2005
  • Laatst online: 18-09 22:29
Je moet gebruik maken van lijst(arrays in het geval van php) Dan kun je deze doorlopen en dan gegevens opvragen uit het item. En dan beheer je in orderregel weer de subtotaal regels op de zelfde manier.

bijvoorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var $Lijst = array();
function laad()
{
    //database trasacties
    this->lijst[] = new orderregel('gegevens');
}

function bekijk()
{
    foreach($this->lijst as $orderregel)
    {
        echo $orderregel->info();
    }
}


Dan heb je toegang tot alles of begrijp ik je nu fout?

[ Voor 7% gewijzigd door Depress op 10-07-2007 19:59 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ik ben zelf ook bezig geweest met een facturatiesysteem. Ik heb hiervoor een combinatie gebruikt van OO/PHP, MySQL .

Ik twijfel aan de actie of je een totaal- en een subtotaalregel zou willen opslaan. Gezien je zelf al zegt dat deze af te leiden zijn vind ik dat een factuur dat zelf moet uitrekenen en het geen 'order' is zoals een product dat op een factuur komt te staan.

Wat je zou kunnen doen is een klasse Factuur, deze klasse factuur heeft een array met factuurregelobjecten. Deze factuurregels zijn instanties van de klasse Factuurregel. (Mocht je toch onderscheidt willen maken tussen verschillende regels dan maak je een abstracte klasse Factuurregel en dan leidt je enkele children daarvan af zoals TotaalFactuurregel, SubTotaalFactuurregel, enzovoort. Geef deze een eigen constructor of een default method die wordt aangeroepen en je kunt ze hun eigen gedrag geven zonder dat je voor elke regel specifiek iets hoeft te implementeren).

Je hebt genoeg aan een methode als private Factuur->update() die je aanroept om de factuur zichzelf te laten onderzoeken. Ik zou een private variabele voor totaal, btwpercentage en dergelijk maken. De update() functie rekent aan de hand van de factuurregels die er op dit moment in zijn instantie uit wat het totaal is en het btw bedrag en dergelijk.

Je kunt daarnaast ook een functie maken als save(). Deze functie roept allereerst update() aan en vervolgens bijvoorbeeld enkele functies om het in de database op te slaan. Wellicht zelf met een boolean parameter aangeven of je een export naar PDF wilt ( is gaaf ).

Conclusie, teken het eerst eens goed voor jezelf uit. Maak een klassendiagram, verdeel verantwoordelijkheden, stel ook eens een domeinmodel op, enzovoort. Aan de hand daarvan kun je al een specifieke implementatie verzinnen voor bijvoorbeeld PHP.

Acties:
  • 0 Henk 'm!

Verwijderd

ik denk dat je meer hetvolgende zoekt ipv wat je nu in gedachte heb

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Factuur{

   public $orderlines = array();

   public function addOrderLine(Orderline &$orderline){   // sowieso al referentie naar $this van Orderline instantie
      $this->orderlines[] = $orderline;
   }

   public function getSubtotal(){
      for($num = 0, $subtotal = 0; $num < count($this->orderlines); $num++)  // loop alle instanties af en vraag prijs op
         $subtotal += $this-> orderlines[$num]-> getPrice();

      return $subtotal;
   }
   
}
class Orderline{
    function getPrice(){
      return rand(); // etc
   }
}


$factuur = new Factuur();

$orderline = new Orderline();
$orderline->doSomething();
$factuur->addOrderLine($orderline);


$factuur->addOrderLine(new Orderline());

// en dan het subtotal:

echo $factuur->getSubtotal();


Het idee is dat het factuur object meerdere orderline objecten bevat.
Er zijn hier ook verschillende design patterns over, alleen daar ben ik helaas niet zo mee bekend.

Edit: precies zoals Michealtje15 wat eerder zei.

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
De eerder door krozz56 voorgestelde klasse Factuur zou ik hernoemen naar Factuurblok, zodat je de klasse Factuur kunt gebruiken om factuurblokken in te zetten en het totaal te berekenen. Je hebt anders geen mogelijkheid meerdere subtotalen te hebben, en dat is wel een eis als ik de TS lees (m.n. de functie berekenTotaal).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ok, thanks tot dusver!

Over naamgeving valt te twisten en ik neem als voorbeeld de benaming, factuurregel, factuurblok en factuur maar even over.
Het voorbeeld van krozz56 helpt me al een heel eind.
De aanvulling van Glowmouse is echter correct, en daar zit nou net het stukje wat mij nog niet helemaal helder is.
Ik wil de factuur inderdaad in 'blokken' opdelen zodat je zoiets krijgt als onderstaand:

4 appel1 euro4 euro
2 kiwi1 euro2 euro
subtotaal groen fruit 6 euro
2 sinsaasappel1 euro2 euro
4 mandarijn1 euro4 euro
subtotaal oranje fruit1 euro6 euro
totaal 12 euro


Naar voorbeeld van krozz56:
1) maak ik een factuur aan,
2) vervolgens maak ik een factuurblok aan
3) ik voeg diverse factuurregels toe aan factuurblok
4) herhaling van 2 en 3

Dus een factuur bestaat uit een array van factuurblokken en deze bestaat weer uit een array van factuurregels.

Maar hoe weet ik nu dat een factuurregel aan factuurblok 1 hangt, en niet aan factuurblok 2?

zoiets?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

$factuur = new Factuur();

$factuurblok1 = new Factuurblok();

$orderline1 = new Orderline();
$orderline1->doSomething();

$orderline2 = new Orderline();
$orderline2->doSomething();

$factuurblok1->addOrderLine($orderline1);
$factuurblok1->addOrderLine($orderline2);

$factuur->addFactuurblok($factuurblok1);


$factuurblok2 = new Factuurblok();

$orderline3 = new Orderline();
$orderline3->doSomething();

$orderline4 = new Orderline();
$orderline4->doSomething();

$factuurblok2->addOrderLine($orderline3);
$factuurblok2->addOrderLine($orderline4);

$factuur->addFactuurblok($factuurblok2);

$factuur->addOrderLine(new Orderline()); 

?>


Ik heb het gevoel dat bovenstaande niet helemaal ok is.

Ik hoop dat het wat duidelijker is.

Acties:
  • 0 Henk 'm!

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
Als je wilt dat een factuurregel weet bij welk factuurblok hij hoort dan moet je een variabele toevoegen in de class van je factuurregel. Bijvoorbeeld:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Orderline {
   private Faktuurblok factuurblok;
   /* en natuurlijk nog veel meer variabelen */

   /* Constructor */
   public function __construct(Factuurblok fb){
      $this->factuurblok =& fb;
   }

   public function getFactuurblok(){
      return $this->factuurblok;
   }
}
// etc...


ohja, je krijgt dan natuurlijk in de code waar je een factuurregel aanmaakt:
PHP:
1
$orderline = new Orderline($factuurblok);


Wat je ook nog kunt doen:
PHP:
1
2
3
4
5
// Ondertussen in je class Factuurblok...
public function addOrderline(Orderline ol){
   $this->orderlines[count($this->orderlines)] =& ol;
   ol->setFactuurblok($this);
}


@Janoz:
Je hebt gelijk, het is inderdaad een beetje vreemd om het op deze manier te doen (de bovenste). :S

[ Voor 34% gewijzigd door coenbijlsma op 11-07-2007 10:31 ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Wat zou er mis moeten zijn met bovenstaande? Het is een beetje afhankelijk van hoe je de add___() functies hebt geimplementeerd, maar in principe is lijkt me dit gewoon netjes. Het lijkt wat raar dat je alles becijfert hebt, maar je kunt je variabelen ook gewoon 'hergebruiken'.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$factuur = new Factuur();

$factuurblok = new Factuurblok();

$orderline = new Orderline();
$orderline->doSomething();
$factuurblok->addOrderLine($orderline);

$orderline = new Orderline();
$orderline->doSomething();
$factuurblok->addOrderLine($orderline);

$factuur->addFactuurblok($factuurblok);

$factuurblok = new Factuurblok();

$orderline = new Orderline();
$orderline->doSomething();
$factuurblok->addOrderLine($orderline);

$orderline = new Orderline();
$orderline->doSomething();
$factuurblok->addOrderLine($orderline);

$factuur->addFactuurblok($factuurblok);


$factuur->addOrderLine(new Orderline());  //?? 


Dit doet exact hetzelfde als je eerste code.

Ik ben trouwens erg benieuwd waar die laatste regel voor is? Wil je ook nog regels toe gaan voegen die niet binnen een blok vallen?


@Coen: Dat hoeft helemaal niet. Sterker nog, ik zou het bij voorkeur niet op jouw manier oplossen. Een factuur regel hoort in een factuur blok. Dat geldt in 'de echte wereld', waarom zou je dat dan ook niet gewoon in je programma laten gelden? Ik zie geen enkele reden om dat dan mar andersom te definieren.

[ Voor 12% gewijzigd door Janoz op 11-07-2007 10:27 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

Verwijderd

volgens mij heeft een 'factuurregel', of beter gezegd een 'product', een eenheidsprijs. Een 'factuurregel' bestaat bestaat dan dus uit een x aantal producten. Dus volgens mij dien je geen 'factuurregels' toe te voegen maar 'producten' (met een optionele eenheid). Intern in je factuur zoek je de juiste 'factuurregel' op en speel je met de eenheden.

Acties:
  • 0 Henk 'm!

  • ikke007
  • Registratie: Juni 2001
  • Laatst online: 18-09 14:10
coenbijlsma schreef op woensdag 11 juli 2007 @ 10:25:
PHP:
1
2
3
4
5
// Ondertussen in je class Factuurblok...
public function addOrderline(Orderline ol){
   $this->orderlines[count($this->orderlines)] =& ol;
   ol->setFactuurblok($this);
}
Ik zou er toch gewoon voor kiezen om niet iedere keer een count() te doen, is totaal overbodig in php.
PHP:
1
  $this->orderlines[] = $ol;

Lets remove all security labels and let the problem of stupidity solve itself


Acties:
  • 0 Henk 'm!

  • coenbijlsma
  • Registratie: Augustus 2004
  • Niet online
echt?? Dat wist ik dus niet; weer wat geleerd ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Is dit iets? Ik kan de klasse ook eventueel posten, ben er beetje mee aan het experimenteren zodat ik dit zelf ook beter onder de knie krijg..
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    $factuur = new Factuur();
    {
        $factuurblok = new Factuurblok();
        {
            $orderline  = new Orderline();
            $product    = new Product();
            $product    ->price = 1;
            $orderline  ->setProduct($product);
            $orderline  ->aantal = 2;
            $factuurblok->addOrderLine($orderline);
        }
        $factuur->addFactuurblok($factuurblok);
    }
    
    foreach($factuur->factuurblokken as $factuurblok){
        foreach($factuurblok->orderlines as $orderline)
            echo "orderline subtotal: ".$orderline->getSubtotal()."<br>";
        echo "factuurblok subtotaal: ".$factuurblok->getSubtotal()." <br>";
    }
    echo "Factuur Totaal: ".$factuur->getTotal()."<br>";
Pagina: 1