Problema OOP e call_user_func : $this not in object context

Ciao a tutti  :)

Ho un problema riguardante una chiamata dinamica ad un metodo di una classe, mi spiego meglio:

Ho una classe base controller che viene estesa per costruire nuove pagine (una classe derivata da controller per pagina).

La classe controller ha un metodo action che prende tra le variabili GET quella che contiene il nome dell'azione richiesta, ecco il codice di querto metodo:

private function action()
   {
      if(method_exists($this,$_GET[CONTROLLER_METHOD_HTTP_VAR]))
      {
         $func = array(get_class($this),$_GET[CONTROLLER_METHOD_HTTP_VAR]);
         $classname = get_class($this);
         $methodname = $_GET[CONTROLLER_METHOD_HTTP_VAR];
         call_user_func(array($classname,$methodname));
      } else {
         throw new methodNotFoundException("L'azione ".$_GET[CONTROLLER_METHOD_HTTP_VAR]." richiesta al modulo ".get_class($this)." non esiste!\n");
      }
   }

quindi un URL del tipo http://miosito.org/index.php?cm=sayHello

richiamerebbe il methodo sayHello della classe controller istanziata in index.php, ad esempio

<?php
include('controllerProva.php');


class page extends controller
{
   function sayHello()
   {
      $this->loadModule("hello");
   }
}
$c = new page();
?>

ma ottengo un messaggio di errore:

Fatal error: Using $this when not in object context in /var/www/bubble-framework/index.php on line 9

 :'(  :'(

Ho spulciato la documentazione di call_user_func(), ma non ho trovato errori... e non capisco perchè php si lamenta del fatto che utilizzi $this in un contesto sbagliato...

se qualcuno avesse qualche idea mi farebbe un graaande favore  :D  :D

Grazie  :bye:

inviato 8 anni fa
fatmatt
X 0 X

il nome della classe corrente lo puoi ottenere anche attraverso la costante magica __CLASS__

prova con quella.

:bye:

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
X 0 X

ciao, grazie per la risposta ma sembra non funzionare  :'(

la costante __CLASS__ al momento della chiamata è valorizzata con "controller" che è effettivamente la classe che viene este sa, non quella utilizzata, quindi cercando di chiamare ad esempio page::sayHello, la classe va a chiamare controller::sayHello

mmm cercherò di spremermi le meningi  :D

risposto 8 anni fa
fatmatt
X 0 X

Ho risolto!  ;D

Mi sono ricordato che cakephp adotta un sistema simile per richiamare i metodi delle classi che estendono app_controller. quindi mi sono andato a guardare l'implementazione del controller di cake php ed ho trovato la risposta:

call_user_func(array(&$this,$methodname));

ehhh W l'Open Source xD

risposto 8 anni fa
fatmatt
X 0 X

solo una domanda : stai cercando di implementare il pattern mvc? ;D

:bye:

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
modificato 8 anni fa
X 0 X

Si vede lontano un miglio eh  ;D  ;D

risposto 8 anni fa
fatmatt
X 0 X

già. :)

è il mio pattern preferito (dopo l'observer e decorator ;D)

risposto 8 anni fa
Andrea Turso
Andrea Turso
86
X 0 X

come specificato nella documentazione ufficiale:

http://it2.php.net/manual/it/language.pseudo-types.php#language.types.callback

se viene specificato il nome della classe, allora viene effettuata una chiamata al metodo statico, che ovviamente non può contenere $this

call_user_func(array('MyClass', 'myCallbackMethod'));

se invece viene passato un oggetto (e $this è un oggetto) allora viene chiamato un metodo dell'oggetto

$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));

la & che hai trovato nel codice di CakePHP serve in PHP 4 a passare un riferimento all'oggetto e non una sua copia. In PHP 5 il passaggio di un oggetto è sempre per riferimento e mai per copia. CakePHP infatti funziona anche con PHP 4.

 :bye:

risposto 8 anni fa
Gianni Tomasicchio
X 0 X

già! in effetti in questo caso l'operatore & è superfluo, però mi ha dato lo spunto giusto  ;D

( "&" comincia anche a darmi sui nervi... sto preparando un esami di fondamenti di informatica in C e non ne posso più...   ;D  :D  ;D )

grazie per la precisazione!!  O0

risposto 8 anni fa
fatmatt
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda