Toon posts:

[PHP] __destruct te vroeg aangeroepen

Pagina: 1
Acties:

Onderwerpen


  • cyberstalker
  • Registratie: september 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
Ik heb een vervelend probleem met PHP5.3.6. De destructor van sommige objecten wordt aangeroepen voordat de laatste call naar het object is gemaakt. Dit gebeurt in een database klasse die ik heb.

Een korte beschrijving:

• Object wordt geconstrueerd
• Queries worden gedraaid
• __destruct wordt aangeroepen (welke weer $this->close() aanroept)
• Queries worden gedraaid, die uiteraard falen.

Dit probleem treedt op omdat ik met objecten werk die gewijzigde properties opslaan bij het destructen. Dit om onnodige queries te voorkomen (meerdere gewijzigde properties kunnen in één query worden opgeslagen). In dit scenario wordt de destructor van de database eerder aangeroepen dan de destructor van objecten die nog dingen willen opslaan.

Hoe kan ik ervoor zorgen dat PHP de database klasse pas opruimt *nadat* alle andere objecten zjin opgeruimd?

Ik ontken het bestaan van IE.


  • Deikke
  • Registratie: juni 2004
  • Laatst online: 14:04
De volgorde van destructie is niet altijd de volgorde dat ze naar elkaar refereren. Het opslaan van data in een destructor is overigens ook een beetje een code smell. Is er geen andere oplossing? Bijvoorbeeld een klasse die alle gewijzigde objecten bijhoud waar je voordat de code afloopt een Save actie op aanroept?

Destructors zijn bedoelt om openstaande resources op te ruimen (voor zover dat nog niet gebeurd was) en eigenlijk niet voor last minute logica.

[Voor 42% gewijzigd door Deikke op 26-11-2011 16:02]


  • mithras
  • Registratie: maart 2003
  • Niet online
cyberstalker schreef op zaterdag 26 november 2011 @ 15:55:
Dit probleem treedt op omdat ik met objecten werk die gewijzigde properties opslaan bij het destructen. Dit om onnodige queries te voorkomen (meerdere gewijzigde properties kunnen in één query worden opgeslagen). In dit scenario wordt de destructor van de database eerder aangeroepen dan de destructor van objecten die nog dingen willen opslaan.
Ik denk eigenlijk dat dit eerder een probleem is: het feit dat je in een destructor dit soort zaken uitvoert. Werk je via active record of unit of work? Met unit of work kan je uiteraard gemakkelijk op gecontrolleerde momenten committen wat het een stuk overzichtelijker houdt.

  • cyberstalker
  • Registratie: september 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
@mithras: Ja, het is een AR implementatie. Ik had gehoopt dat PHP wel zo slim zou zijn om te zien dat het object de database connectie nog gebruikt in de destructor en dus eerst het object opruimt voordat de database connectie is opgeruimd.

@GlowMouse: dat lijkt inderdaad een goede oplossing. Ik denk dat ik dan het beste alle records track in een static variabele en alle bekende records update bij het afsluiten van het script.

Ik ontken het bestaan van IE.


  • mithras
  • Registratie: maart 2003
  • Niet online
cyberstalker schreef op zaterdag 26 november 2011 @ 16:42:
@GlowMouse: dat lijkt inderdaad een goede oplossing. Ik denk dat ik dan het beste alle records track in een static variabele en alle bekende records update bij het afsluiten van het script.
Bedenk dat je een googol WTF factor maakt met jouw creatie hier. Wat ik zou doen is eerst te zoeken hoe je de huidige opzet qua architectuur zodanig beter kan opzetten zodat je deze kronkels niet nodig hebt :)

  • Voutloos
  • Registratie: januari 2002
  • Niet online
Nee alsjeblieft niet. Het hele saven tijdens de destructor idee klopt niet, dus ga alsjeblieft niet ook nog wat ranzige trucs in deze callback stoppen. :X

{signature}


  • ZpAz
  • Registratie: september 2005
  • Laatst online: 15:38
Voutloos schreef op zaterdag 26 november 2011 @ 16:56:
[...]
Nee alsjeblieft niet. Het hele saven tijdens de destructor idee klopt niet, dus ga alsjeblieft niet ook nog wat ranzige trucs in deze callback stoppen. :X
Als ik TS lees saved hij toch niet in de destructor?

Het enige wat je in een destructor moet doen is rommel opruimen, geen andere dingen uitvoeren. Nu is een destructor in php toch wat overrated aangezien aan het einde van je script toch alles wordt opgeruimd.

