Instalando drive PDO PHP do SQL Server no Linux

Instalando o PHP

sudo add-apt-repository ppa:ondrej/php -y
sudo apt-get update
sudo apt-get install php8.1 php8.1-dev php8.1-xml -y --allow-unauthenticated

Instalando os pré requisitos (Ubuntu 16.04 18.04 20.04 22.04)

sudo curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -

sudo curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list > /etc/apt/sources.list.d/mssql-release.list

Instalando o ODBC do SQL Server 17

sudo apt update
sudo ACCEPT_EULA=Y apt install -y msodbcsql17
sudo apt install unixodbc-dev

Opcional: Para usar ferramentas como BCP e SQLcmd

sudo ACCEPT_EULA=Y apt-get install -y mssql-tools
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc

Instalando o driver PDO do SQL Server no PHP

sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv

Setando a configuração do driver

sudo printf "; priority=20\nextension=sqlsrv.so\n" > /etc/php/8.1/mods-available/sqlsrv.ini

sudo printf "; priority=30\nextension=pdo_sqlsrv.so\n" > /etc/php/8.1/mods-available/pdo_sqlsrv.ini

Habilitando a configuração

sudo phpenmod -v 8.1 sqlsrv pdo_sqlsrv

Se estiver usando Apache, ele deve ser reiniciado

sudo service apache2 restart

