[PHP]O/R mapper: addRelation() zorgt voor loop

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik was me aan het oriënteren op O/R mappers maar kwam eigenlijk niet echt een goede oplossing tegen. Ik heb daarom besloten er zelf een te schrijven, maar daar loop ik tegen een probleem aan.

Ik maak dit soort objecten:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
class user extends dbObj{
  public function __construct( $id ){
    //setup dingen
    $this->addRelation( 'address', 'user_id' ); //maakt 1:many relatie
  }
}

class address extends dbObj{
  public function __construct( $id ){
    //setup dingen
    $this->addRelation( 'user', 'id', 'user_id') //maakt 1:many relatie
  }
}
Hoe waarom verder je 1, 2, 3 of 4 argumenten meegeeft is afhankelijk van de type relatie. Een primary id mag je weglaten, dat kan het systeem zelf aanvullen.

Ik heb vervolgens in mijn mapper de volgende code voor addRelation():
PHP:
1
2
3
4
5
6
7
8
9
10
final protected function addRelation( $class, $relId = false, $myId = false, $connector = false ){
    //Controle of allerlei dingen wel kloppen

    $object = new $class();
    if( !$relId ) $relId = $object->__primary;
    if( !$myId ) $myId = $this->__primary;
    if( $connector && class_exists( $connector ) ) $connectorObject = new $connector;
    
    //Analyseer de gegevens en bepaal het type relatie
    }
Ik moet met mijn systeem (denk ik) wel de $class instantiëren (regel #4). Hoe kan ik anders achterhalen of ik met een primary id zit of niet? Ik kom hiermee in een oneindige loop. Het php bestand wil bij uitvoeren zich laten downloaden door de browser, wat een compleet leeg bestand is. Er gebeurt namelijk dit:
  1. Instantieer user
  2. Door constructor wordt addRelation() uitgevoerd. Relatie met address bestaat dus nog niet
  3. Address wordt geinstantieerd door addRelation()
  4. Door constructor wordt addRelation() uitgevoerd. Relatie met user bestaat dus nog niet
  5. addRelation() geeft opdracht tot instantie van $user (dus goto 1).
Hoe kan ik dit tegengaan? Ik zit al weken te piekeren ;( over hoe ik dit kan oplossen, maar heb geen nette manier gevonden (überhaupt geen oplossing eigenlijk)...

Heeft _iemand_ een gouden tip?

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Mn collega heeft een goede ORM gemaakt voor PHP maar dies niet te krijgen. Je kunt wel kijken naar Doctrine, daarmee zijn we aan het testen en ziet er erg goed uit :) Succes!

Acties:
  • 0 Henk 'm!

  • Cousin Boneless
  • Registratie: Juni 2008
  • Laatst online: 28-02 12:55
Als je nog twee singleton classes toevoegt: userPool en addressPool? Je creeert dan niet telkens nieuwe objecten voor het gebruik in de relatie, maar herbruikt de objecten (dmv een lookup) in deze pools. Dit voorkomt de oneindige recursie.
Volgens mij maak je ook een fout dat je meta informatie probeert te achterhalen (__primary bevat de veldnaam waarop de primary key is gezet?) adhv geinstantieerde objecten. Dat kun je dan ook meteen in deze pool classes onderbrengen.
PHP:
1
$this->addRelation( $addressPoolInstance, 'user_id' );

Misschien probeer je het ook wat te generiek op te zetten.. uiteindelijk wil je toch opvragen $user->Addresses en niet $user->Relation['address'] lijkt mij.

Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Ik heb hetzelfde probleem ook gehad :P die loop crashed je apache *heel* hard :+

De truc is: Je wil zo weinig mogelijk performance verliezen c/q overbodige dingen instantiaten en code uitvoeren waar je dat niet hoeft.

Elk dbObject heeft bij mij standaard false als ID. Als de ID false is, worden er van dat object wel de relaties opgezet, maar niet ge-analyzed, ook worden de mappings naar de database tabel worden gelegd en de keys worden opgezet, maar er wordt geen select uitgevoerd om het object te vullen met zn gemapte row.

Zo heb je alle meta-informatie bij elkaar en kun je toch dit misbruiken tijdens het analyzeren en connecten van relaties en in het gedeelte wat je queries bouwt :)

Mijn addRelation ziet dan er ook zo uit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/***
     * Add a new relation to the relation list and set it to be analyzed if used.
     * Newly added relations will standard have RELATION_NOT_ANALYZED for relationtype to optimize speed
     * @param string $classname Connecting classname
     * @param string $connectorclassname Classname to use as connector class
 
*/
    public function addRelation($classname, $connectorclassname=false) 
    {
        $this->relations[$classname] = new stdClass();
        $this->relations[$classname]->relationType = RELATION_NOT_ANALYZED;
        if($connectorclassname != false) $this->relations[$classname]->connectorClass = $connectorclassname;
        if($this->databaseInfo->ID != false) $this->analyzeRelations();     
    }


Voor een toekomstige versie heb ik ook al (zoals slappe kip hierboven opmerkt) een soort van 'database info' singleton in gedachten. Deze kan eenmalig alle informatie cachen zodra deze nodig is, en hierdoor de performance nóg verder opkrikken :) Vraag blijft of erg veel nut heeft, want je moet wel véél objecten aanmaken en oproepen en er actief dingen mee gaan doen voordat dat gedeelte omhoog komt in de debug profilers. (overigens, installeer XDebug, het scheelt je een hoop hoofdpijn ;) )


De trucs kun je zo uit de laatste versie (vers voor je geupload) van m'n dbObject halen. Ik heb wat erg leuke features bij elkaar verzonnen zoals een Find() functie die nu ook een pad kan lopen door aan elkaar gekoppelde objecten, waarbij je in elke stap nog extra where parameters kan toevoegen. Erg leuk om dat in je hoofd te proberen te proppen :P

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * Zoek alle SkillGroupFlowRelation objecten die via 
* FlowRouting -> MainTimeFrameRelation -> MainRouting 
* (die description $this->routing en CustomerID $this->srn->CustomerID heeft) -> 
* SrnMainRelation aan een Srn met $this->srn->ID zit :Y) 
 */

$input = dbObject::Search('SkillGroupFlowRelation', 
                Array('FlowRouting' =>
                    Array("MainTimeframeRelation" => 
                        Array("MainRouting"=> Array(
                                "Description"=> $this->routing,
                                "CustomerID" => $this->srn->CustomerID,
                                "SrnMainRelation" => 
                                        Array("Srn" => Array("ID"=>$this->srn->ID)))))));


meer info en docs en demos:
http://www.schizofreend.nl/Pork.dbObject/

google code base:
http://code.google.com/p/pork-dbobject/downloads/list

hope this helps you :)