"Lambs to the cosmic slaughter!" - Morty


  • mithras
  • Registratie: maart 2003
  • Niet online
ZpAz schreef op zaterdag 26 november 2011 @ 17:07:
[...]


Als ik TS lees saved hij toch niet in de destructor?

Het enige wat je in een destructor moet doen is rommel opruimen, geen andere dingen uitvoeren. Nu is een destructor in php toch wat overrated aangezien aan het einde van je script toch alles wordt opgeruimd.
TS wil dat wel:
Dit probleem treedt op omdat ik met objecten werk die gewijzigde properties opslaan bij het destructen.
Waar ik en Voutloos logischerwijs op reageren ;)

  • ZpAz
  • Registratie: september 2005
  • Laatst online: 15:38
mithras schreef op zaterdag 26 november 2011 @ 17:16:
[...]
TS wil dat wel:


[...]
Waar ik en Voutloos logischerwijs op reageren ;)
Inderdaad fout gelezen.

"Lambs to the cosmic slaughter!" - Morty


  • frickY
  • Registratie: juli 2001
  • Nu online
cyberstalker schreef op zaterdag 26 november 2011 @ 16:42:
@mithras: Ja, het is een AR implementatie. Ik had gehoopt dat PHP wel zo slim zou zijn om te zien dat het object de database connectie nog gebruikt in de destructor en dus eerst het object opruimt voordat de database connectie is opgeruimd.
Dat doet PHP ook, en het Database-object dat je nodig hebt zal ook nog bestaan. Alleen de resource die dat object naar de database heeft is weg omdat die je die al closed in de destruct van een andere instantie van je Database. Athans, ik vermoed dat dit is wat er gebeurd.

Zou je omheen kunnen werken door je resource (bijv Mysqli::close()) niet te callen, of te zorgen dat elke Database-instantie zijn eigen resource creëert in plaats van een bestaande te hergebruiken (zie argumenten voor de connect()-call). Maar zoals anderen al aangeven is kijken naar een geheel andere opzet verstandiger.

[Voor 9% gewijzigd door frickY op 26-11-2011 17:33]


  • Ventieldopje
  • Registratie: december 2005
  • Nu online

Ventieldopje

I'm not your pal, mate!

Is het niet beter om te stoppen met zelf wat in elkaar te flansen en over te stappen op een bestaand ORM/DBAL zoals Doctrine of een compleet bestaand framework als Cake, Yii, Zend, Code Igniter.

Voor een simpel project zou je Doctrine als DBAL kunnen gebruiken, pretty much wat je nu zelf probeert te schrijven of de ingebouwde database classes van je framework gebruiken. Voor grotere projecten zou je kunnen overwegen Doctrine als ORM te gaan gebruiken, scheelt je een hoop ontwikkelings tijd en ben je veel meer bezig met je project dan met dit soort bugs oplossen ;)

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


  • cyberstalker
  • Registratie: september 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
frickY schreef op zaterdag 26 november 2011 @ 17:32:
[...]

Dat doet PHP ook, en het Database-object dat je nodig hebt zal ook nog bestaan. Alleen de resource die dat object naar de database heeft is weg omdat die je die al closed in de destruct van een andere instantie van je Database. Athans, ik vermoed dat dit is wat er gebeurd.
Ik werk in mijn project met een enkel database object. Die houdt dus ook de connectie open totdat close() wordt aangeroepen (of de destructor, die ook close() aanroept).

Ik clone mijn connectie nergens, en gebruik dus overal dezelfde connectie, die door PHP wordt gedestruct.

Ik snap ook het sentiment dat save()n vanuit de __destruct()or misschien niet heel netjes is, maar het is wel handig, aangezien je nooit meer updates op een rij uitvoert dan nodig.

Ik ontken het bestaan van IE.


  • Freeaqingme
  • Registratie: april 2006
  • Nu online
cyberstalker schreef op zaterdag 26 november 2011 @ 21:19:
[...]
Ik snap ook het sentiment dat save()n vanuit de __destruct()or misschien niet heel netjes is, maar het is wel handig, aangezien je nooit meer updates op een rij uitvoert dan nodig.
Tegelijkertijd, als een query een keer om wat voor reden faalt; is het vrijwel onmogelijk om dat duidelijk te maken aan je gebruiker.

No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.


  • Voutloos
  • Registratie: januari 2002
  • Niet online