Referências

    Organizando una base de datos de calles usando PHP y LibreOffice Calc

    En una de mis tareas cotidianas, me encontré con este problema: ¿Cómo organizar una base de datos de calles? ¿Cómo podría hacerlo de manera práctica y utilizando herramientas ya disponibles?

    Entonces resolvió utilizar PHP y LibreOffice Calc.

    Contexto

    Hay un S.I (ERP + CRM) donde se hace la gerencia de todos los clientes. En este sistema todas las informaciones del registro de persona física / jurídica se utilizan en otras partes del mismo sistema. El módulo de CRM de ese sistema utiliza, en una de sus funcionalidades, los datos de dirección (ciudad, barrio, calle) para posicionar al cliente en un mapa.

    Hoy tengo acceso al base de datos del sistema pero no tengo permiso de escritura. Necesito corregir los problemas, enviar por ticket al soporte del sistema y un archivo CSV para que los cambios en el base de datos.

    Problemas

    Las calles registradas están fuera del estándar utilizado en el mapa donde se deben exhibir, con lo que es imposible ubicar al cliente en el mapa.

    Esta es una lista de los elementos que serán corregidos:

    • Los logros que se refieren a la misma calle necesitan tener la misma grafía;
    • Abreviaturas en el nombre de la  Calles;
    • En la grafía de las calles que tiene números, necesitan estar por extenso;
    • Calles que tienen la numeración de inicio y fin en el nombre;
    • Calles con números romanos;

    Solución desarrollada

    En el primer momento, conversando con el equipo del Comercial, me dieron la idea de utilizar el LibreOffice Calc para organizar los datos y hacer las correcciones.

    Obteniendo los datos, organizando y haciendo las primeras correcciones

    Utilizando o LibreOffice Calc:

    Obtuvo los datos accediendo a la base de datos PostgreSQL del sistema y ejecutando un SQL. He copiado los resultados para el LibreOffice Calc.

    De ahí el nombre de las columnas facilitar la identificación y manipulación, quedó así:

    ID LOGRADOURO CODBAIRRO CEP CODCIDADE

     

    Dar nombre a las columnas me ayudó a la hora de usar la opción Clasificar de Calc. He seleccionado todo el área de la tabla donde estaba los datos, dentro de la opción CLASIFICAR, seleccioné la columna LOGRADOURO en la opción Clave de clasificación 1.

    En el Calc, utilizando la opción Buscar y reemplazar he cambiado todos los registros que se encuadran en las condiciones:

    TERMO SUBSTITUÍDO POR
    R. Rua
    R+ESPAÇO Rua
    Tv. +ESPAÇO Travessa
    RUA+ESPAÇO Rua
    Av+ESPAÇO Avenida
    Av.+ESPAÇO Avenida
    Cel.+ESPAÇO Coronel
    Dr.+ESPAÇO Doutor
    Gen.+ESPAÇO General
    Brig.+ESPAÇO Brigadeiro
    Pre.+ESPAÇO Presidente

     

    En algunos casos, existe discordancia si el logradouro es Calle, Avenida o Travessa. Esto tuvo que ser corregido también.

    Utilizando PHP:

    Después de hacer todas las correcciones manuales empecé a analizar los problemas para identificar cuáles serían posibles de ser resueltos usando programación en tiempo hábil.

    El resultado del código desarrollado está abajo:

    <?php
    //ativando os erros
    ini_set(‘display_errors’, ‘On’);
    //Exibindo todos os erros
    error_reporting(E_ALL);
    
    $caminho_do_csv = '/var/www/html/lista-enderecos-mk.csv';
    //O parâmetro FILE_TEXT especifica que o arquivo é retornado na codificação UTF-8.
    $array_csv = file($caminho_do_csv, FILE_TEXT);
    $map_csv = array_map('str_getcsv', $array_csv);
    
    ////////// PROBLEMAS PARA RESOLVER
    //(Feito) 1- Encontrar um padrão e tudo que estiver a direita desse padrão deve ser apagado. Ex: numeração de inicio e fim no nome da rua.
    //(Feito) 2- Retirar os numeros do nome do logradouro. Geralmente os numeros errados estão no final do nome.
    
    //Função para exibir os dados de um mapa de array
    // @return Sem terno
    function exibe_mapa(Array $mapa_de_array)
    {
    if($mapa_de_array != NULL)
    {
    foreach ($mapa_de_array as $key => $valor)
    {
    print("Posição do Array exteno: ".$key."<br/>");
    print("------ID: ".$valor[0]."<br/>");
    print("------Logradouro: ".$valor[1]."<br/>");
    print("------CODBAIRRO: ".$valor[2]."<br/>");
    print("------CEP: ".$valor[3]."<br/>");
    print("------CODCIDADE: ".$valor[4]."<br/>");
    print('---------------------------------------------------------');
    print("<br/>");
    };
    };
    };
    
    //Função para encontrar um padrão de texto em um mapa de array
    // @return Sem terno
    function encontrar_padrao(String $padrao, Array $mapa_de_array)
    {
    //percorrer o array para achar o padrão, se for encontrato, o texto é destacado:
    //<font color='red'> texto </font>
    $qtd_encontrada=0;
    foreach ($mapa_de_array as $key => $valor) {
    print("Posição do Array exteno: ".$key."<br/>");
    print("------ID: ".$valor[0]."<br/>");
    if(stripos($valor[1],$padrao) !== false){
    print("------Logradouro: <font color='red'>".$valor[1]."</font><br/>");
    $qtd_encontrada=$qtd_encontrada+1;
    }else{
    print("------Logradouro: ".$valor[1]."<br/>");
    };
    print('---------------------------------------------------------');
    print("<br/>");
    };
    echo 'Total de ocorrências do padrão: '.$qtd_encontrada;
    };
    
    //Essa função contem o array com as strings que devem ser desconsideradas na busca por algum tipo de padrão de string.
    // @return Retorna 1 se a string passado por parâmetro estever no array e 0 para caso contrário.
    function padrao_desconsiderado(String $string)
    {
    //Array com os padrões que devem ser desconsiderados
    $desconsiderar_padrao = array("ms-","MS-","Ms-","Rua ");
    foreach($desconsiderar_padrao as $valor)
    {
    //A pergunta feita no IF é: Algum dos padrões que estão no array coincide com a string passada por parâmetro?
    //Em outras palavras: $valor C $string || $valor esta CONTIDO em $string?
    if(stripos($string,$valor) !== false){
    return 1;
    break;
    };
    };
    return 0;
    };
    
    //Salvando em um arquivo CSV
    // @return Sem terno
    function salvando_no_arq_csv(Array $mapa_de_array)
    {
    //O primeiro parâmetro é o arquivo.csv que eu já criei e dei permissão 777 nele.
    $fp = fopen('file.csv', 'w+');
    foreach ($mapa_de_array as $key => $valor)
    {
    fputcsv($fp, $valor);
    };
    
    fclose($fp);
    };
    
    //Solução do problema 2
    // @return Retorna o mapa de Array com os campos editados
    function problema2(String $padrao, Array $mapa_de_array)
    {
    //percorrer o Array para achar o padrão.
    //Depois eu edito a posição do array onde foi achado o padrão e salvo o novo texto editado;
    $novo_mapa_de_array = $mapa_de_array;
    foreach ($mapa_de_array as $key => $valor) {
    if(stripos($valor[1],$padrao) !== false){
    //posição onde foi encontrado o padrão
    $posicao = stripos($valor[1],$padrao);
    //Copiando o o valor(Array) que
    $array_temp = $novo_mapa_de_array[$key];
    $array_temp[1] = substr($array_temp[1],0,$posicao);
    $novo_mapa_de_array[$key] = $array_temp;
    };
    };
    return $novo_mapa_de_array;
    };
    
    //Função para encontrar um padrão que atende a expresão regular passada por parâmetro
    // @return Retorna um mapa de Array com o texto corrigido
    function problema3(String $expressao, Array $mapa_de_array)
    {
    //Variável que salva temporáriamente um mapa de array com os padrões encontrados;
    $matches;
    // Novo Array que será retornado contendo o texto editado
    $novo_mapa_de_array = $mapa_de_array;
    
    //percorrer o Array para achar o padrão, se for encontrato o padrão é excluido;
    foreach ($mapa_de_array as $key => $valor)
    {
    //IMPORTANTE: a expressão precisa estár entre barras -> EX: /[0-9]/
    if(preg_match('/'.$expressao.'/',$valor[1]))
    {
    if(padrao_desconsiderado($valor[1]) == 0){
    preg_match('/'.$expressao.'/',$valor[1],$matches, PREG_OFFSET_CAPTURE);
    $temp = $matches[0];
    $array_temp = $novo_mapa_de_array[$key];
    $array_temp[1] = substr($valor[1],0,$temp[1]);
    $novo_mapa_de_array[$key] = $array_temp;
    }else{
    print_r("Valor: ".$valor[1]."<br/>");
    printf("Variável temp[0] padrão: ".$temp[0]."<br/>");
    printf("Variável temp[1] posição: ".$temp[1]."<br/><br/>");
    }
    }
    };
    return $novo_array_de_mapa;
    };
    
    //Resolve problema 2
    //padrão para achar as ruas que tem a numeração de inicio e fim no nome
    $padrao = ' - ';
    
    //Resolve Problema 3
    //Para achar numeros que estão no final do nome da rua
    $expressao_problema_3 = '[0-9]{2,5}$';
    
    $corrigido = problema2($padrao, $map_csv);
    
    $corrigido2 = problema3($expressao_problema_3,$corrigido);
    
    salvando_no_arq_csv($corrigido2);
    
    ?>