Como configurar e usar o PDO para acesso ao banco de dados no Linux

Como configurar e usar o PDO para acesso ao banco de dados no Linux

Objetivo

Aprenda a configurar e usar o PDO para acesso ao banco de dados: dos modos de erro aos métodos buscadores.

Requisitos

  • Um conhecimento padrão do MySQL e mysql cliente da linha de comando;
  • Estar familiarizado com os conceitos fundamentais de programação orientada a objetos
  • Php> = 5.1
  • Tenha um banco de dados MySQL/MariaDB em funcionamento

Dificuldade

MÉDIO

Convenções

  • # - requer que os comandos Linux sejam executados com privilégios de raiz também
    diretamente como usuário root ou por uso de sudo comando
  • $ - Requer que os comandos do Linux sejam executados como um usuário não privilegiado regular

Introdução

PDO é um acrônimo para Objetos de dados PHP: É uma extensão de PHP para interagir com bancos de dados através do uso de objetos. Um de seus pontos fortes reside no fato de que não está estritamente ligado a algum banco de dados específico: sua interface fornece uma maneira comum de acessar vários ambientes diferentes, entre os outros:

  • Mysql
  • Sqlite
  • PostGresql
  • Microsoft SQL Server

Este guia tem como objetivo fornecer uma visão geral completa do PDO, orientando o leitor passo a passo do estabelecimento de uma conexão com o banco de dados, para a escolha do modo de busca mais apropriado, mostrando como criar instruções preparadas e descrever os modos de erro possíveis.

Crie um banco de dados e tabela de teste

A primeira coisa que faremos é criar um banco de dados para este tutorial:

Criar banco de dados solar_system; Conceder todos os privilégios no Solar_system.* Para 'testuser'@'localhost' identificado por 'testpassword'; 
cópia de

Concedemos o usuário testuser todos os privilégios no sistema solar banco de dados, usando testpassword como senha. Agora vamos criar uma tabela e preenchê -la com alguns dados (sem precisão astronômica pretendida):

Use solar_system; Crie planetas de tabela (ID TinyInt (1) não assinado, não nulo Auto_increment, chave primária (id), nome varchar (10) não nulo, color varchar (10) não nulo); Inserir em planetas (nome, cor) valores ('terra', 'azul'), ('mars', 'vermelho'), ('júpiter', 'estranho'); 
cópia de

DSN: Nome da fonte de dados

Agora que temos um banco de dados, devemos definir um Dsn. DSN significa Nome da fonte de dados, E é basicamente um conjunto de informações necessárias para se conectar ao banco de dados, representado na forma de uma string. A sintaxe pode ser diferente, dependendo do banco de dados para o qual você deseja se conectar, mas como estamos interagindo com o MySQL/Mariadb, forneceremos:

  • O tipo de driver a ser usado para a conexão
  • O nome do host da máquina que hospeda o banco de dados
  • A porta a ser usada para a conexão (opcional)
  • O nome do banco de dados
  • O charset (opcional)

O formato da string, no nosso caso, seria o seguinte (vamos armazená -la no $ dsn variável):

$ dsn = "mysql: host = localhost; porta = 3306; dbname = solar_system; charset = utf8"; 
cópia de

Primeiro de tudo, fornecemos o Prefixo do banco de dados. Nesse caso, como estamos nos conectando a um banco de dados MySQL/Mariadb, usamos mysql. Em seguida, separamos o prefixo do resto da corda por um cólon e de cada uma das outras seções por um semicolon.

Nas próximas duas seções, especificamos o nome de anfitrião da máquina em que o banco de dados está hospedado e o porta Para usar para a conexão. Se o último não for fornecido, o padrão será usado, o que, neste caso, é 3306. Imediatamente depois de fornecermos o nome do banco de dados, E depois disso, o CHARST usar.

Criando o objeto PDO

Agora que nosso DSN está pronto, vamos construir o Objeto PDO. O construtor PDO toma a sequência DSN como primeiro parâmetro, o nome do usuário no banco de dados como segundo parâmetro, sua senha como terceira e opcionalmente uma matriz de opções como a quarta:

