Comportamento assurdo di setcookie con i plugin...

Salve,

prima di tutto un saluto a tutta la community ed allo staff, cercando un pò di documentazione riguardante lo Zend Framework sono approdato qui.  :)

Ho molta dimestichezza con php (lo uso dai tempi di php3) ed abbastanza con la programmazione OO, CO, AO; ho seguito da spettatore lo sviluppo dello ZF ad adesso mi è sembrato abbastanza maturo per poterlo utilizzare seriamente :)

Devo dire che la doc eng presente sul sito di zend è buona, ma data la velocità con cui cresce il framework in diversi punti è deficitaria; penso che lo farò presente anche tramite il wiki ufficiale, eventualmente proponendo qualche riga scritta di mio pugno   :P

Adesso passiamo al perché di questo post, in breve: Controller_Plugin + (routeShutDown || dispatchLoopStartup ) + setcookie = kaboom  :buck:

Cosa volevo fare: creare un plugin, caricato in fase di bootstrap del Zend_Controller_Front che si occupasse di gestire il multilanguage.

Cosa ho fatto:

- Ho Creato una classe a se stante XApp_Bootstrap_Helper_Translation (usando il DP. singleton... anche se non era necessario... le ho provate tutte) che:

a. Setta come defaultLang la lingua passata come quella di default

b. Controlla se è settato un cookie (dal nome passato in fase di configurazione della classe), in caso affermative, se il valore del cookie è nell'array delle lingue supportate allora resetta defaultLang alla lingua presente nel cookie

c. con il metodo getDefaultLanguage restituisce il valore di defaultLang

ATTENZIONE: controllo nel metodo setConfig che non siano già settati dei valori, in caso contrario per non andare eventualmente a sovrascrivere la conf precedente (capirete il perchè di questo più avanti).

- Nel plugin di bootstap (on routeStartup), creo una nuova istanza di XApp_Bootstrap_Helper_Translation, prelevo il valore della lingua da usare come default e creo una nuova route per il multilingua:

    public function initRoutes()
    {
       
       $router = $this->_front->getRouter(); // returns a rewrite router by default
       
       //Start BootStrap Helpers
       $lang_helper = Angel_Bootstrap_Helper_Translation::getInstance();
       $lang_helper->setConfig
        (
           Zend_Registry::get('config')->language->default,
           Zend_Registry::get('language_available'),
           Zend_Registry::get('config')->language->cookieName
        );
      
       //Multilanguage Sites
      $multilanguageRoute = new Zend_Controller_Router_Route( ':language/:module/:controller/:action/*',
                                           array(
                                               'language' =>  $lang_helper->getDefaultLanguage(),
                                               'module' => 'default',
                                               'controller' => 'index',
                                               'action'     => 'index'
                                           )
                                       );
                                       
      $router->addRoute('default', $multilanguageRoute);
       
    }

- Ho Creato e registrato il Plugin "XApp_Controller_Plugin_Translation" che in dispatchLoopStartup richiama Zend_Locale,Zend_Translate ed affini caricando i file di lingua per la lingua passata da "$request->getParam('language')" che, nel caso in cui non fosse specificata da url la lingua da usare, dovrebbe restituire:

a. la lingua di default

b. la lingua scelta tramite cookie

nel caso in cui, invece, si visualizzasse una pagina dall'url "completo" (es.  /it/site/contactus) si forzerà la lingua "it" come lingua da usare per visualizzare la pagina.

Alla fine di tutto l'ambaradan setto il cookie che mi dovrebbe tenere in memoria la lingua preferita del visitatore.

I problemi sorgono proprio con quest'ultima azione, non mi so spiegare il perché, ma il cookie viene settato la bellezza di 3 volte! La prima volta bene, la seconda e la 3° con la lingua di default (settata in fase di configurazione) ed il bello è che non riesco a capire da dove esca fuori il valore sballato la 2° e la 3° volta, dato che effettuando il print a video delle variabili usate nel setcookie mi viene sempre restituito il valore corretto.

Da quel che ho letto e dallo schema che uso di riferimento: http://nethands.de/download/zenddispatch_en.pdf NON dovrebbero esserci richiami multipli alla function che setta il cookie!  ???

Ho effettuato anche massive search su tutti i file della libreria zend e della mia app e l'unico dannato setcookie è quello del plugin translate quindi non mi spiego come sia possibile ritrovarsi con 3 setcookie.

A riprova del fatto che viene settato 3 volte il cookie ho provato ad inserire sempre in dispatchLoopStartup del mio plugin Xapp_Controller_Plugin_Translation le seguenti righe:

setcookie(time(), Zend_Registry::get('language'), 86400*24*30, '/');
sleep(1);

var_dump($_COOKIE) richiamando la pagina http://192.168.1.110/en/default/index/index

array(4) {

  ["PHPSESSID"]=>

  string(32) "c6d5fad20be7fcc63075b51d57f9df98"

  [1231308847]=>

  string(2) "en"

  [1231308848]=>

  string(2) "it"

  [1231308849]=>

  string(2) "it"

}

Leggendo i timestamp si comprende che sono settati 3 cookie, di cui il primo è ok, gli altri no   ???

Ho provato a spostare il setcookie nell'IndexController (function init) e sembra che lì il cookie venga settato correttamente quindi, a questo punto non so proprio più cosa pensare  e non voglio di certo mettermi a scrivere nell'init function di ogni controller setcookie  :buck:

Qualcuno ha qualche idea?

Ringrazio anticipatamente,

Antonio.

inviato 7 anni fa
Antonio
modificato 7 anni fa
X 0 X

Mhh, non ho letto tutto il tuo post (maledetta fretta) ma hai già dato un'occhiata a Zend_Translate?

Dovrebbe offrire anche plugin ed helpers che magari fanno al caso tuo.

:bye:

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

Ciao,

utilizzo già il componente Zend_Translate (come ho scritto nel post), inoltre nella documentazione di Zend_Translate di helper e plugin non ne parla... potresti essere più preciso?  :)

Comunque non si spiega il triplo setcookie che avviene solo nei plugine non nelle action  :-\

risposto 7 anni fa
Antonio
modificato 7 anni fa
X 0 X

Scusami :P ho solo dato uno sguardo velocissimo al tuo post prima perché dovevo andare a pranzare. Ora lo leggo con calma e vediamo di venire a capo della situazione :P

Scusami ma perché non provi ad "indovinare" la lingua supportata dal browser?

:bye:

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

cut...

Scusami ma perché non provi ad "indovinare" la lingua supportata dal browser?

:bye:

Faccio anche quello nel plugin, ma se un utente vuole usare una lingua diversa voglio potergli dare questa possibilità anche se non è registrato (per gli utenti registrati e loggati seleziono la lingua scelta nel DB direttamente).

Il problema non è nel come trattare il cookie in lettura o altre cose, quella parte funziona senza problemi. Quello che non si spiega è perché nei plugin mi vengono settati 3 cookie se io ne dico di settare solo uno.

Non posso neanche fare un check per vedere se il cookie è già settato, perché in questo modo chi vuole cambiare la lingua da usare non può farlo perché il cookie non viene sovrascritto.

Se stai sviluppando di tuo una applicazione con Zend Framework potresti fare anche tu il test che ho fatto io?

Mettere in una function (che non sia ciclata, tipo: routeShutDown o dispatchLoopStartup)  di un plugin:

setcookie(time(), 'robaacaso', 86400*24*30, '/');
sleep(1);

e vedere se ti setta 3 cookie diversi.

Sto uscendo pazzo da 3 giorni  :crazy:

 :bye:

risposto 7 anni fa
Antonio
X 0 X

Ciao,

Non c'è nessun anima pia che effettua il breve test che ho descritto nel post precedente?  :'(

Mettere in un metodo che, dalla documentazione ufficiale, non dovrebbe essere richiamato più volte (tipo: routeShutDown o dispatchLoopStartup) di un plugin a caso:

setcookie(time(), 'robaacaso', 86400*24*30, '/');
sleep(1);

e vedere se vengono settati 3 cookie diversi.

Buon weekend,

Antonio.

risposto 7 anni fa
Antonio
X 0 X

Hai provato a fare un semplice debug posizionando un breakpoint sulla riga del setcookie. Dallo stacktrace dovresti capire chi sta chiamando il metodo e con quali parametri

 :bye:

risposto 7 anni fa
Gianni Tomasicchio
X 0 X

Hai provato a fare un semplice debug posizionando un breakpoint sulla riga del setcookie. Dallo stacktrace dovresti capire chi sta chiamando il metodo e con quali parametri

 :bye:

Ciao,

usando Zend Studio per il debug mi ritrovo con dei notice su REQUEST_URI:

Notice: ..../Bootstrap/Helper/Translation.php line 95 - Undefined index:  REQUEST_URI

Per effettuare il debug Zend_Studio utilizza php-cli? In questo caso non è possibile effettuare il debug delle apps scritte con zfw dato che nel router si da per scontato che REQUEST_URI esista  ???

risposto 7 anni fa
Antonio
X 0 X

Con lo Zend Studio, ma anche con altri IDE, puoi effetuare il cosidetto debug remoto, ovvero il debud di una richiesta proveniente da un browser verso un web server su cui è inslattata l'estensione PHP per il debug. In altre parole puoi ricreare e debuggare esattamente lo scenario che vuoi analizzare.

 :bye:

risposto 7 anni fa
Gianni Tomasicchio
X 0 X

Ciao Gianni,

causa influenza ho ripreso adesso ad interessarmi al problema.

Ho sistemato la macchina da develop con PHP5.2.8 + xdebug 2.0.4 ed eclipse + PDT 2.0 e, dai test effettuati risulta che il plugin viene richiamato 3 volte prima dell'effettiva presentazione a video della pagina

Ho inserito breakpoint sulle 3 seguenti righe:

$cookieName = Zend_Registry::get('config')->language->cookieName;
$cookieValue = Zend_Registry::get('language');
//Angel_Cookie::createPhpCookie($cookieName, Zend_Registry::get('language'), 86400*24*30, '/');
setcookie($cookieName, $cookieValue, 86400*24*30, '/');

Ed effettivamente la prima volta il cookie è ok, al 2 e 3° "ciclo" invece mi setta valori errati della lingua.

La documentazione di Zend Framework non fa alcun accenno al fatto che dei plugin vengano inizializzati più volte, quindi vorrei capire cosa sta succedendo  :buck:

Mi sto convincendo sempre di più che passare a JAVA sia la cosa migliore da fare  :-X

Avete qualche idea?

Saluti,

Antonio

risposto 7 anni fa
Antonio
modificato 7 anni fa
X 0 X

I plugin permettono di ridefinire un metodo di hook affinché quel codice venga chiamato dal Dispatcher.

Il Dispatcher esegue il dispatching degli ActionControllers in un ciclo, quindi un plugin che viene eseguito in preDispatch verrà chiamato ad ogni iterazione del DispatchLoop prima che l'ActionController venga segnato come dispatched.

Se ti stai chiedendo perché il dispatching è ciclico la risposta è semplice: è possibile definire uno stack di ActionControllers in modo che la richiesta venga indirizzata man mano da un'azione all'altra (operazione utile quando si creano delle viste composite).

In soldoni: se non vuoi che il tuo plugin venga eseguito più volte prova a registrarlo prima che inizi il ciclo di dispatching; in questo modo verrà eseguito una sola volta poco prima che il dispatcher inizi il suo lavoro.

 :bye:

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

I plugin permettono di ridefinire un metodo di hook affinché quel codice venga chiamato dal Dispatcher.

Il Dispatcher esegue il dispatching degli ActionControllers in un ciclo, quindi un plugin che viene eseguito in preDispatch verrà chiamato ad ogni iterazione del DispatchLoop prima che l'ActionController venga segnato come dispatched.

Se ti stai chiedendo perché il dispatching è ciclico la risposta è semplice: è possibile definire uno stack di ActionControllers in modo che la richiesta venga indirizzata man mano da un'azione all'altra (operazione utile quando si creano delle viste composite).

In soldoni: se non vuoi che il tuo plugin venga eseguito più volte prova a registrarlo prima che inizi il ciclo di dispatching; in questo modo verrà eseguito una sola volta poco prima che il dispatcher inizi il suo lavoro.

 :bye:

Ho letto la documentazione ed infatti il plugin che setta il cookie usa il metodo dispatchLoopStartup, ma il problema persiste.  :-\

risposto 7 anni fa
Antonio
X 0 X

Sto effettuando il debug step per step, riga per riga, e sembra che dopo aver inviato il response ricominci da capo l'esecuzione dalla index.php per 2 volte fino a quando non non si interrompe questo ciclo e viene restituito al browser la risposta.

Bug di php? Che la patch suhosin dia problemi?  ???

In oltre 8 anni di programmazione in php mai successa una cosa del genere  :-X

risposto 7 anni fa
Antonio
X 0 X

Ho reinstallato php da sorgenti con il minimo indispensabile di estensioni, niente da fare!

Se il cookie lo setto in un plugin sempre prima del dispatchLoop, mi viene settato 3 volte; se invece faccio lo stesso in una Action qualsiasi non ci sono problemi.

Sto visionando i sorgenti dello Zend_Controller dato l'unica cosa che mi viene in mente è che se cambiano i response header il framework per qualche motivo ricominci da capo l'esecuzione di tutto il ciclo (routing, dispatch etc etc)  :buck:

 :bye:,

Antonio

risposto 7 anni fa
Antonio
X 0 X

Guarda, in un problema del genere ci sono capitato anch'io, ma non ricordo la soluzione che ho adottato per risolverlo.

Il minimo che posso assicurarti è che non è un problema di ambiente (se è per quello che hai reinstallato php, ricompilandolo addirittura).

Fammi capire che tipo di applicazione hai sviluppato, hai postato troppo poco codice per permetterci di comprendere a fondo il tuo problema.

Prova a dare un'occhiata al codice di questo mio progetto su github e vedi se riesci a trovare qualche spunto:

index.php: file entry-point e bootstrap

init.php: file del plugin di bootstrap.

Il plugin di bootstrap contiene il codice necessario all'applicazione per avviarsi, potresti pensare di implementare un sistema di bootstraping simile al mio, implementando un ipotetico initLanguage che faccia quello di cui hai bisogno.

:bye:

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

Ciao,

intanto grazie per le risposte  :)

