[PHP4] Class overerving

Pagina: 1
Acties:

  • Scyth
  • Registratie: Juli 2001
  • Laatst online: 16-03-2024

Scyth

Fat finger, three beer

Topicstarter
Vooraf: M'n hoster draait PHP4, en gaat in de nabije toekomst niet over naar PHP5. De hosting zelf bevalt me uitermate goed, dus 't zal écht in PHP4 moeten.

Ik heb een verzameling .php bestanden, elk met hun eigen classdef en hun functies zoals hieronder:
• guardian.php
• connect.php
• config.php

(Nog een paar meer, maar dit illustreerd wel al wat ik wil doen)

Nou is er 1 'hoofdclass' genaamd bootstrap in bootstrap.php. In deze class bevind zich in de constructor functie bootstrap een loop waarin alle 'plugins' worden geinclude. Je hebt 'm al door; de 'plugins' zijn de eerder genoemde PHP functies. Elke 'plugin' heeft netjes als classdef
code:
1
2
class <naam> extends bootstrap {
}

Nou wordt bootstrap.php geladen als zijnde een 'essentiële' include, dus een require, in de php die uiteindelijk wat op 't scherm moet toveren; nl. fetchPage.php:
code:
1
require($_SERVER['DOCUMENT_ROOT'].'/bootstrap.php');


Echter, zodra ik dan een van de 'childs' van bootstrap wil aanspreken zoals $connect->, werkt dit niet. Voor mijn gevoel klopt de overerving nu niet, maar ik zou even geen workaround kunnen bedenken.

De reden voor één overkoepelende include is dat er meerdere pagina's zijn dan alleen fetchPage, en de array met plugIns is dynamisch, en wordt in bootstrap gespecificeerd.

Iemand een oplossing over hoe ik alsnog de functies in de plugins aan kan spreken?

Dell Studio XPS 16
Project: BavBierSub 1.0 BavBierSub 2.0


  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Hoe maak je instanties van de betreffende classes aan?

[ Voor 11% gewijzigd door AtleX op 13-12-2006 16:07 ]

Sole survivor of the Chicxulub asteroid impact.


  • Scyth
  • Registratie: Juli 2001
  • Laatst online: 16-03-2024

Scyth

Fat finger, three beer

Topicstarter
Met een loop die alle waarden van de array bij langs loopt, in $fN zet, en init als volgt:
PHP:
1
2
require($_SERVER['DOCUMENT_ROOT'].'/includes/'.$fN.'.php');
$$fN = new $fN;

Mijn excuses aan de codepolitie voor de slechte code, maar ik kon even niets anders logisch bedenken om een array met plugin-namen te includen

EDIT:
Heb de constructor van bootstrap nu zo:

PHP:
1
2
3
4
5
6
7
8
9
10
class bootstrap {
    function bootstrap() {
      $iA = array('guardian','connect','config');
      foreach($iA as $fN) {
        if (is_file($f = ($_SERVER['DOCUMENT_ROOT'].'/includes/'.$fN.'.php'))) {
          require($f);
          $this->$$fN = new $fN;
        } else die();
      } }
}


Echter, ik krijg nu als fout bij de classes die zo geinstantiëerd worden de volgende fout:
Fatal error: Cannot redeclare class config in /srv/blaat.com/includes/config.php on line 17

(line 17 is waar de class geopend staat van config, daarboven is comments)

[ Voor 59% gewijzigd door Scyth op 13-12-2006 16:52 ]

Dell Studio XPS 16
Project: BavBierSub 1.0 BavBierSub 2.0


  • maurad3r
  • Registratie: Oktober 2004
  • Laatst online: 22-11 15:05
Wil je het nog duidelijker hebben dan dit?
Cannot redeclare class config
Het bestand waarin de klas Config zich bezit wordt dus meerdere malen aangeroepen. Oplossing is waarschijnlijk require_once ipv require gebruiken.

[ Voor 3% gewijzigd door maurad3r op 13-12-2006 17:46 ]


  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Dat is geen oplossing Maurad3r, maar een workaround. Waarom probeert hij meerdere malen die class te includen, dat is de vraag.

[edit]
Wordt bij een class die inherit niet de constructor van de parent opnieuw uitgevoerd? Dat zou het probleem wel verklaren.

[ Voor 34% gewijzigd door AtleX op 13-12-2006 18:09 ]

Sole survivor of the Chicxulub asteroid impact.


  • mithras
  • Registratie: Maart 2003
  • Niet online