[ Voor 29% gewijzigd door SchizoDuckie op 26-10-2008 04:58 ]

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Cartman! schreef op zaterdag 25 oktober 2008 @ 16:45:
Mn collega heeft een goede ORM gemaakt voor PHP maar dies niet te krijgen. Je kunt wel kijken naar Doctrine, daarmee zijn we aan het testen en ziet er erg goed uit :) Succes!
Ik ga eens kijken naar Doctrine. Eerder had ik al de keuze gemaakt om niet voor Doctrine te gaan (geen idee meer waarom), maar ze kunnen vast wat informatie geven :p
Cousin Boneless schreef op zondag 26 oktober 2008 @ 02:55:
Als je nog twee singleton classes toevoegt: userPool en addressPool? Je creeert dan niet telkens nieuwe objecten voor het gebruik in de relatie, maar herbruikt de objecten (dmv een lookup) in deze pools. Dit voorkomt de oneindige recursie.
Volgens mij maak je ook een fout dat je meta informatie probeert te achterhalen (__primary bevat de veldnaam waarop de primary key is gezet?) adhv geinstantieerde objecten. Dat kun je dan ook meteen in deze pool classes onderbrengen.
PHP:
1
$this->addRelation( $addressPoolInstance, 'user_id' );
Het is wel een slim idee ja. Ik zou zelf dan niet gaan voor een singleton (gek he, niet optimaal OOP :P), want ik wil het de gebruiker zo makkelijk mogelijk maken. Ze hoeven dus niet voor elk object twee classes te schrijven lijkt me. Ik zou eerder intern een soort van singleton-on-demand maken om de informatie van de objecten te "cachen" (later wellicht nog uit te breiden met echte informatie cache). Maar wel een goed idee, thanks!
Misschien probeer je het ook wat te generiek op te zetten.. uiteindelijk wil je toch opvragen $user->Addresses en niet $user->Relation['address'] lijkt mij.
Zover was ik nog niet (bleef vast zitten bij het aanmaken van de relaties :p), maar dat wordt wel beter opgelost. Ik laat de gebruiker niet zomaar door mijn relaties array lopen, dat wordt netjes afgevangen (heb ik ook wel ideeën over).
SchizoDuckie schreef op zondag 26 oktober 2008 @ 04:45:
Ik heb hetzelfde probleem ook gehad :P die loop crashed je apache *heel* hard :+
Ik hoopte al dat je zou reageren :+. Ik kwam bij mijn "vooronderzoek" ook uit op PorkDb, omdat het juist lightweight is (mijn requirement met stip op nummer 1). Na je code bekeken te hebben vond ik zelf sommige dingen niet heel handig voor de gebruiker en dacht het dus beter te kunnen :p
De truc is: Je wil zo weinig mogelijk performance verliezen c/q overbodige dingen instantiaten en code uitvoeren waar je dat niet hoeft.

Elk dbObject heeft bij mij standaard false als ID. Als de ID false is, worden er van dat object wel de relaties opgezet, maar niet ge-analyzed, ook worden de mappings naar de database tabel worden gelegd en de keys worden opgezet, maar er wordt geen select uitgevoerd om het object te vullen met zn gemapte row.

Zo heb je alle meta-informatie bij elkaar en kun je toch dit misbruiken tijdens het analyzeren en connecten van relaties en in het gedeelte wat je queries bouwt :)

Mijn addRelation ziet dan er ook zo uit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/***
     * Add a new relation to the relation list and set it to be analyzed if used.
     * Newly added relations will standard have RELATION_NOT_ANALYZED for relationtype to optimize speed
     * @param string $classname Connecting classname
     * @param string $connectorclassname Classname to use as connector class
 
*/
    public function addRelation($classname, $connectorclassname=false) 
    {
        $this->relations[$classname] = new stdClass();
        $this->relations[$classname]->relationType = RELATION_NOT_ANALYZED;
        if($connectorclassname != false) $this->relations[$classname]->connectorClass = $connectorclassname;
        if($this->databaseInfo->ID != false) $this->analyzeRelations();     
    }
Mmm, dat is wel een redelijk goede oplossing. Met het door jouw code lopen zag ik dat er bij elke relatie een enorme controleloop uitgevoerd werd, dat leek me niet zo handig.

In dit geval: je instantieert je klasse pas als je dus ook een id is meegegeven? Dan verplaats je het probleem dan toch alleen maar? Nu krijg je de loop alleen als er een id is meegegeven. Of zit ik nu verkeerd te denken? Ik snap :p
Toch is de oplossing niet ideaal: je kan geen relaties aan klasse toevoegen die geen id hebben, i.e. niet van tevoren hebben meegekregen. Of je moet ze tussentijds opslaan, maar of dat nu een ideale oplossing is...
offtopic:
De mappings uit de database, dat moet zeker nieuw zijn?
Voor een toekomstige versie heb ik ook al (zoals slappe kip hierboven opmerkt) een soort van 'database info' singleton in gedachten. Deze kan eenmalig alle informatie cachen zodra deze nodig is, en hierdoor de performance nóg verder opkrikken :) Vraag blijft of erg veel nut heeft, want je moet wel véél objecten aanmaken en oproepen en er actief dingen mee gaan doen voordat dat gedeelte omhoog komt in de debug profilers. (overigens, installeer XDebug, het scheelt je een hoop hoofdpijn ;) )
Zoiets kan je natuurlijk ook nog altijd "op aanvraag" implementeren. Dat de gebruiker de keuze heeft om, wanneer hij veel objecten gebruikt, de "singleton-cache" aan te zetten.

