Usar Cloud SQL for MySQL con PHP

En esta parte del tutorial de Bookshelf para PHP, se muestra cómo crear, leer, actualizar y eliminar datos estructurados en Google Cloud SQL for MySQL.

Esta página forma parte de un tutorial de varias páginas. Para empezar desde lo básico y consultar las instrucciones de configuración, ve a la aplicación Bookshelf de PHP.

Crear una instancia y base de datos de Cloud SQL

Instalar el proxy SQL

Descarga e instala el proxy de Cloud SQL. El proxy de Cloud SQL se usa para conectarse a la instancia de Cloud SQL cuando se ejecuta localmente.

Linux de 64 bits

  1. Descarga el proxy:
    wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
    
  2. Haz que el proxy sea ejecutable:
    chmod +x cloud_sql_proxy
    

Linux de 32 bits

  1. Descarga el proxy:
    wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
    
  2. Haz que el proxy sea ejecutable:
    chmod +x cloud_sql_proxy
    

macOS de 64 bits

  1. Descarga el proxy:
    curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
    
  2. Haz que el proxy sea ejecutable:
    chmod +x cloud_sql_proxy
    

macOS de 32 bits

  1. Descarga el proxy:
    curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
    
  2. Haz que el proxy sea ejecutable:
    chmod +x cloud_sql_proxy
    

Windows de 64 bits

Haz clic con el botón derecho en https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe y selecciona "Guardar vínculo como..." para descargar el proxy y cámbiale el nombre a cloud_sql_proxy.exe.

Windows de 32 bits

Haz clic con el botón derecho en https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe y selecciona "Guardar vínculo como..." para descargar el proxy y cámbiale el nombre a cloud_sql_proxy.exe.
Si el sistema operativo no se incluye aquí, también puedes compilar el proxy desde el origen.

Crear una instancia de Cloud SQL

  1. Crea una instancia de la segunda generación de Cloud SQL for MySQL. Nombre a la instancia library o algo similar. La instancia puede tardar unos minutos en estar lista. Una vez que la instancia esté lista, se debería poder ver en la lista de instancias.
  2. Ahora usa el SDK de Google Cloud de la línea de comandos y ejecuta el siguiente comando. Copia el valor que se muestra para connectionName en el siguiente paso.
    gcloud sql instances describe [YOUR_INSTANCE_NAME]

    El valor de connectionName tiene el formato [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME].

Inicializar la instancia de Cloud SQL

  1. Utiliza el connectionName del paso anterior para iniciar el proxy de Cloud SQL.

    Linux/Mac OS X

    ./cloud_sql_proxy -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:3306

    Windows

    cloud_sql_proxy.exe -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:3306

    Sustituye [YOUR_INSTANCE_CONNECTION_NAME] por el valor de connectionName que registraste en el paso anterior.

    Este paso establece una conexión del ordenador local a la instancia de Cloud SQL para fines de prueba local. Mantén el proxy de Cloud SQL en ejecución todo el tiempo durante la prueba de la aplicación a nivel local.

  2. A continuación, crea un nuevo usuario y base de datos de Cloud SQL.

    CONSOLE

    1. Crea una nueva base de datos mediante la consola de GCP para la library de instancias de Cloud SQL. Por ejemplo, puedes usar el nombre de bookshelf.
    2. Crea un nuevo usuario mediante la consola de GCP para la library de instancias de Cloud SQL.

    MYSQL CLIENT

    1. En una pestaña de línea de comando independiente, usa el cliente MySQL o un programa similar para conectarte a la instancia. Use la contraseña de raíz que configuraste cuando se te solicite.
      mysql --host 127.0.0.1 --user root --password
      
    2. Crea las bases de datos, los usuarios y los permisos de acceso necesarios en la base de datos de Cloud SQL mediante el uso de los siguientes comandos. Sustituye [MYSQL_USER] y [MYSQL_PASSWORD] por el nombre de usuario y contraseña que elijas.
      CREATE DATABASE bookshelf;
      CREATE USER '[MYSQL_USER]' IDENTIFIED BY '[MYSQL_PASSWORD]';
      GRANT ALL ON *.* TO '[MYSQL_USER]';
      

