04. august 2006 - 10:03Der er
11 kommentarer og 1 løsning
Mangler idéer til "object-handler"
Hej php-folk,
Jeg har gennem de sidste par år udviklet på et efterhånden ret stort website og er nu gradvist ved at løbe ind i et problem. Jeg har i toppen af hver php-fil include'et init.php. Denne init.php er med årene blevet enorm stor. Jeg har nemlig tilføjet nye funktioner til init.php hver gang jeg har haft behov for at lave en php-funktion, der kunne nås fra flere sider. Da størrelsen af init.php nu er blevet ret lang, er jeg nu af performance- og overskuelses-mæssige årsager ved at koge alle disse funktioner ned i nogle objekter, fx users.php der er et objekt der håndterer alt ang. brugere, mail.php (sjovt nok et objekt der håndterer post på siden) osv.
Som det er nu inkluderer jeg alle disse objekter således i min init.php:
include("users.php"); include("mail.php"); $user = new user(); $mail = new mail();
osv.
Jeg har nu tænkt på, at det måske kunne være en god idé, at få det lavet sådan disse objekt-filer kun inkluderes når de skal bruges (for at få nedsat sammenlagt kodemængde som skal parses).
Umiddelbart kunne jeg jo bare skrive: include("users.php"); $user = new user();
... i starten af hver fil, der skal bruge user-objektet. Det ville jo være ok og ganske fornuftigt performance-mæssigt. Dog har jeg en anelse om det kan laves noget mere kompakt.
Man kunne lave noget i stil med dette (ikke testet, men håber i kan se princippet):
function obj_exec($obj, $method) { global ${$obj}; if(!$obj) { include($obj.".php"); ${$obj} = new ${$obj}; } return eval(${$obj}."->".$method); } obj_exec("user", "create(".$username.", ".$password.")"); // Eksempel: $user->create([username], [password]) opretter bruger
På den måde behøver man ikke initialisere et objekt før man kalder create-metoden. Men obj_exec("user", "create(".$username.", ".$password.")"); er pænt meget længere og mere uoverskueligt end bare: $user->create($username, $password);
... og derfor er min obj_exec() ikke helt tilfredsstillende. Det må kunne gøres smartere.
Håber I kan se min problemstilling. Det jeg ønsker er ikke et decideret svar, men nærmere idéer til hvordan man kunne opsætte sådan en "object-handler". Jeg er interesseret I at høre fra andre, der har været i samme tanker og hvilke løsning du/I kom frem til. Det kan også være det generelt set ER bedre med "slave-modellen" hvor hver objekt skal inkluderes og laves i toppen af hver fil?
Dernæst - en lille rant omkring brug af exec... Vi starter med et lille citat:
"If eval() is the answer, you're almost certainly asking the wrong question." -- Rasmus Lerdorf, BDFL of PHP
Istedet for at bruge eval (som er farligere en døden selv), så brug fx call_user_func funktionen i php (http://dk.php.net/call_user_func) da du på den måde ikke flirter med døden aka eval..
__autoload hjælper med at auto-include'e filerne -smart! Det vil jeg helt klart bruge! Men det kunne jo også være smart hvis man kunne springe "$test = new test();" over, sådan at hvis man kører:
$test->tester();
og $test ikke findes, så køres
include("test.php"); $test = new $test;
.. automatisk.
Jeg forsøgte med: function __autoload($class_name) { global ${$class_name}; if(!${$class_name}) { require_once $class_name.".php"; ${$class_name} = new ${$class_name}; } }
Men den gik, som jeg regnede med, ikke :) Kan det gøres på en anden måde?
Du kan lave de funktion du ønsker om til statiske funktioner der selv opretter de klasser der er behov for - eg (php5 eksempel, fjern alt det "sjove" for at få php4-kompatibel kode)
<?php class User { public static function create( $name, $password ) { // opret ny bruger her - bemærk du ikke kan refere til $this // du kan dog kalde andre statiske funktioner via // self::funktion(); } }
User::create('myself', 'mypassword'); ?>
Det resultere i noget der minder relativt meget om namespaces, så hvis det kun skal bruges til at gruppere funktioner efter funktionalitet, så er det jo fint
---
Hvis du har brug for at kunne refere til $this, så er Singleton et hit...
<?php class User { private static $instance = null;
private __construct() { // konstruktør }
public static function instance() { if( self::$instance === null ) { self::$instance = new User(); } return self::$instance; }
public function create( $username, $password ) { // gør det du skal her, inkl $this kald } }
Igen tak for svaret. Det giver en billede af hvad der er muligt. Dog føler jeg mig ikke helt 100% sikker på, at jeg ud fra din forklaring er gearet til at vælge den HELT rigtige metode (ikke fordi din forklaring fejler noget, men fordi det simpelthen ikke er muligt at forklare det i det omfang jeg ønsker med så kort en tekst). Jeg er en fyr der meget meget gerne vil være 100% sikker på, at det jeg laver, er i orden :)
Af den grund får du lige et tillægsspørgsmål, som du måske kan svare på: Kender du nogle PHP-bøger, der henvender sig til folk med relativ god php-erfaring, men som gerne lige vil tage sine egenskaber til "sidste niveau" :)
Hmm, der er en bog der hedder noget i retningen af "Power PHP5 Programming" hvilket er meget godt - og så en lille ynglingsbog som ikke er PHP relateret, men som kan give en rigtigt mange gode måder at strukturere sine scripts på - "Design Patterns - Elements of Reusable Object Orientated Programming"
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.