20190413のlaravelに関する記事は4件です。

LaravelでのBrowsersyncを理解して外部開発WebサーバーにあるSSLのLaravelプロジェクトでも自動リロードを実現したい!

各自におかれましてはLaravelで本日もごにょごにょ楽しんでおられることと思い、嬉しく思います。
最近はLaravelを納品に使うことも増えましたので気持ち良い開発環境を構築したい今日このごろです。
さて、今回はファイル変更を検知してブラウザの自動リロードをしたいです。
私の環境ではちょっとしたコツが要りましたのでまとめ。
公式ドキュメントを詳らかに読んだわけではないので、とりあえず、こうやったらうまく動くよ、という記事となります。

公式ドキュメント
https://browsersync.io/docs/options

環境

下記環境で確認しています

  • Laravelプロジェクトは自マシンではなく、外部の開発サーバーに存在
  • 開発サーバーでは本番同等にphp-fpmなどを使ってWebサーバー経由でプロジェクトを配信
  • 開発サーバーでは本番同等に常時SSL化している

開発サーバーというよりステージングサーバーに近い環境です。
私は自マシンを信用していないのでバックアップスクリプトも走っている開発サーバーで作業することが多いです(客のチェックもリアルタイムにできるのでプロジェクトも進めやすい)。
自マシンでやる場合はもうすでに他の方の記事があるのでGoogle検索してください。ただし、この記事を読めばわりと柔軟に対応できると思います。まずLaravelをBrowsersyncなしで動作させ、それにappendでBrowsersyncをくっつけるイメージでいけばだいたいなんとかなります。

Browsersyncとは

Laravelを標準的にインストールしたら一緒に入ってくるファイル変更検知で自動ブラウザリロードの仕組みです。

LaravelプロジェクトでBrowsersyncを使ったリクエストをさばく仕組み

Browersyncは下記のような動作でリクエストをさばきます。

リクエストをインターセプト

BrowserSyncはListenしているhost、portでリクエストをインターセプトします。

proxy配下へリクエストをバケツリレー、なんか付加してブラウザへレスポンスを返却

  • proxy配下へリクエスト内容をバケツリレーします(ここがProxyのこと)
  • 配下から返却をBrowserSyncが取得
  • BrowserSyncはリロードの仕組みを返却に付与
  • レスポンスをブラウザへ返却

自動リロードの仕組み

わかれば簡単なのですが下記の動きをします。(前項にてサーバー側からブラウザへ命令を送信できる仕組みができています。)

チェック設定のファイルの変更を検知

設定ファイルのfilesに設定した内容でファイルシステムの変更をチェックします。

変更があればブラウザリロード命令を発行

  • レスポンスに付与した仕組みを使ってブラウザへリロード命令を送ります。
  • ブラウザは画面のリロードを実行

やったね。

実際の設定/コマンド

実際の設定/コマンドは下記となります。

webpack.mix.jsの内容

最小構成で下記となります。

mix.js('resources/js/app.js', 'public/js') // ただのmixだな
   .sass('resources/sass/app.scss', 'public/css') // ただのmixだな
   .browserSync({ // ここから
     proxy: {
        target: "http[s]://あなたのLaravelプロジェクトトップへアクセスできるURL" // 最後に/は不要
     },
     https: true, // httpsのサイトをproxyするならtrueをセット
     files: [ // チェックするファイルは下記で十分ではないかな。
       './resources/**/*',
       './app/**/*',
       './config/**/*',
       './routes/**/*',
       './public/**/*'
     ],
     open: false, //BrowserSync起動時にブラウザを開かない
     reloadOnRestart: true //BrowserSync起動時にブラウザにリロード命令おくる
});
  • proxy.targetのURLがhttpsのサイトの場合はhttpstrueにしてください
  • filesに'./*/'とかしているとファイル多すぎてBrowsersyncが落ちます

設定(Firewall)

デフォルトの3000番でBrowserSyncのListenが入りますので3000番をFireWallで通してください。

$ sudo ufw allow 3000
$ sudo ufw reload

npm run watchでBrowsersyncの起動

$ cd [your project path]
$ npm run watch

npm run watchにてデフォルトポート3000番でBrowsersyncが動作開始します。
下記のような表示がコンソールにでますので

