はじめに
今年はほぼ間違いなくPHPしかもLaravelを触ることになるので、簡単なサイトを作成することにしました。
環境構築から一通りやることがあるので、覚えておくためにまとめておきます。
前提
Windowsで作業してるので、MacやLinux使っている人には不要な作業も記載しています。
一通り記載するつもりですが、記載が漏れて不要な作業が書かれていたらごめんなさい。
環境
PHP 7.2
Laravel Framework 5.7.19
Postgres 11.1(psql 9.5.11)
Docker for Windows 2.0.0.0-win81 (29211)
nginx 1.15.8
今回作るもの
色々とやろうとしましたが、簡単なサイトなら何かの一覧表示すればいいやということで、データベースに登録した本一覧が画面に表示されるまでを作ることにしました。
Laravelの環境構築
まずはLaravelを使用出来るようにする必要があります。
今回はlaradockを使用して楽させてもらいます。
上で記載した環境は書いた当時(2019/01/03)のlaradockで使用されているバージョンそのままです。
laradockのclone
Githubにありますので、cloneしてもってきます。
場所はどこでも大丈夫です。
git clone https://github.com/Laradock/laradock.git
laradockの環境設定
Docker for Windows + Postgres用の設定変更をするのとコンテナ起動のためにフォルダ内に移動します。
cd laradock
そして設定ファイルのサンプルをベースに書き換えるために設定ファイルをコピーしておきます。
cp env-example .env
laradockのデフォルトはmysqlを使用する設定となっていてpostgresがインストールされないため、されるように以下の設定をtrue
に変更します。
WORKSPACE_INSTALL_PG_CLIENT=true
次にdocker-compose.ymlも修正します。
修正の前にpostgres用のnamed volumeを作成しておきます。
postgresの永続化はwindowsだと上手くいかずnamed volumeを作成してそこを指定するというのが一般的です。
docker create volume --name postgres_db
named volumeを作成したらdocker-compose.ymlのpostgresのvoluesを作成したnamed volumeに変更します。
なんとなく必要のないdocker-entrypoint-initdb.d
の設定も書き換えていますが、気にしないでください。
postgres_db:/var/lib/postgresql/data
./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
後、なぜかelasticsearchのvolume設定が変でエラーになってしまうので、使用しませんが修正しておきます。
elasticsearch:/usr/share/elasticsearch/data
${DATA_PATH_HOST}/elasticsearch:/usr/share/elasticsearch/data
最後にvolumesの使用設定を一番下に追加して終わりです。
## volumes
volumes:
postgres_db:
external: true
次にlaradockでnginxを使用することになるので先回りして設定を変更しておきます。
laradock/nginx/sites/default.conf
のroot
を今回作成するパスに変更します。
app01
という名前で作成するつもりなので、下記のような設定にしていますが、自身の作成したい名前に合わせてフォルダ名は入力してください。
やる際はconfのバックアップを取得した方が無難です。
root /var/www/app01/public;
コンテナ起動
必要なことは終わったのでコンテナを起動します。
docker-compose up -d nginx postgres
初回は色々と時間かかるので、待ってる間は適当に暇をつぶしてください。
Laravelプロジェクトの生成
コンテナ起動後はコンテナ内に入ってLaravelプロジェクトを生成します。
laradockはworkspace
という全ての操作が可能なコンテナが用意されるので、ここから操作していきます。
docker-compose exec workspace bash
コンテナに入ったら/var/www
配下にいますので、composerを使用してプロジェクトを生成します。
composerはデフォルトで入っているので、何もせず使用してOKです。
root@cdcd5245e1ef:/var/www# composer create-project laravel/laravel app01
プロジェクトの生成確認
プロジェクトが生成された確認はhttp://localhost/
にブラウザからアクセスすれば分かります。
nginxの設定次第なので、URLは適宜読み替えてください。
Laravelのデフォルト画面が出てくれば無事に生成することが出来ました。
データベースの設定
プロジェクトの生成が終わると、cloneしたフォルダと同階層にapp01が出来ています(laradockのデフォルト設定)。
そこが実際に実装を行っていくプロジェクトです。
まずはデータベースの設定を行っていきます。
プロジェクトのrootフォルダに.env
ファイルがありますので、開いてDBの設定を入れておきます。
ここで記載しているのはlaradockのデフォルト設定で作成した情報となりますので、違う設定でコンテナ作った人は読み替えてください。
注意点としては、DB_HOST
はpostgresだとpostgres
にしないと駄目だということぐらいです。
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
もう一つ/config/database.php
も同じ感じで修正します。
見れば分かると思うので割愛します。
schema
についてはこちらのファイルでしか設定できないので、public
が嫌な場合はコンテナ入って作って設定を変えてください。
今回はプロダクトじゃなくて自分の勉強用なので変更せずいきます。
Laravel標準認証機能を使用する
今回は認証機能を使用する必要はないのですが、折角なので機能確認目的でデフォルトの認証機能について作成しておきます。
マイグレーションついでにデータベースの設定が正しいかもチェックしておきます。
root@cdcd5245e1ef:/var/www/app01# php artisan make:auth
root@cdcd5245e1ef:/var/www/app01# php argisan migrate
マイグレーションに成功したらこんな感じでユーザー系のテーブルが生成されます。
root@cdcd5245e1ef:/var/www/app01# psql -U default -h postgres
Password for user default:
psql (9.5.12, server 11.1)
WARNING: psql major version 9.5, server major version 11.
Some psql features might not work.
Type "help" for help.
default=# \d
List of relations
Schema | Name | Type | Owner
--------+-------------------+----------+---------
public | migrations | table | default
public | migrations_id_seq | sequence | default
public | password_resets | table | default
public | users | table | default
public | users_id_seq | sequence | default
Index画面を変更する
一覧を表示するためIndex画面を流用して書き換えを行います。
デフォルトのRoutingはroutes/web.php
に書いているので、そこでIndexページのphpファイルがresources/views/welcome.blade.php
であることが確認できます。
新しく作成するのも面倒なので、このままこれを使いまわしたいと思います。
デザインに関しては今回はある程度適当に作ってしまおうと思うので、デフォルトのwelcome.blade.php
を親にして@yield('content')
にコンテンツを記述するように修正をします。
ついでにタイトルとかスタイルも修正しています。。
修正後はviews/layouts/index.blade.php
として保存します。
ちなみにhtmlとかcss周りはそれなりに表示出来ればいいやーぐらいで作成しています(今回の勉強したい主題ではないので)。
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Simple library</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Nunito', sans-serif;
font-weight: 200;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
justify-content: center;
}
.position-ref {
position: relative;
}
.top-right {
position: absolute;
right: 10px;
top: 18px;
}
.title {
font-size: 84px;
}
.content {
text-align: center;
}
.m-b-md {
margin-bottom: 30px;
}
@yield('style')
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@auth
@else
<a href="{{ route('login') }}">Login</a>
@if (Route::has('register'))
<a href="{{ route('register') }}">Register</a>
@endif
@endauth
</div>
@endif
<div class="content">
<div class="title m-b-md">Books</div>
<div>
@yield('content')
</div>
</div>
</div>
</body>
</html>
中身も適当に作ります。
今回はページャーについては作成しないで、取れたもの全て表示するとします。
いったん仮で作成したもので表示確認だけ行って次の作業に移ります。
@extends('layouts.index')
@section('style')
ul li {
list-style: none;
float:left;
display: table-cell;
}
.item-list {
width : 20%;
}
.item-title {
font-size : 14px;
}
.item-img {
width : 150px;
height : 150px;
}
@endsection
@section('content')
<div>
<ul>
<li class="item-list">
<p class="item-title">タイトル</p>
<img src="" class="item-img">
</li>
</ul>
</div>
@endsection
Index用のControllerの作成
データベースからデータを取得しないと成り立たないので、Contollerを作成していきます。
Controllerの生成
Contollerはコマンドから生成できるので、コンテナに入って生成します。
root@cdcd5245e1ef:/var/www/app01# php artisan make:controller IndexController
Routingの変更
今まで直接viewを返していましたが、Controller経由で返却するようroutes/web.php
のRoutingを変更します。
Route::get('/', 'IndexController@index');
Contollerの仮実装
まだ貸すための本が取得出来ない状態なので、いったんwelcome.blade.php
を返却するよう仮実装を行います。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class IndexController extends Controller
{
public function index()
{
return view('welcome');
}
}
データを取得できるようにする
migrate用ファイルの生成
まずはテーブルを生成するための実装を行っていきます。
migration用のファイルもコマンドから生成します。
php artisan make:migration create_books_table
データベース定義の作成
作成したファイルに定義を追加していきます。
今回はタイトルと画像URLを保存するとします。
作成したphpファイルに定義を追加してコンテナからmigrateして完了です。
カラムは単純ですが一応not null制約とindexを付けてみます。
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->text('title')->nullable(false);
$table->text('img_url')->nullable(false);
$table->timestamps();
$table->index('title');
});
}
pgadmin上でnot null制約とindexがきちんと付与されているかだけチェックしておきます。
-- Table: public.books
-- DROP TABLE public.books;
CREATE TABLE public.books
(
id integer NOT NULL DEFAULT nextval('books_id_seq'::regclass),
title text COLLATE pg_catalog."default" NOT NULL,
img_url text COLLATE pg_catalog."default" NOT NULL,
created_at timestamp(0) without time zone,
updated_at timestamp(0) without time zone,
CONSTRAINT books_pkey PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE public.books
OWNER to "default";
-- Index: books_title_index
-- DROP INDEX public.books_title_index;
CREATE INDEX books_title_index
ON public.books USING btree
(title COLLATE pg_catalog."default")
TABLESPACE pg_default;
Controllerからデータを全部取得する
テーブルに適当なデータを入れておいたとします。
(自分は確認用にアマゾンから適当な商品名と画像リンクを使わせていただきました)
そこからデータを取得をするべくControllerの修正を行います。
修正点はuse Illuminate\Support\Facades\DB;
を追加したのとviewへの変数受け渡しとして['books' => DB::table('books')->get()]
を追加した2点です。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class IndexController extends Controller
{
public function index()
{
return view('welcome', ['books' => DB::table('books')->get()]);
}
}
viewで取得したデータを表示できるようにする
viewの方も動的に出力できるよう修正します。
修正点は@foreach
の追加とタイトル、URLの埋め込みをそれぞれしています。
@extends('layouts.index')
@section('style')
ul li {
list-style: none;
float:left;
display: table-cell;
}
.item-list {
width : 20%;
}
.item-title {
font-size : 14px;
}
.item-img {
width : 150px;
height : 150px;
}
@endsection
@section('content')
<div>
<ul>
@foreach ($books as $book)
<li class="item-list">
<p class="item-title">{{ $book->title }}}</p>
<img src="{{$book->img_url}}" class="item-img">
</li>
@endforeach
</ul>
</div>
@endsection
さいごに
Laradock導入からHTML除けば2時間くらいでここまで来ることが出来ています(HTMLに小1時間ほど悩んだ)。
PHPは全然触ったことないけど(現時点で3時間くらい)、書き方覚えればなんとかいけそうなぐらい簡単でした。
これから使うプロダクトも増えてくるでしょうし、そんなに難しくないので一度は触っておいた方が良いかもしれません。
参考にしたサイト
https://qiita.com/J_Shell/items/695a30fd38444d065ae5
https://gist.github.com/yano/64c07ee81db24985fe8f6091cace503d
https://readouble.com/laravel/5.7/ja/