Per iniziare a giocare con ZF ho utilizzato la struttura di base (personalizzandola un pò) creata automaticamente quando si apre un nuovo progetto con Zend Studio per Eclipse. Quindi anche io ho un plugin di bootstrap che "on routeStartup" mi inizializza le cose fondamentali.

A differenza tua inizializzo anche il sistema di logging (con file stream e db), un motore di ricerca lucene, le sessioni, diversi plugin (per ora solo quello di autenticazione e quello che si occupa di recuperare le varie traduzioni e nel quale vi è quel dattato setcookie), il routing (trovi il sorgente della funzione in un mio precedente post.

Plugin Initializer (on routeStartup):

public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
          $this->initDb();
          $this->initSessions();
          $this->initSearchLucene();
        $this->initHelpers();
        $this->initView();
        $this->initControllers();
        $this->initPlugins();
        $this->initRoutes();
    }

Plugin Initializer (funzione initRoutes): la trovi nel primo messaggio del 3d

Plugin Initializer (funzione initPlugins):

    public function initPlugins()
    {       
               require_once 'Angel/Controller/Plugin/Translation.php';
         $this->_front->registerPlugin(new Angel_Controller_Plugin_Translation());
         
         require_once 'Angel/Controller/Plugin/Authentication';
         $this->_front->registerPlugin(new Angel_Controller_Plugin_Authentication());
    }

Dato che L'inizializzazione di tutto ciò che serve per le Traduzioni non sono un paio di righe, ho preferito creare un plugin apposito (mi sembra anche più corretto dal punto di vista della programmazione), stesso dicasi per "Angel_Bootstrap_Helper_Translation"  che richiamo in init routes per sapere che lingua settare di default.

Provo per testing ad accorpare tutto nel plugin Initializer e vediamo cosa ne esce...

Ciao :)

PS: Nel tuo progetto, nella index dovresti mettere anche (lo si dovrebbe fare da php5.x in poi): date_default_timezone_set('Europe/Rome');

risposto 7 anni fa
Antonio
X 0 X

HO RISOLTO!

Sembra che un dannatissimo

$request->getRequest()->getParam('language')

non venga ben visto nel plugin in dispatchLoopStartup (vorrei capire il perché...).

A causa di questa cosa ho perso 5giorni  :buck: :buck:, ringrazio trashofmasters e Gianni per il supporto  ;)

Antonio

risposto 7 anni fa
Antonio
modificato 7 anni fa
X 0 X

lol.

Probabilmente è dovuto al fatto che la richiesta non è esattamente intesa come semplice richiesta del browser. Infatti l'oggetto della richiesta viene utilizzato da differenti meccanismi interni del Front controller e del Dispatcher, e il suo stato cambia continuamente durante il processo. :D

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

io sono sempre dell'opinione che un bel "debug remoto" con un IDE decente potrebbe fornire tutte le risposte

 :bye:

risposto 7 anni fa
Gianni Tomasicchio
X 0 X

io sono sempre dell'opinione che un bel "debug remoto" con un IDE decente potrebbe fornire tutte le risposte

 :bye:

Eclipse + PDT2.0 con xdebug 2.0.4

Ho fatto il debug riga per riga e non pensavo che il problema fosse quel getparams perché, in tutti i casi, il valore la prima volta veniva settato bene e poi sovrascritto (ripeto che viene settato 3 volte il cookie per chissà quale motivo)  :-X

Per riuscire a trovare l'errore ho dovuto reimplementare tutto in maniera diversa, per poi confrontare il codice.

 :bye:

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