PHP / RegEx - Logic para prefixar os nomes de tabela
Pergunta
Então, eu estou tentando construir um script que automagicamente prepends nomes de coluna válido com seu prefixo tabela apropriada (por exemplo, "t." Ou "r".)
$t_columns = array('id', 'name', 'label');
$r_columns = array('related_value');
ENTRADA:
id > 1 AND (name = 'Hello' OR label IN ('World', 'Planet name AND label')) AND (related_value > 1 AND related_value < 50)
SAÍDA:
t.id > 1 AND (t.name = 'Hello' OR t.label IN ('World', 'Planet name AND label')) AND (r.related_value > 1 AND r.related_value < 50)
Observe como você não pode fazer um normal de str_replace . Qual seria o código mais simples (Eu estou supondo preg_replace ) para garantir que todos os nomes de tabelas são devidamente anexado?
Solução
Isto pode ser feito em uma série de maneiras, e também usando regex. Eu pessoalmente uso uma abordagem matriz. Primeiro de tudo, eu definir a tabela deturpação desta maneira:
$table = array(
'id' => 't.id',
'name' => 't.name',
'label' => 't.label',
'related_value' => 'r.related_value'
);
Isso vai fazer muito mais fácil o str_replace () chamada:
function mangling(&$v, $k, $table)
{
if (($k & 1) == 0)
$v = str_replace(array_keys($table), array_values($table), $v);
}
$spans = explode("'", ' ' . $input);
array_walk($spans, 'mangling', $table);
$output = implode("'", $spans);
Outras dicas
Depois de pensar de alguns segundos, aqui está como eu enfrentá-lo:
Passeio pela corda, char por char, procurando aspas simples, mas a ignorar os caracteres sobre escaparam. O material entre duas aspas simples unescaped (ou seja, as cordas) seria substituído com um token único, e colocado em uma matriz associativa, com aquele sinal como a chave, ea string original como o valor.
Agora que temos as cordas fora do caminho, fazer um str_replace()
(ou preg_replace()
, se você insistir) para os nomes das colunas conhecidos. Eu provavelmente construir os nomes de coluna em uma matriz associativa, com o nome alternativo de mesa como a chave, e o valor como uma matriz numérica contendo os nomes das colunas. Desta forma, a substituição pode ser automatizado.
Uma vez que os nomes de tabelas são preenchidos, basta fazer uma str_replace()
para os tokens, para substituir as cordas originais de volta a seus lugares, e você está feito.
Eu tenho certeza que alguém poderia chicote um regexp super-impressionante (e provavelmente ao lado unmaintainable) para fazer tudo isso em uma batida. Mas eu prefiro usar regexps apenas em situações em que as expressões regulares são, na verdade, a ferramenta certa, não onde um CFL seria mais adequado.
Eu não sei se uma expressão regular é uma boa idéia aqui. Eu diria que valeria a pena a quantidade mínima de maior complexidade computacional para realizar a validação se em PHP. Então, se o seu banco de dados requer alterações, você não tem que puxar seu cabelo para fora se preocupar com a forma de aumentar a robustez da sua expressão regular.
Como Jamie Zawinski uma vez disse: "Algumas pessoas, quando confrontado com um problema, pense 'eu sei, eu vou usar expressões regulares.' Agora eles têm dois problemas. "
Em termos de criação de um fluxo de trabalho que irá certificar-se que você está trabalhando no banco de dados certo, eu consideraria tendo uma abordagem orientada a objetos. Aulas para T e mesas R pode ser instanciado filhos de uma classe de modelo responsável por construir o objeto do tipo tabela correta usando a lógica condicional dentro do mesmo método, em vez de uma regex.