Establecer configuración

  1. Ve al directorio getting-started-php/2-structured-data y copia el archivo settings.yml.dist:

    cp config/settings.yml.dist config/settings.yml
    
  2. Abre config/settings.yml para editarlo.

  3. Sustituye YOUR_PROJECT_ID por el ID del proyecto.

  4. Establece el valor de bookshelf_backend en mysql.

  5. Establece los valores de cloudsql_connection_name, cloudsql_database_name, cloudsql_user, cloudsql_password y cloudsql_port con los valores apropiados para la instancia de Cloud SQL. Como estás usando mysql, debes usar el puerto 3306. Por ejemplo:

    cloudsql_connection_name: your_project_name:your_region:your_instance
    cloudsql_database_name: bookshelf
    cloudsql_user: phpapp
    cloudsql_password: password
    cloudsql_port: 3306
    
  6. Guarda y cierra settings.yml.

También debes actualizar app.yaml antes de desplegar:

  1. Abre app.yaml para editarlo.

  2. Elimina los comentarios de las líneas beta_settings y cloud_sql_instances. Establece el valor de cloud_sql_instances con el valor que usaste para cloudsql_connection_name en config/settings.yml. Debería tener el formato your_project_name:your_region:your_instance.

  3. Guarda y cierra app.yaml.

Instalar dependencias

Introduce el siguiente comando en el directorio de 2-structured-data.

composer install

Ejecutar la aplicación en la máquina local

  1. Inicia un servidor web local:

    php -S localhost:8000 -t web
    
  2. Introduce la siguiente dirección en el navegador web.

    http://localhost:8000

Ahora puedes navegar por las páginas web de la aplicación donde podrás agregar, editar y eliminar libros.

