Há alguns dias, escrevi sobre Usando PHP com Docker e Couchbasemas nunca me aprofundei nas práticas recomendadas para usar PHP e bancos de dados NoSQL. Por exemplo, como você lê e grava dados com o Couchbase Server usando PHP? O que acontece quando você precisa criar algumas consultas avançadas ou criar índices de alto desempenho?
Veremos alguns exemplos de uso do Servidor Couchbase com PHP, uma extensão do tutorial anterior sobre como colocar o banco de dados e o aplicativo da Web em contêineres.
Enquanto o tutorial anterior é incrivelmente útil para o desenvolvimento de microsserviços, mas não é um pré-requisito para o material que discutiremos a seguir.
Supondo que você tenha algum ambiente PHP configurado e pronto para servir aplicativos, precisamos obter o Couchbase PHP SDK para comunicação com nosso banco de dados. Se você estiver usando o Debian ou o Ubuntu, execute o seguinte:
|
1 2 3 4 5 6 7 |
wget http://packages.couchbase.com/releases/couchbase-release/couchbase-release-1.0-2-amd64.deb sudo dpkg -i couchbase-release-1.0-2-amd64.deb rm couchbase-release-1.0-2-amd64.deb sudo apt-get update sudo apt-get install libcouchbase-dev build-essential php5-dev zlib1g-dev sudo pecl install pcs-1.3.3 sudo pecl install couchbase |
Os comandos do Terminal acima foram retirados do manual oficial do CDocumentação do ouchbase PHP. Primeiro, o SDK é baixado e instalado, seguido por vários pacotes Debian que são necessários. Por fim, a extensão do Couchbase é baixada e seu pacote peças dependência.
Depois que as dependências forem instaladas, adicione o seguinte ao seu php.ini file:
|
1 |
extension=couchbase.so |
Se estiver usando um ambiente diferente do Debian ou Ubuntu para hospedar seu aplicativo PHP, consulte a documentação para obter outras etapas de instalação do SDK.
Execução de operações CRUD com o Couchbase Server e PHP
O Couchbase, em sua forma mais simples, é um banco de dados de valor-chave. Com isso em mente, podemos fazer operações como leitura, gravação, substituição e exclusão (CRUD), todas baseadas na chave de um determinado documento.
Veja o seguinte código PHP, por exemplo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php header("Content-Type: application/json"); $cluster = novo CouchbaseCluster("couchbase://localhost"); $bucket = $cluster->openBucket("default", ""); tente { $result = $bucket->get("nraboy"); } catch (CouchbaseException $e) { $bucket->insert("nraboy", array( "firstname" => "Nic", "lastname" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "website" => "https://www.thepolyglotdeveloper.com" ) )); $result = $bucket->get("nraboy"); } echo json_encode($result->value); ?> |
O código acima pressupõe que todos os dados impressos estarão no formato JSON. Primeiro nos conectamos a um cluster do Couchbase, neste caso um único nó localizado em nossa máquina local. Por máquina local, quero dizer que, nesse cenário, o Couchbase e o PHP estão operando no mesmo servidor.
Depois que uma conexão é estabelecida, podemos abrir um determinado Bucket que usaremos para armazenar dados em nosso aplicativo e ler dados. O Bucket neste exemplo é denominado padrão e não tem senha.
É aqui que as coisas ficam interessantes:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
tente { $result = $bucket->get("nraboy"); } catch (CouchbaseException $e) { $bucket->insert("nraboy", array( "firstname" => "Nic", "lastname" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "website" => "https://www.thepolyglotdeveloper.com" ) )); $result = $bucket->get("nraboy"); } |
Primeiro, tentamos obter um determinado documento em nosso Bucket pelo nome da chave. Se for lançado um erro por motivos como a inexistência dessa chave, nós o detectaremos e tentaremos criar um novo documento com essa chave.
Os dados inseridos podem ser tão complexos quanto você desejar. No Couchbase, eles são armazenados como JSON e são flexíveis, ao contrário das alternativas de bancos de dados relacionais.
Depois de ler os dados com êxito, podemos tentar imprimi-los de volta ao cliente:
|
1 |
echo json_encode($result->value); |
Se quiséssemos, poderíamos usar outros comandos do SDK, como substituir ou remover dependendo de nossas necessidades. No entanto, na maioria das vezes, estaremos trabalhando com grandes quantidades de dados em que talvez não saibamos todas as chaves para consulta.
É aqui que o N1QL e o PHP podem se unir.
Execução de consultas SQL em NoSQL com PHP e N1QL
Se esta é a primeira vez que você ouve falar do N1QL, trata-se de uma sintaxe SQL que funciona com dados JSON no Couchbase. Isso significa que, se você conhece SQL de um banco de dados relacional como o Postgres, saberá a maior parte do N1QL.
Vamos usar o exemplo anterior de CRUD e prepará-lo para o N1QL:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?php header("Content-Type: application/json"); $bucketName = "default"; $cluster = novo CouchbaseCluster("couchbase://localhost"); $bucket = $cluster->openBucket($bucketName, ""); tente { $query = CouchbaseN1qlQuery::fromString("CREATE INDEX `people` ON `$bucketName` (lastname)"); $bucket->query($query); } catch (CouchbaseException $e) { printf("Não foi possível criar o índice. Talvez ele já exista? (código: %d)\n", $e->getCode()); } $query = CouchbaseN1qlQuery::fromString("SELECT firstname, lastname, social_media FROM `$bucketName` WHERE lastname = \$lastname"); $query->namedParams(array("lastname" => "Raboy")); $result = $bucket->query($query); Se(empty($result->rows)) { $data = array( "firstname" => "Nic", "lastname" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "website" => "https://www.thepolyglotdeveloper.com" ) ); $query = CouchbaseN1qlQuery::fromString("INSERT INTO `$bucketName` (KEY, VALUE) VALUES ('nraboy', " . json_encode($data) . ")"); $bucket->query($query); $query = CouchbaseN1qlQuery::fromString("SELECT firstname, lastname, social_media FROM `$bucketName` WHERE lastname = \$lastname"); $query->namedParams(array("lastname" => "Raboy")); $query->consistency(CouchbaseN1qlQuery::REQUEST_PLUS); $result = $bucket->query($query); } echo json_encode($result->rows); ?> |
Como no exemplo anterior, estamos estabelecendo uma conexão e abrindo um determinado Bucket NoSQL. Como planejamos consultar os documentos no banco de dados por valores diferentes de suas chaves, precisamos criar índices.
|
1 2 3 4 5 6 |
tente { $query = CouchbaseN1qlQuery::fromString("CREATE INDEX `people` ON `$bucketName` (lastname)"); $bucket->query($query); } catch (CouchbaseException $e) { printf("Não foi possível criar o índice. Talvez ele já exista? (código: %d)\n", $e->getCode()); } |
O procedimento acima cria um índice que estamos chamando de pessoas que indexa o sobrenome propriedade de documentos dentro do padrão Bucket. Isso significa que poderemos consultar todos os documentos com base em um sobrenome valor.
Se o índice já existir, receberemos uma exceção, e é por isso que estamos tentando capturá-la.
Com o índice instalado, queremos tentar consultar os documentos:
|
1 2 3 |
$query = CouchbaseN1qlQuery::fromString("SELECT firstname, lastname, social_media FROM `$bucketName` WHERE lastname = \$lastname"); $query->namedParams(array("lastname" => "Raboy")); $result = $bucket->query($query); |
No exemplo acima, estamos construindo uma consulta para várias propriedades dentro de documentos que atendem à lógica condicional do ONDE cláusula. Se não quiséssemos definir cada propriedade, poderíamos ter usado facilmente o caractere asterisco.
Assim como em um banco de dados relacional, os bancos de dados NoSQL podem ser vítimas de ataques de injeção de SQL, e é por isso que estamos usando uma consulta parametrizada. Isso nos permite dividir em parâmetros os dados que são potencialmente gerados pelo usuário. Esses dados podem ter sido enviados por meio de um formulário.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Se(empty($result->rows)) { $data = array( "firstname" => "Nic", "lastname" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "website" => "https://www.thepolyglotdeveloper.com" ) ); $query = CouchbaseN1qlQuery::fromString("INSERT INTO `$bucketName` (KEY, VALUE) VALUES ('nraboy', " . json_encode($data) . ")"); $bucket->query($query); $query = CouchbaseN1qlQuery::fromString("SELECT firstname, lastname, social_media FROM `$bucketName` WHERE lastname = \$lastname"); $query->namedParams(array("lastname" => "Raboy")); $query->consistency(CouchbaseN1qlQuery::REQUEST_PLUS); $result = $bucket->query($query); } |
Se os resultados da consulta anterior retornarem como uma matriz vazia, isso significa que nenhum documento foi encontrado com esse critério. Se a matriz estiver vazia, queremos criar novos dados de modo semelhante ao que fizemos no exemplo anterior. Desta vez, estamos criando dados por meio de uma consulta N1QL e um INSERIR declaração.
Depois que os dados são inseridos, queremos consultá-los. O problema aqui é que estamos consultando com base em um índice e esse índice pode não ter sido atualizado ainda. Para garantir que receberemos os dados mais recentes, podemos definir a consistência da consulta e aguardar até que o índice seja atualizado.
Por fim, imprimimos o resultado na tela.
Conclusão
Você acabou de receber uma rápida introdução ao uso de aplicativos de exemplo NoSQL e PHP executados em Couchbase. Nos exemplos que vimos, era tudo CRUD ou tudo N1QL. Você não é, de forma alguma, obrigado a usar um ou outro. Você pode usar CRUD e N1QL no mesmo aplicativo.
O Docker funciona muito bem para criar contêineres de microsserviço usando este exemplo. Para ver como colocar esse aplicativo em contêineres, confira o tutorial anterior que escrevi, intitulado, Implantar um aplicativo PHP com Couchbase como contêineres do Docker.
Se você quiser obter mais informações sobre como usar o SDK PHP do Couchbase, consulte a seção Portal do desenvolvedor do Couchbase.