Laravel : gitリポジトリからローカル環境でのプロジェクト複製の流れ

———————
$ git clone https://github.com/***/***.git
$ cd ***
$ git branch ${issue}
$ git checkout ${issue}
// vendorの作成
$ php composer.phar install
// .envファイルの作成 ※.env.exampleの複製ではなく、必要に応じてMAIL_DRIVER、AWS_ACCESS_KEY、PUSHER_APP_IDなどを記述する
.env
$ php artisan key:generate

// mysql
mysql> create database ***_dev
mysql> use ***_dev
// テーブルの初期値入力

$ php artisan migrate
$ php composer.phar dump-autoload
———————

.env作成のところは、DATABASEだけでなく、MAIL_DRIVER、AWS_ACCESS_KEY、PUSHER_APP_IDを自分用のアカウントで作らないといけないので、丁寧にドキュメントを作成する必要がありそう。

extendsの条件分岐

非同期などの機能を実装する際に、同じルーティングで、blade内のインクルードファイルを切り分けたい時
-> if elseだと両方のextendsが読み込まれる為、 三項演算子(?:;)で切り分ける

## 前

@if($id == 1)
	@extends('layouts.hoge')
@else
	@extends('layouts.foo')
@endif

## 後

@extends(($id == 1) ? 'layouts.hoge':'layouts.foo')

ルーティングは要検討か。

laravel 6.x Mailgunからメール送信する書き方

公式ドキュメント: https://readouble.com/laravel/6.x/ja/mail.html

# 前準備
### mailgun
mailgun登録
https://app.mailgun.com/

### guzzleインストール
$ php composer.phar require guzzlehttp/guzzle

※guzzleとは?
https://github.com/guzzle/guzzle
-> Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services.

### .env

MAIL_DRIVER=mailgun
MAILGUN_DOMAIN=**********.mailgun.org
MAILGUN_SECRET=**********

### config/mail.php
driverをsmtpからmailgunに変更

'driver' => env('MAIL_DRIVER', 'mailgun'),

### config/services.php
特に変更なし

 'mailgun' => [
        'domain' => env('MAILGUN_DOMAIN'),
        'secret' => env('MAILGUN_SECRET'),
        'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
    ],

// route, controller, bladeは省略

以上

smtpとは異なり、.envにMAILGUN_DOMAINとMAILGUN_SECRETを設定する必要がある。
services.phpのendpointはデフォルトのまま

smtpを独自に作るとなると大変だが、APIだとサクッと書ける

Laravelでgmailから送信する設定

# gmailから送信する設定
### メール送信するgoogle account
– セキュリティ->2段階認証プロセス on
– アプリパスワード->(メール, mac(or windows))を選択

### .env

MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=${domain}@gmail.com
MAIL_PASSWORD=${生成されたアプリ パスワード}
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=${domain}@gmail.com
MAIL_FROM_NAME=sample

$ php artisan config:cache

// route, controller, bladeは省略

587ポートとは?
->メール送信時に使われてきたTCP25番ポート以外で、メール送信の為の専用ポート
->25番ポートブロックでも送信可能になる

outlookでもsmtpホストがありますが、殆ど使われていないのでしょうか。

メール送信時のcontroller・mailableクラスの変数の書き方

– to, cc, bccなど宛先はcontrollerで書く
– mailableクラスのコンストラクターに引数を渡す
– constructorに初期値を設定し、callback関数でルートからプレビューを行うこともできる
– メール本文は、text, htmlどちらも可能。改行はbrタグ

### controller

use Illuminate\Support\Facades\Mail;
use App\Mail\TestMail;
public function index()
    {
        //
        $name = '山本太郎';
        $date = '2020/02/11';
        $status = '完了';
        $to = 'test@gmail.com';
        $cc = 'cc@gmail.com';
        
        Mail::to($to)
            ->cc($cc)
            ->send(new TestMail($name, $date, $status));
        return "its works";
    }

### app/Mail/TestMail.php
$ php artisan make:mail TestMail

public function __construct($name='山田太郎', $date='2020/01/01', $status='テスト')
    {
        //
        $this->title = $date . 'テスト送信';
        $this->date = $date;
        $this->name = $name;
        $this->status = $status;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this
            ->from('from@example.com')
            ->subject($this->title)
            ->view('email.test')->with([
                'name' => $this->name,
                'date' => $this->date,
                'status' => $this->status,
            ]);
    }

### view

{{ $date }}<br>
メール本文<br>
{{ $name }}さんのステータスは{{ $status}}です

### routeプレビュー時

Route::get('/send', 'MailController@index');
Route::get('/send/preview', function(){
	return new App\Mail\TestMail();
});

メールの送信方法と、メール内容の設定はMVCで切り離されているので、非常に管理しやすいように思います。

mailtrapによるテスト送信の流れ

Dev、STG環境でのメール送信にmailtrapを使用できる
https://mailtrap.io/

### 特徴
– 開発用
– Inboxに保管できるメール数の上限は50通
– Inboxはひとつだけ

### .env
Integrationsの”Laravel”の内容を記述します

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

### make:mail
$ php artisan make:mail TestMail

app/Mail/TestMail.php が生成される

public function build()
    {
        return $this
            ->from('from@example.com')
            ->subject('テスト送信')
            ->view('email.test');
    }

### メール本文
resources/views/email/test.blade.php

メール本文

### route

Route::get('/send', 'MailController@index');

### controller
$ php artisan make:controller –resource MailController

public function index()
    {
        //
        Mail::to('test@gmail.com')
            ->send(new TestMail());
        return "its works";
    }

$ php artisan serve –host 192.168.33.10 –port 8000

mailtrapを確認すると、送信済となっています。
controllerから、メールを送る際に変数を扱いたいと思うので、続けてやっていきたいと思います。

Promiseとは?

### 「同期処理」と「非同期処理」
– 同期処理は上から下へ順番に1つずつ処理
– 非同期処理は時間が掛かりそうな処理を実行した後に、結果を待たずにすぐ次の処理を実行

## promise
引数「resolve」に取得したい値を設定することで、非同期処理の結果を格納

var result = new Promise(function(resolve){
		resolve(new Date);
	});

	result.then(function(data){
		console.log(data.getFullYear());
	});

then()の処理を実行することで、階層が複雑化しない

Pusher & Laravel Echo

Pusherとは?
-> WebSocketを介して、リアルタイムの双方向機能を統合し、迅速にするためのシンプルなホストされているAPI

参考: Laravel Broadcasting
https://readouble.com/laravel/6.x/ja/broadcasting.html
-> イベントをPusherチャンネルによりブロードキャストする
-> laravel echoとは、JavaScriptライブラリで、チャンネルの購読とLaravelによるイベントブロードキャストのリッスンを苦労なしに実現

### 1. Pusherにregister
https://pusher.com/

### 2 .env
pusherのapp keysからCredentialsを.envに追記

PUSHER_APP_ID=${}
PUSHER_APP_KEY=${}
PUSHER_APP_SECRET=${}
PUSHER_APP_CLUSTER=${}

BROADCAST_DRIVERをpusherに変更

BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

### 3. config/app.php
BroadcastServiceProviderのコメントアウト削除

        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // コメントアウト削除
        App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

### 4. Pusher Channels HTTP PHP Library
Pusher用のパッケージインストール
https://github.com/pusher/pusher-http-php

$ php composer.phar require pusher/pusher-php-server

### 5. Laravel Eco パッケージインストール
$ npm install –save laravel-echo pusher-js

### 6. resources/js/bootstrap.js
Laravel Echoに関するコードのコメント解除
forceTLSをfalseに変更

import Echo from 'laravel-echo';

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: false
});

build
$ npm run dev

### 7. app.jsに差し替え
前)

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>

後)

<script src="/js/app.js"></script>

### 8. イベント作成

$ php artisan make:event MessageCreated

app/Events/MessageCreated.php

