目的
ハンズオン形式で、受講者の環境を統一したいという考えがあって、それにはGoogle Cloud Shellが便利かと思い環境を作ってみました。
開発でLaravelのチュートリアルなんかをやるために開発環境を作ったりするのですが、今から学ぼうとしている人にはなかなか難しいことだと思います。公式にはHomesteadというvagrant環境があるのですが、vagrantの意味がわからないと、「vagrantで環境用意してください」と言われても、、という気もするので調査してみました。
環境
- Laravel 5.5系
- 開発環境 Google Cloud Shell
- php 7.0
- データベース sqlite3
Google Cloud Shellについて
https://cloud.google.com/shell/
- Googleが提供するテンポラリーなVM
- ブラウザから使える端末
- ホームディレクトリはアカウントに紐付いて永続化
- ホーム以外は、シャットダウンとともに消える
- ありがちなツールが一通りインストール済み
- 無料
※料金体系は、無料とのことなんですが、ブースト機能とか使っても無料なのかちょっとよくわかっていない。
チュートリアル
Cloud Shellの起動
https://console.cloud.google.com/getting-started
から右上のコンソールのアイコンをクリックして、端末の起動。(初回の起動は少し時間がかかる)
下部にコンソールウィンドウが開いて、ログイン済みの状態になる。
必要なミドルウェアをインストール
php-zip, php-sqlite3ライブラリが入っていないので入れる。
$ sudo apt install -y php-zip php-sqlite3
こういったaptでのインストールは、ホーム外へのインストールなので、VMがシャットダウンされると消えてクリーンな状態になる。ハンズオン講習のような一時的な開発で消えて良い場合は環境がクリーンに戻るので便利。
(永続的な開発でのツール導入であればホームディレクトリ下にインストールする)
Laravelプロジェクト"blog"の作成
$ composer create-project --prefer-dist laravel/laravel blog "5.5.*"
Composerはすでにインストールずみなので、Laravelのインストールとプロジェクトを作成する。Laravelのバージョンは5.5系最新を指定。blogというプロジェクト名で作成。
blogディレクトリでサーバ起動
開発用のWebサーバーが提供されているのでそれを使って起動。apacheやnginxを別途インストールすることもできる。
$ cd blog
$ php artisan serve
artisanは、Laravelで用意されている便利コマンド群を提供するツール。php artisan
で実行してみると使用できるコマンドがたくさんあるのが分かる。開発でも頻繁に使用する。
ポート8000番でサーバーが起動する。Cloud Shellはクラウド上のシェルだが、一部のポートのみ開放してインターネット経由でアクセスできる。
ポート開放とWebアクセス。
クラウドシェルのタブの右側にあるアイコンからポート開放する。デフォルトでは8080を開放してプレビューするようになっているが、8000番に変更する。
変更してプレビューでブラウザのタブが開き、自分のCloud ShellセッションにHTTP経由でアクセスする。
ブラウザにはLaravelインストール直後の状態が表示される。
とても簡単。
コードエディタ
ホームディレクトリ配下のファイルを開いて編集できる。今まで開いていた端末もコードエディタの下部に移行してくる。今後はこちらの端末を使う。
blog/resources/views/welcome.blade.php
を開いて、タイトル部分を編集。
これはHTMLのテンプレートのようなもの。
ブラウザで開いたページをリロードすると表示が変わることを確認できる。
Ctrl+Cで一旦Webサーバーは終了。
設定ファイルの編集
laravelアプリケーションの設定ファイルである.env
ファイルを編集する。
ドットファイルは非表示になっているので、コードエディタの設定を変更して表示されるようにする。
デフォルトでは、.git, .DS_Store, .*
となっているが、.git, .DS_Store
と修正する。.*
をフィルタ対象外にする。(,だけ残したりすると設定が正しく動作しないようです)
ファイルツリーに戻ると、.envファイルが表示されているので、それを編集してデータベースの設定を変える。
今回はデータベースにsqlite3を使用する。
(Cloud Shellでmysql-serverをインストールして、mysqlを使用することも可能です。)
DB_CONNECTIONにsqliteを設定する。
sqliteのデータベースファイルは、DB_DATABASEでパスを指定することができるが、今回はデフォルトのパス(database/database.sqlite
になる)を使用する。その他のDB設定は使用しないのでコメントアウトしておく。
DB_CONNECTION=sqlite
#DB_HOST=127.0.0.1
#DB_PORT=3306
#DB_DATABASE=
#DB_USERNAME=
#DB_PASSWORD=
データベースマイグレーション
sqliteのデータベースファイルが生成されていないので空のファイルとして生成する。
touch コマンドで生成。
$ touch database/database.sqlite
artisanのmigrateコマンドでデータベーステーブル生成。
$ php artisan migrate
Migration table created successfully.
〜〜〜
sqliteでテーブルが作成されていることを確認。
$ sqlite3 database/database.sqlite ".tables"
migrations password_resets users
モデルの作成
artisan make:model
でブログ投稿"Post" のモデルの雛形を作成しつつ、migrationファイルも生成する。
$ php artisan make:model -m Post
Model created successfully.
Created Migration: xxx_create_posts_table
blog/app
のフォルダに PostモデルのファイルPost.php
が、
blog/database/migrations
のフォルダにpostsテーブルのマイグレーションファイルが生成されます。
マイグレーションファイルを編集して、postsテーブルの定義を記述。
#...中略...
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title'); #追加
$table->string('body'); #追加
$table->timestamps();
});
}
#...中略...
postsのテーブル定義ができたので、これもmigrationで生成する。
$ php artisan migrate
Migrating: 2018_xx_xx_xxxxxx_create_posts_table
Migrated: 2018_xx_xx_xxxxxx_create_posts_table
tinkerで対話的にデータを投入
Postのデータが何もないので、データを投入します。SQLを書いてINSERTしても良いのですが、作成したモデルを確かめるつもりで tinkerという対話シェル上で実行します。
ちょっとわかりにくいですが、Postのオブジェクトを生成→値を設定して→saveというのを2回繰り返しています。
$ php artisan tinker
Psy Shell v0.9.4 (PHP 7.0.27-0+deb9u1 — cli) by Justin Hileman
>>> $p = new App\Post()
=> App\Post {#2283}
>>> $p->title = "Title1"
=> "Title1"
>>> $p->body = "Body text1";
=> "Body text1"
>>> $p->save()
=> true
>>> $p = new App\Post()
=> App\Post {#2287}
>>> $p->title = "Title2"
=> "Title2"
>>> $p->body = "Body text2";
=> "Body text2"
>>> $p->save()
=> true
>>> exit
tinkerシェルを抜けたあとに、sqliteでデータを確認すると、postsに2レコード増えています。
sqlite3 database/database.sqlite "SELECT * FROM posts"
1|Title1|Body text1|2018-05-30 01:00:00|2018-05-30 01:00:00
2|Title2|Body text2|2018-05-30 01:00:10|2018-05-30 01:00:10
※laravelにはSeederという仕組みも用意されてあって初期データを生成するのもコードで準備しておいて、いつでも再生成できるようになります。
ルーティングに処理追加
blog/routes/web.php
にwelcomeビューへのルーティングが記述されています。
postsの全検索結果を、ビューに渡すようにします。
Route::get('/', function () {
$posts = App\Post::all();
return view('welcome', ['posts'=>$posts]);
});
ビュー修正
resources/views/welcome.blade.php
のテンプレートの大部分を削除して、postをforeachでレンダリングするように修正します。
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<ul>
@foreach($posts as $post)
<li>{{$post->title}} : {{$post->body}}</li>
@endforeach
</ul>
</html>
ブラウザで確認
再び Webサーバーを起動してブラウザから確認。
$ php artisan serve
レンダリングされることが確認できる。
コントローラーの作成
web.phpでpostsを検索する処理を書いたが、web.phpはコントローラーへの振り分けのみ記述し、データを取得する処理はPostControllerで記述するようにする。
artisan make:Controller
コマンドでコントローラー作成。
$ php artisan make:Controller PostController
Controller created successfully
# ...中略...
use App\Post; //Postクラスのuse
class PostController extends Controller
{
public function index(){
$posts = Post::all();
return view('welcome', ['posts'=>$posts]);
}
}
web.phpのルーティングをコントローラーの呼び出しに修正。
Route::get('/', 'PostController@index');
再び Webサーバーを起動してブラウザから同様に動作することを確認。
$ php artisan serve