cUrl gebruiken vanuit child class
Ik heb een parent class die doormiddel van een private methode een andere child class aanmaakt. De child class extends de parent class.
Vervolgens voer ik in de child class een methode uit die gedefineerd wordt in de parent class. In die methode wordt een property gebruikt uit de parent class die in de __construct van de parent class wordt ingesteld op: $this->ch = curl_init();
Eerder genoemde methode (gedefineerd in de parent class) gebruikt $this->ch voor het uitvoeren van een aantal curl_exec's. Wanneer ik de methode echter probeer uit te voeren krijg ik de foutmelding dat $this->ch = NULL en dus !niet een resource voor curl is. Dit blijkt ook wanneer ik in de child class var_dump($this->ch); uitvoer.
Hoe kan ik de methode uit de parent class toch gewoon gebruiken in de child class?
parent::__construct uitvoeren in de child class is geen optie. Via een andere methode die in de __construct van de parent class wordt aangeroepen wordt namelijk de child class geladen. Oftewel, de child class wordt dan een tweede keer geïnitialiseerd en die ïnitialiseerd de child class weer enz., enz.
De $this->ch in de child class pas instellen op $this->ch = curl kan ook niet omdat in de parent class $this->ch al nodig is en $this->ch in de child class met deze curl_session moet draaien.
Hieronder nog even een (vereenvoudigde) weergave ter verduidelijking:
parent.class.php
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
classParent{
protected$ch;
function__construct(){
$this->ch=curl_init();
loadClass();
}
privatefunctionloadClass(){
include('apps/'.$_GET['app'].'/lib/class.php');
returnnew$_GET['app'];
}
publicfunctioncurlGet($url){
curl_setop($this->ch,CURLOPT_URL,$url);// error child.class.php verwijs naar deze lijn
curl_setop($this->ch,CURLOPT_RETURNTRANSFER,true);// error child.class.php verwijs naar deze lijn
return(curl_exec($this->ch));
}
}
?>
classParent{
protected$ch;
function__construct(){
$this->ch=curl_init();
loadClass();
}
privatefunctionloadClass(){
include('apps/'.$_GET['app'].'/lib/class.php');
returnnew$_GET['app'];
}
publicfunctioncurlGet($url){
curl_setop($this->ch,CURLOPT_URL,$url);// error child.class.php verwijs naar deze lijn
curl_setop($this->ch,CURLOPT_RETURNTRANSFER,true);// error child.class.php verwijs naar deze lijn
return(curl_exec($this->ch));
}
}
?>
child.class.php
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
classChildextendsParent{
function__construct(){
curlGet($url);// error: PHP Warning: curl_setopt() expects parameter 1 to be resource, null given in Parent.class.php on line 16 & 17
}
}
?>
classChildextendsParent{
function__construct(){
curlGet($url);// error: PHP Warning: curl_setopt() expects parameter 1 to be resource, null given in Parent.class.php on line 16 & 17
}
}
?>
Ik hoop dat iemand me met bovenstaande vraag kan helpen.
Alvast bedankt voor jullie hulp en tijd,
Wilfred Dijksman
Gewijzigd op 30/01/2013 22:31:07 door Wilfred Dijksman
Maar een mogelijke oplossing van je probleem.
Laat de construct niet direct die curl property aanmaken, maar een getter ervoor. Check in die getter of de variabele al is geinitialiseerd of niet en maak aan indien nodig:
Code (php)
(een reden temeer om al je properties private te hebben en altijd op vragen via een getter)
Gewijzigd op 30/01/2013 22:48:46 door Erwin H
Ik moet inderdaad toegeven dat mijn code hoogst waarschijnlijk niet 'helemaal' optimaal is ;) (hobby/beginner (qua OOP)). De situatie zoals jij deze beschrijft (parent die een child maakt van zichzelf) doet zich gelukkig niet voor. De parent class heeft een methode die wordt aangeroepen via de __construct en die een nieuwe child class aanmaakt.
Over je mogelijke oplossing:
Probleem wordt dan dat er meerdere cUrl sessies komen omdat $this->ch dan twee keer wordt ingesteld op curl_init(); Voor de werking van het systeem is één dezelfde sessie in cUrl vereist (cUrl logt in de parent class in op een systeem en haalt in de child class data op uit datzelfde systeem. Dit moet in dezelfde cUrl sessie gebeuren omdat anders de login die cUrl heeft gedaan in de parent class verlopen is.).
Is het trouwens raar dat de property $this->ch; niet wordt mee genomen naar een child class (die ge-extends is)? Want als dat zo is moet de indeling veranderen en moet ik/we niet allemaal functies erbij gaan halen.
Overigens had ik over getters wel eens eerder gelezen. Ga ik in het vervolg op proberen te letten!
In ieder geval bedankt voor je hulp tot zover. Met de getters is mijn code er in ieder geval weer iets beter op geworden ;) Mocht je nog een idee hebben dan hoor ik het graag.
Met vriendelijke groet,
Wilfred Dijksman
Gewijzigd op 31/01/2013 07:21:48 door Koen Vlaswinkel
Quote:
Je moet wel bedenken dat een constructor van de parent niet automatisch wordt aangeroepen. Daarvoor gebruik je parent::__construct(); in de constructor van de child class.
Oh? Waar haal je dat vandaan?
Alleen als je zelf een constructor maakt in de child class, dus in dit geval wel. Hier override je de constructor, dus moet je de parent constructor wel callen in dit geval.
Wilfred Dijksman op 30/01/2013 22:30:30:
Hoe kan ik de methode uit de parent class toch gewoon gebruiken in de child class?
parent::__construct uitvoeren in de child class is geen optie. Via een andere methode die in de __construct van de parent class wordt aangeroepen wordt namelijk de child class geladen. Oftewel, de child class wordt dan een tweede keer geïnitialiseerd en die ïnitialiseerd de child class weer enz., enz.
parent::__construct uitvoeren in de child class is geen optie. Via een andere methode die in de __construct van de parent class wordt aangeroepen wordt namelijk de child class geladen. Oftewel, de child class wordt dan een tweede keer geïnitialiseerd en die ïnitialiseerd de child class weer enz., enz.
Zoals ik in me eerste post al schreef is het aanroepen van parent::__construct helaas geen oplossing.
In ieder geval bedankt voor het mee denken! Wel raar trouwens dat je de __construct overwrite als je child class ook een construct heeft. Het komt er in de praktijk dus op neer dat extends alleen maar de methodes en properties meeneem, maar niet de waarde van de properties die ze tijdens het initialiseren van de parent class al hebben gekregen. Laat dat nou net zijn wat ik wel nodig heb :(
Iemand nog een idee?
Met vriendelijke groet,
Wilfred Dijksman
Gewijzigd op 31/01/2013 10:30:19 door Wilfred Dijksman
En er is niks vreemds aan, als je een method override wordt de oude method niet meer gebruikt.
parent::__construct uitvoeren in de child class is geen optie. Via een andere methode die in de __construct van de parent class wordt aangeroepen wordt namelijk de child class geladen. Oftewel, de child class wordt dan een tweede keer geïnitialiseerd en die ïnitialiseerd de child class weer enz., enz. Zie ook mijn citaat in mijn vorige reactie en het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
class Child extends Parent{
function __construct(){
parent::__construct
}
}
?>
class Child extends Parent{
function __construct(){
parent::__construct
}
}
?>
Sanenvattend: als ik parent::__construct gebruik komt het script in een soort van loop waarin hij telkens classes gaat aanmaken. Dit eindigt in een error: Cannot redeclare class Child.
De rede dat de parent een child aanmaakt is omdat afhankelijk van de app die geladen moet worden (via $_GET['app']) er een andere class geladen en geïnitialiseerd moet worden.
Ik hoop dat het verhaal zo een beetje duidelijk is. Vragen en/of mogelijk oplossingen hoor ik graag.
Met vriendelijke groet,
Wilfred Dijksman
Gewijzigd op 31/01/2013 11:55:31 door Wilfred Dijksman
Moet het dan perse een extension zijn?
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Toevoeging op 31/01/2013 15:12:03:
Ja, het is een systeem wat meerdere modules/apps heeft die wel dezelfde basis functies nodig hebben. Die basis functies zitten in de parent class.
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Toevoeging op 31/01/2013 15:12:16:
Ja, het is een systeem wat meerdere modules/apps heeft die wel dezelfde basis functies nodig hebben. Die basis functies zitten in de parent class.
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Toevoeging op 31/01/2013 15:12:44:
Ja, het is een systeem wat meerdere modules/apps heeft die wel dezelfde basis functies nodig hebben. Die basis functies zitten in de parent class.
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Ik vrees dat ik weeral zal moeten spreken vanuit mijn C achtergrond.
Ik vind dat elke class best een constructor kan hebben.
Ik vind dat elke extend best een eigen constructor kan hebben.
Normaal zou ik daar nooit over zagen/klagen, maar in dit topic is het relevant.
Jij zou in je parent class een methode init() kunnen schrijven; waar je regelt wat echt moet geregeld worden. $this->init() wordt uitgevoerd in de constructor.
Dan kan je in de child die init aanspreken; laat je de constructor van de parent met rust. Geen verwarring, geen conflict, geen probleem meer.
Gewijzigd op 31/01/2013 15:15:35 door Kris Peeters
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Toevoeging op 31/01/2013 15:15:22:
Ja, het is een systeem wat meerdere modules/apps heeft die wel dezelfde basis functies nodig hebben. Die basis functies zitten in de parent class.
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Toevoeging op 31/01/2013 15:18:28:
Mijn excuses. Ik probeer een bericht te bewerken maar dat gaat even niet helemaal lekker. Mss dat een mod het voor elkaar krijg mijn berichten in te perken tot het laatst geposte bericht?
Toevoeging op 31/01/2013 15:21:26:
@Kirs Peeters, thnsx voor je snelle reactie. Een soortgelijke mogelijkheid zoals jij deze aandraagt is eerder al aangedragen. Probleem is dan dat de curl_session in de parent class een andere is dan in de child class. Dit moeten dezelfde zijn omdat de child class anders geen data kan ophalen (in de parent class wordt ingelogd, die sessie heeft child class nodig).
Mocht je nog vragen/opmerkingen/ideeën hebben, dan hoor ik het graag.
Met vriendelijke groet,
Wilfred Dijksman
Het lijkt me niet wenselijk dat een extend members van zijn parent aanmaakt.
m.a.w. misschien is het beter dat je iets anders gebruikt dan een extend.
Tim Slootweg op 31/01/2013 14:55:43:
Moet het dan perse een extension zijn?
Wilfred Dijksman op 31/01/2013 15:10:08:
Ja, het is een systeem wat meerdere modules/apps heeft die wel dezelfde basis functies nodig hebben. Die basis functies zitten in de parent class.
Dit lijkt me geen goed OOP argument.
Dit is niet de reden waarom men een extend maakt.
Niets houdt je tegen om methodes uit een andere class aan te spreken.
- Je kan die functies statisch maken.
- Je kan een member van de hoofd-class meegeven aan de "child"; dan heb je ook diens methodes ook ter beschikking.
Gewijzigd op 31/01/2013 16:04:40 door Kris Peeters
Je kan natuurlijk wel gewoon een instantie aanmaken van een nader klasse met setters en getters is alles dan ook te verplaatsen.
Wilfred Dijksman op 31/01/2013 00:33:35:
Over je mogelijke oplossing:
Probleem wordt dan dat er meerdere cUrl sessies komen omdat $this->ch dan twee keer wordt ingesteld op curl_init(); Voor de werking van het systeem is één dezelfde sessie in cUrl vereist (cUrl logt in de parent class in op een systeem en haalt in de child class data op uit datzelfde systeem. Dit moet in dezelfde cUrl sessie gebeuren omdat anders de login die cUrl heeft gedaan in de parent class verlopen is.).
Probleem wordt dan dat er meerdere cUrl sessies komen omdat $this->ch dan twee keer wordt ingesteld op curl_init(); Voor de werking van het systeem is één dezelfde sessie in cUrl vereist (cUrl logt in de parent class in op een systeem en haalt in de child class data op uit datzelfde systeem. Dit moet in dezelfde cUrl sessie gebeuren omdat anders de login die cUrl heeft gedaan in de parent class verlopen is.).
Maar dat is dus juist niet waar in de code die ik je gaf. Alleen de allereerste keer dat getCh() wordt aangeroepen (hetzij door de parent, hetzij door de child) wordt $this->ch geinitialiseerd met curl_init(), daarna wordt elke keer de al geinitialiseerde sessie gebruikt. Dat was nu juist de grap van het voorbeeld dat ik je gaf.
@Erwin H: Ik begrijp je idee. Ik heb het geprobeerd. Maar in de praktijk wordt $this->ch twee keer geïnitialiseerd. Een class die extend neemt de properties en methoden mee maar niet de waarde van die properties die eerder zijn ingesteld (zo lijkt het in ieder geval).
Als je maar één externe cURL-verbinding gebruikt die moet worden gedeeld door alle apps en sessies, is dat in wezen een singleton omdat je maar één instantie van het object gebruikt. Ondersteunt de externe server die de cURL-respons afhandelt bijvoorbeeld maximaal twee gelijktijdige verbindingen, dan kun je daarop een variant maken.
Wilfred Dijksman op 31/01/2013 22:00:47:
Een class die extend neemt de properties en methoden mee maar niet de waarde van die properties die eerder zijn ingesteld (zo lijkt het in ieder geval).
Dat is klinklare onzin. Een class die een andere class extend neemt de properties over inclusief alle waardes. Wat heb je anders aan private en protected properties?
Voorbeeld:
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
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
<?php
class Parent2{
private $test;
protected function getTest(){
if ( $this->test == null ){
echo 'init<br>';
$this->test = 'een waarde<br>';
}
return $this->test;
}
public function __construct(){
echo $this->getTest();
}
}
class Child2 extends Parent2{
public function geefTest(){
echo $this->getTest();
}
}
$obj = new Child2();
$obj->geefTest();
?>
class Parent2{
private $test;
protected function getTest(){
if ( $this->test == null ){
echo 'init<br>';
$this->test = 'een waarde<br>';
}
return $this->test;
}
public function __construct(){
echo $this->getTest();
}
}
class Child2 extends Parent2{
public function geefTest(){
echo $this->getTest();
}
}
$obj = new Child2();
$obj->geefTest();
?>
Dit geeft als uitkomst:
Niet twee keer init dus, het private property wordt maar 1 keer geinitialiseerd.
Maar....
Wilfred Dijksman op 31/01/2013 22:00:47:
@Erwin H: Ik begrijp je idee. Ik heb het geprobeerd. Maar in de praktijk wordt $this->ch twee keer geïnitialiseerd.
Dit is niet omdat je een class extend, maar omdat je twee instanties aanmaakt. In de constructor creeer je nog een instantie (via new $_GET['app'];) Daar ga je mis, want inderdaad, dan krijg je twee verschillende instanties met ieder hun eigen properties en eigen waardes. Daarmee kom je dus weer terug bij het feit dat je opzet gewoon, uhm, vreemd is.
Wat je moet doen, als je echt maar 1 instantie van curl wilt hebben, is dat deel uit je class halen en in een aparte class plaatsen. Je doet dit nu wel op een nogal vreemde manier, door de parent apart aan te maken (waardoor je dus een child krijgt die parent extend EN een parent instantie in een property heeft), maar zo krijg je hele vreemde connecties.
@Ward van der Put: De session die in curl start moet in de child dezelfde session zijn. De parent class logt in op een website (submit user/pass) en de child class haalt vervolgens data op van een andere pagina op dezelfde website (die alleen zichtbaar is als je bent ingelogd (dus session die geopend is in de parent class is nodig)). Wanneer de request van de remote is afgehandeld is de sessie niet meer nodig en hoeft deze dus ook niet aan de remote kant gecached te worden.
@Erwin: Haha, het kwam mijn idd ook over als klare onzin. En zoals ik eerder al heb gezegd: mijn code(opbouw) zal hoogst waarschijnlijk een groot aantal verbeter punten hebben. Ik ben mijzelf dan ook bewust van het feit dat mijn huidige oplossing een slechte work-around is. Overigens heb ik je verhaal vandaag meerdere keren moeten doorgelezen om het goed te begrijpen.
Volgens mij begrijp je mij alleen verkeerd (of ik jou :s): Via new $_GET['app']; wordt de child class geïnitialiseerd (en niet de parrent class (voor een tweede keer)). Van de parent class is dus maar 1 instantie. In de parent class komt daar een instantie van de child class bij. Van beide classes is dus één instantie (zou ik zeggen).
Maybe I'm wrong… ;) Iig nogmaals dank voor jullie hulp en tijd voor zover!
Wilfred Dijksman
Toevoeging op 02/02/2013 22:57:16:
Toevoeging op 31/01/2013 15:12:44:
Ja, het is een systeem wat meerdere modules/apps heeft die wel dezelfde basis functies nodig hebben. Die basis functies zitten in de parent class.
Toevoeging op 31/01/2013 15:10:14:
Ik heb ondertussen een oplossing voor mijn probleem:
Ik laad een variabele met daarin het parent class object in de child class zodat via die variabele alles toegankelijk is vanuit de child class. Zie ook het voorbeeld hieronder:
parent.class.php
Code (php)
child.class.php
Code (php)
Opmerking: Nadeel van deze methode is natuurlijk wel dat de visability van properties en methodes omzeilt wordt.
Mochten jullie nog opmerkingen / andere suggesties hebben dan hoor ik dat graag. Nogmaals dankt voor jullie meedenken tot zover.
Met vriendelijke groet,
Wilfred Dijksman
Gewijzigd op 02/02/2013 23:37:25 door Tim S