[PHP] Eval child class property

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Goedemorgen,

Al een tijdje gebruik ik eval() in PHP om title's en h1's uit de database om te zetten naar de waarde die ze moeten krijgen, bijvoorbeeld:

PHP:
1
2
$this->H1 = "Welkom op $Site->Naam";
eval("\$this->H1 = \"$this->H1\";");


aangezien $Site->Naam gevuld is met "Example.com", wordt de waarde van H1 hier dan ook gevuld met "Welkom op Example.com";

Dit werkt allemaal goed, totdat ik hetvolgende probeerde:

PHP:
1
2
$this->H1 = "$Stad->Naam - $Stad->Land->Naam";
eval("\$this->H1 = \"$this->H1\";");


$Stad->Naam zet ie netjes om, maar $Stad->Land->Naam niet.
Ik krijg dan de logische foutmelding: Object of class Land could not be converted to string

Ik heb nooit geweten dat de eval()-functie van PHP een voor een de properties af gaat en dan uiteindelijk bij een Class komt en een error geeft omdat ie hem niet om kan zetten naar een String. Wanneer ik namelijk gewoon ..
PHP:
1
$this->H1 = $Stad->Land->Naam;

.. doe, dan vult ie netjes de H1 met bijvoorbeeld "Nederland".

Ik heb al gekeken naar __toString() e.d., maar daarmee krijg ik ook niet het gewenste resultaat.
Heeft iemand van jullie wellicht een idee hoe ik dit kan oplossen?

Alvast bedankt!

De oplossing
Het probleem was niet de eval()-functie, maar het niet gebruiken van de curly syntax.
Verwijderd in "[PHP] Eval child class property"

[ Voor 6% gewijzigd door Verwijderd op 19-12-2009 22:04 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ik begrijp niet wat je nou aan het doen bent, eerst zet je $this->H1 en vervolgens voer je een eval uit die $this->h1 zijn eigen waarde geeft.

Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Waarom die eval's? Je kan toch gewoon een echo doen?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Sorry, wellicht had ik erbij moeten zetten dat de H1 gevuld wordt uit de database.

In de database zit een veld met bijvoorbeeld de waarde "{0} - {1}, $Stad->Naam, $Stad->Land->Naam".
Met een zelfgeschreven String::Format functie maak ik daar "$Stad->Naam - $Stad->Land->Naam" van, maar daarna moet ik dus o.a. $Stad->Naam omzetten in "Amsterdam".

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Vanwaar die enorm onhandige opzet? Als je eval nodig hebt om iets uit je database op je scherm te krijgen moeten er toch alarmbellen gaan rinkelen lijkt me.

Acties:
  • 0 Henk 'm!

  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
Afgezien van het feit dat ik denk bij deze opzet 'WTF!?' kan je toch ook na die String Format gewoon een String replace doen waar je die $Stad->Naam etc. vervangt?

Engineering is like Tetris. Succes disappears and errors accumulate.


Acties:
  • 0 Henk 'm!

  • boe2
  • Registratie: November 2002
  • Niet online

boe2

'-')/

die code is een major wtf moment :p

wat is er mis met echo $this->H1 dan?

'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind.' - Pratchett.


Acties:
  • 0 Henk 'm!

  • Ssander
  • Registratie: December 2009
  • Laatst online: 12-06-2023
Eval in deze situatie gebruiken is/lijkt totaal onlogisch. Je zult toch eerst je motivatie moeten vertellen waarom je het zo doet anders zul je denk ik weinig feedback op je vraag krijgen.

En eerlijk gezegd ben ik ook wel benieuwd waarom je het zo doet.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Oke :-) het ziet er inderdaad een beetje vreemd uit, wanneer je niet weet wat er nu precies gebeurd. Hier komt ie dan :-)
  1. Via de URL, zoek ik het bijbehorende Pagina object in mijn database.
  2. Dit Pagina object bevat een ObjectType en een property 'H1'
  3. Deze H1 is bijvoorbeeld gevuld met "$Stad->Naam - $Stad->Land->Naam"
  4. Het ObjectType van de Pagina is in dit geval "Stad"
  5. Daarna wordt er een Stad object aangemaakt en wordt het object aan de hand van de url parameters gevuld.
  6. De Stad is nu gevuld uit de database en blijkt bijvoorbeeld "Amsterdam" te zijn.
  7. Stad->Naam = Amsterdam, $Stad->Land->Naam = Nederland,.. vanzelfsprekend
Op dit moment is $Pagina->H1 nog steeds "$Stad->Naam - $Stad->Land->Naam", maar ik weet nu dat de naam van de stad Amsterdam is. Dus dit wil ik gaan omzetten naar de daadwerkelijke H1.

Daar ik in mijn Pagina object beide dingen weet, dus $Stad en $Pagina ($this), probeer ik door middel van een simpele Eval, dus ($this->H1 = $this->H1), de waarde van de H1 om te zetten in de echte waarde.

Een str_replace werkt hier niet, aangezien ik niet weet wat in die H1 zit. Dit is natuurlijk voor iedere pagina anders.
Het echo'en van $this->H1 helpt natuurlijk ook niet, aangezien alles in mijn Controller gebeurd en ik hierin niets kan echo'en, maar wanneer ik in mijn View de waarde H1 op het scherm tover, zonder hiervan de waardes om te zetten, krijg ik natuurlijk gewoon de string "$Stad->Naam, etc." te zien en niet "Amsterdam, etc."

Vandaar dat ik Eval() gebruik, en dit werkt ook aardig, totdat ik dus 1 laag dieper ga dan mijn parent object. $Stad->Naam werkt zonder problemen, maar $Stad->Land->Naam werkt niet. Omdat hij dan op een of andere manier "$Stad->Land" wil omzetten naar een String, terwijl dit een object is.

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Verwijderd schreef op zaterdag 19 december 2009 @ 12:51:
maar wanneer ik in mijn View de waarde H1 op het scherm tover
Je zegt dat je een View hebt maar ondertussen bevatten al je objecten stukjes templates als property?

{signature}


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Voutloos schreef op zaterdag 19 december 2009 @ 13:02:
[...]
Je zegt dat je een View hebt maar ondertussen bevatten al je objecten stukjes templates als property?
Waar maak je dat uit op? Mijn Pagina object bevat een property H1, waarin de logica van de H1 staat. Mede omdat deze, naast op de website, ook elders gebruikt kan en zal worden.
Maar goed, een dergelijke opmerking helpt natuurlijk ook niet het zoeken naar een eventuele oplossing.

Acties:
  • 0 Henk 'm!

  • Ssander
  • Registratie: December 2009
  • Laatst online: 12-06-2023
Dit is een erg ingewikkelde manier om te doen wat je wilt. Als je in je view {$stad} en {$land} variabelen hebt en deze variabelen in de DB opslaat in 'stad' en 'land' velden kun je makkelijk de juiste data op de juiste plek zetten in je controller. Hoe je het nu doet is totaal niet efficient.

Kijk eens naar een template engine als Smarty om te zien hoe het daar werkt.

Edit: en om je directe probleem op te lossen: werkt iets al dit wel?

code:
1
2
eval("$land = $stad->land");
eval("$this->H1 = $land->naam");


Ik ben niet erg bekend met eval() dus bovenstaande zal niet direct werken, maar je begrijpt het concept.

[ Voor 25% gewijzigd door Ssander op 19-12-2009 13:20 ]


Acties:
  • 0 Henk 'm!

  • boe2
  • Registratie: November 2002
  • Niet online

boe2

'-')/

hele tijd geleden dat ik php nog aangeraakt heb, maar
code:
1
2
eval("$land = $stad->land");
eval("$this->H1 = $land->naam");

is toch identiek hetzelfde als
code:
1
$this->H1 = $stad->land->naam
:?