Ik wil het gebruiken voor mijn cms, waar het aantal objecten snel uit de hand kan lopen. Ik ga dus daarom wel voor die singleton achtige oplossing, maar inderdaad meer op een soort guard / informant achtige manier. :)
De trucs kun je zo uit de laatste versie (vers voor je geupload) van m'n dbObject halen. Ik heb wat erg leuke features bij elkaar verzonnen zoals een Find() functie die nu ook een pad kan lopen door aan elkaar gekoppelde objecten, waarbij je in elke stap nog extra where parameters kan toevoegen. Erg leuk om dat in je hoofd te proberen te proppen :P

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * Zoek alle SkillGroupFlowRelation objecten die via 
* FlowRouting -> MainTimeFrameRelation -> MainRouting 
* (die description $this->routing en CustomerID $this->srn->CustomerID heeft) -> 
* SrnMainRelation aan een Srn met $this->srn->ID zit :Y) 
 */

$input = dbObject::Search('SkillGroupFlowRelation', 
                Array('FlowRouting' =>
                    Array("MainTimeframeRelation" => 
                        Array("MainRouting"=> Array(
                                "Description"=> $this->routing,
                                "CustomerID" => $this->srn->CustomerID,
                                "SrnMainRelation" => 
                                        Array("Srn" => Array("ID"=>$this->srn->ID)))))));


meer info en docs en demos:
http://www.schizofreend.nl/Pork.dbObject/

google code base:
http://code.google.com/p/pork-dbobject/downloads/list

hope this helps you :)
Ah, ik ga even je nieuwe versie inspecteren. En opnieuw beoordelen of ik het beter kan :+ 8)7
offtopic:
Ah, en nog meer nieuwe features dus ;)

[ Voor 3% gewijzigd door mithras op 26-10-2008 11:19 ]


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

mithras schreef op zondag 26 oktober 2008 @ 09:59:
[...]
Ik hoopte al dat je zou reageren :+. Ik kwam bij mijn "vooronderzoek" ook uit op PorkDb, omdat het juist lightweight is (mijn requirement met stip op nummer 1). Na je code bekeken te hebben vond ik zelf sommige dingen niet heel handig voor de gebruiker en dacht het dus beter te kunnen :p
Kun je een paar dingen benoemen? Ik ben altijd op zoek naar de snelste / slimste weg. Gemak 'als programmeur zijnde' is *juist* de basis van heel Pork.dbObject.
Mmm, dat is wel een redelijk goede oplossing. Met het door jouw code lopen zag ik dat er bij elke relatie een enorme controleloop uitgevoerd werd, dat leek me niet zo handig.
De checks en de grootte van die loop vallen best mee hoor, meeste is niet veel meer als wat jij doet in je voorbeeld :) gooi die handel maar eens door een profiler zou ik zeggen.
Toch is de oplossing niet ideaal: je kan geen relaties aan klasse toevoegen die geen id hebben, i.e. niet van tevoren hebben meegekregen. Of je moet ze tussentijds opslaan, maar of dat nu een ideale oplossing is...
offtopic:
De mappings uit de database, dat moet zeker nieuw zijn?
Ik snap even niet helemaal wat je bedoelt denk ik., jij bedoelt een dat een object eerst ge-Save()-'d moet worden voordat het een ID krijgt en ge-Connect() kan worden aan een andere dbObject?
[...]
Zoiets kan je natuurlijk ook nog altijd "op aanvraag" implementeren. Dat de gebruiker de keuze heeft om, wanneer hij veel objecten gebruikt, de "singleton-cache" aan te zetten.
Zo werk ik idd al mn hele leven :P 'op aanvraag' is alleen meestal m'n eigen "oke, nu heb ik dit nodig, nu ga ik het bouwen" :P
Ik wil het gebruiken voor mijn cms, waar het aantal objecten snel uit de hand kan lopen. Ik ga dus daarom wel voor die singleton achtige oplossing, maar inderdaad meer op een soort guard / informant achtige manier. :)

