Pergunta

Eu estava lendo recentemente esta discussão , em algum das piores práticas PHP. Na segunda resposta, há um mini discussão sobre o uso de extract(), e estou me perguntando o que todo o Huff está em causa.

Eu, pessoalmente, usá-lo para cortar até uma determinada matriz, como $_GET ou $_POST onde eu então higienizar as variáveis ??mais tarde, como eles têm sido convenientemente chamado para mim.

Essa prática é ruim? Qual é o risco aqui? Quais são seus pensamentos sobre o uso de extract()?

Foi útil?

Solução

Eu acho que é apenas má prática na medida em que pode levar a uma série de variáveis ??que futuros mantenedores (ou você mesmo em poucas semanas) não têm idéia de onde eles estão vindo. Considere este cenário:

extract($someArray); // could be $_POST or anything

/* snip a dozen or more lines */

echo $someVariable;

Onde $someVariable vem? Como pode alguém diga?

Eu não ver o problema em acessar as variáveis ??de dentro da matriz que começou em, então você realmente precisa apresentar um bom caso para usando extract() para mim pensar pena de ele . Se você está realmente preocupado com a digitação alguns caracteres extras em seguida, basta fazer isso:

$a = $someLongNameOfTheVariableArrayIDidntWantToType;

$a['myVariable'];

Eu acho que aqui sobre os aspectos da segurança de TI os comentários são exagerados tanto. A função pode ter um segundo parâmetro que realmente dá-lhe bastante bom controle sobre as variáveis ??recém-criados, incluindo não substituindo as variáveis ??existentes (EXTR_SKIP), apenas substituindo variáveis ??existentes (assim você pode criar uma lista branca) (EXTR_IF_EXISTS), ou a adição de prefixos para as variáveis ??(EXTR_PREFIX_ALL).

Outras dicas

Vamos lá agora. As pessoas culpam a ferramenta em vez do usuário.

Isso é como falar contra unlink() porque você pode apagar arquivos com ele. extract() é uma função como qualquer outro, usá-lo com sabedoria e responsabilidade. Mas não dizem que é ruim por si só, isso é apenas ignorante.

o risco é:. Fazê dados não confiança dos usuários, e extrair para os meios símbolo tabela atual, suas variáveis ??poderia ser substituído por algo fornecido pelo usuário

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

    extract($_GET);

    system($systemCall);

    do {
        print_r($data[$i];
        $i++;
    } while ($i != 3);

?>

(um exemplo sem sentido)

mas agora que um usuário malicioso que adivinha ou conhece as chamadas de código:

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

em vez de

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

Agora, $ chamada de sistema e $ i são substituídos, resultando em seu script de exclusão de seus dados em primeiro lugar e pendurado então.

Não há nada de errado com ele. Caso contrário, não tomaria ser implementado. Muitos (MVC) enquadramentos usá-lo quando você passa (atribuir) variáveis ??para Views. Você só precisa usá-lo com cuidado. Higienizar essas matrizes antes de passá-lo para extrair () e certifique-se que não substitui as suas variáveis. Não se esqueça que esta função também aceita mais alguns argumentos! Usando o segundo e terceiro argumentos que você pode controlar o comportamento se colisão ocorre. Você pode substituir, ignorar ou adicionar prefixo. http://www.php.net/extract

Se não for utilizada com cuidado pode confundir o Parreira fora de outras você trabalha com considerar:

<?php

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


?>

Os rendimentos:

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

seria útil para usar em uma ofuscação. Mas eu não consigo superar a "Onde foi que var vem?" problema que eu me deparo.

As pessoas ficam tudo-em-braços sobre extrato porque tem o potencial a ser mal utilizado. Fazer algo como extract ($ _ POST) não é uma boa idéia em qualquer caso, mesmo se você sabe o que está fazendo. No entanto, o tem de usos quando você está fazendo coisas como expor variáveis ??para um modelo de visão ou algo similar. Basicamente, só usá-lo quando você está muito certo de que você tem uma boa razão para fazê-lo, e entender como usar o parâmetro de tipo de extrato, se você começa a idéia de passar algo louco como $ _POST a ele.

Eu acho que a razão pela qual muitas pessoas não recomendo usá-lo é que extrair $_GET e superglobals $_POST (mesmo $_REQUEST) registra variáveis ??no espaço global com o mesmo nome de cada chave dentro dessas matrizes, que é register_globals basicamente emulando = 1.

Eu vou deixar as PHP manuais fazer a falar para me.

Fundo: extract($_REQUEST) é o mesmo que definir register_globals = On no php.ini

Se você extrair em uma função, as variáveis ??só vai estar disponível nesse âmbito. Isto é frequentemente usado em vistas. Exemplo simples:

//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>

Com alguns diretórios alternativos, verifica se o arquivo existe e definida variáveis ??e métodos -. Você praticamente replicadas Zend_View

Você também pode adicionar $ this-> VariaveisDeSaida = get_defined_vars ();. após a incluir para executar código com específica variabels e obter o resultado destes para uso com código PHP velho

Extract é seguro, desde que você usá-lo de forma segura. O que você quer fazer é filtro de chaves do array para apenas os que você pretende usar e talvez verificar que todas essas chaves existir se sua situação exige a sua existência.

#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);

ou

#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'])
));

O risco é o mesmo que com register_globals. Você habilitar o atacante variáveis ??definidas em seu script, simplesmente por interferir com o pedido.

extrato Never ($ _ GET) em um escopo global. Fora isso, ele tem seus usos, como chamar uma função que poderia (potencialmente) tem um monte de argumentos opcionais.

Esta deve olhar vagamente familiar para desenvolvedores do 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>'
));

Como alguém observou em um segmento diferente, aqui é uma maneira mais segura para uso extrato , em apenas permitindo-lhe extrair variáveis ??especificadas, em vez de tudo o que a matriz contém.

Isso serve um duplo propósito de documentar quais variáveis ??estão saindo dele para rastreamento de volta uma variável não vai ser tão difícil.

Cada uso de método pode levar a algumas condições em que pode ser um ponto de falha para a aplicação. Pessoalmente, sinto que o extrato () não deve ser usado para a entrada do usuário (que não é previsível) e para dados que não são higienizados.

Mesmo CodeIgniter usa o código do núcleo extrair, então deve haver nenhum mal em usar o método se os dados é higienizado e bem tratadas.

Eu tenho usado o extrato em modelos CodeIgniter com as EXTR_IF_EXISTS mudar e limitar o número de variáveis, ele funciona muito bem.

Esteja ciente de que extract() não é seguro se você estiver trabalhando com dados de usuário (como resultados de pedidos), por isso é melhor usar essa função com o EXTR_IF_EXISTS bandeiras e EXTR_PREFIX_ALL.

Se você usá-lo, é seguro usar

Para apenas expor um pouco sobre respostas anteriores ... Não é errado nada com extrato (), desde que você filtrar a entrada corretamente (como outros já indicado); caso contrário você pode acabar com problemas de segurança enormes como este:

<?php

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

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

extract($_GET);

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

Um bom motivo adicional para nenhum extrato de uso prolongado () é que há um impulso no PHP para usar HHVM que está reivindicando para fazer PHP cerca de 10x mais rápido. Facebook (que fez) é usá-lo, a Wikipedia é sobre ele, e WordPress é rumores de estar a olhar para ele.

HHVM não permite extract ()

Ainda é tipo de alfa, por isso não é a maior preocupação

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top