[ Voor 14% gewijzigd door boe2 op 19-12-2009 18:26 ]

'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind.' - Pratchett.


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 21:34

MueR

Admin Tweakers Discord

is niet lief

Een classic case van "If eval() is the answer, you're almost certainly asking the wrong question". Je zou dit veel beter kunnen oplossen met een template. String replaces op tags als {{STAD}} zijn nog altijd stukken efficienter. Daarbij neem ik aan dat je toch aparte handlers gebruikt voor de diverse pagina, dus dan weet je op welke pagina wat in de titel moet komen. Het misbruik van eval hier is totaal nutteloos.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Bee.nl
  • Registratie: November 2002
  • Niet online

Bee.nl

zoemt

Boeboe schreef op zaterdag 19 december 2009 @ 18:22:
hele tijd geleden dat ik php nog aangeraakt heb, maar
code:
1
2
eval("$land = $stad->land");
eval("$this->H1 = $land->naam");

is toch identiek hetzelfde als
code:
1
$this->H1 = $stad->land->naam
:?
Normaalgesproken wel ja, ware het niet dat hij php code als string heeft opgeslagen. Nu wilt hij deze string weer uitvoeren als php code middels de eval() functie.

Ik denk dat hetgene wat MueR hierboven voorstelt een goede oplossing is: gebruik maken van simpele string replaces. Hiermee moet je een heel eind komen.

Eigenlijk hadden ze eval() gewoon evil() moeten noemen. O-)

Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 06-09 00:37

curry684

left part of the evil twins

Bee.nl schreef op zaterdag 19 december 2009 @ 18:36:
[...]

Eigenlijk hadden ze eval() gewoon evil() moeten noemen. O-)
Mjah da's dan weer jammer voor de 0.0001% van de gevallen dat het wel wenselijk en nuttig is ;)

Professionele website nodig?


Acties:
  • 0 Henk 'm!

  • mjax
  • Registratie: September 2000
  • Laatst online: 22:06
Los van de ranzige constructie - waar nu wel genoeg over gezegd is - werkt dit misschien wel?

PHP:
1
2
3
4
<?php
$this->H1 = "$Stad->Naam - {$Stad->Land->Naam}";
eval("\$this->H1 = \"$this->H1\";");
?>

Acties:
  • 0 Henk 'm!

  • Bee.nl
  • Registratie: November 2002
  • Niet online

Bee.nl

zoemt

mjax schreef op zaterdag 19 december 2009 @ 19:43:
Los van de ranzige constructie - waar nu wel genoeg over gezegd is - werkt dit misschien wel?

PHP:
1
2
3
4
<?php
$this->H1 = "$Stad->Naam - {$Stad->Land->Naam}";
eval("\$this->H1 = \"$this->H1\";");
?>
Ja, in die vorm zal het wel werken. De (ge-escape-te) double quotes in je eval string geven het antwoord eigenlijk al weg. De variabelen in je string worden ge-expand en zodoende moet je de curly syntax gebruiken bij complexe expressies. Een simpele verwijzing naar een $object->property pakt de parser nog wel, maar veel gekker moet je het niet maken.

Conclusie: Het heeft eigenlijk helemaal niets met de eval() functie te maken. :P

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
mjax schreef op zaterdag 19 december 2009 @ 19:43:
Los van de ranzige constructie - waar nu wel genoeg over gezegd is - werkt dit misschien wel?

PHP:
1
2
3
4
<?php
$this->H1 = "$Stad->Naam - {$Stad->Land->Naam}";
eval("\$this->H1 = \"$this->H1\";");
?>
Bee.nl schreef op zaterdag 19 december 2009 @ 20:45:
[...]
Ja, in die vorm zal het wel werken. De (ge-escape-te) double quotes in je eval string geven het antwoord eigenlijk al weg. De variabelen in je string worden ge-expand en zodoende moet je de curly syntax gebruiken bij complexe expressies. Een simpele verwijzing naar een $object->property pakt de parser nog wel, maar veel gekker moet je het niet maken.

