Domanda

Di recente ho letto questa discussione , su alcuni delle peggiori pratiche PHP. Nella seconda risposta c'è una mini discussione sull'uso di extract () , e mi sto solo chiedendo di cosa si occupi.

Lo uso personalmente per tagliare un determinato array come $ _GET o $ _POST dove poi igienizzo le variabili in un secondo momento, poiché sono state convenientemente chiamate per me .

Questa è una cattiva pratica? Qual è il rischio qui? Cosa ne pensi dell'uso di extract () ?

È stato utile?

Soluzione

Trovo che sia solo una cattiva pratica in quanto può portare a una serie di variabili che i futuri manutentori (o te stesso tra qualche settimana) non hanno idea da dove provengano. Considera questo scenario:

extract($someArray); // could be 

Trovo che sia solo una cattiva pratica in quanto può portare a una serie di variabili che i futuri manutentori (o te stesso tra qualche settimana) non hanno idea da dove provengano. Considera questo scenario:

$a = $someLongNameOfTheVariableArrayIDidntWantToType;

$a['myVariable'];

Da dove proviene $ someVariable ? Come si può dire?

Non vedo il problema nell'accedere alle variabili dall'array in cui sono iniziate, quindi dovresti davvero presentare un buon caso per usando extract () per me pensare che ne valga la pena. Se sei davvero preoccupato di scrivere alcuni caratteri extra, fai semplicemente questo:

<*>

Penso che i commenti qui sugli aspetti della sicurezza siano in qualche modo esagerati. La funzione può accettare un secondo parametro che in realtà ti dà un controllo abbastanza buono sulle variabili appena create, incluso non sovrascrivere alcuna variabile esistente ( EXTR_SKIP ), SOLO sovrascrivere variabili esistenti (in modo da poter creare una lista bianca) ( EXTR_IF_EXISTS ) o aggiungendo prefissi alle variabili ( EXTR_PREFIX_ALL ).

POST or anything /* snip a dozen or more lines */ echo $someVariable;

Da dove proviene $ someVariable ? Come si può dire?

Non vedo il problema nell'accedere alle variabili dall'array in cui sono iniziate, quindi dovresti davvero presentare un buon caso per usando extract () per me pensare che ne valga la pena. Se sei davvero preoccupato di scrivere alcuni caratteri extra, fai semplicemente questo:

<*>

Penso che i commenti qui sugli aspetti della sicurezza siano in qualche modo esagerati. La funzione può accettare un secondo parametro che in realtà ti dà un controllo abbastanza buono sulle variabili appena create, incluso non sovrascrivere alcuna variabile esistente ( EXTR_SKIP ), SOLO sovrascrivere variabili esistenti (in modo da poter creare una lista bianca) ( EXTR_IF_EXISTS ) o aggiungendo prefissi alle variabili ( EXTR_PREFIX_ALL ).

Altri suggerimenti

Dai adesso. Le persone danno la colpa allo strumento anziché all'utente.

È come parlare contro unlink () perché puoi eliminare i file con esso. extract () è una funzione come le altre, usala con saggezza e responsabilità. Ma non pretendere che sia di per sé negativo, è semplicemente ignorante.

il rischio è: non fidarti dei dati degli utenti e l'estrazione nella tabella dei simboli corrente significa che le tue variabili potrebbero essere sovrascritte da qualcosa che l'utente fornisce.