AtleX schreef op woensdag 13 december 2006 @ 18:08:
[...]
[edit]
Wordt bij een class die inherit niet de constructor van de parent opnieuw uitgevoerd? Dat zou het probleem wel verklaren.
Volgens mij is dat ook het probleem, want wanneer je een class ("klasse 1") extends naar een andere class ("klasse 2"), wordt bij het constructen van klasse1 óók de constructor van klasse2 uitgevoerd.
Aangezien de constructor van klasse2 in jou geval klasse1 als child aanmaakt, lukt dat niet.

Volgens mij is dit gewoon al goed:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
class a{
  function a(){
    //constructor
    $this->b = new b();
  }
}
class b{
  function do_something(){
    //...
  }
}
$a = new a();
$a->b->do_something();

  • yiko
  • Registratie: September 2003
  • Laatst online: 20-04 20:19
De parent constructor wordt niet automatisch opgeroepen in de constructor van een geërfde klasse.
Dus het probleem zal zich toch ergens moeten zitten in het al eerder includen van config.php

  • Scyth
  • Registratie: Juli 2001
  • Laatst online: 16-03-2024

Scyth

Fat finger, three beer

Topicstarter
yiko schreef op woensdag 13 december 2006 @ 21:31:
De parent constructor wordt niet automatisch opgeroepen in de constructor van een geërfde klasse.
Dus het probleem zal zich toch ergens moeten zitten in het al eerder includen van config.php
Integendeel. De constructor van bootstrap wordt wel degelijk twee keer aangeroepen.
Een simpele
PHP:
1
echo 'meep';

aan het begin van de constructor van bootstrap resulteert in dit:
code:
1
2
meepmeep
Fatal error: Cannot redeclare class config in /srv/blaat.com/includes/config.php on line 17


Hij wordt dus twee keer aangeroepen alvorens tot een halt te komen door een fatal error. Zou die error er niet zijn, zou hij dus recursief door blijven loopen met includen 8)7

in fetchPage.php maar even een call maken naar een doIncludes() functie in bootstrap denk ik.
I'll keep you posted.

Dell Studio XPS 16
Project: BavBierSub 1.0 BavBierSub 2.0


  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 18:37
AtleX schreef op woensdag 13 december 2006 @ 18:08:
Dat is geen oplossing Maurad3r, maar een workaround. Waarom probeert hij meerdere malen die class te includen, dat is de vraag.
Op zich is het natuurlijk wel een oplossing. Require_once() is er voor bedoeld om te garanderen dat files die maar een keer moeten worden geinclude (zoals class definities) ook maar 1 keer worden geinclude. Ik gebruik zelf eigenlijk nooit wat anders...

Maar goed neemt niet weg dat er hier iets onbedoelds gebeurd, en dat is nooit handig in een script. In PHP(4) is het zo dat een klasse die overerft van een andere klasse (alleen) de constructor van zijn parent aanroept wanneer hij zelf geen constructor heeft.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class a {
  function a() {
    echo 'constructor a()';
  }
}

class b extends a {
  function b() {
    echo 'constructor b()';
  }
}

class c extends a {}
class d extends b {}
//edit voor de volledgheid...
class e extends c {}

$a = new a(); // -> constructor a();
$b = new b(); // -> constructor b();
$c = new c(); // -> constructor a();
$d = new d(); // -> constructor b();
//edit voor de volledigheid
$e = new e(); // -> constructor a(); 


Ik vermoed daarom dat de config klasse zelf geen constructor heeft.

[ Voor 4% gewijzigd door T-MOB op 13-12-2006 22:09 ]

Regeren is vooruitschuiven


Verwijderd

Scyth schreef op woensdag 13 december 2006 @ 16:04:
Ik heb een verzameling .php bestanden, elk met hun eigen classdef en hun functies zoals hieronder:
• guardian.php
• connect.php
• config.php

Nou is er 1 'hoofdclass' genaamd bootstrap in bootstrap.php. In deze class bevind zich in de constructor functie bootstrap een loop waarin alle 'plugins' worden geinclude. Je hebt 'm al door; de 'plugins' zijn de eerder genoemde PHP functies. Elke 'plugin' heeft netjes als classdef
code:
1
2
class <naam> extends bootstrap {
}
Disclaimer: ik heb nauwelijks ervaring met PHP, maar wel vrij veel ervaring met object oriented programmeren.
Maar ik snap niet zo gek veel van jouw objectmodel en waarom je daar uberhaupt deze inheritance nodig zou hebben...