[...]
Ah, ik ga even je nieuwe versie inspecteren. En opnieuw beoordelen of ik het beter kan :+ 8)7
offtopic:
Ah, en nog meer nieuwe features dus ;)
Suc6, ik hoor wel wat je er van vindt :)

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
SchizoDuckie schreef op zondag 26 oktober 2008 @ 14:02:
[...]

Kun je een paar dingen benoemen? Ik ben altijd op zoek naar de snelste / slimste weg. Gemak 'als programmeur zijnde' is *juist* de basis van heel Pork.dbObject.
Als je echt al mijn kritieken wil weten moet je nog even wachten, want ik heb nu eigenlijk tentamens (en ben dus al teveel met programmeren bezig geweest :p). Het zit o.a. in de methods voor relaties: concept van "automatisch" bepalen is imho niet echt handig. Dat probleem wordt verholpen met een customRelation(). Dat is denk ik meer een pleister op een bestaande wond die je zelf hebt gemaakt. Verder is de manier van zoeken nu wel uitgebreid, maar voor simpele dingen moet je teveel typen. Ik denk zelf dat op een andere manier het sneller kan. Daar ben ik nog niet aan begonnen, dus let's see :+
De checks en de grootte van die loop vallen best mee hoor, meeste is niet veel meer als wat jij doet in je voorbeeld :) gooi die handel maar eens door een profiler zou ik zeggen.
Ja ik moet binnenkort maar eens gaan profilen, ook mijn eigen zaakje :p
Ik snap even niet helemaal wat je bedoelt denk ik., jij bedoelt een dat een object eerst ge-Save()-'d moet worden voordat het een ID krijgt en ge-Connect() kan worden aan een andere dbObject?
Laat maar, ik had verkeerd gekeken. Je voert een save() uit na een connectie, maar dat is wel logisch. Het hoeft niet denk ik (moet ik nog even over nadenken), maar wat ik eerder zei klopte niet...
Zo werk ik idd al mn hele leven :P 'op aanvraag' is alleen meestal m'n eigen "oke, nu heb ik dit nodig, nu ga ik het bouwen" :P
Nee, ik bedoel meer dat de programmeur functies kan enablen. Ik heb een eigen library van functies geschreven, waar je bijvoorbeeld dit kan doen:
PHP:
1
2
3
$template = qwik::get( 'template' ); //Roept template engine op
$database = qwik::get( 'db' ); //Roept database op
$database->loadMapper();
Bij die laatste aanroep laadt pas de gehele O/R mapper in (ook al is hij maar 550 regeltjes). Naast gebruiksvriendelijkheid focus ik meer op lightweight dan op functionaliteit. Ik heb liever dat ik dus on-demand de mapper laad en wanneer ik het niet gebruik, ik het hele gebeuren ook niet automatisch include :)
Daarmee bedoelde ik dus eigenlijk ook het "on demand aanzetten van de cache":
PHP:
1
2
3
4
$database = qwik::get( 'db' );
$database->loadMapper();
$database->setConstraintsFromDatabase( true );
$database->setMapperCache( true );
Nu gaat (voorbeeldcode) de O/R mapper pas de objecten qua types linken aan de database (regel 3) en die informatie wordt meteen ook gecached (regel 4). Zo kan je dus geheugen verminderen door functionaliteit weg te laten. Het is eenzelfde idee achter het __autoload(). Dat bedoelde ik er eigenlijk meer mee :P

Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Ik snap je techniek, maar begrijp ik dat jij in 1x je gehele database schema in het geheugen laadt ook al heb je die nodig? Mijn dbobjects kan je instantiaten, en dan worden *alleen* de classes ge-autoload en de db geanaliseerd als je een class aanroept die ID != false hebt. Net zo light-weight dus imo? :)

