classe met functie

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Jan R

Jan R

16/04/2022 08:21:14
Quote Anchor link
Hoi

Ik heb een classe welke een nogal langdurige functie inzit. Meerdere query's en berekeningen. Ik heb het resultaat echter nodig in meerdere functies. Wat lijkt jullie de beste methode om niet steeds de totale berekening te maken.

  • Een static resultaat. if isSet dan stuur dat resultaat anders rekenenen maar
  • Een gewone global variable
  • Resultaat opslaan in session.
  • ...

Ik wil wel niet laten rekenen voordat resultaat nodig is.

Jan
Gewijzigd op 16/04/2022 08:26:36 door Jan R
 
PHP hulp

PHP hulp

29/11/2022 02:41:33
 
Rob Doemaarwat

Rob Doemaarwat

16/04/2022 09:15:16
Quote Anchor link
Daar hebben ze nou getters voor uitgevonden:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

class Foo{

  protected $_moeilijkeBerekening = null;

  public function getMoeilijkeBerekening(){
    if($this->_moeilijkeBerekening === null){
      $this->_moeilijkeBerekening = 1 + 1; //de "moeilijke berekening"
    }

    return $this->_moeilijkeBerekening;
  }

}


?>

De eerste keer dat je ->getMoeilijkeBerekening() aanroept doet ie de "moeilijke berekening", daarna pakt ie gewoon de opgeslagen waarde (deze "caching" beperkt zich dan natuurlijk wel tot de huidige call).

(merk op dat het resultaat van je "moeilijke berekening" niet null "mag" zijn, omdat je anders alsnog elke keer de "moeilijke berekening" gaat doen).

Zelf gebruik ik zoiets: https://www.yiiframework.com/doc/guide/2.0/en/concept-properties , dan hoef je op voorhand niet overal een getter+setter van te maken (omdat dat "later" misschien handig zou zijn = omdat je anders door de hele code heen ->waarde moet vervangen door ->getWaarde() ). En het scheelt je ook weer het typen van get...() en set...() .
Gewijzigd op 16/04/2022 09:16:51 door Rob Doemaarwat
 
Ward van der Put
Moderator

Ward van der Put

16/04/2022 10:16:50
Quote Anchor link
Als de uitkomst afhankelijk is van meerdere query's, kun je het resultaat ook opslaan in de database. Zo'n computed pattern heeft onder andere als voordeel dat je de uitkomst alleen hoeft aan te passen wanneer de onderliggende databasegegevens veranderen.

Daarmee beperk je het aantal herberekeningen tot de situaties waarin je zeker weet dat een herberekening nodig is: het systeem wordt niet meer gestuurd door de gevraagde output maar door de input van data. Bijkomend voordeel is dat je dit automatisch kunt doen met een databasetrigger zodat clients geen last hebben van een vertraging.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/04/2022 11:15:19
Quote Anchor link
En een verdeling over meerdere classes kan ook. Zo zie je vaak dat de queries in een class zitten en de berekeningen waarbij de uitkomst nodig is van de queries in een andere class. Voorbeeldje:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
39
40
41
42
43
44
45
46
47
<?php

class MoelijkeBerekening
{
    protected $repository;
    
    public function __construct(FooRepository $repository) {
        $this->repository = $repository;
    }

    
    public function calculateSomething() {
        $total = 0;
        
        $result1 = $this->repository->getSomeData();
        $result2 = $this->repository->getOtherData(2);
        
        // ....
        
        foreach($result1 as $result) {
            $total += $this->hulpfunctie($result);
        }

        
        return $total;
    }


    private function hulpfunctie($result) {
        
        // doe iets
        
        return $something;
    }
}


class FooRepository extends BaseRepository
{
    public function getSomeData() {
        return $this->db->get('SELECT a, b, c FROM table1 WHERE ....');
    }

    
    public function getOtherData(int $id) {
        return $this->db->get('SELECT d, e, f FROM table2 WHERE id=?');
    }

    
    // en nog meer functies
}

?>
Gewijzigd op 16/04/2022 11:17:06 door Frank Nietbelangrijk
 
Jan R

Jan R

16/04/2022 11:35:33
Quote Anchor link
Bedankt. Hier moet ik wel mee verder kunnen.
 
Ad Fundum

Ad Fundum

17/04/2022 01:07:39
Quote Anchor link
Wat ik zou aanraden:
- doe de berekeningen met SQL in de database, dan heb je het minste last van I/O
- sla de berekeningen op in de database met een materialized view, daarna gaat het supersnel.

Het probleem van PHP is dat elk script opnieuw wordt uitgevoerd door php-fpm, en dat al je variabelen (globaal en in classes) leeg zijn bij het starten van elk script. Je kunt het oplossen met sessies maar dan moet PHP steeds al je data serialiseren en deserialiseren, en het kost ook meer opslagruimte op een tijdelijke plek (meestal ergens op het bestandssysteem) waar je dan ook weer extra rekening mee moet houden in verband met veiligheid. En alles hangt weer af van je php.ini en hoe je sessies gebruikt in PHP.

Klein maar niet onbelangrijk detail: MySQL en MariaDB zijn vrij beperkte database engines, en ondersteunen geen materialized views. Tenzij je zwemt in tijd zou ik dan een betere database gebruiken of toch kiezen voor opslaan in sessies.
Gewijzigd op 17/04/2022 01:13:33 door Ad Fundum
 
Jan R

Jan R

17/04/2022 07:43:37
Quote Anchor link
ook hier blijf ik beperkt met wat provider levert en toestaat :(
 
Ad Fundum

Ad Fundum

17/04/2022 20:13:33
Quote Anchor link
Als je iets wilt gebruiken wat lijkt op een materialized view, kan je ook daarvoor zelf een tabel aanmaken in MySQL. Maar het kost je wel weer extra tijd om het te maken:
https://fromdual.com/mysql-materialized-views
https://stackoverflow.com/questions/40733970/materialized-view-in-mysql
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.