cyberstalker schreef op zaterdag 26 november 2011 @ 21:19:
Ik snap ook het sentiment dat save()n vanuit de __destruct()or misschien niet heel netjes is, maar het is wel handig, aangezien je nooit meer updates op een rij uitvoert dan nodig.
Dat is op zich een mooie feature, maar als je acties netjes in elkaar zitten, kan je gewoon die save() calls verplaatsen naar het einde van relevante acties en ben je zo klaar zonder magisch PHP gezeik? En als bonus heb je inderdaad dan wel nog een error handling mogelijkheid.

{signature}


  • Cartman!
  • Registratie: april 2000
  • Niet online
Je wil AR maar het komt meer neer op UOW naar mijn idee. Kijk eens naar Doctrine 2, die doet opzich wat je doet maar je moet alleen handmatig flushen (=wijzigingen opslaan). Ik kwam van Zend_Db dus het leek me eerst ver gezocht maar Doctrine 2 is zoveel krachtiger dan Zend_Db dat ik niet meer terug wil. De destruct ervoor misbruiken is gewoon geen goede manier, zoals Voutloos al aanhaalt kun je een error in je queries niet meer goed afhandelen (duplicate bijv).

  • cyberstalker
  • Registratie: september 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
Omdat ik de redenen om niet voor opslaan in de constructor te kiezen wel begrijp, maar ik het onhandig vind om op elke rij handmatig te save()n, heb ik het nu omgebouwd.

Alle rijen die worden geconstruct worden bijgehouden en er is één statische save() functie waarmee gelijk alle rijen kunnen worden opgeslagen. Hierbij is dus nog wel de mogelijkheid om een Exception te gooien en af te handelen, maar zonder het ongemak van losse save()s.

Bijkomend voordeel is dat er nu per bestaande rij maar één object instantie is.

Ik ontken het bestaan van IE.


  • Manuel
  • Registratie: maart 2008
  • Laatst online: 26-11 12:33
cyberstalker schreef op zaterdag 26 november 2011 @ 22:13:
Omdat ik de redenen om niet voor opslaan in de constructor te kiezen wel begrijp, maar ik het onhandig vind om op elke rij handmatig te save()n, heb ik het nu omgebouwd.
Als ik vragen mag, wat is er precies zo onhandig aan om elke keer save() (of flush()) aan te roepen? Het is maar 1 regeltje extra en het zorgt er ook nog eens voor dat je fouten kunt afhandelen en zelfs nog fatsoenlijk kunt weergeven. De uren die je nu spendeert voor het maken van een oplossing had je ook kunnen gebruiken om '$sth->save()' te C/P.

offtopic:
Een RDBMS kan makkelijk 50qps halen mits de queries geen zware acties uitvoeren.

  • Voutloos
  • Registratie: januari 2002
  • Niet online
50? Heb je nog steeds je 486 in gebruik of zo?
edit:
uiteraard. ;)

[Voor 21% gewijzigd door Voutloos op 27-11-2011 00:18]

{signature}


  • Manuel
  • Registratie: maart 2008
  • Laatst online: 26-11 12:33
Het ging mij alleen even om het idee, ik mag hopen dat dat duidelijk is. :P

  • Cartman!
  • Registratie: april 2000
  • Niet online
cyberstalker schreef op zaterdag 26 november 2011 @ 22:13:
maar zonder het ongemak van losse save()s.
Fixed that for you. Ik raad je nogmaals aan om naar bestaande ORM-oplossingen te kijken, die hebben hier zoveel beter over nagedacht dan jij (en ik, dat ook).
Pagina: 1


Nintendo Switch (OLED model) Apple iPhone 13 LG G1 Google Pixel 6 Call of Duty: Vanguard Samsung Galaxy S21 5G Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True

Tweakers maakt gebruik van cookies

Bij het bezoeken van het forum plaatst Tweakers alleen functionele en analytische cookies voor optimalisatie en analyse om de website-ervaring te verbeteren. Op het forum worden geen trackingcookies geplaatst. Voor het bekijken van video's en grafieken van derden vragen we je toestemming, we gebruiken daarvoor externe tooling die mogelijk cookies kunnen plaatsen.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Forum cookie-instellingen

Bekijk de onderstaande instellingen en maak je keuze. Meer informatie vind je in ons cookiebeleid.

Functionele en analytische cookies

Deze cookies helpen de website zijn functies uit te voeren en zijn verplicht. Meer details

janee

    Cookies van derden

    Deze cookies kunnen geplaatst worden door derde partijen via ingesloten content en om de gebruikerservaring van de website te verbeteren. Meer details

    janee