Genera dynamicmente le classi in fase di runtime in php?

Ecco cosa voglio fare:

$clsName = substr(md5(rand()),0,10); //generate a random name $cls = new $clsName(); //create a new instance function __autoload($class_name) { //define that instance dynamically } 

Ovviamente questo non è quello che sto facendo in realtà, ma fondamentalmente ho nomi sconosciuti per una class e in base al nome, voglio generare la class con determinate properties; ecc.

Ho provato a usare eval (), ma mi sta dando dei risvolti privati ​​e $ this-> riferimenti …

//modificare

Ok, ovviamente il mio breve e dolce "ecco quello che voglio fare" ha causato enormi conflitti e costernazione tra coloro che potrebbero essere in grado di fornire risposte. Nella speranza di get una risposta effettiva sarò più dettagliato.

Ho una struttura di validation che utilizza i suggerimenti sul codice nel sito che gestisco. Ogni function ha due definizioni

 function DoSomething($param, $param2){ //code } function DoSomething_Validate(vInteger $param, vFloat $param2){ //return what to do if validation fails } 

Sto cercando di aggiungere un validatore per le chiavi primarie nel mio database. Non voglio creare una class separata per OGNI tabella (203). Quindi il mio piano era di fare qualcosa di simile

 function DoSomething_Validate(vPrimaryKey_Products $id){ } 

Dove __autoload genera una sottoclass di vPrimaryKey e imposta il parametro table su Products.

Felice adesso?

Questa è quasi certamente una ctriggers idea.

Penso che sarebbe meglio spendere il tuo tempo creando uno script che creerebbe le tue definizioni di class per te, e non provando a farlo in fase di runtime.

Qualcosa con una firma da row di command come:

 ./generate_classs_from_db <host> <database> [tables] [output dir] 

è divertente, in realtà questa è una delle poche cose in cui la valutazione non sembra una ctriggers idea.

fintanto che è ansible garantire che nessun input dell'utente inserirà mai la valutazione.

hai ancora dei lati negativi come quando usi una cache bytecode che il codice non sarà memorizzato nella cache, ecc., ma i problemi di sicurezza di eval sono praticamente legati alla capacità di input dell'utente nell'eval, o alla conclusione in un ambito sbagliato.

se sai cosa stai facendo, eval ti aiuterà con questo.

Detto questo, secondo me stai molto meglio quando non fai affidamento sul tipo di suggerimento per la tua validation, ma hai una function

 DoSomething_Validate($id) { // get_class($id) and other validation foo here } 

So che questa è una vecchia domanda e ci sono risposte che functionranno, ma volevo offrire alcuni frammenti che avrebbero risposto alla domanda originale e penso offrano una soluzione più ampia se qualcuno wheresse finire qui come ho fatto quando ho cercato una risposta a questo problema.

Crea una singola class dynamic

 <?php // Without properties $myclassname = "anewclassname"; eval("class {$myclassname} { }"; // With a property $myclassname = "anewclassname"; $myproperty = "newproperty"; eval("class {$myclassname} { protected \${$myproperty}; }"; ?> 

Finché riesci a uscire correttamente dal tuo text, potresti anche aggiungere una function.

Ma cosa succede se vuoi creare dynamicmente classi basate su qualcosa che potrebbe essere dinamico come creare una class per each tabella nel tuo database come la domanda originale menzionata?

Crea più classi dinamiche

 <?php // Assumes $dbh is a pdo connection handle to your MySQL database $stmt=$dbh->prepare("show tables"); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); $handle = null; $classcode = ''; foreach ($result as $key => $value) { foreach ($value as $key => $value) { $classcode = "class {$value} { "; $stmt2=$dbh->prepare("DESC $value"); $stmt2->execute(); $result2 = $stmt2->fetchAll(PDO::FETCH_ASSOC); foreach ($result2 as $key => $value) { $classcode .= "public \${$value['Field']}; "; } $classcode .= "}"; eval($classcode); } } ?> 

Questo genererà dynamicmente una class per each tabella in un database. Per each class, viene creata anche una properties; che prende il nome da each colonna.

Ora è stato sottolineato che non dovresti farlo. Finché controlli ciò che accade nella valutazione, il rischio di sicurezza non è un problema. MA – probabilmente c'è una soluzione che ha più senso se ci pensi abbastanza profondamente. Pensavo di avere il perfetto caso d'uso per creare dynamicmente nuove classi. L'attento esame del problema ha dimostrato il contrario.

Una ansible soluzione: usa stdClass per creare oggetti che sono solo contenitori di dati e non hanno bisogno di alcun metodo.

Inoltre, come accennato, è ansible utilizzare uno script per generare manualmente molte classi. Nel caso di classi che eseguono il mirroring delle tabelle del database, è ansible utilizzare la stessa logica di cui sopra e invece di eseguire un'eval, scrivere tali informazioni in un file.

Penso che l'utilizzo di eval() non sia una soluzione affidabile, soprattutto se lo script o il software verranno distribuiti a client diversi. I provider di hosting condivisi disabilitano sempre la eval() .

Sto pensando ad un migliore approccio come questo:

 <?php function __autoload( $class ) { require 'classs/'.$class.'.php'; } $class = 'App'; $code = "<?php class $class { public function run() { echo '$class<br>'; } ".' public function __call($name,$args) { $args=implode(",",$args); echo "$name ($args)<br>"; } }'; file_put_contents('classs/App.php' ,$code); $a = new $class(); $a->run(); 

Dopo aver terminato di eseguire il codice, è ansible eliminare il file, se lo si desidera, l'ho testato e funziona perfettamente.

 function __autoload($class) { $code = "class $class {` public function run() { echo '$class<br>'; } ".' public function __call($name,$args) { $args=implode(",",$args); echo "$name ($args)<br>"; } }'; eval($code); } $app=new Klasse(); $app->run(); $app->HelloWorld(); 

Questo potrebbe aiutare a creare una class in fase di runtime. Crea anche un'esecuzione methor e un metodo catchall per methods sconosciuti, ma è meglio creare oggetti in runtime, non classi.

Usare eval () è davvero una ctriggers idea. Si apre un grande buco di sicurezza. Basta non usarlo!

Si prega di leggere le risposte degli altri su come questa sia davvero una pessima idea.

Una volta capito questo, ecco una piccola demo su come potresti, ma non dovresti farlo.


 <?php $clname = "TestClass"; eval("class $clname{}; \$cls = new $clname();"); var_dump($cls);