Hace unos días escribí sobre usando PHP con Docker y Couchbasepero nunca me he adentrado en las mejores prácticas para utilizar PHP y bases de datos NoSQL. Por ejemplo, ¿cómo lees y escribes datos con Couchbase Server mientras usas PHP? ¿Qué pasa cuando necesitas crear algunas consultas avanzadas o crear índices de alto rendimiento?
Vamos a ver algunos ejemplos para utilizar Servidor Couchbase con PHP, una extensión del tutorial anterior sobre la contenedorización de la base de datos y la aplicación web.
Mientras que el tutorial anterior es increíblemente útil para el desarrollo de microservicios, no es un prerrequisito para el material que discutiremos más adelante.
Asumiendo que tienes algún entorno PHP configurado y listo para servir aplicaciones, necesitamos obtener el SDK PHP de Couchbase para la comunicación con nuestra base de datos. Si estás en Debian o Ubuntu, ejecuta lo siguiente:
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 |
Los comandos de terminal anteriores se han extraído de la versión oficial de CDocumentación PHP de ouchbase. Primero se descarga e instala el SDK, seguido de varios paquetes Debian necesarios. Por último, se descarga la extensión Couchbase y se instala su piezas
dependencia.
Una vez instaladas las dependencias, añada lo siguiente a su archivo php.ini file:
1 |
extension=couchbase.so |
Si utiliza un entorno distinto de Debian o Ubuntu para alojar su aplicación PHP, consulte la documentación para conocer otros pasos de instalación del SDK.
Realización de operaciones CRUD con Couchbase Server y PHP
Couchbase en su forma más simple es una base de datos clave-valor. Con esto en mente, podemos hacer operaciones como leer, escribir, reemplazar y borrar (CRUD) todo basado en la clave de un documento en particular.
Tomemos como ejemplo el siguiente código PHP:
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 = nuevo CouchbaseCluster("couchbase://localhost"); $bucket = $cluster->openBucket("default", ""); intentar { $result = $bucket->get("nraboy"); } catch (CouchbaseException $e) { $bucket->insert("nraboy", array( "firstname" => "Nic", "apellido" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "sitio web" => "https://www.thepolyglotdeveloper.com" ) )); $result = $bucket->get("nraboy"); } echo json_encode($result->value); ?> |
El código anterior asume que cualquier dato impreso estará en formato JSON. Primero nos conectamos a un cluster de Couchbase, en este caso un solo nodo localizado en nuestra máquina local. Por máquina local quiero decir que en este escenario Couchbase y PHP están ambos operando en el mismo servidor.
Una vez establecida la conexión, podemos abrir un Bucket concreto que utilizaremos para almacenar datos dentro de nuestra aplicación y para leer datos. El Bucket en este ejemplo se llama por defecto
y no tiene contraseña.
Aquí es donde las cosas se ponen interesantes:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
intentar { $result = $bucket->get("nraboy"); } catch (CouchbaseException $e) { $bucket->insert("nraboy", array( "firstname" => "Nic", "apellido" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "sitio web" => "https://www.thepolyglotdeveloper.com" ) )); $result = $bucket->get("nraboy"); } |
Primero intentamos obtener un documento concreto de nuestro Bucket por el nombre de la clave. Si se produce un error por razones como la inexistencia de dicha clave, lo detectaremos e intentaremos crear un nuevo documento con dicha clave.
Los datos que insertas pueden ser tan complejos como quieras hacerlos. Dentro de Couchbase se almacena como JSON y es flexible, a diferencia de las alternativas de bases de datos relacionales.
Después de leer los datos correctamente, podemos intentar imprimirlos de vuelta al cliente:
1 |
echo json_encode($result->value); |
Si quisiéramos, podríamos utilizar otros comandos del SDK como sustituir
o eliminar
en función de nuestras necesidades. Sin embargo, la mayoría de las veces vamos a trabajar con cantidades masivas de datos en las que es posible que no conozcamos todas las claves de consulta.
Aquí es donde N1QL y PHP pueden unirse.
Realización de consultas SQL contra NoSQL con PHP y N1QL
Si es la primera vez que oyes hablar de N1QL, es una sintaxis SQL que funciona con datos JSON en Couchbase. Esto significa que si conoces SQL de una base de datos relacional como Postgres, conocerás la mayor parte de N1QL.
Tomemos el ejemplo CRUD anterior, y preparémoslo para 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 = "por defecto"; $cluster = nuevo CouchbaseCluster("couchbase://localhost"); $bucket = $cluster->openBucket($bucketName, ""); intentar { $query = CouchbaseN1qlQuery::fromString("CREATE INDEX `people` ON `$bucketName` (lastname)"); $bucket->query($query); } catch (CouchbaseException $e) { printf("No se ha podido crear el índice. ¿Quizás ya existe? (código: %d)\n", $e->getCode()); } $query = CouchbaseN1qlQuery::fromString("SELECT firstname, lastname, social_media FROM `$bucketName` WHERE lastname = `$lastname"); $query->namedParams(array("apellido" => "Raboy")); $result = $bucket->query($query); if(empty($result->rows)) { $data = array( "firstname" => "Nic", "apellido" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "sitio web" => "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("apellido" => "Raboy")); $query->consistency(CouchbaseN1qlQuery::REQUEST_PLUS); $result = $bucket->query($query); } echo json_encode($result->rows); ?> |
Al igual que en el ejemplo anterior, estamos estableciendo una conexión y abriendo un determinado Bucket NoSQL. Como tenemos previsto consultar los documentos de la base de datos por valores distintos de su clave, necesitamos crear índices.
1 2 3 4 5 6 |
intentar { $query = CouchbaseN1qlQuery::fromString("CREATE INDEX `people` ON `$bucketName` (lastname)"); $bucket->query($query); } catch (CouchbaseException $e) { printf("No se ha podido crear el índice. ¿Quizás ya existe? (código: %d)\n", $e->getCode()); } |
Lo anterior crea un índice que vamos a llamar gente
que indexa el apellido
propiedad de los documentos dentro del por defecto
Cubo. Esto significa que podremos consultar todos los documentos basados en un apellido
valor.
Si el índice ya existe, obtendremos una excepción, que es por lo que estamos tratando de atraparlo.
Con el índice en su lugar, queremos tratar de consultar los documentos:
1 2 3 |
$query = CouchbaseN1qlQuery::fromString("SELECT firstname, lastname, social_media FROM `$bucketName` WHERE lastname = `$lastname"); $query->namedParams(array("apellido" => "Raboy")); $result = $bucket->query($query); |
En el ejemplo anterior, estamos construyendo una consulta para varias propiedades dentro de los documentos que cumplen la lógica condicional de la directiva DONDE
cláusula. Si no quisiéramos definir cada propiedad podríamos haber utilizado fácilmente el carácter asterisco.
Al igual que con una base de datos relacional, las bases de datos NoSQL pueden ser víctimas de ataques de inyección SQL, razón por la cual estamos utilizando una consulta parametrizada. Esto nos permite dividir los datos potencialmente generados por el usuario en parámetros. Estos datos podrían haber sido enviados a través de un formulario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
if(empty($result->rows)) { $data = array( "firstname" => "Nic", "apellido" => "Raboy", "social_media" => array( "twitter" => "https://www.twitter.com/nraboy", "sitio web" => "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("apellido" => "Raboy")); $query->consistency(CouchbaseN1qlQuery::REQUEST_PLUS); $result = $bucket->query($query); } |
Si los resultados de la consulta anterior vuelven como un array vacío, significa que no se han encontrado documentos con ese criterio. Si el array está vacío, queremos crear nuevos datos de forma similar a como lo hicimos en el ejemplo anterior. Esta vez estamos creando datos a través de una consulta N1QL y una consulta INSERTAR
declaración.
Una vez insertados los datos, queremos consultarlos. El problema es que estamos haciendo una consulta basada en un índice y ese índice puede no haber sido actualizado todavía. Para garantizar que obtenemos los datos más recientes, podemos establecer la consistencia de la consulta y esperar hasta que el índice se haya actualizado.
Por último, imprimimos el resultado en la pantalla.
Conclusión
Usted acaba de obtener una rápida introducción al uso de NoSQL y PHP aplicaciones de ejemplo que se ejecutan en Couchbase. En los ejemplos que vimos, era todo CRUD o todo N1QL. No estás, de ninguna manera, obligado a utilizar uno u otro. Puedes usar CRUD y N1QL dentro de la misma aplicación.
Docker funciona muy bien para crear contenedores de microservicios con este ejemplo. Para ver cómo contenerizar esta aplicación, echa un vistazo al tutorial anterior que escribí titulado, Desplegar una aplicación PHP con Couchbase como contenedores Docker.
Si desea obtener más información sobre el uso del SDK PHP de Couchbase, consulte la página Portal para desarrolladores de Couchbase.