$ options = [PDO :: att_errmode => PDO :: Errmode_Exception, PDO :: att_default_fetch_mode => PDO :: fetch_assoc]; $ pdo = novo PDO ($ dsn, 'testUser', 'testpassword', $ options); 
cópia de

No entanto, as opções podem ser especificadas também após a construção do objeto, através do SetAttribute () método:

$ pdo-> setAttribute (PDO :: att_errmode, PDO :: errmode_exception); 
cópia de

Definindo o comportamento da PDO em erros

Vamos dar uma olhada em algumas das opções disponíveis para PDO :: att_errmode. Esta opção é realmente importante, porque define o comportamento de DOP em caso de erros. As opções possíveis são:

PDO :: Errmode_silent

Este é o padrão. PDO acaba de definir o código de erro e a mensagem de erro. Eles podem ser recuperados usando o Erro de código() e errorInfo () métodos.

PDO :: Errmode_Exception

Esta é, na minha opinião, a recomendada. Com esta opção, além de definir o código e as informações de erro, o PDO jogará um PdoException, que quebrará o fluxo de scripts, e é particularmente útil em caso de Transações de PDO (Vamos ver quais transações são posteriormente neste tutorial).

PDO :: Errmode_warning

Com esta opção, o PDO definirá o código de erro e as informações como indexadas PDO :: Errmode_silent, mas também produzirá um AVISO, que não quebrará o fluxo do script.

Definindo o modo de busca padrão

Outra configuração importante pode ser especificada através do PDO :: Default_fetch_mode. constante. Ele permite especificar o método de busca padrão a ser usado ao recuperar os resultados de uma consulta. Estas são as opções mais usadas:

PDO :: fetch_both:

Este é o padrão. Com ele, o resultado recuperado por uma consulta de busca será indexado por inteiro e pelo nome da coluna. A aplicação deste modo de busca ao recuperar uma linha da tabela dos planetas nos daria este resultado:

$ stmt = $ PDO-> Query ("Selecione * FROM PLANETES"); $ resultados = $ stmt-> busca (PDO :: fetch_both); 
cópia de
Array ([id] => 1 [0] => 1 [nome] => Terra [1] => Terra [cor] => azul [2] => azul) 

PDO :: fetch_assoc:

Com esta opção, o resultado será armazenado em um matriz associativa em que cada chave será o nome da coluna, e cada valor será o valor correspondente em uma linha:

$ stmt = $ PDO-> Query ("Selecione * FROM PLANETES"); $ resultados = $ stmt-> busca (PDO :: fetch_assoc);
cópia de
Array ([id] => 1 [nome] => Earth [cor] => azul) 

PDO :: fetch_num

Este modo de busca retorna a linha buscada para um 0 Array Indexado:

Array ([0] => 1 [1] => Terra [2] => azul) 

PDO :: fetch_column

Esse método de busca é útil ao recuperar apenas os valores de uma coluna e retornará todos os resultados dentro de uma matriz simples e unidimensional. Por exemplo, esta consulta:

$ stmt = $ PDO-> Query ("Selecione o nome dos planetas");
cópia de

Retornaria este resultado:

Array ([0] => Terra [1] => Marte [2] => Júpiter) 

PDO :: fetch_key_pair

Este método de busca é útil ao recuperar os valores de apenas 2 colunas. Ele retornará os resultados na forma de uma matriz associativa na qual os valores recuperados do banco de dados para a primeira coluna especificada na consulta serão usados ​​como teclas de matriz, enquanto os valores recuperados para a segunda coluna representarão o associativo associativo Valores da matriz:

$ stmt = $ PDO-> Query ("Selecione o nome, cor dos planetas"); $ resultado = $ stmt-> fetchall (PDO :: fetch_key_pair); 
cópia de

Retornaria:

Array ([terra] => azul [marte] => vermelho [júpiter] => estranho) 

PDO :: fetch_object:

Ao usar o PDO :: fetch_object constante, um objeto anônimo será criado para cada linha recuperada. Suas propriedades (públicas) serão nomeadas após as colunas, e os resultados da consulta serão usados ​​como seus valores. A aplicação deste modo de busca na mesma consulta acima nos devolveria um resultado no formulário:

$ resultados = $ stmt-> busca (PDO :: fetch_obj);
cópia de
objeto stdclass ([nome] => terra [cor] => azul) 

PDO :: fetch_class:

Este modo de busca, como o acima, atribuirá o valor das colunas às propriedades de um objeto, mas neste caso devemos especificar uma classe existente que deve ser usada para criar o objeto. Vamos demonstrar, primeiro vamos criar uma aula:

classe planeta private $ nome; privado $ cor; função pública setName ($ planet_name) $ this-> name = $ planet_name;  função pública setColor ($ planet_color) $ this-> color = $ planet_color;  função pública getName () return $ this-> nome;  função pública getColor () return $ this-> color;  
cópia de

Por favor, ignore a ingenuidade do código acima e apenas observe que as propriedades da classe do planeta estão privado e a classe não tem construtor. Agora vamos tentar buscar os resultados.

Ao usar buscar() com PDO :: fetch_class você deve usar o setFechMode () Método no objeto de declaração antes de tentar recuperar os dados, por exemplo:

$ stmt = $ PDO-> Query ("Selecione o nome, cor dos planetas"); $ stmt-> setFetchMode (PDO :: fetch_class, 'planeta');
cópia de

Fornecemos a opção de busca constante PDO :: fetch_class Como o primeiro argumento do método setFetchMode () e o nome da classe que deve ser usado para criar o objeto ('planeta' neste caso) como o segundo. Agora corremos:

$ planet = $ stmt-> fetch ();
cópia de

Um objeto planeta deveria ter sido criado:

var_dump ($ planeta);
cópia de
Objeto do Planeta ([Nome: Planet: Private] => Terra [Cor: Planet: Private] => Blue) 

Observe como os valores recuperados resultantes da consulta foram atribuídos às propriedades correspondentes do objeto, mesmo que sejam privadas.

Atribuir propriedades após a construção do objeto

A classe do planeta não possui o construtor explícito definido, portanto, não há problemas ao atribuir as propriedades; Mas e se a classe tivesse um construtor no qual a propriedade fosse designada ou manipulada? Como os valores são atribuídos antes que o construtor seja chamado, eles teriam sido substituídos.

PDO ajuda a fornecer o Fetch_props_late Constante: Ao usá -lo, os valores serão atribuídos às propriedades depois o objeto é construído. Por exemplo:

classe planeta private $ nome; privado $ cor; Função pública __construct ($ name = Moon, $ color = cinza) $ this-> name = $ name; $ this-> color = $ color;  função pública setName ($ planet_name) $ this-> name = $ planet_name;  função pública setColor ($ planet_color) $ this-> color = $ planet_color;  função pública getName () return $ this-> nome;  função pública getColor () return $ this-> color; 
cópia de

Modificamos nossa aula do planeta, fornecendo um construtor que leva dois argumentos: o primeiro é nome e o segundo é cor. Esses argumentos têm um valor padrão, respectivamente de lua e cinza: Isso significa que, se nenhum valores forem explicitamente, esses serão os padrões atribuídos.

Nesse caso, se não usarmos Fetch_props_late, Independentemente dos valores recuperados do banco de dados, as propriedades sempre terão os valores padrão, porque serão substituídos quando o objeto for construído. Vamos verificar isso. Primeiro, executamos a consulta:

$ stmt = $ PDO-> Query ("Selecione o nome, cor de solar_system onde nome = 'terra'"); $ stmt-> setFetchMode (PDO :: fetch_class, 'planeta'); $ planet = $ stmt-> fetch ();
cópia de

Então nós jogamos o Planeta Objeta e verifique quais valores suas propriedades têm:

var_dump ($ planeta); objeto (planeta)#2 (2) ["Nome": "Planet": Private] => String (4) "Moon" ["Color": "Planet": Private] => String (4) "Gray" 
cópia de

Como esperado, os valores recuperados do banco de dados foram substituídos pelos padrões. Agora, demonstramos como esse problema pode ser resolvido usando Fetch_props_late (A consulta é a mesma que acima):

$ stmt-> setFetchMode (PDO :: Fetch_class | PDO :: Fetch_Props_late, 'Planet'); $ planet = $ stmt-> fetch (); var_dump ($ planeta); objeto (planeta)#4 (2) ["nome": "planeta": privado] => string (5) "terra" ["cor": "planeta": privado] => string (4) "azul" 
cópia de