<?php
    $systemCall = 'ls -lh';
    $i = 0;

    extract(

il rischio è: non fidarti dei dati degli utenti e l'estrazione nella tabella dei simboli corrente significa che le tue variabili potrebbero essere sovrascritte da qualcosa che l'utente fornisce.

yourscript.php?i=10&systemCall=rm%20-rf

(un esempio senza senso)

ma ora un utente malintenzionato che indovina o conosce le chiamate in codice:

yourscript.php?data[]=a&data[]=b&data[]=c

anziché

<*>

ora, $ systemCall e $ i vengono sovrascritti, con il risultato che lo script elimina prima i dati e poi si blocca.

GET); system($systemCall); do { print_r($data[$i]; $i++; } while ($i != 3); ?>

(un esempio senza senso)

ma ora un utente malintenzionato che indovina o conosce le chiamate in codice:

<*>

anziché

<*>

ora, $ systemCall e $ i vengono sovrascritti, con il risultato che lo script elimina prima i dati e poi si blocca.

Non c'è niente di sbagliato in questo. Altrimenti non verrebbe implementato. Molti framework (MVC) lo usano quando si passano (assegnano) variabili a Views. Hai solo bisogno di usarlo con attenzione. Disinfetta quelle matrici prima di passarle a extract () e assicurati che non sovrascriva le tue variabili. Non dimenticare che questa funzione accetta anche qualche argomento in più! Utilizzando il secondo e il terzo argomento è possibile controllare il comportamento in caso di collisione. Puoi ignorare, saltare o aggiungere prefisso. http://www.php.net/extract

Se non usato con attenzione, può confondere gli altri con cui lavori:

<?php

    $array = array('huh' => 'var_dump', 'whatThe' => 'It\'s tricky!', 'iDontGetIt' => 'This Extract Function');
    extract($array);
    $huh($whatThe, $iDontGetIt);


?>

Rendimento:

string(12) "It's tricky!"
string(21) "This Extract Function"

Sarebbe utile da usare in un offuscamento. Ma non riesco a superare il " da dove proviene quella var? & Quot; problema in cui mi imbatto.

Le persone ottengono tutte le armi per estrarre perché ha il potenziale da abusare. Fare qualcosa come extract ($ _ POST) non è comunque una buona idea, anche se sai cosa stai facendo. Tuttavia, ha i suoi usi quando stai facendo cose come esporre le variabili a un modello di vista o qualcosa di simile. Fondamentalmente, usalo solo quando sei molto sicuro di avere una buona ragione per farlo, e capisci come usare il parametro type extract se ti viene l'idea di passare qualcosa di folle come $ _POST.

Suppongo che il motivo per cui molte persone non raccomandano di usarlo è che l'estrazione di $ _GET e $ _POST (anche $ _REQUEST ) superglobals registra le variabili nello spazio dei nomi globale con lo stesso nome di ciascuna chiave all'interno di tali array, che sostanzialmente emula REGISTER_GLOBALS = 1.

Lascerò il manuale di PHP parlare per me.

Background: extract ($ _ REQUEST) è uguale all'impostazione register_globals = On in php.ini

Se si estrae in una funzione, le variabili saranno disponibili solo in quell'ambito. Questo è spesso usato nelle viste. Esempio semplice:

//View.php
class View {
    function render($filename = null) {
        if ($filename !== null) {
            $this->filename = $filename;
        }
        unset($filename);
        extract($this->variables);
        ob_start();
        $this->returned = include($this->dir . $this->filename);
        return ob_get_clean();
    }
}

//test.php
$view = new View;
$view->filename = 'test.phtml';
$view->dir = './';
$view->variables = array('test' => 'tset');
echo $view->render('test.phtml');
var_dump($view->returned);

//test.phtml
<p><?php echo $test; ?></p>

Con alcune directory alternative, controlla se il file esiste e ha definito variabili e metodi: hai praticamente replicato Zend_View.

Puoi anche aggiungere $ this- > outVariables = get_defined_vars (); dopo l'inclusione per eseguire il codice con variabili specifiche e ottenere il risultato di questi per l'uso con il vecchio codice php.

Estrai è sicuro finché lo usi in modo sicuro. Quello che vuoi fare è filtrare le chiavi dell'array solo su quelle che intendi utilizzare e magari verificare che tutte quelle chiavi esistano se il tuo scenario richiede la loro esistenza.

#Extract only the specified keys.
$extract=array_intersect_key(
    get_data()
    ,$keys=array_flip(['key1','key2','key3','key4','key5'])
);

#Make sure all the keys exist.
if ($missing=array_keys(array_diff_key($keys,$extract))) {
    throw new Exception('Missing variables: '.implode(', ',$missing));
}

#Everything is good to go, you may proceed.
extract($extract);

o

#If you don't care to check that all keys exist, you could just do this.
extract(array_intersect_key(
    get_data()
    ,array_flip(['key1','key2','key3','key4','key5'])
));

Il rischio è lo stesso di register_globals. Consenti all'attaccante di impostare variabili nel tuo script, semplicemente manomettendo la richiesta.

Non estrarre mai ($ _ GET) in un ambito globale. Oltre a ciò, ha i suoi usi, come chiamare una funzione che potrebbe (potenzialmente) avere molti argomenti opzionali.

Questo dovrebbe apparire vagamente familiare agli sviluppatori di WordPress:

function widget (Array $args = NULL)
{
    extract($args);

    if($before_widget) echo $before_widget;

    // do the widget stuff

    if($after_widget) echo $after_widget;
}

widget(array(
    'before_widget' => '<div class="widget">',
    'after_widget' => '</div>'
));

Come qualcuno ha notato in una discussione diversa, qui è un modo più sicuro utilizzare extract , consentendogli solo di estrarre le variabili specificate, anziché tutto ciò che l'array contiene.

Questo ha un duplice scopo di documentare quali variabili ne escono, quindi non sarà così difficile rintracciare una variabile.

L'utilizzo di ogni metodo può comportare alcune condizioni in cui può rappresentare un punto di errore per l'applicazione. Personalmente ritengo che extract () non dovrebbe essere usato per l'input dell'utente (che non è prevedibile) e per i dati che non sono disinfettati.

Anche il codice core di CodeIgniter usa extract, quindi non ci deve essere alcun danno nell'uso del metodo se i dati sono disinfettati e gestiti bene.

Ho usato l'estrazione nei modelli CodeIgniter con l'opzione EXTR_IF_EXISTS e limitando il numero di variabili, funziona abbastanza bene.

Tieni presente che extract () non è sicuro se stai lavorando con i dati dell'utente (come i risultati delle richieste), quindi è meglio usare questa funzione con i flag EXTR_IF_EXISTS e EXTR_PREFIX_ALL .

Se lo usi correttamente, è sicuro da usare

Per spiegare un po 'le risposte precedenti ... Non c'è niente di sbagliato in extract () fintanto che si filtra correttamente l'input (come altri hanno affermato); altrimenti potresti finire con enormi problemi di sicurezza come questo:

<?php

// http://foobar.doo?isLoggedIn=1

$isLoggedIn = (new AdminLogin())->isLoggedIn(); // Let's assume this returns FALSE

extract(

Per spiegare un po 'le risposte precedenti ... Non c'è niente di sbagliato in extract () fintanto che si filtra correttamente l'input (come altri hanno affermato); altrimenti potresti finire con enormi problemi di sicurezza come questo:

<*>GET); if ($isLoggedIn) { echo "Okay, Houston, we've had a problem here."; } else { echo "This is Houston. Say again, please."; }

Un altro buon motivo per non usare più extract () è che c'è un momento in PHP per usare HHVM che sostiene di rendere PHP circa 10 volte più veloce. Facebook (chi l'ha creato) lo sta usando, Wikipedia è su di esso e si dice che WordPress lo guardi.

HHVM non consente extract ()

È ancora una specie di alfa, quindi non è la preoccupazione maggiore

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top