[Browsersync] Proxying: https://xxxxxxxxxxxxx
[Browsersync] Access URLs:
 ---------------------------------------
       Local: https://localhost:3000
    External: https://192.168.xxx.xxx:3000

External:のURLにアクセスすればOKです。

他設定例

php artisan serveで起動したLaravelへアクセスする場合

webpack.mix.jsは下記になります。

mix.js('resources/js/app.js', 'public/js') // ただのmixだな
   .sass('resources/sass/app.scss', 'public/css') // ただのmixだな
   .browserSync({ // ここから
    proxy: {
        target: "http://127.0.0.1:8000" // 最後に/は不要
    },
    files: [ // チェックするファイルは下記で十分ではないかな。
       './resources/**/*',
       './app/**/*',
       './config/**/*',
       './routes/**/*',
       './public/**/*'
    ],
    open: false, //BrowserSync起動時にブラウザを開かない
    reloadOnRestart: true //BrowserSync起動時にブラウザにリロード命令おくる
});

ターミナル1つ目でphp artisan serve

$ (sudo) php artisan serve --host 0.0.0.0

場合によってはsudoいるかも。既存で動いているLaravelプロジェクトをいじっているプロセスがあればパーミッションデナイドでエラー画面になりました。

ターミナル2つ目でnpm run watch

$ npm run watch

まとめ

Browsersyncの待受ポートとか変更したい場合は公式ドキュメントにあるので参考にしてください。
調べてみると既存記事よりもずっとシンプルな設定に落ち着きました。
enjoy.

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lumen のjsonレスポンスを拡張する

Laravelではレスポンスマクロというものがある。

いろいろなルートやコントローラで、再利用するためのカスタムレスポンスを定義したい場合はResponseファサードのmacroメソッドが使用できます。

https://readouble.com/laravel/5.5/ja/responses.html

しかしLumenで試すとエラーが出る。そんなものなどないらしい。

Uncaught BadMethodCallException: Method error does not exist. in /var/www/html/src/vendor/illuminate/support/Traits/Macroable.php:74

この記事にかいてある通りResponseファサードがLaravelとは違うみたいですね。

Responseファサードがありません。
Responseファサードのクラス自体はあるのですが、getFacadeAccessor()が返すResponseFactoryContractクラスがDIコンテナに登録されていないので使えません。

https://qiita.com/crhg/items/2ca642904955a2846de7

けどなんとか拡張したいので下記のようにresponseヘルパーのjsonメソッドを追ってみる。
/vendor/laravel/lumen-framework/src/Http/ResponseFactory.php
→ /vendor/illuminate/http/JsonResponse.php

お、何かMacroableトレイトを使てるっぽい。JsonResponseに追加すればよさそう。

/vendor/illuminate/http/JsonResponse.php
class JsonResponse extends BaseJsonResponse
{
    use ResponseTrait, Macroable {
        Macroable::__call as macroCall;
    }

試す

サービスプロバイダを作成

app/Providers/ResponseMacroServiceProvider.php
    public function boot()
    {
        JsonResponse::macro('success', function ($data) {
            $rows = [
                'message' => 'success',
                'option_params' => '',
                'data' => $data,
            ];
            return JsonResponse::create($rows);
        });
    }