Finalmente obtivemos os resultados desejados. Mas e se o construtor de classe não tiver valores padrão e eles devem ser fornecidos ? Simples: podemos especificar os parâmetros do construtor na forma de uma matriz como um terceiro argumento, após o nome da classe, no método setFetchMode (). Por exemplo, vamos alterar o construtor:

classe planeta private $ nome; privado $ cor; função pública __construct ($ nome, $ color) $ this-> name = $ name; $ this-> color = $ color;  […]
cópia de

Os argumentos do construtor agora são obrigatórios, então executaríamos:

$ stmt-> setFetchMode (PDO :: Fetch_class | PDO :: Fetch_Props_late, 'Planet', ['Moon', 'Gray']);
cópia de

Nesse caso, os parâmetros que fornecemos servem exatamente como valores padrão, necessários para inicializar o objeto sem erros: eles serão substituídos pelos valores recuperados do banco de dados.

Buscar vários objetos

Claro que é possível buscar vários resultados como objetos, usando buscar() Método dentro de um loop de tempo:

while ($ planet = $ stmt-> fetch ()) // faça coisas com os resultados 
cópia de

ou buscando todos os resultados de uma só vez. Neste caso, como dito acima, usando o Fetchall () Método, você não precisa especificar o modo de busca antes de chamar o próprio método, mas no momento você chama:

$ stmt-> fetchall (PDO :: fetch_class | PDO_FETCH_PROPS_LATE, 'Planet', ['lua', 'Gray']); 
cópia de

PDO :: fetch_into

Com este conjunto de métodos buscados, o PDO não criará um novo objeto, mas atualizará as propriedades de uma existente, mas apenas se forem público, ou se você usar o __definir Método mágico dentro do objeto.

Preparado vs declarações diretas

O PDO tem duas maneiras de executar consultas: uma é a maneira direta e de uma etapa. O outro, mais seguro é usar declarações preparadas.

Consultas diretas

Ao usar consultas diretas, você tem dois métodos principais: consulta() e exec (). Os retornos anteriores retornam um Pdostatemnt objeto que você pode usar para acessar resultados através do buscar() ou Fetchall () Métodos: você o usa para declaração que não modifica uma tabela, como Selecione.

O último, em vez disso, retorna o número de linhas que foram alteradas pela consulta: nós a usamos para declarações que modificam linhas, como INSERIR, EXCLUIR ou ATUALIZAR. Declarações diretas devem ser usadas apenas quando não há variáveis ​​na consulta e você absolutamente confia que ela é segura e escape adequadamente.

Declarações preparadas

A PDO suporta também declarações preparadas em dois estágios: isso é útil ao usar variáveis ​​na consulta, e é mais seguro em geral, porque o preparar() o método executará toda a escapar necessária para nós. Vamos ver como as variáveis ​​são usadas. Imagine que queremos inserir as propriedades de um objeto de planeta no Planetas mesa. Primeiro, prepararíamos a consulta:

$ stmt = $ pdo-> preparar ("inserir em planetas (nome, cor) valores (?, ?) "); 
cópia de

Como dito antes, primeiro usaríamos o preparar() Método que toma a consulta SQL como argumento, usando espaços reservados para as variáveis. Agora os espaços reservados podem ter dois tipos:

Espaços reservados posicionais

Ao usar ? Esponto de espaços reservados posicionais, podemos obter um código mais conciso, mas devemos fornecer os valores a serem substituídos na mesma ordem dos nomes das colunas, em uma matriz fornecida como argumento para o executar() método:

$ stmt-> execute ([$ planeta-> nome, $ planeta-> cor]); 
cópia de

Nomeado espaço reservado

Usando Nomeado espaço reservado, Não precisamos respeitar uma ordem específica, mas vamos criar mais código detalhado. Ao executar o executar() Método, devemos fornecer os valores na forma de um matriz associativa em que cada chave seria o nome do espaço reservado usado, e o valor associado seria o que seria substituído na consulta. Por exemplo, a consulta acima se tornaria:

$ stmt = $ pdo-> preparar ("inserir em planetas (nome, cor) valores (: nome, color)"); $ stmt-> execute (['nome' => $ planet-> nome, 'color' => $ planet-> cor]); 
cópia de