Conclusie: Het heeft eigenlijk helemaal niets met de eval() functie te maken. :P
Bedankt heren, ik heb inderdaad niet gedacht aan de curly syntax!

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Begrijp ik nou goed dat je deze workaround die jouw ranzige oplossing mogelijk maakt gewoon accepteert en vervolgens die smeerlapperij gewoon voortzet? Sorry dat ik het niet wat tactvoller zeg, maar ik heb hier domweg geen andere woorden voor. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
NMe schreef op zondag 20 december 2009 @ 03:23:
Begrijp ik nou goed dat je deze workaround die jouw ranzige oplossing mogelijk maakt gewoon accepteert en vervolgens die smeerlapperij gewoon voortzet? Sorry dat ik het niet wat tactvoller zeg, maar ik heb hier domweg geen andere woorden voor. ;)
Voor nu inderdaad wel :X Het stukje code gaat gewoon op de refactor lijst met een linkje o.a. naar dit topic. Nu hoef ik namelijk maar 1 regel code toe te voegen in m'n Pagina->ParseHeadTags() method.

Het probleem is een beetje dat ik geen, zoals hierboven werd gezegd, aparte handlers heb voor iedere pagina. Ik probeer een zo'n generiek mogelijke oplossing hiervoor te zoeken. En waar ik nu op uit ben gekomen, de eval() methode, doet precies wat ik op dit moment nodig heb.

Excuses dus, maar wel bedankt voor een druk op de neus, waardoor ik dit niet zomaar laat liggen, maar het wel op de refactorlijst zet :>

Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 06-09 00:37

curry684

left part of the evil twins

Kudo's voor de reactie, maar met alle respect hoort deze code niet op je refactorlijst. Die lijst zet je dingen op die 'kandidaat zijn voor vervanging/herschrijven' omdat ze bijv. beter kunnen, te snel afgeraffeld zijn of omdat specs veranderd zijn. Dit stukje code is, als ik je goed begrijp, fundamenteel voor het functioneren van de website en dermate ranzig dat je het functioneren van de hele website ermee in gevaar brengt. Als je wacht met het te herschrijven ga je daar serieus spijt van hebben.

Professionele website nodig?


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 21:34

MueR

Admin Tweakers Discord

is niet lief

Om nog even iets toe te voegen bij curry's reactie. Indien je baas, of jijzelf, twijfelt of het verstandig is dit stuk code compleet te schrappen, ga de performance eens benchmarken. Doe een string replace variant er bij. Allebei een kleine 50.000 keer draaien en tijd meten. Ik vraag me af of je server uberhaupt de 50k haalt met de eval(). Eval is namelijk best zwaar. Nou zal je jezelf misschien afvragen waarom je dat uberhaupt moet doen. Stel je voor dat Tweakers.net je site plots noemt in een nieuwsartikel, en je krijgt een paar honderd bezoekers in een paar minuten. Dat ga je merken in performance. Mogelijk met downtime tot gevolg.

Stel je nu eens voor dat een slashdot hetzelfde doet. Voorop gesteld, tenzij je over een flink serverpark met goede loadbalancing beschikt, je server gaat in dat geval plat. Niks aan te doen. De vraag is dan alleen of dat in enkele seconden gaat, of in enkele minuten. Eval is dusdanig imperformant dat dit echt een enorme bottleneck op je server kan veroorzaken.

Daarnaast sluit ik me volledig aan bij Curry; je gaat spijt krijgen als je hier mee wacht. Ik heb al een keer een site compleet kunnen herschrijven omdat bepaalde elementen in de basis niet goed waren opgezet. Daar leer je als programmeur natuurlijk wel van, maar het scheelt je toch een hoop tijd om nu te gaan nadenken over wat je doet, dan dat je later tegen een betonnen muur zit en vanaf nul moet herstarten.

Anyone who gets in between me and my morning coffee should be insecure.

Pagina: 1