PHP での Cloud Datastore の使用

PHP Bookshelf チュートリアルのこのパートでは、Google Cloud Datastore で構造化データを作成、読み取り、更新、および削除する方法を解説します。

このページは、複数のページから構成されるチュートリアルの一部です。最初から設定手順を確認するには、PHP Bookshelf アプリに移動してください。

設定の構成

  1. getting-started-php/2-structured-data ディレクトリに移動して、settings.yml.dist ファイルをコピーします。

    cp config/settings.yml.dist config/settings.yml
    
  2. 編集のため config/settings.yml を開きます。

  3. YOUR_PROJECT_ID は、実際のプロジェクト ID に置き換えます。

  4. bookshelf_backend の値を datastore に設定します。

  5. settings.yml を保存して閉じます。

Cloud Datastore は、自動的に初期化されて App Engine アプリに接続されるフルマネージド サービスです。そのため、これ以上の設定は不要です。

依存関係のインストール

2-structured-data ディレクトリで、次のコマンドを入力します。

composer install

ローカルマシンでのアプリの実行

  1. ローカル ウェブサーバーを起動します。

    php -S localhost:8000 -t web
    
  2. ウェブブラウザで、次のアドレスを入力します。

    http://localhost:8000

これで、このアプリのウェブページを表示し、書籍の追加、編集、削除を行うことができます。

App Engine フレキシブル環境へのアプリのデプロイ

  1. サンプルアプリをデプロイします。

    gcloud app deploy
    
  2. ウェブブラウザで、次のアドレスを入力します。[YOUR_PROJECT_ID] は実際のプロジェクト ID で置き換えます。

    https://[YOUR_PROJECT_ID].appspot.com
    

    アプリを更新する場合は、最初にデプロイしたときと同じコマンドを使って、更新バージョンをデプロイできます。デプロイを行うと、アプリの新しいバージョンが作成され、それがデフォルトのバージョンに設定されます。古いバージョンはそのまま残り、関連付けられた VM インスタンスも同様に残ります。すべてのアプリ バージョンと VM インスタンスが課金対象のリソースとなるのでご注意ください。

    アプリのデフォルト以外のバージョンを削除することで、コストを削減できます。

    アプリのバージョンを削除する手順は次のとおりです。

    1. GCP Console の [App Engine のバージョン] ページに移動します。

      [バージョン] ページに移動

    2. 削除したい、デフォルト以外のアプリのバージョンの横にあるチェックボックスをクリックします。
    3. ページ上部にある [削除] ボタンをクリックし、アプリのバージョンを削除します。

    課金対象のリソースをクリーンアップする方法の詳細については、このチュートリアルの最後のステップにあるクリーンアップ セクションを参照してください。

    アプリケーションの構造

    次の図は、アプリケーションを構成するコンポーネントと、それらの接続関係を示しています。

    Bookshelf アプリのデプロイ プロセスと構造

    コードの説明

    以前のステップで settings.yml を編集して、bookshelf_backend の値を datastore に設定しました。これにより、アプリは src/DataModel/Datastore.php で定義された Datastore クラスを読み込みます。Datastore クラスは、Cloud Datastore API をラップし、Cloud Datastore データベースに書籍情報を格納します。

    controllers.php にある次のコードが GET '/books/' ルートのハンドラを定義し、登録しています。$model 変数は Datastore クラスのインスタンスです。$model->listBooks メソッドが、書籍の配列とカーソルを含む配列を戻します。その後、list.html.twig テンプレートに従って 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'],
        ));
    });

    次の Twig テンプレートは、Cloud Datastore から取得した書籍のリストを生成するテンプレートです。このテンプレートは books という名前の配列変数を受信します。配列内の書籍ごとに、タイトルと著者名を表示します。また、テンプレートが受信する next_page_token 変数は、[More] ボタンを表示するかどうかを決定します。

    {% 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 %}

    このコードは、GET '/books/{id}' ルートのハンドラを定義して登録します。{id} は、個々の書籍の ID です。ハンドラは、$model->read メソッドを呼び出し、指定された書籍の情報を Cloud Datastore から取得します。Twig テンプレート エンジンが 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));
    });

    view.html.twig テンプレートは、book という名前の変数を受信し、書籍のタイトル、出版日、著者名、説明を表示します。

    <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>

    ユーザーが [Add book] をクリックすると、GET /books/add のハンドラは、タイトル、著者名などの書籍情報を入力するフォームを表示します。ユーザーが [Save] をクリックすると、POST /books/add のハンドラがリクエストから新しい書籍情報を取得し、$model->create を呼び出して書籍を Cloud Datastore に格納します。

    $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");
    });

    次のテンプレートは、書籍情報の入力用フォームです。

    {% 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 %}

    このサンプルコードには、書籍情報を個別に編集または削除するハンドラも追加されています。

    $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);
    });
このページは役立ちましたか?評価をお願いいたします。