Os métodos Prepare e Executar podem ser usados ​​ao executar consultas que modificam ou apenas recuperam dados do banco de dados. No primeiro caso, usamos os métodos de busca que vimos acima para recuperar os dados, enquanto em último podemos recuperar o número de linhas afetadas usando o Contagem de linhas() método.

Os métodos BindValue () e BindParam ()

Para fornecer os valores a serem substituídos na consulta, também podemos usar o bindValue () e bindParam () métodos. O primeiro vincula o valor da variável fornecida ao espaço posicional ou nomeado de nome utilizado ao preparar a consulta. Usando o exemplo acima que teríamos feito:

$ stmt-> bindValue ('nome', $ planet-> nome, PDO :: param_str); 
cópia de

Nós ligamos o valor de $ planeta-> nome para o :nome espaço reservado. Observe que o uso de métodos BindValue () e BindParam () podemos especificar, como terceiro argumento, o tipo da variável, usando a constante de PDO relacionada, neste caso PDO :: param_str.

Usando bindParam (), Em vez disso, podemos vincular a variável ao espaço reservado relacionado ao preparar a consulta. Observe que, neste caso, a variável está vinculada por referência, e seu valor só será substituído pelo espaço reservado no momento executar() Método é chamado. A sintaxe é a mesma que acima:

$ stmt-> bindParam ('nome', $ planet-> nome, PDO :: param_str) 
cópia de

Ligamos a variável $ planet-> nome para o :nome espaço reservado, não seu valor atual! Como dito acima, a conversão será realizada exatamente quando o executar() O método será chamado, de modo que o espaço reservado será substituído pelo valor que a variável tem naquele momento.

Transações de PDO

As transações fornecem uma maneira de preservar a consistência ao emitir várias consultas. Todas as consultas são feitas em um "lote" e comprometidas com o banco de dados apenas se todas forem bem -sucedidas. As transações não funcionarão em todos os bancos de dados e não para todos SQL Construções, porque alguns deles causam e implícita (lista completa aqui)

Com um exemplo extremo e estranho, imagine que o usuário deve selecionar uma lista de planetas e, cada vez que ele envia uma nova seleção, você deseja excluir o anterior do banco de dados antes de inserir o novo. O que aconteceria se a exclusão fosse bem -sucedida, mas não a inserção? Teríamos um usuário sem planetas! Normalmente, é assim que as transações são implementadas:

$ PDO-> BEGNTRANSACION (); tente $ stmt1 = $ pDO-> EXEC ("Excluir dos planetas"); $ stmt2 = $ pdo-> preparar ("inserir em planetas (nome, cor) valores (?, ?) "); foreach ($ planetas como $ planeta) $ stmt2-> execute ([$ planet-> getName (), $ planet-> getColor ()]); $ pdo-> commit (); catch ( PDoException $ e) $ pdo-> rollback ();
cópia de

Primeiro de tudo BeginTransaction () Método do objeto PDO Desativa a consulta AutoComit e, em seguida, dentro de um bloco de tentativa, as consultas são executadas na ordem procurada. Neste ponto, se não PdoException é levantado, as consultas são cometidas com o comprometer-se() método, caso contrário, através do reversão () Método, as transações são revertidas e a autocomit é restaurada.

Dessa forma, sempre haverá consistência ao emitir várias consultas. É óbvio que você pode usar transações de PDO apenas quando o PDO :: att_errmode está configurado para PDO :: Errmode_Exception.

Tutoriais do Linux relacionados:

  • Coisas para instalar no Ubuntu 20.04
  • Como alterar a senha do usuário do mariadb
  • Como criar uma pilha de lâmpadas à base de docker usando o docker em…
  • Instalação do Ampache Raspberry Pi
  • Uma introdução à automação, ferramentas e técnicas do Linux
  • OpenLITESPEED WordPress Instalação
  • Coisas para fazer depois de instalar o Ubuntu 20.04 fossa focal linux
  • Ubuntu 20.04 WordPress com instalação do Apache
  • Ubuntu 20.04: WordPress com instalação nginx
  • Instale o MySQL no Ubuntu 20.04 LTS Linux