2012-01-23 6 views
13

Sto cercando un modo per impostare l'ambito di require_once() nell'ambito globale, quando require_once() viene utilizzato all'interno di una funzione. Qualcosa come il seguente codice dovrebbe funzionare:C'è un modo per impostare esplicitamente l'ambito di require_once() su global?

file di

`foo.php ':

<?php 

$foo = 42; 

codice vero e proprio:

<?php 

function includeFooFile() { 
    require_once("foo.php"); // scope of "foo.php" will be the function scope 
} 

$foo = 23; 

includeFooFile(); 
echo($foo."\n"); // will print 23, but I want it to print 42. 

c'è un modo per impostare in modo esplicito la portata di require_once()? C'è una soluzione piacevole?

+3

L'ambito di 'require_once' è impostato esplicitamente dove si definisce l'uso di esso. – hakre

+0

Posso pensare ad un orribile lavoro in giro, se lo vuoi ... – DaveRandom

+1

Non c'è. È necessario elencare in modo esplicito le variabili da utilizzare come alias nell'ambito globale. O nella funzione o in cima al tuo script di inclusione. – mario

risposta

1

È possibile utilizzare questa funzione hacky ho scritto:

/** 
* Extracts all global variables as references and includes the file. 
* Useful for including legacy plugins. 
* 
* @param string $__filename__ File to include 
* @param array $__vars__  Extra variables to extract into local scope 
* @throws Exception 
* @return void 
*/ 
function GlobalInclude($__filename__, &$__vars__ = null) { 
    if(!is_file($__filename__)) throw new Exception('File ' . $__filename__ . ' does not exist'); 
    extract($GLOBALS, EXTR_REFS | EXTR_SKIP); 
    if($__vars__ !== null) extract($__vars__, EXTR_REFS); 
    unset($__vars__); 
    include $__filename__; 
    unset($__filename__); 
    foreach(array_diff_key(get_defined_vars(), $GLOBALS) as $key => $val) { 
     $GLOBALS[$key] = $val; 
    } 
} 

Si muove ogni nuova definizione vars di nuovo in sp globale asso quando ritorna il file include. C'è un avvertimento che se il file incluso include un altro file, non sarà in grado di accedere alle variabili definite nel file principale tramite $GLOBALS perché non sono ancora state globalizzate.

5

Oltre a "globalizzare" la variabile, non v'è alcun modo per farlo:

global $foo; 
$foo = 42; 

O

$GLOBALS['foo'] = 42; 

Allora il tuo valore dovrebbe essere 42 quando si stampa fuori.

UPDATE

Per quanto riguarda l'inclusione di classi o funzioni, si noti che tutte le funzioni e le classi sono sempre considerati globale a meno che non stiamo parlando di un metodo di classe. A quel punto, il metodo in una classe è disponibile solo dalla definizione della classe stessa e non come una funzione globale.

+0

Ho appena provato la tua risposta e ha funzionato bene. Non dovrebbero esserci problemi, se il file 'foo.php' contiene funzioni o classi, giusto? –

+0

No, nessun problema ... leggi l'aggiornamento che pubblicherò in pochi secondi ... –

+1

Thx Mathieu. La tua soluzione funziona perfettamente per la mia applicazione. –

1

In attesa dei vostri esatti requisiti, è possibile utilizzare constants. Richiedi il tuo file nell'ambito globale, ma al suo interno imposta una costante.

IE file.php:

define('MY_CONSTANT', 42); 

Poi ovunque nello script basta usare MY_CONSTANT per fare riferimento al valore, non sarà in grado di modificare una volta che è stato impostato però. Oltre a questo, potresti globalizzare la tua variabile come dice l'altra risposta, ma non è chiaro al 100% cosa stai cercando di ottenere oltre al semplice recupero di un valore dal file incluso? In tal caso le costanti dovrebbero andare bene.

Aggiornamento: Ora hai spiegato che si desidera un oggetti di immobili da essere disponibili in tutto il mondo, vi suggerisco di guardare nella creazione di un static class, che una volta creata un'istanza in ambito globale può essere utilizzato ovunque nella vostra app. Leggi la pagina di manuale collegata, ha un esempio di nudo.

+0

Penso che l'utente voglia essere in grado di aggiornare un valore esistente, ma se si tratta solo di costanti esterne, allora il metodo è il migliore ovviamente –

+0

Nella mia applicazione '$ pippo' sarà un oggetto. Gli oggetti non possono essere memorizzati in costanti, giusto? –

+0

No, compra potresti creare una classe statica, aggiornando la mia risposta ora ... – Dunhamzzz

2

Sarà necessario dichiarare globale nel foo.php:

<?php 
global $foo; 
$foo = 42; 
?> 

Altrimenti probabilmente non è possibile.

Si potrebbe provare a giocare con extract(), get_defined_vars(), global e $GLOBALS in varie combinazioni forse ... come iterazione attraverso tutte le variabili definite e chiedendo globale su di loro prima di richiedere un file ...

$vars = get_defined_vars(); 
foreach($vars as $varname => $value) 
{ 
    global $$varname; //$$ is no mistake here 
} 
require... 

Ma non sono abbastanza sicuro se arrivi dove vuoi andare ...

+0

Ah btw ... ho detto che è un po 'orribile, tutto qui dovrebbe essere usato solo come esempi sbagliati come NON fare cose ... probabilmente c'è una soluzione molto bella per il problema di base che stai cercando di risolvere, senza orribili uso improprio del namespace globale;) – bardiir

2

Poiché la portata è esplicitamente definito in cui si utilizza require e simili, si avrebbe bisogno di specificare cosa fare con le variabili all'interno del campo di applicazione della funzione di:

function includeFooFile() { 
    require_once("foo.php"); // scope of "foo.php" will be the function scope 

    foreach (get_defined_vars() as $k => $v) 
    { 
     $GLOBALS[$k] = &$v; 
    } 
} 

Questo esempio si prende cura di entrambi, variabili e riferimenti che potrebbero essere ciò che stai cercando. Demo. Si noti che require_once funzionerà solo una volta e definirà le variabili solo una volta.

3

questo è sicuramente non un'opera "bella" in giro, ma che avrebbe funzionato:

function includeFooFile() { 
    require_once("foo.php"); 
    foreach (get_defined_vars() as $key => $value) { 
    // Ignore superglobals 
    if (!in_array($key, array('GLOBALS','_SERVER','_GET','_POST','_FILES','_COOKIE','_SESSION','_REQUEST','_ENV'))) { 
     $GLOBALS[$key] = $value; 
    } 
    } 
} 

Tuttavia, il file incluso non può definire le funzioni o classi (e forse anche altre cose che non posso al momento pensa a) perché causerà un errore di analisi, poiché non è possibile nidificare classi o funzioni.

EDIT a quanto pare è possibile includere funzioni nel file. Avevo sempre pensato che non si poteva, ma dopo aver provato sembra che tu possa.

+1

Questo sembra essere una soluzione funzionante per il mio problema. Ora ci proverò ... –

+1

Sì! Ha funzionato bene, quindi accetterò la tua risposta. –

+0

@DaveRandom: questo non supporta l'aliasing e i superglobali sono già stati sovrascritti, quindi non è necessario controllarli teoricamente. In pratica, 'get_defined_vars()' non li restituisce comunque nello scope della funzione locale. – hakre

1

non l'ho provato (dal usando vars globali è una cattiva idea tbh) ma questo potrebbe potenzialmente funzionare:

require_once '...'; 
$GLOBALS = array_merge($GLOBALS, get_defined_vars()); 

In alternativa si può semplicemente farlo manualmente:

foreach (get_defined_vars() as $k => $v) { 
    $GLOBALS[$k] = $v; 
} 
+0

Perché pensi che usare le vars globali sia una cattiva idea? –

+0

È un dogma :) puoi google per esso, ci sono più che sufficienti spiegazioni, più adatto a qualsiasi lingua. Fondamentalmente, anche se hai bisogno che i dati siano accessibili a livello globale, mettili da qualche parte dove non possa interferire con qualcos'altro. In PHP una variabile di classe statica è una buona alternativa (imho). –

Problemi correlati