    public function register()
    {

サービスプロバイダーを登録。

bootstrap/app.php
$app->register(App\Providers\ResponseMacroServiceProvider::class);

あとはルーティングやコントローラーを追加する。

app/Http/Controllers/BlogContloer.php
    /**
     * ブログ一覧取得
     * @return JsonResponse
     */
    public function getBlogList(): JsonResponse
    {
        $data = [
            'id' => 1,
            'title' => '楽しいゆるふわPHPer'
        ];
        return JsonResponse::success($data);
    }

curlで確認。

curl -s "http://localhost:8080/api/blog" | jq

{
  "message": "success",
  "option_params": "",
  "data": {
    "id": 1,
    "title": "楽しいゆるふわPHPer"
  }
}

まとめ

Lumenにはレスポンスマクロはない。しかし、再利用するためのカスタムレスポンスを定義したい場合はJsonResponseクラスのmacroメソッドが使用できるよって話。(MacroトレイトをuseしてるならResponseクラスとかでもできる)

(参考)
https://qiita.com/crhg/items/2ca642904955a2846de7

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでLaravel環境を構築する②~MySQL、laravelの導入~]

DockerでLaravel環境を構築する②~PHPの導入~の続きです。これで最後です。

MySQLのインストール

次にDBを使えるようにするため、MySQLをインストールしていきます。

docker-compose.yml
services:
# 省略
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

environmentはDockerコンテナ内で使用する環境変数を指定できます。
ただしこれで終わりではなく、最後に(laravelをインストールした後に)
今設定したこれらの値を、laravelのアプリ内に設定することで、実際にmysqlを使えるようにしていきます。

また、volumesによって、mysqlのデータを永続化しています。
最終的なdocker-compose.ymlは以下のようになります。

docker-compose.yml
version: '3'
services:
  web:
    image: nginx:1.15.6
    ports:
      - "8000:80"
    depends_on:
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    image: php:7.2-fpm
    depends_on:
    - mysql
    volumes:
      - .:/var/www/html
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

Laravelのインストール

次は、Laravelをインストールします。

laravelのインストールにはcomporserが必要ですが、最初に作成したPHPにはそれがありません。なので,
imageを取得してPHPを立ち上げるのではなく、「phpのimage+comporserのインストール」ができるDockerfileを作成します。
dockerディレクトリの下にphpというディレクトリを作り、そこにDockerfileを作成し、内容を以下のようにします。

docker/php/Dockerfile ↓

FROM php:7.2-fpm

# install composer
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim

RUN apt-get update \
    && apt-get install -y libpq-dev \
    && docker-php-ext-install pdo_mysql pdo_pgsql

WORKDIR /var/www/html

次に、docker-compose.yml内のappサービスを以下のように書き換え、「build: ./docker/php」で、Dockerにホストされているimageからではなく、
作成したDockerfileからビルドするようにします。

docker-compose.yml
app:
    build: ./docker/php
    depends_on:
      - mysql
    volumes:
      - .:/var/www/html

そして、Nginxの設定(docker/default.conf)のroot(ドキュメントルート、4行目あたり)を書き換えて以下のようにします。

root  /var/www/html/my-laravel-app(自分の作成したlaravelアプリの名前)/public;

これで、nginxをリスタートします。

docker-compose restart

再度アクセスし、

スクリーンショット 2019-04-13 13.57.55.png

このようになればOKです!

最後に、(MySQLのインストールの続き)
環境変数の各値を、Laravel内のプロジェクトの .envファイルに記入します。

$ cd my-laravel-app(作成したlaravelのアプリに移動)
$ vi .env 

こんな感じで、.envファイルを開き、

以下のようになっている箇所を

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

docker-compose.ymlで定義した内容に合わせ、このように変更してください。

DB_HOSTのところは、docker-composeで定義したサービス名になります。

.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=sample
DB_USERNAME=user
DB_PASSWORD=password

以上で、作成したlaravelアプリで、mysqlが使えるようになっています。

nginxをリスタートし

$ docker-compose restart

再度アクセスして、コンテナの中に入ります。

$ docker-compose exec app bash
root@xxxxxxxxx:/var/www/html# 

#で入力待ちになっていればOKです。

作成したlaravelのアプリに移動して、マイグレーションを実行し、以下のようになれば完成です!!

root@xxxxxxxxx:/var/www/html#  cd my-laravel-app(作成したlaravelのアプリに移動)
root@xxxxxxxxx:/var/www/html#  php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 開発環境の構築(CentOS7)

①Laravelのインストールとディレクトリ構成

下記を参考にphp開発環境の構築及びDBの設定が済んでいることを前提とします.

参考:Vagrantでphp開発環境を構築(CentOS7.2)

