Toon posts:

[php5] static method invoked by...

Pagina: 1
Acties:

Verwijderd

Topicstarter
Dag schuurvolk,

Ik ben bezig met het schrijven van een ActiveRecord class voor php die m.b.v. method overloading dynamisch de database bewerkt.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
class ActiveRecord { 
  function __call($name, $args) {
    // do something
  }
  function save() {
    // do something
  }
  ...
}
class Book extends ActiveRecord
{
}

In de class ActiveRecord zit ook een static final method retrieveByPK($key) zodat een dergelijke constructie als hieronder mogelijk is.
code:
1
$book = Book::retrieveByPK(4);

Wat wil nou het geval. Aangezien statische methodes niet runtime geresolved worden, levert een get_class() in de retrieveByPK methode niet de naam van de class die de methode aanroept. Erg vervelend aangezien retrieveByPK een nieuw Book object moet aanmaken en ik loose coupling wil houden zodat elke class ActiveRecord kan extenden.

Op zend.com wordt een oplossing genoemd met betrekking met dit probleem, alleen is het nogal een omslachtige (in iedere subclass de retrieveByPK definieren en de get_class waarde meegeven aan de parent.

Nu heb ik een oplossing bedacht die ranziger is dan hierboven qua performance, maar volgens mij redelijk zou moeten werken. Ik zou graag willen weten wat jullie er van vinden en of jullie een oplossing hebben voor mijn probleem.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    function _get_class() {
        
        $trace = debug_backtrace();
        $traceSize = sizeOf($trace);
        for ($i = 0; $i < $traceSize; $i++) {
            if ($trace[$i]['type'] == '::') {
                $lineNumber = $trace[$i]['line'];
            }
        }
        $fp = fopen($trace[$i]['file'], 'r');
        $i = 0;
        while ($i++ < $lineNumber) {
            // wie meer dan 1024 characters op een regel plaatst in code is niet goed wijs...
            $line = fgets($fp);
        }
        fclose($fp);
        preg_match('/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)::/', $line, $matches);
        return $matches[1];

    }

Deze code gebruikt de debug_backtrace() gegevens om het bestand te openen voor lezen dat de methode aanroept. Vervolgens wordt de juiste regel opgezocht en wordt met behulp van de regular expression de naam opgehaald en geretouneerd.

In de categorie ranzig scoort deze methode hoog, maar het werkt redelijk (zolang je maar een instructie per regel plaatst. Iemand een betere oplossing?

[ Voor 14% gewijzigd door Verwijderd op 04-02-2006 11:34 ]


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Mischien beter om dan af te stappen van de statische calls omdat je eigenlijk gewoon 'echte' polymorphisme nodig hebt? Dat zou echter ook betekenen dat je van het Active Object pattern moet afwijken en een apart object moet maken waarmee je de objecten ophaalt en opslaat. Misschien ben je al bekend met het Repository pattern?

[ Voor 4% gewijzigd door Michali op 04-02-2006 12:00 ]

Noushka's Magnificent Dream | Unity


Verwijderd

Wat je gemaakt heb is een creatieve oplossing maar volgens mij is de performance hit veel te groot voor wat je eraan wint. Voor iedere call de stack trace aflopen, de class file openen en scannen om aan je class te geraken.. :\

Zoals de meneer boven mij zegt, ik denk dat je beter een compromis zoekt. Ofwel inderdaad een object instantieren, ofwel tevreden stellen met calls als Book::retrieveBookByPK(4);

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Als je de conventie hebt om alle source bestanden de naam van de class te geven, dan zou je ook iets als dit kunnen doen:
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
<?php

// Super.php

class Super
{
    public static function test()
    {
        $debugBacktrace = debug_backtrace();
        $pathInfo = pathinfo($debugBacktrace[0]['file']);
        $class = basename($pathInfo['basename'], "." . $pathInfo['extension']);
        var_dump($class);
    }
}

// Sub.php

class Sub extends Super
{
}

// client.php

Sub::test();

?>


Edit:

Hmm, ik bedenk me ineens dat de file waarde dan waarschijnlijk gevuld is met Super.php ipv Sub.php. Dus dat gaat dan denk ik ook niet op. Helaas...

[ Voor 19% gewijzigd door Michali op 04-02-2006 15:10 ]

Noushka's Magnificent Dream | Unity