Desplegar la aplicación en el entorno flexible de App Engine

  1. Despliega la aplicación de muestra:

    gcloud app deploy
    
  2. Introduce la siguiente dirección en el navegador web. Sustituye [YOUR_PROJECT_ID] por el ID del proyecto:

    https://[YOUR_PROJECT_ID].appspot.com
    

    Si actualizas la aplicación, puedes desplegar la versión actualizada al introducir el mismo comando que utilizaste para desplegar la aplicación por primera vez. El nuevo despliegue crea una nueva versión de la aplicación y la promociona a la versión predeterminada. Las versiones anteriores de la aplicación se mantienen, al igual que las instancias de VM asociadas. Ten en cuenta que todas estas versiones de aplicaciones e instancias de VM son recursos facturables.

    Si eliminas las versiones no predeterminadas de la aplicación, puedes reducir los costes.

    Para eliminar una versión de la aplicación, sigue las instrucciones a continuación:

    1. In the GCP Console, go to the Versions page for App Engine.

      Go to the Versions page

    2. Select the checkbox for the non-default app version you want to delete.
    3. Click Delete to delete the app version.

    Si quieres obtener información completa sobre cómo limpiar los recursos facturables, consulta la sección sobre limpiar los recursos en el último paso de este tutorial.

    Estructura de la aplicación

    Este diagrama muestra los componentes de la aplicación y su funcionamiento.

    Proceso y estructura de despliegue de la aplicación Bookshelf

    Información sobre el código

    Anteriormente, editaste settings.yml y estableciste el valor de bookshelf_backend en mysql. Esto informa a la aplicación que cargue la clase Sql, que se define en src/DataModel/Sql.php. La clase Sql encapsula la API PDO y es responsable de almacenar libros en la base de datos Cloud SQL.

    Este código en controllers.php define y registra un controlador para la ruta GET '/books'. La variable $model es una instancia de la clase Sql. El método $model->listBooks devuelve una matriz que contiene una matriz de libros y un cursor. Luego, el motor de plantillas Twig procesa la lista de libros de acuerdo con la plantilla list.html.twig:

    $app->get('/books/', function (Request $request) use ($app) {
        /** @var DataModelInterface $model */
        $model = $app['bookshelf.model'];
        /** @var Twig_Environment $twig */
        $twig = $app['twig'];
        $token = $request->query->get('page_token');
        $bookList = $model->listBooks($app['bookshelf.page_size'], $token);
    
        return $twig->render('list.html.twig', array(
            'books' => $bookList['books'],
            'next_page_token' => $bookList['cursor'],
        ));
    });

    Esta es la plantilla Twig que se usa para listar libros recuperados de la base de datos de Cloud SQL. La plantilla recibe una variable de matriz llamada books. Para cada libro en la matriz, muestra el título y el autor. La plantilla también recibe una variable next_page_token que determina si se muestra el botón Más.

    {% for book in books %}
    <div class="media">
      <a href="/books/{{book.id}}">
        <div class="media-left">
          <img src="http://placekitten.com/g/128/192">
        </div>
        <div class="media-body">
          <h4>{{book.title}}</h4>
          <p>{{book.author}}</p>
        </div>
      </a>
    </div>
    {% else %}
    <p>No books found</p>
    {% endfor %}

    Este código define y registra un controlador para la ruta GET '/books/{id}', donde {id} es el ID de un libro individual. El controlador llama al método $model->read para obtener el libro especificado de Cloud SQL. El motor de plantillas Twig procesa el libro de acuerdo con la plantilla view.html.twig:

    $app->get('/books/{id}', function ($id) use ($app) {
        /** @var DataModelInterface $model */
        $model = $app['bookshelf.model'];
        $book = $model->read($id);
        if (!$book) {
            return new Response('', Response::HTTP_NOT_FOUND);
        }
        /** @var Twig_Environment $twig */
        $twig = $app['twig'];
    
        return $twig->render('view.html.twig', array('book' => $book));
    });

    La plantilla view.html.twig recibe una variable llamada book y muestra el título, la fecha de publicación, el autor y la descripción del libro.

    <div class="media">
      <div class="media-body">
        <h4 class="book-title">
          {{book.title}}
          <small>{{book.published_date}}</small>
        </h4>
        <h5 class="book-author">By {{book.author|default('Unknown', True)}}</h5>
        <p class="book-description">{{book.description}}</p>
      </div>
    </div>

    Cuando el usuario hace clic en Agregar libro, el controlador para GET /books/add muestra un formulario para introducir el título, el autor y otra información sobre un libro. Cuando el usuario hace clic en Guardar, el controlador para POST /books/add obtiene el nuevo libro de la petición y llama a $model->create para almacenar el libro en Cloud SQL:

    $app->get('/books/add', function () use ($app) {
        /** @var Twig_Environment $twig */
        $twig = $app['twig'];
    
        return $twig->render('form.html.twig', array(
            'action' => 'Add',
            'book' => array(),
        ));
    });
    
    $app->post('/books/add', function (Request $request) use ($app) {
        /** @var DataModelInterface $model */
        $model = $app['bookshelf.model'];
        $book = $request->request->all();
        $id = $model->create($book);
    
        return $app->redirect("/books/$id");
    });

    A continuación se presenta la plantilla para el formulario de entrada del libro:

    {% extends "base.html.twig" %}
    
    {% block content %}
    <h3>{{action}} book</h3>
    
    <form method="POST" enctype="multipart/form-data">
    
      <div class="form-group">
        <label for="title">Title</label>
        <input type="text" name="title" id="title" value="{{book.title}}" class="form-control"/>
      </div>
    
      <div class="form-group">
        <label for="author">Author</label>
        <input type="text" name="author" id="author" value="{{book.author}}" class="form-control"/>
      </div>
    
      <div class="form-group">
        <label for="published_date">Date Published</label>
        <input type="text" name="published_date" id="published_date" value="{{book.published_date}}" class="form-control"/>
      </div>
    
      <div class="form-group">
        <label for="description">Description</label>
        <textarea name="description" id="description" class="form-control">{{book.description}}</textarea>
      </div>
    
      <button id="submit" type="submit" class="btn btn-success">Save</button>
    </form>
    
    {% endblock %}

    El código de ejemplo incluye más controladores para editar y eliminar libros individuales:

    $app->get('/books/{id}/edit', function ($id) use ($app) {
        /** @var DataModelInterface $model */
        $model = $app['bookshelf.model'];
        $book = $model->read($id);
        if (!$book) {
            return new Response('', Response::HTTP_NOT_FOUND);
        }
        /** @var Twig_Environment $twig */
        $twig = $app['twig'];
    
        return $twig->render('form.html.twig', array(
            'action' => 'Edit',
            'book' => $book,
        ));
    });
    
    $app->post('/books/{id}/edit', function (Request $request, $id) use ($app) {
        $book = $request->request->all();
        $book['id'] = $id;
        /** @var DataModelInterface $model */
        $model = $app['bookshelf.model'];
        if (!$model->read($id)) {
            return new Response('', Response::HTTP_NOT_FOUND);
        }
        if ($model->update($book)) {
            return $app->redirect("/books/$id");
        }
    
        return new Response('Could not update book');
    });
    $app->post('/books/{id}/delete', function ($id) use ($app) {
        /** @var DataModelInterface $model */
        $model = $app['bookshelf.model'];
        $book = $model->read($id);
        if ($book) {
            $model->delete($id);
    
            return $app->redirect('/books/', Response::HTTP_SEE_OTHER);
        }
    
        return new Response('', Response::HTTP_NOT_FOUND);
    });
¿Te ha resultado útil esta página? Enviar comentarios: