- 投稿日:2019-04-13T20:39:38+09:00
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のサイトの場合はhttpsはtrueにしてください- 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.参考
- 投稿日:2019-04-13T19:18:12+09:00
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.phpclass JsonResponse extends BaseJsonResponse { use ResponseTrait, Macroable { Macroable::__call as macroCall; }試す
サービスプロバイダを作成
app/Providers/ResponseMacroServiceProvider.phppublic 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クラスとかでもできる)
- 投稿日:2019-04-13T17:06:28+09:00
DockerでLaravel環境を構築する②~MySQL、laravelの導入~]
DockerでLaravel環境を構築する②~PHPの導入~の続きです。これで最後です。
MySQLのインストール
次にDBを使えるようにするため、MySQLをインストールしていきます。
docker-compose.ymlservices: # 省略 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.ymlversion: '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.ymlapp: 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再度アクセスし、
このようになればOKです!
最後に、(MySQLのインストールの続き)
環境変数の各値を、Laravel内のプロジェクトの .envファイルに記入します。$ cd my-laravel-app(作成したlaravelのアプリに移動) $ vi .envこんな感じで、.envファイルを開き、
以下のようになっている箇所を
.envDB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secretdocker-compose.ymlで定義した内容に合わせ、このように変更してください。
DB_HOSTのところは、docker-composeで定義したサービス名になります。
.envDB_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
- 投稿日:2019-04-13T12:18:51+09:00
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') @stopheader.blade.php@section('header') <header class="header"> <h1>Laravelサンプルサイト</h1> </header> @stopfooter.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') @stopsample.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')
