Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2006
    Messaggi
    10

    Oggetto globale e visibilità.

    Ciao!

    Probabilmente è una domanda banale, ma con php5 (sono nuovo nuovo del linguaggio in questione in generale...) non ho chiaro come realizzare la seguente cosa:

    immaginate di avere un classe di connessione ad un db che definisce un costruttore con username, pwd, host, etc...e che contiene altri metodi di "accesso" al db stesso per eseguire stored procedure, PS, etc...

    Ora, diciamo che banalmente nell'index.php (per ora tralascio volutamente questioni di SESSIONI e cose simili...) abbiamo uno skeleton che effettua un case simile a questo:
    <?php
    ....
    if(isset($_GET['show_login'])) {
    show_login_form();
    }

    else if(isset($_POST['login'])) {
    $db_connection = new db_handle("127.0.0.1", "db", $_POST['usernm'], $_POST['passwd']);
    $db_connection->db_connect();
    }
    php>

    Nel form sono ovviamente inseriti i dati di connessione e tramite POST viene richiamato il primo ramo elseif. Ora, mettiamo di voler richiamare un altro metodo di db_connection, ma da un altro ramo...l'oggetto non è più ovviamente visibile, però era logico crearlo lì dato che era a quel punto che veniva richiesta la connessione ed erano disponibili i dati.

    Quindi, come si può "globalizzare" quell'oggetto? Ho provato in alcuni modi usando il modificatore global ma non funziona: se l'oggetto fosse inizializzato a livello globale (prima dell'if ad esempio...) allora si, ma essendo inizializzato in un ramo la cosa non funziona.

    COsa mi sfugge?

    Grazie!

    Ciao!

  2. #2
    Inserisci l'oggetto nell'array $GLOBALS oppure utilizza il pattern singleton.

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2006
    Messaggi
    10
    Originariamente inviato da filippo.toso
    Inserisci l'oggetto nell'array $GLOBALS oppure utilizza il pattern singleton.
    Ciao!

    Grazie per il consiglio! L'idea del singleton effettivamente è del tutto corretta, ma nel tentare di implementarlo mi sto imbattendo in un comportamento alquanto strano: la variabile statica "perde" il suo valore quando reinizia un ciclo di $_GET/$_POST.

    Spiego bene quando accade questa cosa e secondo me da cosa dipende: immagina di avere un file index.php così costruito:

    <html vario...>
    <?php
    include_once("db_handle.php5");

    //Skeleton call.
    if(isset($_GET['show_login'])) {
    show_login_form();
    }
    else if(isset($_GET['order_by']) && isset($_GET['call'])) {
    db_handle::getIstance()->show_SP_table(); //Una funzione che ritorna dati...
    }

    else if(isset($_POST['login'])) {
    db_handle::getIstance("127.0.0.1", "db", $_POST['usernm'], $_POST['passwd'])->db_connect();
    db_handle::getIstance()->show_SP_table();
    }
    ?>

    In pratica, al caricamento della pagina viene visualizzato il famoso form e all'atto del POST viene invocata l'istanza di db_handle che, essendo NULL, viene creata con i dati appositi, si effettua la connessione e si richiama una funzione (show_SP_table) che visualizza alcuni dati. Fino a qui tutto ok.

    Ora, nella tabella ci sono dei Link che generano un URL contenente i parametri order_by e call. Quando si clicca su uno di questi link lo skeleton precedente viene rieseguito (RIESEGUENDO ANCHE LA include_once...) e questa volta entra nel primo else if dove rieffettua db_handle::getIstance()->show_SP_table(); A questo punto muore con un errore sulla mysqli_query chiamata da show_SP_table:

    mysqli_query() expects parameter 1 to be mysqli, null given

    OVVIO! Il parametro $connection richiesto da mysqli_query è ORA NULL. Infatti, debuggando, ho verificato che quando richiama la suddetta getIstance() si cerca di RE-inizializzare la variabile statica poichè viene trova ANCORA a null nonostante sia stata inizializzata dalla getIstance() precedente!!! Ovviamente la getIstance attuale non contiene parametri e i valori di default sono NULL, dunque la mysqli_query fallisce per quello.

    Il problema è che la variabile statica viene RE-inizializzata, cioè trovata a NULL, quando non doveva esserlo più!

    Il codice esprime ovviamente in modo chiaro di non reinizilizzare la variabile qualora sia stata già inizializzata:

    <?php
    class db_handle {
    protected $hostname;
    protected $db_select;
    protected $usernm;
    protected $passwd;
    protected $connection; //Connection variable used for all queries.

    private static $istance = NULL;

    private function __construct($host, $db, $user, $passw) {
    $this->hostname = htmlspecialchars($host);
    $this->db_select = htmlspecialchars($db);
    $this->usernm = htmlspecialchars($user);
    $this->passwd = htmlspecialchars($passw);
    }

    public static function getIstance($host=NULL, $db=NULL, $user=NULL, $passw=NULL) {
    if(is_null(self::$istance)) {
    $c_class = __CLASS__;
    self::$istance = new $c_class($host, $db, $user, $passw);
    }

    return self::$istance;
    }

    // Altre funzioni...
    }
    ?>

    Quindi, tutte le chiamate che fanno uso dell'istanza dopo la PRIMA inizializzazione vanno a buon fine, ma quando viene richiamato lo skeleton, e quindi nuovamente la getIstance(), sembra che ciò che è avvenuto prima sia stato spazzato via e necessiti di reinizializzazione.

    Può dipendere dall'include_once? Il fatto è che uso proprio include_once per evitare che reincludendo il codice possa perdere le inzializzazioni precedenti, non dovrebbe funzionare proprio in questo modo?

    Non so che pesci prendere...

    Grazie ancora!

    Ciao!

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2006
    Messaggi
    10
    Ci sto diventando matto su questa cosa...è impossibile quel comportamento...ho provato anche ad inserire la classe nello stesso file index.php ma ha lo stesso comportamento. Non vorrei fosse sempre un problema di reinterpretazione del codice...ma mi sembra strano, non cono/scevo/sco il php, ma di certo mi sta piacendo poco ora come ora :berto: VVoVe:

  5. #5
    Prova a spostare:

    db_handle::getIstance("127.0.0.1", "db", $_POST['usernm'], $_POST['passwd'])->db_connect();

    subito dobo l'include_once().

  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2006
    Messaggi
    10
    Originariamente inviato da filippo.toso
    Prova a spostare:

    db_handle::getIstance("127.0.0.1", "db", $_POST['usernm'], $_POST['passwd'])->db_connect();

    subito dobo l'include_once().
    Ovviamente non funziona, la connect fallisce perchè non ha ancora disponibili l'username e la password...ma, voglio dire, dovrebbe essere un problema abbastanza comune mi sembra strano non trovarci il bandolo della matassa in questo modo...mi sembra anche molto strano il reset della variabile statica a dir il vero...

  7. #7
    Se l'errore di cui parli avviene alla riga "db_handle::getIstance()->show_SP_table(); //Una funzione che ritorna dati...", allora è un problema di logica applicativa.

  8. #8
    Utente di HTML.it
    Registrato dal
    Apr 2006
    Messaggi
    10
    Originariamente inviato da filippo.toso
    Se l'errore di cui parli avviene alla riga "db_handle::getIstance()->show_SP_table(); //Una funzione che ritorna dati...", allora è un problema di logica applicativa.
    Guarda, mi pare strano. L'errore avviene in quel punto perchè la getIstance cerca di ISTANZIARE NUOVAMENTE (quando NON dovrebbe + farlo poichè l'ha già fatto all'atto della connessione in precedenza!) l'oggetto (cosa contraria al pattern singleton, tra l'altro...) ed i parametri non sono impostati perchè si presuppone, appunto, inizializzati in precedenza. Con NuSphere ho fatto il debug passo per passo e quello che succede è esattamente quello che descrivevo: la seconda volta che si chiama la getIstance() la variabile static che referenzia l'oggetto è di nuovo a NULL, ma la prima volta tutto era andato a buon fine e quindi si presuppone che quell'oggetto doveva essere conservato. Non capisco dove e come possa generarsi un side effect di questo tipo. E' abbastanza assurdo. Ho provato a fare la stessa identica cosa in C# (non è certo paragonabile a php...) e funziona.

  9. #9
    Il problema è un errore di logica di base.

    Tu parli di "seconda volta che si chiama la getIstance()" ma invece dovresti parlare di "alla successiva richiesta HTTP".

    In PHP non esiste un Application server che mantiene un oggetto istanziato tra una richiesta e quella successiva a meno di salvarlo esplicitamente in sessione e comunque resterebbe a livello di utente e non funzionerebbe con proprietà tipo le risorse (es. connessioni a DB non persistenti).

    Prova a salvare in sessione i dati di accesso al DB (i parametri di getIstance()) e richiamare getIstance() con tutti i parametri all'inzio di ogni richiesta HTTP e vedrai che funziona correttamente.

  10. #10
    Utente di HTML.it
    Registrato dal
    Apr 2006
    Messaggi
    10
    Originariamente inviato da filippo.toso
    Il problema è un errore di logica di base.

    Tu parli di "seconda volta che si chiama la getIstance()" ma invece dovresti parlare di "alla successiva richiesta HTTP".

    In PHP non esiste un Application server che mantiene un oggetto istanziato tra una richiesta e quella successiva a meno di salvarlo esplicitamente in sessione e comunque resterebbe a livello di utente e non funzionerebbe con proprietà tipo le risorse (es. connessioni a DB non persistenti).

    Prova a salvare in sessione i dati di accesso al DB (i parametri di getIstance()) e richiamare getIstance() con tutti i parametri all'inzio di ogni richiesta HTTP e vedrai che funziona correttamente.
    Scusami per la terminologia, hai ragione, cmq è così: proprio alla successiva richiesta HTTP accade quello che ho descritto. Mi esprimevo in quel modo poichè è proprio la seconda richiesta HTTP che fa entrare in quel ramo...

    Detto questo, però, hai ragione sul discorso che non si mantengono gli oggetti ed evidentemente è proprio quello il problema, mi vorrai scusare per la mia totale inesperienza server-side ma purtroppo queste tecnologie non mi hanno mai attirato e ora mi ritrovo a lavorarci a mio discapito

    Grazie ancora!

    Ciao!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.