Over je optionele functionaliteit: dat soort meuk enable/disable ik netjes in m'n settings.ini :) Zo zou je dus idd die schema cache in kunnen bouwen, al denk ik dat ik eerder zou kiezen om netjes m'n dbobject te subclassen voor dit soort stuff. Dat houdt je code netter en overzichtelijker als je diep in je classes moet gaan graven om een optioneel iets er in te bouwen.

[ Voor 10% gewijzigd door SchizoDuckie op 27-10-2008 00:36 ]

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
SchizoDuckie schreef op maandag 27 oktober 2008 @ 00:35:
Ik snap je techniek, maar begrijp ik dat jij in 1x je gehele database schema in het geheugen laadt ook al heb je die nodig? Mijn dbobjects kan je instantiaten, en dan worden *alleen* de classes ge-autoload en de db geanaliseerd als je een class aanroept die ID != false hebt. Net zo light-weight dus imo? :)
Nee, loadMapper() doet alleen een include van qwik.db.or.php waar de qwikDbObject klasse in staat. Het is slechts een voorbeeld dat je zonder loadMapper() aan te roepen niet je php vermoeit met extra code.

En het database schema, daar doe ik nog niet aan. Ik zet in php slechts een object beschrijving (extenden van qwikDbObject met database=>property mapping & relaties, zoals jij ook doet). Het opzoeken van de types in de database doe ik dus nog niet. Het getConstraintsFromDatabase() is slechts een voorbeeld dat je alleen de functionaliteit van het opleggen van bepaalde constraints die in je database zijn aangegeven (bijvoorbeeld int(4) of varchar(255)) ophaalt wanneer je aangeeft dat je dat wil. Het is namelijk wel een overweging waarbij het ten koste gaat van je snelheid (x aantal extra queries uitvoeren). Deze optie heb ik nog niet ingebouwd in mijn systeem hoor, maar het is wel een optie om dat te doen :)
Over je optionele functionaliteit: dat soort meuk enable/disable ik netjes in m'n settings.ini :) Zo zou je dus idd die schema cache in kunnen bouwen, al denk ik dat ik eerder zou kiezen om netjes m'n dbobject te subclassen voor dit soort stuff. Dat houdt je code netter en overzichtelijker als je diep in je classes moet gaan graven om een optioneel iets er in te bouwen.
Dat cachen heb ik nog niet, dus ook eigenlijk geen idee wat ik daarmee ga doen. Het subclassen is wel wat netter, maar of het zoveel voordelen oplevert? Dat weet ik nog niet...

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Wat SchizoDuckie bedoeld is niet dat je van alles ophaalt uit de database, maar dat je voor elk request weer je complete domein definitie gaat lopen parsen. Objecten worden gedefinieerd en relaties worden gelegd.

Ik ga even een knuppel in het hoenderhok gooien:
Gezien de manier waarop php werkt lijkt me een in php geschreven runtime draaiende OR mapper nodeloos vertragend. Voor elk request waarbij iets met de DB gedaan wordt, wordt telkens weer het domein model verwerkt (of wordt dynamisch gekeken tot hoever het domein model ingeladen moet worden). Ik heb het hier alleen nog maar over de definities hoe dit in elkaar zit en hoe dit aan elkaar gelinkt is.

