classe met functie
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
Code (php)
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
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.
Als de uitkomst afhankelijk is van meerdere query's, kun je het resultaat ook opslaan in de database. Zo'n 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.
Code (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
39
40
41
42
43
44
45
46
47
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
}
?>
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
Bedankt. Hier moet ik wel mee verder kunnen.
- 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.
ook hier blijf ik beperkt met wat provider levert en toestaat :(
https://fromdual.com/mysql-materialized-views
https://stackoverflow.com/questions/40733970/materialized-view-in-mysql