[Problema]
Apesar de ter experiência anterior em programação, um novato em PHP fica perplexo com um erro padrão de atributo. O código:
class Foo {
public $path = array(
realpath(".")
);
}
gera um erro de sintaxe. No entanto, o seguinte funciona perfeitamente:
$path = array(
realpath(".")
);
Surge a pergunta: por que funções não podem ser invocadas em atributos padrão? Isso é intencional ou uma falha na implementação?
[Resposta]
O código do compilador PHP indica que esta restrição é intencional, embora nenhuma justificativa oficial esteja disponível. A implementação confiável desta funcionalidade apresenta certos desafios, conforme evidenciado pelas limitações na implementação atual do PHP.
A gramática do compilador define uma declaração de variável de classe como:
class_variable_declaration: //... | T_VARIABLE '=' static_scalar //... ;
Portanto, para atribuir valores de variáveis como $path, o valor esperado deve estar alinhado com um escalar estático. Isso abrange matrizes com valores que também são escalares estáticos:
static_scalar: /* compile-time evaluated scalars */ //... | T_ARRAY '(' static_array_pair_list ')' // ... //... ;
Se a gramática permitisse a seguinte sintaxe, que se alinha com o exemplo de código, o script encontraria um erro de "Tipo de ligação inválido":
class_variable_declaration: //... | T_VARIABLE '=' T_ARRAY '(' array_pair_list ')' // ... ;
A análise do exemplo de código fornecido revela as seguintes etapas:
zend_do_begin_class_declaration() // Adds an opcode array_init(), zend_do_add_static_array_element() // Do not create new opcodes, add array to class properties zend_do_declare_property() // Declares the property zend_do_early_binding() // Consumes the last opcode and evaluates it
Se o opcode não for esperado (por exemplo, relacionado a funções ou métodos), um erro será gerado.
Permitindo matrizes não estáticas gera um opcode INIT_ARRAY, que interrompe zend_do_early_binding():
DECLARE_CLASS 'Foo' SEND_VAL '.' DO_FCALL 'realpath' INIT_ARRAY
Para acomodar chamadas de função em padrões de atributos, seria necessária uma nova matriz de opcode com escopo definido para a declaração da variável de classe, semelhante às definições de método. No entanto, determinar o momento de tal avaliação apresenta desafios adicionais.
Outras linguagens dinâmicas conseguiram resolver isso, mas continua sendo um recurso ausente no PHP, potencialmente devido à sua complexidade e baixa prioridade percebida.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3