namespace App\Events;
use App\Message;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class MessageCreated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public $message;

    public function __construct(Message $message)
    {
        //
        $this->message = $message;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('chat');
    }
}

### 9. Controller
event発火

public function create(Request $request)
    {
        //
        $message = Message::create([
            'body' => $request->message
        ]);
        event(new MessageCreated($message));
    }

### 10. config/broadcasting.php
‘useTLS’をtrueからfalseに変更

'connections' => [

        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'useTLS' => false,
            ],
        ],

### 11. view

<div id="chat">
		<textarea v-model="message"></textarea>
		<br>
		<button type="button" @click="send()">送信</button>

		<div v-for="m in messages">
			<span v-text="m.created_at"></span>:&nbsp;
			<span v-text="m.body"></span>
		</div>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
	<script src="/js/app.js"></script>
    <script>
    	new Vue({
    		el: '#chat',
    		data: {
    			message: '',
    			messages: []
    		},
    		methods: {
    			getMessages(){
    				const url = '/ajax/chat';
    				axios.get(url)
    					.then((response) => {
    						this.messages = response.data;
    					});
    			},
    			send(){
                    const axiosPost = axios.create({
                        xsrfHeaderName: "X-XSRF-TOKEN",
                        withCredentials: true
                    })
    				const url = '/ajax/chat';
    				const params = { message: this.message };
    				axiosPost.post(url, params)
    					.then((response) => {
    						this.message = '';
    					});
    			},
    		},
    		mounted(){
    			this.getMessages();
    			Echo.channel('chat')
    				.listen('MessageCreated', (e) =>{
    					this.getMessages();
    				});
    		} 
    	});
    </script>

※送信前

※送信後

JSコンソールと、storage/logs/laravel.logでエラー内容を確認しながら、修正していきます。
axiosのPOSTは、xsrfHeaderNameにX-XSRF-TOKENを指定してcsrf対策を施すようにします。

Pusherの挙動

DevToolでコンソールを開きながら、getting startedで挙動を確認します。

### index.html

<h1>Pusher Test</h1>
    <p>
        Try publishing an event to channel <code>my-channel</code>
        with event name <code>my-event</code>.
    </p>
     <script src="https://js.pusher.com/5.0/pusher.min.js"></script>
    <script>
        Pusher.logToConsole = true;

        var pusher = new Pusher('****************',{
            cluster: 'ap3',
            forceTLS: true
        });

        var channel = pusher.subscribe('my-channel');
        channel.bind('my-event', function(data){
            alert(JSON.stringify(data));
        });
    </script>

### server side
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar require pusher/pusher-php-server

require __DIR__ . '/vendor/autoload.php';

$options = array(
	'cluster' => 'ap3',
	'useTLS' => true
);
$pusher = new Pusher\Pusher(
	'********************',
	'********************',
	'******',
	$options
);

$data['message'] = 'hello world';
$pusher->trigger('my-channel', 'my-event', $data);

server側からclient側でデータが渡っていることを確認できます。

vue.jsのmountedとは?

公式: mounted
https://jp.vuejs.org/v2/api/index.html#mounted
elがマウントされた丁度後に呼ばれる
-> ビュー全体がレンダリングされた後にのみ実行される
-> createdはDOMがまだ作られていない状態、mountedはDOMが生成された直後の状態

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
	<script>
    	new Vue({
    		el: '#chat',
    		data: {
    			message: '',
    			messages: []
    		},
    		methods: {
    		},
    		mounted(){
    			this.$nextTrick(function(){
    				
    			})
    		} 
    	});
    </script>

### createdとmounted

new Vue({
    		el: '#app',
    		data: {
    		},
    		methods: {
    			showEl : function(){
    				console.log(this.$el)
    			}
    		},
    		created(){
    				console.log('created')
    				console.log(this.$el)
    		},
    		mounted(){
    			    console.log('created')
    				console.log(this.$el)
    		} 
    	});

createdを実装するイメージが湧かないが、mountedの使い方はわかりました。