Guardian, connect en config zijn zo te zien op zichzelf staande classes die worden geinitieerd en eventueel beheerd door bootstrap (de container die de plugins moet beheren en basisfunctionaliteit aan de plugins beschikbaar moet stellen?).
Dan is 't onzin om die plugins bootstrap te laten extenden. 'extends' houdt in dat die plugins alles kunnen wat de base class kan, en nog iets meer. Wanneer die plugins toch al door die base class container worden beheerd, hoeven ze die dingen (database toegang, etc.) helemaal niet te kunnen
maar is 't genoeg (en beter) wanneer ze aan die container bv. database toegang kunnen vragen.

Het is wel handig om een base plugin class te maken die de communicatie met de bootstrap instance die de plugin beheert implementeert, en guardian, connect en config daarop te laten extenden. Dan heeft inheritance opeens zin... ;)

  • Scyth
  • Registratie: Juli 2001
  • Laatst online: 16-03-2024

Scyth

Fat finger, three beer

Topicstarter
Verwijderd schreef op woensdag 13 december 2006 @ 22:07:
[...]
Guardian, connect en config zijn zo te zien op zichzelf staande classes die worden geinitieerd en eventueel beheerd door bootstrap (de container die de plugins moet beheren en basisfunctionaliteit aan de plugins beschikbaar moet stellen?).
Dan is 't onzin om die plugins bootstrap te laten extenden. 'extends' houdt in dat die plugins alles kunnen wat de base class kan, en nog iets meer. Wanneer die plugins toch al door die base class container worden beheerd, hoeven ze die dingen (database toegang, etc.) helemaal niet te kunnen
maar is 't genoeg (en beter) wanneer ze aan die container bv. database toegang kunnen vragen.
De extends waren een noodgreep om 't werkend te krijgen, maar toen ik zag dat het niet werkte, heb ik 't er ook gewoon weer uit gehaald. Soort van desperate act voordat ik hier om raad kwam vragen zeg maar.

Update
Ondertussen heb ik wat ik eigenlijk wou dus voor elkaar, echter alsnog met limitaties.
De classes in bootstrap dien ik nu zo aan te spreken:
PHP:
1
$pageContent = $bootStrap->connect->query('SELECT itemTe...');

en dat werkt. op een simpele $pageContent = $bootStrap->connect->giveID(); geeft de connect class netjes zijn ID terug. Echter ik vind 't ongelovelijk lelijk om iedere keer $bootStrap-> voor een stomme call te zetten. Kan ik niet met een of andere magische handige functie de door $bootStrap beheerde functies omschrijven zodat ze 'lokaal' te benaderen zijn?

Dell Studio XPS 16
Project: BavBierSub 1.0 BavBierSub 2.0


Verwijderd

Misschien zal 't in PHP4 best kunnen, maar 't zou dan wel alle OO wetten met voeten treden...
'query' is een method van 'connect', en 'connect' is een property/member van 'bootstrap'.
En $bootStrap is de instance van de class bootstrap die je zelf in het leven hebt geroepen om te kunnen beschikken over z'n properties en methods.
Wil je 't netjes OO houden, dan ontkom je niet aan het feit dat je alles via $bootStrap aan zult moeten spreken.

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

T-MOB schreef op woensdag 13 december 2006 @ 22:06:
[...]


Op zich is het natuurlijk wel een oplossing. Require_once() is er voor bedoeld om te garanderen dat files die maar een keer moeten worden geinclude (zoals class definities) ook maar 1 keer worden geinclude. Ik gebruik zelf eigenlijk nooit wat anders...
Ja, maar in dit geval blijf je gewoon tot in de eeuwigheid includen. Als hij meerdere malen in dezelfde loop iets probeert te includen en daar krijg je een error op is include_once() geen oplossing.

[ Voor 4% gewijzigd door AtleX op 14-12-2006 10:05 . Reden: Linkje naar include_once() toegevoegd, beter laat dan nooit. :z ]

Sole survivor of the Chicxulub asteroid impact.


  • Scyth
  • Registratie: Juli 2001
  • Laatst online: 16-03-2024

Scyth

Fat finger, three beer

Topicstarter
AtleX schreef op donderdag 14 december 2006 @ 08:26:
[...]

Ja, maar in dit geval blijf je gewoon tot in de eeuwigheid includen. Als hij meerdere malen in dezelfde loop iets probeert te includen en daar krijg je een error op is include_once() geen oplossing.
Ik heb 't eerst wel eventjes opgelost met include_once(). 't werkt nu zo:
de constructor van bootstrap called een functie doIncludes() in dezelfde class. (Dit om de constructor netjes en overzichtelijk te houden). Met een global boolean hou ik op een ietwat nasty manier bij of de doIncludes() al aangeroepen is.

Ben druk op zoek naar een betere manier, maar dit werkt eerst.

Dell Studio XPS 16
Project: BavBierSub 1.0 BavBierSub 2.0

Pagina: 1