Ikzelf zou eerder mijn heil zoeken in een 'compile time OR mapper'. Uiteraard heeft php niet echt een compile time, maar dat is wel te simuleren door een stuk programmatuur dat php-code genereert. Dat klinkt misschien vreemd, maar dat is ook hoe Smarty bijvoorbeeld werkt.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Janoz schreef op maandag 27 oktober 2008 @ 13:24:
Wat SchizoDuckie bedoeld is niet dat je van alles ophaalt uit de database, maar dat je voor elk request weer je complete domein definitie gaat lopen parsen. Objecten worden gedefinieerd en relaties worden gelegd.

Ik ga even een knuppel in het hoenderhok gooien:
Gezien de manier waarop php werkt lijkt me een in php geschreven runtime draaiende OR mapper nodeloos vertragend. Voor elk request waarbij iets met de DB gedaan wordt, wordt telkens weer het domein model verwerkt (of wordt dynamisch gekeken tot hoever het domein model ingeladen moet worden). Ik heb het hier alleen nog maar over de definities hoe dit in elkaar zit en hoe dit aan elkaar gelinkt is.

Ikzelf zou eerder mijn heil zoeken in een 'compile time OR mapper'. Uiteraard heeft php niet echt een compile time, maar dat is wel te simuleren door een stuk programmatuur dat php-code genereert. Dat klinkt misschien vreemd, maar dat is ook hoe Smarty bijvoorbeeld werkt.
Dat is dus idd wat die 'schema manager' singleton zou moeten gaan doen. Die kan de structuur onthouden (serialize ftw) en de volgende keer weer inladen. dát zou wel performance kunnen schelen, maar dan zit je weer met het feit dat je minder flexibel bent als je een wijziging aan een bestaande class maakt. hoe weet die mapper dat? Dan moet je z'n cache bijv. met de hand leeggooien, en als je dat vergeet kom je alsnog met vage dingen in aanraking :P

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Singletons in php vind ik persoonlijk een beetje zinloos aangezien er binnen php alleen maar een requestscope bestaat, maar met het serializen zit je inderdaad al een stuk in de buurt. Je houdt inderdaad het probleem van die caching.

Je oplossing is echter nog wel wat zwaar wanneer je maar iets simpels met de db wilt doen. Denk daarbij bijvoorbeeld aan een request om een plaatje op te roepen met een id waar in de database vervolgens de (locatie van de) afbeelding bijgezocht moet worden. Als je daarvoor eerst je complete domein definitie in moet gaan laden.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Janoz schreef op maandag 27 oktober 2008 @ 14:31:
Singletons in php vind ik persoonlijk een beetje zinloos aangezien er binnen php alleen maar een requestscope bestaat, maar met het serializen zit je inderdaad al een stuk in de buurt. Je houdt inderdaad het probleem van die caching.

Je oplossing is echter nog wel wat zwaar wanneer je maar iets simpels met de db wilt doen. Denk daarbij bijvoorbeeld aan een request om een plaatje op te roepen met een id waar in de database vervolgens de (locatie van de) afbeelding bijgezocht moet worden. Als je daarvoor eerst je complete domein definitie in moet gaan laden.
Daarom laadt die van mij ook alleen de benodigde classes in als ze gebruikt gaan worden 8-)

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Ik heb nog even zitten te denken :) De cache functionaliteit van de 'schema manager' zou je simpel kunnen opzetten door (bijv. alleen in debug mode) de md5 sum van de classes die gebruikt worden te cachen, en het schema te rebuilden als er een sum gewijzigd is of er een nieuwe class ingeladen wordt :)

Morgen maar eens wat profiler testjes doen of dat sneller is als je het unserialized vanuit een file vs dynamisch opbouwt

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Tja, dan wordt het wel weer wat duurder he. Neem weer de case waarbij je enkel met een ID een url uitleest. Als je dan vervolgens de MD5 van allemaal bestanden gaat trekken en deze vergelijken met waardes die je uit een ander bestand leest dan wordt het toch wel weer wat duur imho.

Ik blijf er bij dat je het hele OR genereer gebeuren niet @runtime moet doen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'

Pagina: 1