  • 下記コマンドを実行してください(Laravelをインストールします).
仮想マシン
# laravelインストーラをインストールする
$ composer global require "laravel/installer=~1.1"
# laravelプロジェクトを作成する
$ composer create-project laravel/laravel /var/www/[プロジェクト名] --prefer-dist

ディレクトリ構成は下記のようになっており,主にコントローラであるHttp/Controllers/と,ビューであるresources/views/配下を編集することで開発を進めていきます.

ディレクトリ構成
app
  ├ Http/
  |  └ Controllers/
  |      ├ Auth/
  |      └ Controller.php
  ├ config/
  |  ├ app.php
  |  └ database.php
  ├ database/
  |  └ migrations/
  ├ public/
  |  ├ css/
  |  └ js/
  ├ resources/
  |  ├ assets
  |  └ views
  ├ routes/
  |  └ web.php
  └ .env
  • Http/Controllers/ : コントーラを配置するフォルダ.
  • config/app.php : アプリケーション全体の設定をするファイル(ロケール情報など).
  • config/database.php : 接続するデータベースに関しての設定をするファイル.
  • database/migrations/ : マイグレーションファイルを配置するフォルダ.
  • public/ : 外部からアクセス可能なフォルダ.CSSやJSはここに配置する.
  • resources/views/ : ビューを配置するフォルダ.
  • routes/ : ルーティング情報を配置するフォルダ.

②サンプルページの作成

Laravelでviewを作成する際は,Bladeというテンプレートエンジンを用います.

今回は下記のような構成で,サンプルページを作ってみることにします.

  • layouts/common.blade.php : ベースとなるテンプレートファイル
  • layouts/head.blade.php : HTMLのHeadタグの中に書き込むテンプレートファイル
  • layouts/header.blade.php : ヘッダーのテンプレートファイル
  • layouts/footer.blade.php : フッターのテンプレートファイル
  • pages/sample.blade.php : サンプルページのビューファイル(ページごとに作成します)

テンプレートファイルは,layout/ディレクトリを作ってその配下に,ビューファイルはpages/ディレクトリを作ってその配下に配置しました.これらの配置場所によって,呼び出す際の指定方法が変わってくるので気をつけてください.

参考:Blade テンプレートについて - Laravel学習帳
参考:LaravelのBladeテンプレートでレイアウト部分を共通にする

common.blade.php
<!DOCTYPE HTML>
<html lang="ja">
<head>
    {{-- Head部分 --}}
    @yield('head')
</head>
<body>
    {{-- ヘッダー部分 --}}
    @yield('header')

    <div class="container">

    <div class="main">
        {{-- コンテンツ部分 --}}
        @yield('content')
    </div>

    <div class="sub">
        {{-- サブコンテンツ部分 --}}
        @yield('sub')
        {{-- ページサブコンテンツ部分 --}}
        @yield('pageSub')
    </div>

    </div>
    {{-- フッター部分 --}}
    @yield('footer')
</body>
head.blade.php
@section('head')
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>Laravelサンプルサイト | @yield('title')</title>
<meta name="description" content=@yield('description')>
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- テンプレート共通CSS -->
<link type="text/css" href="{{asset('/css/app.css')}}" rel="stylesheet">
@yield('pageCss')
@stop
header.blade.php
@section('header')
<header class="header">
    <h1>Laravelサンプルサイト</h1>
</header>
@stop
footer.blade.php
@section('footer')
<footer class="footer">
    <small>@created by koukibuu3</small>
</footer>
<!-- テンプレート共通JS -->
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="{{{asset('/js/app.js')}}}"></script>
@yield('pageJs')
@stop
sample.blade.php
{{-- レイアウトの読み込み --}}
@extends('layouts.common')

{{-- CSSの読み込み --}}
@section('pageCss')
<!-- ページ独自CSS -->
<link type="text/css" href="{{asset('/css/sample.css')}}" rel="stylesheet">
@stop

@section('title')
サンプルページ
@stop

{{-- Headの読み込み --}}
@include('layouts.head')

{{-- ヘッダーの読み込み --}}
@include('layouts.header')

{{-- メインコンテンツ --}}
@section('content')
    <h2>This is sample page.</h2>
    <table>
        <tr>
            <th>ID</th>
            <th>NAME</th>
            <th>EMAIL</th>
        </tr>
        <?php foreach ($data as $val) { ?>
        <tr>
            <td><?php echo $val->id; ?></td>
            <td><?php echo $val->name; ?></td>
            <td><?php echo $val->email; ?></td>
        </tr>
        <?php } ?>
    </table>
@stop

{{-- JSの読み込み --}}
@section('pageJs')
<!-- ページ独自JS -->
<script type="text/javascript" src="{{{asset('/js/sample.js')}}}"></script>
@stop

{{-- フッターの読み込み --}}
@include('layouts.footer')
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む