Gebruikt $this van parent class mogelijk?
Ik ben opzoek naar de manier om het volgende op de best-pratize aan te pakken.
Ik heb een class waar een $this in bestaat. Vanuit deze class maak ik een nieuwe instance aan van een andere class. Binnen deze tweede class wil ik gebruik maken van de $this van de eerste class.
De manier waarop ik het nu doe is als volgt:
```
Class Eerste {
public function een_funtie() {
$tweedeClass = new Tweede();
$resultaat = $tweedeClass->nog_een_functie(this);
}
}
Class Tweede {
public function nog_een_functie($eersteClass) {
$doeIets = $eersteClass;
}
}
```
Is het mogelijk dit op een andere manier te doen? De tweede class wordt namelijk ook gebruikt door andere stukken code, dus ik zou $this niet graag het als een argument willen meegeven. Uiteraard zou ik de tweede class kunnen extenden, maar dat wil ik niet omdat de eerste class eigenlijk een Trait is van een vendor module.
Ik kijk uit naar jullie reacties.
Bvd, mvg,
Bastiaan
Gewijzigd op 21/01/2020 10:25:20 door Bastiaan Haastrecht
Wat je beschrijft heet "Dependency injection", je 2e class heeft een afhankelijkheid van je eerste class.
Dit kun je op meerdere manieren oplossen, jouw oplossing is daar 1 van maar wat ik persoonlijk netter vind is het volgende:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
Class Eerste {
public funcion een_functie() {
$tweedeClass = new Tweede($this);
$resultaat = $tweedeClass->nog_een_functie();
}
}
Class Tweede {
protected $eersteClass;
public function __construct(Eerste $eerste) {
$this->eersteClass = $eerste;
}
public function nog_een_functie() {
$doelets = $this->eersteClass;
}
}
?>
Class Eerste {
public funcion een_functie() {
$tweedeClass = new Tweede($this);
$resultaat = $tweedeClass->nog_een_functie();
}
}
Class Tweede {
protected $eersteClass;
public function __construct(Eerste $eerste) {
$this->eersteClass = $eerste;
}
public function nog_een_functie() {
$doelets = $this->eersteClass;
}
}
?>
Let wel op dat je dit niet te ver door trekt, dependencies die "gestapeld" zijn worden snel onoverzichtelijk.
Daarnaast moet je uitkijken voor Circular dependencies, anders raakt je code in een oneindige lus.
Zoek eens op Dependency injection (DI), het factory pattern en service managers/containers. Er zijn tal van mooie oplossingen voor.
Gewijzigd op 21/01/2020 10:36:24 door Thom nvt
Dank je wel, hier kan ik mee verder!
Quote:
dus ik zou $this niet graag het als een argument willen meegeven.
Waarom niet? Dat is namelijk precies wat je doet? Of bedoel je: deze wil ik niet elke keer opnieuw als argument meegeven? Dan doe je dat eenmalig bij de constructie en onthoud je de referentie zoals hierboven staat beschreven. Dit is ook vrij normaal: door de scope kent de class Tweede de class Eerste niet tenzij je hem daar op een of andere manier op attent maakt.
Quote:
De tweede class wordt namelijk ook gebruikt door andere stukken code
Classes worden gebruikt door middel van hun instanties (objecten van de class) (als je static methoden even buiten beschouwing laat). Op dit moment maak je een object van Tweede aan binnen de Eerste class, en daarmee is dit object alleen bekend binnen de scope van (een object van) de class Eerste. Zou het dan niet logischer zijn om dit om te draaien en een object van Eerste aan te maken binnen een (globaler beschikbaar) object van Tweede? Want anders zou je opnieuw deze instanties moeten doorgeven aan andere code/objecten/classes. Als het de Tweede class is die je elders wilt hergebruiken - nu zit het object verpakt in een ander object (van class Eerste). Of je creëert deze objecten los van elkaar, en je combineert ze op een later tijdstip. Meerdere opties mogelijk.
Het hangt natuurlijk van de rest van de code af en de interacties tussen de objecten hoe je dit structureert, dus het is moeilijk om op voorhand precies te zeggen hoe je dit aanpakt.
Het bovenstaande voorbeeld is nogal abstract. Heb je een concrete case?
Ik waardeer jullie input, ik ben geen opgeleide programmeur maar kan mijn weg inmiddels in php (en overige talen) goed vinden, wat ik alleen niet heb is gefundeerde achtergrond over hoe je bepaalde cases moet aanpakken. Nooit te oud om wat te leren.
Gewijzigd op 21/01/2020 20:38:11 door Bastiaan Haastrecht
Zo te lezen wil een aanpassing doen aan een bestaande class uit een composer package zodat je functionaliteit kan toevoegen.
Aanpassingen aan code die niet van jou is moet je niet doen, dan kun je later die package niet meer updaten.
In plaats daarvan zou je de class moeten extenden en de method die de regels wegschrijft moeten overschrijven met jouw eigen code. Vervolgens gebruik je alleen jouw eigen instantie van die class zodat de gewenste functionaliteit gebruikt kan worden en voor de rest het "origineel" gebruikt word.
Op die manier volg pas je niets aan in de externe code en heb je toch de functionaliteit die je wil.
Als ik het verkeerd begrijp heb ik nog wat meer uitleg nodig of wellicht een representatief code voorbeeld (Heb je het op GitHub/Bitbucket/GitLab staan bijv?)
In laravel maak ik een job aan, daar voeg ik de betreffende composer package als een Trait in toe. Vervolgens in deze job, waar dus alle methods van die Trait nu onder $this beschikbaar zijn voeg ik in de job een method addInput() toe.
Ik kan niet de volledige app delen, maar heb een gist aangemaakt om je het concept te laten zien.
https://gist.github.com/BasvanH/540d92555877345f905ac527ba3f6114
Wat ik persoonlijk mooier zou vinden is dat ik in de TestClass een Trait zou includen die de jobstatus van output zou kunnen voorzien. Alleen moet ik dan wel het jobid binnen die Trait hebben anders kan ik niet de regel in de db vinden.
Toevoeging op 23/01/2020 08:40:34:
Ik heb het mooier opgelost. Ik heb een eigen trait gemaakt die bovenop de Laravel Log Facade ligt (onderwater Monolog). Ik vang daarmee de Log::errors berichten af, stop ze in een global static variable die ik vervolgens vanuit de job kan uitlezen. Zo hoef ik niets te bruggen. In mijn trait forward ik alle overige Log calls af via __callStatic Magic Method.
Toch bedankt voor het meedenken.
Pas wel op met global static variabelen, dat is niet echt de OOP manier.